dsh-codearts 1.2.10 → 1.2.12

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-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}}";
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;align-items:center;gap:6px;display:flex}.xoziZG_accountToggle{align-items:center;gap:6px;display:inline-flex}.xoziZG_accountToggleLabel{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-size:12px;line-height:20px}.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,98 @@ 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
- "accountHint": "xoziZG_accountHint",
76
- "heatLegendChip": "xoziZG_heatLegendChip",
77
- "balance": "xoziZG_balance",
78
- "claimAllRow": "xoziZG_claimAllRow",
79
- "balanceUnit": "xoziZG_balanceUnit",
80
- "heatAxisSlot": "xoziZG_heatAxisSlot",
81
- "creditBlock": "xoziZG_creditBlock",
75
+ "balanceMeta": "xoziZG_balanceMeta",
76
+ "statSub": "xoziZG_statSub",
77
+ "usageTipRow": "xoziZG_usageTipRow",
78
+ "sectionLabel": "xoziZG_sectionLabel",
82
79
  "statusLine": "xoziZG_statusLine",
83
- "modelChart": "xoziZG_modelChart",
84
- "sectionHead": "xoziZG_sectionHead",
80
+ "statValue": "xoziZG_statValue",
81
+ "doctorRow": "xoziZG_doctorRow",
85
82
  "usageBar": "xoziZG_usageBar",
86
- "accountCard": "xoziZG_accountCard",
83
+ "choices": "xoziZG_choices",
84
+ "claimAllRow": "xoziZG_claimAllRow",
85
+ "balanceRow": "xoziZG_balanceRow",
87
86
  "usageTipName": "xoziZG_usageTipName",
88
- "choiceRow": "xoziZG_choiceRow",
87
+ "modelTokens": "xoziZG_modelTokens",
89
88
  "fieldLabel": "xoziZG_fieldLabel",
90
- "modelRow": "xoziZG_modelRow",
91
- "expiryRow": "xoziZG_expiryRow",
92
- "headText": "xoziZG_headText",
93
- "modelTrack": "xoziZG_modelTrack",
94
- "heatHourCell": "xoziZG_heatHourCell",
95
- "header": "xoziZG_header",
96
- "accountToolbar": "xoziZG_accountToolbar",
97
- "statGrid": "xoziZG_statGrid",
98
- "skeletonBreath": "xoziZG_skeletonBreath",
99
- "balanceRow": "xoziZG_balanceRow",
100
89
  "modelFill": "xoziZG_modelFill",
101
- "heatAxis": "xoziZG_heatAxis",
102
- "accountRow": "xoziZG_accountRow",
103
- "heatGrid": "xoziZG_heatGrid",
90
+ "heatCell": "xoziZG_heatCell",
91
+ "skeleton": "xoziZG_skeleton",
92
+ "section": "xoziZG_section",
93
+ "meta": "xoziZG_meta",
94
+ "creditBlock": "xoziZG_creditBlock",
95
+ "modelRequests": "xoziZG_modelRequests",
104
96
  "field": "xoziZG_field",
105
- "link": "xoziZG_link",
97
+ "balance": "xoziZG_balance",
98
+ "accountCard": "xoziZG_accountCard",
99
+ "avatar": "xoziZG_avatar",
106
100
  "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",
101
+ "name": "xoziZG_name",
102
+ "accountToggleLabel": "xoziZG_accountToggleLabel",
103
+ "manualSummary": "xoziZG_manualSummary",
104
+ "manual": "xoziZG_manual",
105
+ "heatAxisSlot": "xoziZG_heatAxisSlot",
113
106
  "manualForm": "xoziZG_manualForm",
114
- "card": "xoziZG_card",
115
- "actions": "xoziZG_actions",
116
- "usageFill": "xoziZG_usageFill",
117
- "usageTipRow": "xoziZG_usageTipRow",
118
- "modelTokens": "xoziZG_modelTokens",
107
+ "creditRows": "xoziZG_creditRows",
108
+ "expiryRow": "xoziZG_expiryRow",
109
+ "modelRow": "xoziZG_modelRow",
110
+ "area": "xoziZG_area",
111
+ "updated": "xoziZG_updated",
112
+ "body": "xoziZG_body",
113
+ "accountEntry": "xoziZG_accountEntry",
114
+ "accountInfo": "xoziZG_accountInfo",
115
+ "heatWeekday": "xoziZG_heatWeekday",
116
+ "accountRow": "xoziZG_accountRow",
117
+ "heatLegendChip": "xoziZG_heatLegendChip",
118
+ "modelSpec": "xoziZG_modelSpec",
119
+ "tabPanel": "xoziZG_tabPanel",
120
+ "modelChart": "xoziZG_modelChart",
121
+ "accountToggle": "xoziZG_accountToggle",
122
+ "usageTipSep": "xoziZG_usageTipSep",
123
+ "count": "xoziZG_count",
119
124
  "trendTip": "xoziZG_trendTip",
120
- "section": "xoziZG_section",
121
125
  "tabs": "xoziZG_tabs",
122
- "meta": "xoziZG_meta",
123
- "bar": "xoziZG_bar",
126
+ "heatAxis": "xoziZG_heatAxis",
127
+ "doctorName": "xoziZG_doctorName",
128
+ "accountToolbar": "xoziZG_accountToolbar",
129
+ "hint": "xoziZG_hint",
130
+ "link": "xoziZG_link",
131
+ "header": "xoziZG_header",
132
+ "heatHourCell": "xoziZG_heatHourCell",
133
+ "statLabel": "xoziZG_statLabel",
134
+ "desc": "xoziZG_desc",
135
+ "usageFill": "xoziZG_usageFill",
136
+ "headText": "xoziZG_headText",
124
137
  "barFill": "xoziZG_barFill",
125
- "modelRequests": "xoziZG_modelRequests",
126
- "skeleton": "xoziZG_skeleton",
138
+ "actions": "xoziZG_actions",
127
139
  "modelName": "xoziZG_modelName",
128
- "updated": "xoziZG_updated",
129
- "manualSummary": "xoziZG_manualSummary",
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
140
  "skeletonRow": "xoziZG_skeletonRow",
137
- "balanceMeta": "xoziZG_balanceMeta",
138
- "statSub": "xoziZG_statSub",
139
- "count": "xoziZG_count",
140
- "name": "xoziZG_name",
141
+ "check": "xoziZG_check",
141
142
  "accountRowActions": "xoziZG_accountRowActions",
142
- "danger": "xoziZG_danger",
143
- "statLabel": "xoziZG_statLabel",
144
- "usageTipSep": "xoziZG_usageTipSep",
145
- "modelShare": "xoziZG_modelShare",
146
- "heatCell": "xoziZG_heatCell",
143
+ "choiceRow": "xoziZG_choiceRow",
144
+ "skeletonBreath": "xoziZG_skeletonBreath",
145
+ "doctorList": "xoziZG_doctorList",
146
+ "bar": "xoziZG_bar",
147
+ "balanceUnit": "xoziZG_balanceUnit",
148
+ "accountHint": "xoziZG_accountHint",
149
+ "modelTrack": "xoziZG_modelTrack",
147
150
  "heatLegend": "xoziZG_heatLegend",
148
- "manual": "xoziZG_manual",
149
- "avatar": "xoziZG_avatar",
150
- "error": "xoziZG_error",
151
- "body": "xoziZG_body",
151
+ "card": "xoziZG_card",
152
152
  "creditLink": "xoziZG_creditLink",
153
- "accountName": "xoziZG_accountName",
154
- "statValue": "xoziZG_statValue",
153
+ "modelShare": "xoziZG_modelShare",
155
154
  "expiryLabel": "xoziZG_expiryLabel",
156
- "hint": "xoziZG_hint",
155
+ "creditFooter": "xoziZG_creditFooter",
156
+ "accountName": "xoziZG_accountName",
157
+ "sectionHead": "xoziZG_sectionHead",
157
158
  "usageTip": "xoziZG_usageTip",
158
- "accountEntry": "xoziZG_accountEntry",
159
- "sectionLabel": "xoziZG_sectionLabel",
160
- "creditRows": "xoziZG_creditRows"
159
+ "statCard": "xoziZG_statCard",
160
+ "heatGrid": "xoziZG_heatGrid",
161
+ "error": "xoziZG_error",
162
+ "accountNameRow": "xoziZG_accountNameRow",
163
+ "creditRow": "xoziZG_creditRow",
164
+ "creditHint": "xoziZG_creditHint",
165
+ "danger": "xoziZG_danger",
166
+ "statGrid": "xoziZG_statGrid"
161
167
  };
162
168
  //#endregion
163
169
  //#region src/client/CodeArtsPluginCard.tsx
@@ -222,6 +228,49 @@ const DOCK_DEFAULT = {
222
228
  * 后台再刷新 —— 比每次都先闪骨架舒服,也不会把「还没读到」误判成未登录。
223
229
  */
224
230
  let lastStatusSnapshot = null;
231
+ const lastTestResults = {};
232
+ /**
233
+ * 上下文窗口这类数字不适合印全值(1048576 比 1M 难读),按 K/M 取整。
234
+ *
235
+ * undefined 表示上游没给 —— 此时后端下发的 32768 是兜底值,不能当成真的印出来。
236
+ */
237
+ function formatWindow(tokens) {
238
+ if (tokens === void 0 || !Number.isFinite(tokens) || tokens <= 0) return "—";
239
+ if (tokens >= 1048576) return `${Math.round(tokens / 1048576)}M`;
240
+ if (tokens >= 1024) return `${Math.round(tokens / 1024)}K`;
241
+ return String(tokens);
242
+ }
243
+ /** 体检里一条检查的标题。账号级检查按 id 找回备注名,别让用户对着哈希猜。 */
244
+ function doctorCheckLabel(id, accounts, t) {
245
+ if (id.startsWith("account:")) {
246
+ const accountId = id.slice(8);
247
+ const account = accounts.find((entry) => entry.id === accountId);
248
+ const name = account?.label?.trim() || account?.userName?.trim() || accountId;
249
+ return `${t("doctorCheckAccount")} ${name}`;
250
+ }
251
+ switch (id) {
252
+ case "runtime": return t("doctorCheckRuntime");
253
+ case "accounts": return t("doctorCheckAccounts");
254
+ case "models": return t("doctorCheckModels");
255
+ case "usage": return t("doctorCheckUsage");
256
+ case "pi-ai": return t("doctorCheckPiAi");
257
+ default: return id;
258
+ }
259
+ }
260
+ /** 体检的 hints 是稳定 id(见 web-status.ts 的 doctorReport),这里翻成人话。 */
261
+ function doctorHintText(id, t) {
262
+ switch (id) {
263
+ case "no-account": return t("doctorHintNoAccount");
264
+ case "account-stale": return t("doctorHintAccountStale");
265
+ case "account-no-key": return t("doctorHintAccountNoKey");
266
+ case "account-expired": return t("doctorHintAccountExpired");
267
+ case "empty-catalog": return t("doctorHintEmptyCatalog");
268
+ case "usage-missing": return t("doctorHintUsageMissing");
269
+ case "dsh-home-missing": return t("doctorHintDshHome");
270
+ case "pi-ai": return t("doctorHintPiAi");
271
+ default: return t("doctorHintOther", { id });
272
+ }
273
+ }
225
274
  /** 一个 Tab 面板;未选中的用 hidden 留在 DOM 里,草稿和滚动位置都别丢。 */
226
275
  function TabPanel({ id, labelledBy, active, children }) {
227
276
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -753,8 +802,18 @@ function UsageSection({ usage, accounts, t }) {
753
802
  totals: entry.totals
754
803
  }));
755
804
  const today = usage.today;
756
- const hasUsage = usage.allTime.requests > 0 || today.requests > 0;
805
+ const failures = usage.failuresToday ?? {
806
+ total: 0,
807
+ byKind: {}
808
+ };
809
+ const hasUsage = usage.allTime.requests > 0 || today.requests > 0 || failures.total > 0;
757
810
  const hit = hitPercentOf(today);
811
+ const attempts = today.requests + failures.total;
812
+ const failRate = attempts > 0 ? Math.round(failures.total / attempts * 100) : void 0;
813
+ const latency = usage.latencyToday ?? {
814
+ samples: 0,
815
+ overflow: false
816
+ };
758
817
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
759
818
  className: CodeArtsPluginCard_module_css_default.section,
760
819
  children: [
@@ -814,6 +873,43 @@ function UsageSection({ usage, accounts, t }) {
814
873
  className: CodeArtsPluginCard_module_css_default.statValue,
815
874
  children: formatCount(today.requests)
816
875
  })]
876
+ }),
877
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
878
+ className: CodeArtsPluginCard_module_css_default.statCard,
879
+ children: [
880
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
881
+ className: CodeArtsPluginCard_module_css_default.statLabel,
882
+ children: t("usageStatFailures")
883
+ }),
884
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
885
+ className: CodeArtsPluginCard_module_css_default.statValue,
886
+ children: failRate === void 0 ? "—" : `${failRate}%`
887
+ }),
888
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
889
+ className: CodeArtsPluginCard_module_css_default.statSub,
890
+ children: t("usageStatFailureCount", { n: formatCount(failures.total) })
891
+ })
892
+ ]
893
+ }),
894
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
895
+ className: CodeArtsPluginCard_module_css_default.statCard,
896
+ children: [
897
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
898
+ className: CodeArtsPluginCard_module_css_default.statLabel,
899
+ children: t("usageStatLatency")
900
+ }),
901
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
902
+ className: CodeArtsPluginCard_module_css_default.statValue,
903
+ children: latency.p95 === void 0 ? "—" : latency.overflow ? ">30 s" : `${formatCount(latency.p95)} ms`
904
+ }),
905
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
906
+ className: CodeArtsPluginCard_module_css_default.statSub,
907
+ children: latency.p50 === void 0 ? t("usageStatLatencyEmpty") : t("usageStatLatencyDetail", {
908
+ p50: formatCount(latency.p50),
909
+ n: formatCount(latency.samples)
910
+ })
911
+ })
912
+ ]
817
913
  })
818
914
  ]
819
915
  }),
@@ -899,7 +995,12 @@ function CodeArtsPluginCard({ t }) {
899
995
  /** 正在实测的模型 id;同一时间只测一个,避免把上游并发槽位占满。 */
900
996
  const [testingId, setTestingId] = (0, react.useState)(null);
901
997
  /** 逐模型的测试结果(通过/失败 + 原因)。 */
902
- const [testResults, setTestResults] = (0, react.useState)({});
998
+ const [testResults, setTestResults] = (0, react.useState)(() => ({ ...lastTestResults }));
999
+ /** 正在提交 paused/pinned 的账号 id。 */
1000
+ const [flagBusy, setFlagBusy] = (0, react.useState)(null);
1001
+ const [doctor, setDoctor] = (0, react.useState)(null);
1002
+ const [doctorBusy, setDoctorBusy] = (0, react.useState)(false);
1003
+ const [doctorError, setDoctorError] = (0, react.useState)(null);
903
1004
  /** 正在领取的账号 id;批量领取时是 CLAIM_ALL。null 表示没有在飞。 */
904
1005
  const [claimingId, setClaimingId] = (0, react.useState)(null);
905
1006
  /** 逐账号的领取结果文案。 */
@@ -1103,6 +1204,52 @@ function CodeArtsPluginCard({ t }) {
1103
1204
  setBusy(false);
1104
1205
  }
1105
1206
  }
1207
+ /**
1208
+ * 改一个账号的 paused/pinned 标记。
1209
+ *
1210
+ * 暂停 ≠ 删除:凭证还在,只是不参与轮转(比如这个号今天额度用完了,但明天还要用)。
1211
+ * 置顶改变的是 pick() 的优先级,不是顺序本身 —— 取消置顶就回到「最久未用优先」。
1212
+ */
1213
+ async function setAccountFlag(id, patch) {
1214
+ setFlagBusy(id);
1215
+ setMsg(null);
1216
+ try {
1217
+ const res = await fetch("/api/codearts/accounts", {
1218
+ method: "POST",
1219
+ headers: {
1220
+ "Content-Type": "application/json",
1221
+ Accept: "application/json"
1222
+ },
1223
+ body: JSON.stringify({
1224
+ id,
1225
+ ...patch
1226
+ })
1227
+ });
1228
+ if (!res.ok) {
1229
+ const data = await res.json().catch(() => ({}));
1230
+ throw new Error(typeof data.error === "string" ? data.error : `HTTP ${res.status}`);
1231
+ }
1232
+ await refresh();
1233
+ } catch (err) {
1234
+ setMsg(err instanceof Error ? err.message : String(err));
1235
+ } finally {
1236
+ setFlagBusy(null);
1237
+ }
1238
+ }
1239
+ /** 点「体检」拉一次本机报告;只读,不改任何状态。 */
1240
+ async function runDoctor() {
1241
+ setDoctorBusy(true);
1242
+ setDoctorError(null);
1243
+ try {
1244
+ const res = await fetch("/api/codearts/doctor", { headers: { Accept: "application/json" } });
1245
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
1246
+ setDoctor(await res.json());
1247
+ } catch (err) {
1248
+ setDoctorError(err instanceof Error ? err.message : String(err));
1249
+ } finally {
1250
+ setDoctorBusy(false);
1251
+ }
1252
+ }
1106
1253
  const all = selection?.choices.length ?? 0;
1107
1254
  const blockedCount = selection?.choices.filter((c) => c.blocked === true).length ?? 0;
1108
1255
  const wire = draft.length === all ? [] : draft;
@@ -1145,8 +1292,16 @@ function CodeArtsPluginCard({ t }) {
1145
1292
  * 上游的清单会列出调不动的模型(81003.401),刷新救不了;只有真发一次最小请求
1146
1293
  * 才知道。测试成功会清掉后端记的「异常」标记,所以结束后重拉一次 selection。
1147
1294
  */
1295
+ function recordTest(id, result) {
1296
+ lastTestResults[id] = result;
1297
+ setTestResults((current) => ({
1298
+ ...current,
1299
+ [id]: result
1300
+ }));
1301
+ }
1148
1302
  async function testModel(id) {
1149
1303
  setTestingId(id);
1304
+ delete lastTestResults[id];
1150
1305
  setTestResults((current) => {
1151
1306
  const next = { ...current };
1152
1307
  delete next[id];
@@ -1163,23 +1318,17 @@ function CodeArtsPluginCard({ t }) {
1163
1318
  });
1164
1319
  const data = await res.json().catch(() => null);
1165
1320
  if (!res.ok) throw new Error(data?.message ?? `HTTP ${res.status}`);
1166
- setTestResults((current) => ({
1167
- ...current,
1168
- [id]: {
1169
- ok: data?.ok === true,
1170
- message: data?.message ?? "",
1171
- ms: data?.ms
1172
- }
1173
- }));
1321
+ recordTest(id, {
1322
+ ok: data?.ok === true,
1323
+ message: data?.message ?? "",
1324
+ ms: data?.ms
1325
+ });
1174
1326
  await refreshSelection();
1175
1327
  } catch (err) {
1176
- setTestResults((current) => ({
1177
- ...current,
1178
- [id]: {
1179
- ok: false,
1180
- message: err instanceof Error ? err.message : String(err)
1181
- }
1182
- }));
1328
+ recordTest(id, {
1329
+ ok: false,
1330
+ message: err instanceof Error ? err.message : String(err)
1331
+ });
1183
1332
  } finally {
1184
1333
  setTestingId(null);
1185
1334
  }
@@ -1498,37 +1647,74 @@ function CodeArtsPluginCard({ t }) {
1498
1647
  }),
1499
1648
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1500
1649
  className: CodeArtsPluginCard_module_css_default.accountInfo,
1501
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1502
- className: CodeArtsPluginCard_module_css_default.accountNameRow,
1503
- children: [
1504
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1505
- className: CodeArtsPluginCard_module_css_default.accountName,
1506
- children: accountName(account)
1507
- }),
1508
- account.stale && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNeedsSignIn") }),
1509
- !account.signable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNoKey") })
1510
- ]
1511
- }), accountLine !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1512
- className: CodeArtsPluginCard_module_css_default.meta,
1513
- children: accountLine
1514
- })]
1650
+ children: [
1651
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1652
+ className: CodeArtsPluginCard_module_css_default.accountNameRow,
1653
+ children: [
1654
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1655
+ className: CodeArtsPluginCard_module_css_default.accountName,
1656
+ children: accountName(account)
1657
+ }),
1658
+ account.paused && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountPaused") }),
1659
+ account.pinned && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1660
+ tone: "success",
1661
+ children: t("accountPinned")
1662
+ }),
1663
+ account.stale && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNeedsSignIn") }),
1664
+ !account.signable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("accountNoKey") })
1665
+ ]
1666
+ }),
1667
+ accountLine !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1668
+ className: CodeArtsPluginCard_module_css_default.meta,
1669
+ children: accountLine
1670
+ }),
1671
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1672
+ className: CodeArtsPluginCard_module_css_default.meta,
1673
+ children: t("accountToday", {
1674
+ n: formatCount(status?.usage?.byAccountToday[account.id]?.requests ?? 0),
1675
+ failed: formatCount(status?.usage?.failuresByAccountToday?.[account.id] ?? 0)
1676
+ })
1677
+ })
1678
+ ]
1515
1679
  }),
1516
1680
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1517
1681
  className: CodeArtsPluginCard_module_css_default.accountRowActions,
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, {
1525
- variant: "outline",
1526
- size: "sm",
1527
- className: CodeArtsPluginCard_module_css_default.danger,
1528
- disabled: busy || loginPending,
1529
- onClick: () => void removeAccount(account.id),
1530
- children: t("accountRemove")
1531
- })]
1682
+ children: [
1683
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1684
+ className: CodeArtsPluginCard_module_css_default.accountToggle,
1685
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1686
+ className: CodeArtsPluginCard_module_css_default.accountToggleLabel,
1687
+ children: t("accountEnabled")
1688
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
1689
+ checked: !account.paused,
1690
+ disabled: busy || loginPending || flagBusy === account.id,
1691
+ label: `${accountName(account)} ${t("accountEnabled")}`,
1692
+ onChange: (next) => void setAccountFlag(account.id, { paused: !next })
1693
+ })]
1694
+ }),
1695
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1696
+ variant: "outline",
1697
+ size: "sm",
1698
+ disabled: busy || loginPending || flagBusy === account.id,
1699
+ onClick: () => void setAccountFlag(account.id, { pinned: !account.pinned }),
1700
+ children: account.pinned ? t("accountUnpin") : t("accountPin")
1701
+ }),
1702
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1703
+ variant: account.stale ? "primary" : "outline",
1704
+ size: "sm",
1705
+ disabled: busy || loginPending,
1706
+ onClick: () => void startOAuthLogin(account.id),
1707
+ children: reloginId === account.id && loginPending ? t("reloginPending") : t("accountRelogin")
1708
+ }),
1709
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1710
+ variant: "outline",
1711
+ size: "sm",
1712
+ className: CodeArtsPluginCard_module_css_default.danger,
1713
+ disabled: busy || loginPending,
1714
+ onClick: () => void removeAccount(account.id),
1715
+ children: t("accountRemove")
1716
+ })
1717
+ ]
1532
1718
  })
1533
1719
  ]
1534
1720
  }), credit !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreditBlock, {
@@ -1612,7 +1798,7 @@ function CodeArtsPluginCard({ t }) {
1612
1798
  }),
1613
1799
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1614
1800
  className: CodeArtsPluginCard_module_css_default.choices,
1615
- children: selection.choices.map((choice) => {
1801
+ children: (selection.choices ?? []).map((choice) => {
1616
1802
  const result = testResults[choice.id];
1617
1803
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1618
1804
  className: CodeArtsPluginCard_module_css_default.choiceRow,
@@ -1624,6 +1810,17 @@ function CodeArtsPluginCard({ t }) {
1624
1810
  onChange: (on) => setModel(choice.id, on),
1625
1811
  label: modelName(choice)
1626
1812
  }),
1813
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1814
+ className: CodeArtsPluginCard_module_css_default.modelSpec,
1815
+ title: t("modelSpecTitle", {
1816
+ context: choice.contextWindow === void 0 ? "?" : formatCount(choice.contextWindow),
1817
+ output: choice.maxTokens === void 0 ? "?" : formatCount(choice.maxTokens)
1818
+ }),
1819
+ children: t("modelSpec", {
1820
+ context: formatWindow(choice.contextWindow),
1821
+ output: formatWindow(choice.maxTokens)
1822
+ })
1823
+ }),
1627
1824
  choice.benefit === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, {
1628
1825
  tone: choice.blocked === true ? "warning" : "success",
1629
1826
  children: choice.blocked === true ? t("benefitBlocked") : t("benefit")
@@ -1706,80 +1903,129 @@ function CodeArtsPluginCard({ t }) {
1706
1903
  id: panelId("display"),
1707
1904
  labelledBy: tabId("display"),
1708
1905
  active: activeTab === "display",
1709
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1710
- className: CodeArtsPluginCard_module_css_default.section,
1711
- children: [
1712
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1713
- className: CodeArtsPluginCard_module_css_default.sectionHead,
1714
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1715
- className: CodeArtsPluginCard_module_css_default.sectionLabel,
1716
- children: t("displayTitle")
1717
- })
1718
- }),
1719
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1720
- className: CodeArtsPluginCard_module_css_default.hint,
1721
- children: t("displayHint")
1722
- }),
1723
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1724
- className: CodeArtsPluginCard_module_css_default.choices,
1725
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1726
- className: CodeArtsPluginCard_module_css_default.choiceRow,
1727
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1728
- className: CodeArtsPluginCard_module_css_default.check,
1729
- checked: dock.credits,
1730
- disabled: !dockWritable || dockSaving,
1731
- onChange: (on) => void toggleDock("credits", on),
1732
- label: t("displayCreditsToggle")
1733
- })
1734
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1735
- className: CodeArtsPluginCard_module_css_default.choiceRow,
1736
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1737
- className: CodeArtsPluginCard_module_css_default.check,
1738
- checked: dock.queue,
1739
- disabled: !dockWritable || dockSaving,
1740
- onChange: (on) => void toggleDock("queue", on),
1741
- label: t("displayQueueToggle")
1906
+ children: [
1907
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1908
+ className: CodeArtsPluginCard_module_css_default.section,
1909
+ children: [
1910
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1911
+ className: CodeArtsPluginCard_module_css_default.sectionHead,
1912
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1913
+ className: CodeArtsPluginCard_module_css_default.sectionLabel,
1914
+ children: t("displayTitle")
1742
1915
  })
1743
- })]
1744
- }),
1745
- !dockWritable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1746
- className: CodeArtsPluginCard_module_css_default.hint,
1747
- children: t("displayNotWritable")
1748
- }),
1749
- dockError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1750
- className: CodeArtsPluginCard_module_css_default.error,
1751
- children: t("displayFailed", { message: dockError })
1752
- })
1753
- ]
1754
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1755
- className: CodeArtsPluginCard_module_css_default.section,
1756
- children: [
1757
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1758
- className: CodeArtsPluginCard_module_css_default.sectionHead,
1759
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1760
- className: CodeArtsPluginCard_module_css_default.sectionLabel,
1761
- children: t("displaySidebarTitle")
1916
+ }),
1917
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1918
+ className: CodeArtsPluginCard_module_css_default.hint,
1919
+ children: t("displayHint")
1920
+ }),
1921
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1922
+ className: CodeArtsPluginCard_module_css_default.choices,
1923
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1924
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
1925
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1926
+ className: CodeArtsPluginCard_module_css_default.check,
1927
+ checked: dock.credits,
1928
+ disabled: !dockWritable || dockSaving,
1929
+ onChange: (on) => void toggleDock("credits", on),
1930
+ label: t("displayCreditsToggle")
1931
+ })
1932
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1933
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
1934
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1935
+ className: CodeArtsPluginCard_module_css_default.check,
1936
+ checked: dock.queue,
1937
+ disabled: !dockWritable || dockSaving,
1938
+ onChange: (on) => void toggleDock("queue", on),
1939
+ label: t("displayQueueToggle")
1940
+ })
1941
+ })]
1942
+ }),
1943
+ !dockWritable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1944
+ className: CodeArtsPluginCard_module_css_default.hint,
1945
+ children: t("displayNotWritable")
1946
+ }),
1947
+ dockError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1948
+ className: CodeArtsPluginCard_module_css_default.error,
1949
+ children: t("displayFailed", { message: dockError })
1762
1950
  })
1763
- }),
1764
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1765
- className: CodeArtsPluginCard_module_css_default.hint,
1766
- children: t("displaySidebarHint")
1767
- }),
1768
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1769
- className: CodeArtsPluginCard_module_css_default.choices,
1770
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1771
- className: CodeArtsPluginCard_module_css_default.choiceRow,
1772
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1773
- className: CodeArtsPluginCard_module_css_default.check,
1774
- checked: dock.sidebar,
1775
- disabled: !dockWritable || dockSaving,
1776
- onChange: (on) => void toggleDock("sidebar", on),
1777
- label: t("displaySidebarToggle")
1951
+ ]
1952
+ }),
1953
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1954
+ className: CodeArtsPluginCard_module_css_default.section,
1955
+ children: [
1956
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1957
+ className: CodeArtsPluginCard_module_css_default.sectionHead,
1958
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1959
+ className: CodeArtsPluginCard_module_css_default.sectionLabel,
1960
+ children: t("displaySidebarTitle")
1961
+ })
1962
+ }),
1963
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1964
+ className: CodeArtsPluginCard_module_css_default.hint,
1965
+ children: t("displaySidebarHint")
1966
+ }),
1967
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1968
+ className: CodeArtsPluginCard_module_css_default.choices,
1969
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1970
+ className: CodeArtsPluginCard_module_css_default.choiceRow,
1971
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
1972
+ className: CodeArtsPluginCard_module_css_default.check,
1973
+ checked: dock.sidebar,
1974
+ disabled: !dockWritable || dockSaving,
1975
+ onChange: (on) => void toggleDock("sidebar", on),
1976
+ label: t("displaySidebarToggle")
1977
+ })
1778
1978
  })
1779
1979
  })
1780
- })
1781
- ]
1782
- })]
1980
+ ]
1981
+ }),
1982
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1983
+ className: CodeArtsPluginCard_module_css_default.section,
1984
+ children: [
1985
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1986
+ className: CodeArtsPluginCard_module_css_default.sectionHead,
1987
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1988
+ className: CodeArtsPluginCard_module_css_default.sectionLabel,
1989
+ children: t("doctorTitle")
1990
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1991
+ variant: "outline",
1992
+ size: "sm",
1993
+ disabled: doctorBusy,
1994
+ onClick: () => void runDoctor(),
1995
+ children: doctorBusy ? t("doctorRunning") : t("doctorRun")
1996
+ })]
1997
+ }),
1998
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1999
+ className: CodeArtsPluginCard_module_css_default.hint,
2000
+ children: t("doctorHint")
2001
+ }),
2002
+ doctorError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2003
+ className: CodeArtsPluginCard_module_css_default.error,
2004
+ children: t("doctorFailed", { message: doctorError })
2005
+ }),
2006
+ doctor !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2007
+ className: CodeArtsPluginCard_module_css_default.doctorList,
2008
+ children: doctor.checks.map((check) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2009
+ className: CodeArtsPluginCard_module_css_default.doctorRow,
2010
+ children: [
2011
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: check.ok ? "done" : "warning" }),
2012
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2013
+ className: CodeArtsPluginCard_module_css_default.doctorName,
2014
+ children: doctorCheckLabel(check.id, accounts, t)
2015
+ }),
2016
+ check.detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2017
+ className: CodeArtsPluginCard_module_css_default.meta,
2018
+ children: check.detail
2019
+ })
2020
+ ]
2021
+ }, check.id))
2022
+ }), doctor.hints.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2023
+ className: CodeArtsPluginCard_module_css_default.hint,
2024
+ children: doctor.hints.map((id) => doctorHintText(id, t)).join(";")
2025
+ })] })
2026
+ ]
2027
+ })
2028
+ ]
1783
2029
  })
1784
2030
  ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1785
2031
  className: CodeArtsPluginCard_module_css_default.section,
@@ -2430,14 +2676,14 @@ if (typeof document !== "undefined" && document.querySelector("style[data-plugin
2430
2676
  document.head.appendChild(tag);
2431
2677
  }
2432
2678
  var CodeArtsPanel_module_css_default = {
2433
- "head": "Z66cgG_head",
2434
- "body": "Z66cgG_body",
2435
2679
  "title": "Z66cgG_title",
2680
+ "page": "Z66cgG_page",
2681
+ "body": "Z66cgG_body",
2436
2682
  "desc": "Z66cgG_desc",
2437
- "back": "Z66cgG_back",
2438
2683
  "icon": "Z66cgG_icon",
2439
- "page": "Z66cgG_page",
2440
- "backCaret": "Z66cgG_backCaret"
2684
+ "back": "Z66cgG_back",
2685
+ "backCaret": "Z66cgG_backCaret",
2686
+ "head": "Z66cgG_head"
2441
2687
  };
2442
2688
  //#endregion
2443
2689
  //#region src/client/CodeArtsPanel.tsx
@@ -2592,6 +2838,39 @@ const zh = {
2592
2838
  usageTipHit: "命中率",
2593
2839
  usageStatHit: "缓存命中",
2594
2840
  usageStatRequests: "今日请求",
2841
+ usageStatFailures: "今日失败率",
2842
+ usageStatFailureCount: "失败 {n} 次",
2843
+ usageStatLatency: "首字 P95",
2844
+ usageStatLatencyDetail: "P50 {p50} ms · {n} 次",
2845
+ usageStatLatencyEmpty: "还没有成功请求",
2846
+ modelSpec: "{context} 上下文 · {output} 输出",
2847
+ modelSpecTitle: "上游返回的上下文窗口 {context} token,最大输出 {output} token",
2848
+ accountPaused: "已暂停",
2849
+ accountPinned: "已置顶",
2850
+ accountEnabled: "启用",
2851
+ accountPin: "置顶",
2852
+ accountUnpin: "取消置顶",
2853
+ accountToday: "今日 {n} 次 · 失败 {failed}",
2854
+ doctorTitle: "体检",
2855
+ doctorHint: "只查本机状态(版本、凭证、目录、账本、pi-ai 兼容),不联网、不改任何东西。",
2856
+ doctorRun: "开始体检",
2857
+ doctorRunning: "检查中…",
2858
+ doctorFailed: "体检失败:{message}",
2859
+ doctorCheckAccount: "账号",
2860
+ doctorCheckRuntime: "运行环境",
2861
+ doctorCheckAccounts: "账号数量",
2862
+ doctorCheckModels: "模型目录",
2863
+ doctorCheckUsage: "用量账本",
2864
+ doctorCheckPiAi: "pi-ai 兼容",
2865
+ doctorHintNoAccount: "还没有账号:先添加一个,或用 token 手动接入。",
2866
+ doctorHintAccountStale: "有账号需要重新登录。",
2867
+ doctorHintAccountNoKey: "有账号缺少签名私钥,无法自动续期。",
2868
+ doctorHintAccountExpired: "有账号凭证已过期:重新登录即可续上。",
2869
+ doctorHintEmptyCatalog: "模型目录为空:点「重拉目录」或检查上游连通性。",
2870
+ doctorHintUsageMissing: "用量账本没有接上:重启宿主后再看。",
2871
+ doctorHintDshHome: "没有设置 DSH_HOME:凭证和账本会写到默认位置。",
2872
+ doctorHintPiAi: "宿主口的 pi-ai 版本与插件预期不一致,可能影响流式解析。",
2873
+ doctorHintOther: "未知提示:{id}",
2595
2874
  usageRequests: "{n} 次请求",
2596
2875
  usageTrendWeek: "本月 · 每日 token",
2597
2876
  usageTrendHour: "今天 · 逐小时 token",
@@ -2745,6 +3024,39 @@ const en = {
2745
3024
  usageTipHit: "Hit rate",
2746
3025
  usageStatHit: "Cache hit",
2747
3026
  usageStatRequests: "Today requests",
3027
+ usageStatFailures: "Failure rate today",
3028
+ usageStatFailureCount: "{n} failed",
3029
+ usageStatLatency: "First token P95",
3030
+ usageStatLatencyDetail: "P50 {p50} ms · {n} samples",
3031
+ usageStatLatencyEmpty: "No successful request yet",
3032
+ modelSpec: "{context} ctx · {output} out",
3033
+ modelSpecTitle: "Context window {context} tokens, max output {output} tokens reported upstream",
3034
+ accountPaused: "Paused",
3035
+ accountPinned: "Pinned",
3036
+ accountEnabled: "Enabled",
3037
+ accountPin: "Pin",
3038
+ accountUnpin: "Unpin",
3039
+ accountToday: "Today {n} · {failed} failed",
3040
+ doctorTitle: "Health check",
3041
+ doctorHint: "Local checks only (version, credentials, catalog, ledger, pi-ai compat). No network, changes nothing.",
3042
+ doctorRun: "Run check",
3043
+ doctorRunning: "Checking…",
3044
+ doctorFailed: "Health check failed: {message}",
3045
+ doctorCheckAccount: "Account",
3046
+ doctorCheckRuntime: "Runtime",
3047
+ doctorCheckAccounts: "Account count",
3048
+ doctorCheckModels: "Model catalog",
3049
+ doctorCheckUsage: "Usage ledger",
3050
+ doctorCheckPiAi: "pi-ai compat",
3051
+ doctorHintNoAccount: "No account yet: sign in or paste a token first.",
3052
+ doctorHintAccountStale: "An account needs to sign in again.",
3053
+ doctorHintAccountNoKey: "An account has no signing key and cannot refresh automatically.",
3054
+ doctorHintAccountExpired: "An account credential has expired: sign in again to renew it.",
3055
+ doctorHintEmptyCatalog: "Model catalog is empty: refresh it or check upstream connectivity.",
3056
+ doctorHintUsageMissing: "Usage ledger is not wired: restart the host and retry.",
3057
+ doctorHintDshHome: "DSH_HOME is not set: credentials and ledger fall back to the default location.",
3058
+ doctorHintPiAi: "Host pi-ai version differs from what the plugin expects; streaming parsing may be affected.",
3059
+ doctorHintOther: "Unknown hint: {id}",
2748
3060
  usageRequests: "{n} request(s)",
2749
3061
  usageTrendWeek: "This month · tokens per day",
2750
3062
  usageTrendHour: "Today · tokens by hour",