dsh-codearts 1.2.3 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +75 -0
- package/README.en.md +4 -0
- package/README.md +1 -0
- package/lib/bin.mjs +2 -2
- package/lib/client/index.d.cts +45 -6
- package/lib/client/index.js +645 -221
- package/lib/index.d.mts +35 -0
- package/lib/index.mjs +44 -11
- package/lib/{usage-CzJjkqOp.mjs → usage-DGIuT79_.mjs} +101 -8
- package/package.json +1 -1
package/lib/client/index.js
CHANGED
|
@@ -22,81 +22,129 @@ function stripModelSuffixes(name) {
|
|
|
22
22
|
return base.replace(/\s*[((]\s*(?:(?:免费|福利)(?:\s+x\d+(?:\.\d+)?)?|x\d+(?:\.\d+)?)\s*[))]\s*$/, "").trim();
|
|
23
23
|
}
|
|
24
24
|
//#endregion
|
|
25
|
+
//#region src/client/panel-switch.ts
|
|
26
|
+
/**
|
|
27
|
+
* 「要不要在 DSH 侧边栏占一格」这个偏好,浏览器侧的单一真相。
|
|
28
|
+
*
|
|
29
|
+
* 为什么不靠组件返回 null 来隐藏:宿主是按**槽位里的注册条目**(entry metadata)
|
|
30
|
+
* 画侧边栏导航行的 —— 只要注册还在,那一行就在;渲染函数 return null 只会留下一个
|
|
31
|
+
* 「空白但可点」的按钮。所以开关必须落到「注册 / 不注册」上,这里只存那个意图,
|
|
32
|
+
* 真正的注册动作由 index.tsx 的 sync 控制器按它做。
|
|
33
|
+
*
|
|
34
|
+
* 默认 **false**:读不到配置时必须当作关闭。侧边栏那一格是所有插件共用的全局座位,
|
|
35
|
+
* 猜错的代价比「少一个入口」大得多(用户还能从「设置 → 插件」进同一张卡片)。
|
|
36
|
+
*/
|
|
37
|
+
let wanted = false;
|
|
38
|
+
/** 当前是否要显示侧边栏入口。 */
|
|
39
|
+
function sidebarPanelWanted() {
|
|
40
|
+
return wanted;
|
|
41
|
+
}
|
|
42
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
43
|
+
/**
|
|
44
|
+
* 改开关。值没变就直接返回 —— 调用方会在每次刷新状态时调用它,
|
|
45
|
+
* 无变化的重注册会让侧边栏闪一下。
|
|
46
|
+
*/
|
|
47
|
+
function setSidebarPanelWanted(next) {
|
|
48
|
+
if (wanted === next) return;
|
|
49
|
+
wanted = next;
|
|
50
|
+
for (const listener of [...listeners]) try {
|
|
51
|
+
listener();
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error("[dsh-codearts] sidebar panel listener failed:", error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** 订阅开关变化,返回取消订阅函数。 */
|
|
57
|
+
function subscribeSidebarPanelWanted(listener) {
|
|
58
|
+
listeners.add(listener);
|
|
59
|
+
return () => {
|
|
60
|
+
listeners.delete(listener);
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
25
64
|
//#region \0dsh-css:/home/runner/work/dsh-codearts/dsh-codearts/src/client/CodeArtsPluginCard.module.css.mjs
|
|
26
|
-
const css = ".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_modelChart{flex-direction:column;gap:2px;margin-top:8px;display:flex}.xoziZG_modelRow{font-variant-numeric:tabular-nums;grid-template-columns:minmax(0,1.2fr) minmax(48px,1fr) 56px 52px 64px;align-items:center;gap:8px;padding:4px 0;display:grid}.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_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}";
|
|
27
|
-
const tagId = "dsh-codearts/CodeArtsPluginCard.module.css";
|
|
28
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
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_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_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}";
|
|
66
|
+
const tagId$1 = "dsh-codearts/CodeArtsPluginCard.module.css";
|
|
67
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
29
68
|
const tag = document.createElement("style");
|
|
30
69
|
tag.dataset.plugin = "dsh-codearts";
|
|
31
|
-
tag.dataset.pluginCss = tagId;
|
|
32
|
-
tag.textContent = css;
|
|
70
|
+
tag.dataset.pluginCss = tagId$1;
|
|
71
|
+
tag.textContent = css$1;
|
|
33
72
|
document.head.appendChild(tag);
|
|
34
73
|
}
|
|
35
74
|
var CodeArtsPluginCard_module_css_default = {
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"modelFill": "xoziZG_modelFill",
|
|
39
|
-
"danger": "xoziZG_danger",
|
|
40
|
-
"expiryRow": "xoziZG_expiryRow",
|
|
41
|
-
"accountEntry": "xoziZG_accountEntry",
|
|
42
|
-
"accountHint": "xoziZG_accountHint",
|
|
43
|
-
"manualSummary": "xoziZG_manualSummary",
|
|
44
|
-
"body": "xoziZG_body",
|
|
45
|
-
"barFill": "xoziZG_barFill",
|
|
75
|
+
"claimAllRow": "xoziZG_claimAllRow",
|
|
76
|
+
"bar": "xoziZG_bar",
|
|
46
77
|
"updated": "xoziZG_updated",
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"tabPanel": "xoziZG_tabPanel",
|
|
53
|
-
"accountInfo": "xoziZG_accountInfo",
|
|
78
|
+
"check": "xoziZG_check",
|
|
79
|
+
"expiryLabel": "xoziZG_expiryLabel",
|
|
80
|
+
"creditFooter": "xoziZG_creditFooter",
|
|
81
|
+
"accountName": "xoziZG_accountName",
|
|
82
|
+
"choices": "xoziZG_choices",
|
|
54
83
|
"card": "xoziZG_card",
|
|
55
|
-
"
|
|
84
|
+
"tabPanel": "xoziZG_tabPanel",
|
|
56
85
|
"sectionHead": "xoziZG_sectionHead",
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
86
|
+
"usageTipRow": "xoziZG_usageTipRow",
|
|
87
|
+
"fieldLabel": "xoziZG_fieldLabel",
|
|
88
|
+
"desc": "xoziZG_desc",
|
|
89
|
+
"usageTipName": "xoziZG_usageTipName",
|
|
90
|
+
"modelFill": "xoziZG_modelFill",
|
|
62
91
|
"modelTrack": "xoziZG_modelTrack",
|
|
63
|
-
"
|
|
64
|
-
"check": "xoziZG_check",
|
|
92
|
+
"hint": "xoziZG_hint",
|
|
65
93
|
"headText": "xoziZG_headText",
|
|
66
|
-
"
|
|
94
|
+
"creditRow": "xoziZG_creditRow",
|
|
95
|
+
"accountInfo": "xoziZG_accountInfo",
|
|
96
|
+
"modelRow": "xoziZG_modelRow",
|
|
97
|
+
"usageTipSep": "xoziZG_usageTipSep",
|
|
67
98
|
"creditHint": "xoziZG_creditHint",
|
|
68
|
-
"
|
|
99
|
+
"modelRequests": "xoziZG_modelRequests",
|
|
100
|
+
"statGrid": "xoziZG_statGrid",
|
|
69
101
|
"accountCard": "xoziZG_accountCard",
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"sectionLabel": "xoziZG_sectionLabel",
|
|
102
|
+
"body": "xoziZG_body",
|
|
103
|
+
"name": "xoziZG_name",
|
|
104
|
+
"danger": "xoziZG_danger",
|
|
74
105
|
"usageBar": "xoziZG_usageBar",
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"bar": "xoziZG_bar",
|
|
79
|
-
"header": "xoziZG_header",
|
|
80
|
-
"fieldLabel": "xoziZG_fieldLabel",
|
|
81
|
-
"choices": "xoziZG_choices",
|
|
82
|
-
"creditBlock": "xoziZG_creditBlock",
|
|
83
|
-
"creditRow": "xoziZG_creditRow",
|
|
106
|
+
"accountRowActions": "xoziZG_accountRowActions",
|
|
107
|
+
"modelShare": "xoziZG_modelShare",
|
|
108
|
+
"sectionLabel": "xoziZG_sectionLabel",
|
|
84
109
|
"field": "xoziZG_field",
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
110
|
+
"statusLine": "xoziZG_statusLine",
|
|
111
|
+
"area": "xoziZG_area",
|
|
112
|
+
"accountEntry": "xoziZG_accountEntry",
|
|
113
|
+
"choiceRow": "xoziZG_choiceRow",
|
|
114
|
+
"accountRow": "xoziZG_accountRow",
|
|
115
|
+
"statValue": "xoziZG_statValue",
|
|
89
116
|
"manualForm": "xoziZG_manualForm",
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"
|
|
117
|
+
"balance": "xoziZG_balance",
|
|
118
|
+
"statLabel": "xoziZG_statLabel",
|
|
119
|
+
"error": "xoziZG_error",
|
|
120
|
+
"barFill": "xoziZG_barFill",
|
|
121
|
+
"creditLink": "xoziZG_creditLink",
|
|
122
|
+
"avatar": "xoziZG_avatar",
|
|
123
|
+
"balanceMeta": "xoziZG_balanceMeta",
|
|
124
|
+
"creditBlock": "xoziZG_creditBlock",
|
|
125
|
+
"manualSummary": "xoziZG_manualSummary",
|
|
126
|
+
"actions": "xoziZG_actions",
|
|
95
127
|
"accountToolbar": "xoziZG_accountToolbar",
|
|
96
|
-
"
|
|
128
|
+
"balanceRow": "xoziZG_balanceRow",
|
|
129
|
+
"meta": "xoziZG_meta",
|
|
130
|
+
"expiryRow": "xoziZG_expiryRow",
|
|
131
|
+
"count": "xoziZG_count",
|
|
132
|
+
"statCard": "xoziZG_statCard",
|
|
133
|
+
"usageFill": "xoziZG_usageFill",
|
|
134
|
+
"modelTokens": "xoziZG_modelTokens",
|
|
135
|
+
"tabs": "xoziZG_tabs",
|
|
136
|
+
"link": "xoziZG_link",
|
|
97
137
|
"creditRows": "xoziZG_creditRows",
|
|
98
|
-
"
|
|
99
|
-
"
|
|
138
|
+
"modelChart": "xoziZG_modelChart",
|
|
139
|
+
"statSub": "xoziZG_statSub",
|
|
140
|
+
"accountNameRow": "xoziZG_accountNameRow",
|
|
141
|
+
"balanceUnit": "xoziZG_balanceUnit",
|
|
142
|
+
"manual": "xoziZG_manual",
|
|
143
|
+
"accountHint": "xoziZG_accountHint",
|
|
144
|
+
"header": "xoziZG_header",
|
|
145
|
+
"usageTip": "xoziZG_usageTip",
|
|
146
|
+
"section": "xoziZG_section",
|
|
147
|
+
"modelName": "xoziZG_modelName"
|
|
100
148
|
};
|
|
101
149
|
//#endregion
|
|
102
150
|
//#region src/client/CodeArtsPluginCard.tsx
|
|
@@ -128,6 +176,10 @@ function formatCount(value) {
|
|
|
128
176
|
function formatCredits(value) {
|
|
129
177
|
return Number.isFinite(value) ? new Intl.NumberFormat().format(Math.round(value)) : "0";
|
|
130
178
|
}
|
|
179
|
+
/** 浮层里的明细数字要精确到个位并带千分位,不用 k/M 缩写。 */
|
|
180
|
+
function exactCount(value) {
|
|
181
|
+
return formatCredits(value);
|
|
182
|
+
}
|
|
131
183
|
/** 批量领取的 claimingId 哨兵(真实账号 id 不会等于它)。 */
|
|
132
184
|
const CLAIM_ALL = "*";
|
|
133
185
|
/** 一次领取操作的文案:优先用后端逐号结果,老后端只回一条时按 id 归位。 */
|
|
@@ -142,10 +194,14 @@ function claimMessagesOf(data, accountIds, t) {
|
|
|
142
194
|
for (const id of accountIds) out[id] = claimText(data, t);
|
|
143
195
|
return out;
|
|
144
196
|
}
|
|
145
|
-
/**
|
|
197
|
+
/**
|
|
198
|
+
* 开关的兜底值:后端没这条路由(老版本)时按「都显示」渲染,与原有行为一致。
|
|
199
|
+
* 侧边栏那一格相反 —— 缺省关闭。
|
|
200
|
+
*/
|
|
146
201
|
const DOCK_DEFAULT = {
|
|
147
202
|
credits: true,
|
|
148
|
-
queue: true
|
|
203
|
+
queue: true,
|
|
204
|
+
sidebar: false
|
|
149
205
|
};
|
|
150
206
|
/** 一个 Tab 面板;未选中的用 hidden 留在 DOM 里,草稿和滚动位置都别丢。 */
|
|
151
207
|
function TabPanel({ id, labelledBy, active, children }) {
|
|
@@ -358,12 +414,25 @@ function ManualTokenForm({ t, token, label, busy, onToken, onLabel, onSubmit })
|
|
|
358
414
|
});
|
|
359
415
|
}
|
|
360
416
|
/**
|
|
417
|
+
* 缓存命中率:缓存输入 / 全部输入,钳在 0~100。
|
|
418
|
+
*
|
|
419
|
+
* 上游没给缓存字段、或今天压根没有输入时返回 undefined —— 统计块里显示「—」,
|
|
420
|
+
* 不要把「没有数据」写成「0%」。
|
|
421
|
+
*/
|
|
422
|
+
function hitPercentOf(totals) {
|
|
423
|
+
const cached = totals.cachedTokens ?? 0;
|
|
424
|
+
if (cached <= 0 || totals.promptTokens <= 0) return void 0;
|
|
425
|
+
return Math.min(100, Math.round(cached / totals.promptTokens * 100));
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
361
428
|
* 横向条形列表:名称 / 条 / token / 占比 / 请求数。
|
|
362
429
|
*
|
|
363
430
|
* 条长按「占组内总量的比例」画(不是按最大值归一化),所以几条加起来就是全部。
|
|
364
431
|
* token 全 0 的日子(只有请求数、没收到 usage 帧)退回按请求数画。
|
|
365
432
|
*/
|
|
366
433
|
function UsageBars({ rows, t }) {
|
|
434
|
+
/** 当前悬停的那一行;卡片浮层只在它上面出现。 */
|
|
435
|
+
const [hovered, setHovered] = (0, react.useState)(null);
|
|
367
436
|
const tokenMode = rows.some((row) => row.totals.totalTokens > 0);
|
|
368
437
|
const valueOf = (row) => tokenMode ? row.totals.totalTokens : row.totals.requests;
|
|
369
438
|
const sum = rows.reduce((total, row) => total + valueOf(row), 0);
|
|
@@ -374,13 +443,18 @@ function UsageBars({ rows, t }) {
|
|
|
374
443
|
children: top.map((row) => {
|
|
375
444
|
const value = valueOf(row);
|
|
376
445
|
const share = sum > 0 ? value / sum * 100 : 0;
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
|
|
446
|
+
const totals = row.totals;
|
|
447
|
+
const cached = totals.cachedTokens;
|
|
448
|
+
const pct = hitPercentOf(totals);
|
|
449
|
+
const detail = [t("usageRequests", { n: formatCount(totals.requests) }), t("usageTokens", {
|
|
450
|
+
prompt: formatTokens$1(totals.promptTokens),
|
|
451
|
+
completion: formatTokens$1(totals.completionTokens)
|
|
380
452
|
})].join(" · ");
|
|
381
453
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
382
454
|
className: CodeArtsPluginCard_module_css_default.modelRow,
|
|
383
455
|
title: `${row.label} · ${detail}`,
|
|
456
|
+
onMouseEnter: () => setHovered(row.id),
|
|
457
|
+
onMouseLeave: () => setHovered((prev) => prev === row.id ? null : prev),
|
|
384
458
|
children: [
|
|
385
459
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
386
460
|
className: CodeArtsPluginCard_module_css_default.modelName,
|
|
@@ -403,7 +477,43 @@ function UsageBars({ rows, t }) {
|
|
|
403
477
|
}),
|
|
404
478
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
405
479
|
className: CodeArtsPluginCard_module_css_default.modelRequests,
|
|
406
|
-
children: t("usageRequestCount", { n: formatCount(
|
|
480
|
+
children: t("usageRequestCount", { n: formatCount(totals.requests) })
|
|
481
|
+
}),
|
|
482
|
+
hovered === row.id && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
483
|
+
className: CodeArtsPluginCard_module_css_default.usageTip,
|
|
484
|
+
role: "tooltip",
|
|
485
|
+
children: [
|
|
486
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
487
|
+
className: CodeArtsPluginCard_module_css_default.usageTipName,
|
|
488
|
+
children: row.label
|
|
489
|
+
}),
|
|
490
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: CodeArtsPluginCard_module_css_default.usageTipSep }),
|
|
491
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
492
|
+
className: CodeArtsPluginCard_module_css_default.usageTipRow,
|
|
493
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageTipInput") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: exactCount(totals.promptTokens) })]
|
|
494
|
+
}),
|
|
495
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
496
|
+
className: CodeArtsPluginCard_module_css_default.usageTipRow,
|
|
497
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageTipOutput") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: exactCount(totals.completionTokens) })]
|
|
498
|
+
}),
|
|
499
|
+
(totals.reasoningTokens ?? 0) > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
500
|
+
className: CodeArtsPluginCard_module_css_default.usageTipRow,
|
|
501
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageTipReasoning") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: exactCount(totals.reasoningTokens ?? 0) })]
|
|
502
|
+
}),
|
|
503
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
504
|
+
className: CodeArtsPluginCard_module_css_default.usageTipRow,
|
|
505
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageTipCached") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: cached === void 0 ? t("usageTipNoCache") : exactCount(cached) })]
|
|
506
|
+
}),
|
|
507
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: CodeArtsPluginCard_module_css_default.usageTipSep }),
|
|
508
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
509
|
+
className: CodeArtsPluginCard_module_css_default.usageTipRow,
|
|
510
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageTipRequests") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageRequestCount", { n: formatCount(totals.requests) }) })]
|
|
511
|
+
}),
|
|
512
|
+
pct !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
513
|
+
className: CodeArtsPluginCard_module_css_default.usageTipRow,
|
|
514
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageTipHit") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [pct, "%"] })]
|
|
515
|
+
})
|
|
516
|
+
]
|
|
407
517
|
})
|
|
408
518
|
]
|
|
409
519
|
}, row.id);
|
|
@@ -418,7 +528,6 @@ function UsageBars({ rows, t }) {
|
|
|
418
528
|
* 「打断后重新提问要等」的原因。
|
|
419
529
|
*/
|
|
420
530
|
function UsageSection({ usage, accounts, t }) {
|
|
421
|
-
const total = usage.today.requests;
|
|
422
531
|
const stateLabel = {
|
|
423
532
|
ok: t("usageStateOk"),
|
|
424
533
|
capped: t("usageStateCapped"),
|
|
@@ -436,7 +545,9 @@ function UsageSection({ usage, accounts, t }) {
|
|
|
436
545
|
label: entry.id.split(" · ")[0],
|
|
437
546
|
totals: entry.totals
|
|
438
547
|
}));
|
|
439
|
-
const
|
|
548
|
+
const today = usage.today;
|
|
549
|
+
const hasUsage = usage.allTime.requests > 0 || today.requests > 0;
|
|
550
|
+
const hit = hitPercentOf(today);
|
|
440
551
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
441
552
|
className: CodeArtsPluginCard_module_css_default.section,
|
|
442
553
|
children: [
|
|
@@ -447,7 +558,10 @@ function UsageSection({ usage, accounts, t }) {
|
|
|
447
558
|
children: t("usageTitle")
|
|
448
559
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
449
560
|
className: CodeArtsPluginCard_module_css_default.count,
|
|
450
|
-
children: t("
|
|
561
|
+
children: t("usageRange", {
|
|
562
|
+
today: formatCount(today.requests),
|
|
563
|
+
last30: formatCount(usage.last30.requests)
|
|
564
|
+
})
|
|
451
565
|
})]
|
|
452
566
|
}),
|
|
453
567
|
!hasUsage ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
@@ -455,38 +569,46 @@ function UsageSection({ usage, accounts, t }) {
|
|
|
455
569
|
children: t("usageEmpty")
|
|
456
570
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
457
571
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
458
|
-
className: CodeArtsPluginCard_module_css_default.
|
|
459
|
-
children: [
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
572
|
+
className: CodeArtsPluginCard_module_css_default.statGrid,
|
|
573
|
+
children: [
|
|
574
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
575
|
+
className: CodeArtsPluginCard_module_css_default.statCard,
|
|
576
|
+
children: [
|
|
577
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
578
|
+
className: CodeArtsPluginCard_module_css_default.statLabel,
|
|
579
|
+
children: t("usageStatTokens")
|
|
580
|
+
}),
|
|
581
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
582
|
+
className: CodeArtsPluginCard_module_css_default.statValue,
|
|
583
|
+
children: formatTokens$1(today.totalTokens)
|
|
584
|
+
}),
|
|
585
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
586
|
+
className: CodeArtsPluginCard_module_css_default.statSub,
|
|
587
|
+
children: [t("usageStatIn", { n: formatTokens$1(today.promptTokens) }), (today.reasoningTokens ?? 0) > 0 ? ` · ${t("usageStatThinking", { n: formatTokens$1(today.reasoningTokens ?? 0) })}` : ""]
|
|
588
|
+
})
|
|
589
|
+
]
|
|
590
|
+
}),
|
|
591
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
592
|
+
className: CodeArtsPluginCard_module_css_default.statCard,
|
|
593
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
594
|
+
className: CodeArtsPluginCard_module_css_default.statLabel,
|
|
595
|
+
children: t("usageStatHit")
|
|
596
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
597
|
+
className: CodeArtsPluginCard_module_css_default.statValue,
|
|
598
|
+
children: hit === void 0 ? "—" : `${hit}%`
|
|
599
|
+
})]
|
|
600
|
+
}),
|
|
601
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
602
|
+
className: CodeArtsPluginCard_module_css_default.statCard,
|
|
603
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
604
|
+
className: CodeArtsPluginCard_module_css_default.statLabel,
|
|
605
|
+
children: t("usageStatRequests")
|
|
606
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
607
|
+
className: CodeArtsPluginCard_module_css_default.statValue,
|
|
608
|
+
children: formatCount(today.requests)
|
|
609
|
+
})]
|
|
610
|
+
})
|
|
611
|
+
]
|
|
490
612
|
}),
|
|
491
613
|
accounts.length > 1 && accountRows.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
492
614
|
className: CodeArtsPluginCard_module_css_default.hint,
|
|
@@ -571,14 +693,21 @@ function CodeArtsPluginCard({ t }) {
|
|
|
571
693
|
const res = await fetch("/api/codearts/dock", { headers: { Accept: "application/json" } });
|
|
572
694
|
if (!res.ok) return;
|
|
573
695
|
const data = await res.json();
|
|
574
|
-
if (data.dock !== void 0)
|
|
696
|
+
if (data.dock !== void 0) {
|
|
697
|
+
const next = {
|
|
698
|
+
...DOCK_DEFAULT,
|
|
699
|
+
...data.dock
|
|
700
|
+
};
|
|
701
|
+
setDock(next);
|
|
702
|
+
setSidebarPanelWanted(next.sidebar);
|
|
703
|
+
}
|
|
575
704
|
setDockWritable(data.writable === true);
|
|
576
705
|
} catch {}
|
|
577
706
|
}
|
|
578
707
|
/**
|
|
579
708
|
* 改一个开关:先按新值渲染,写失败再退回去。
|
|
580
709
|
*
|
|
581
|
-
* 这里不像模型勾选那样攒草稿再点保存 ——
|
|
710
|
+
* 这里不像模型勾选那样攒草稿再点保存 —— 只有几个布尔,攒草稿反而让用户猜
|
|
582
711
|
* 「我刚才那一下到底生效没有」。
|
|
583
712
|
*/
|
|
584
713
|
async function toggleDock(key, on) {
|
|
@@ -589,6 +718,7 @@ function CodeArtsPluginCard({ t }) {
|
|
|
589
718
|
});
|
|
590
719
|
setDockSaving(true);
|
|
591
720
|
setDockError(null);
|
|
721
|
+
if (key === "sidebar") setSidebarPanelWanted(on);
|
|
592
722
|
try {
|
|
593
723
|
const res = await fetch("/api/codearts/dock", {
|
|
594
724
|
method: "POST",
|
|
@@ -603,9 +733,17 @@ function CodeArtsPluginCard({ t }) {
|
|
|
603
733
|
throw new Error(typeof data.error === "string" ? data.error : `HTTP ${res.status}`);
|
|
604
734
|
}
|
|
605
735
|
const data = await res.json();
|
|
606
|
-
if (data.dock !== void 0)
|
|
736
|
+
if (data.dock !== void 0) {
|
|
737
|
+
const next = {
|
|
738
|
+
...DOCK_DEFAULT,
|
|
739
|
+
...data.dock
|
|
740
|
+
};
|
|
741
|
+
setDock(next);
|
|
742
|
+
setSidebarPanelWanted(next.sidebar);
|
|
743
|
+
}
|
|
607
744
|
} catch (error) {
|
|
608
745
|
setDock(previous);
|
|
746
|
+
if (key === "sidebar") setSidebarPanelWanted(previous.sidebar);
|
|
609
747
|
setDockError(error instanceof Error ? error.message : String(error));
|
|
610
748
|
} finally {
|
|
611
749
|
setDockSaving(false);
|
|
@@ -1282,11 +1420,11 @@ function CodeArtsPluginCard({ t }) {
|
|
|
1282
1420
|
t
|
|
1283
1421
|
})
|
|
1284
1422
|
}),
|
|
1285
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
1423
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(TabPanel, {
|
|
1286
1424
|
id: panelId("display"),
|
|
1287
1425
|
labelledBy: tabId("display"),
|
|
1288
1426
|
active: activeTab === "display",
|
|
1289
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1427
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1290
1428
|
className: CodeArtsPluginCard_module_css_default.section,
|
|
1291
1429
|
children: [
|
|
1292
1430
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -1331,7 +1469,35 @@ function CodeArtsPluginCard({ t }) {
|
|
|
1331
1469
|
children: t("displayFailed", { message: dockError })
|
|
1332
1470
|
})
|
|
1333
1471
|
]
|
|
1334
|
-
})
|
|
1472
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1473
|
+
className: CodeArtsPluginCard_module_css_default.section,
|
|
1474
|
+
children: [
|
|
1475
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1476
|
+
className: CodeArtsPluginCard_module_css_default.sectionHead,
|
|
1477
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1478
|
+
className: CodeArtsPluginCard_module_css_default.sectionLabel,
|
|
1479
|
+
children: t("displaySidebarTitle")
|
|
1480
|
+
})
|
|
1481
|
+
}),
|
|
1482
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1483
|
+
className: CodeArtsPluginCard_module_css_default.hint,
|
|
1484
|
+
children: t("displaySidebarHint")
|
|
1485
|
+
}),
|
|
1486
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1487
|
+
className: CodeArtsPluginCard_module_css_default.choices,
|
|
1488
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1489
|
+
className: CodeArtsPluginCard_module_css_default.choiceRow,
|
|
1490
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Checkbox, {
|
|
1491
|
+
className: CodeArtsPluginCard_module_css_default.check,
|
|
1492
|
+
checked: dock.sidebar,
|
|
1493
|
+
disabled: !dockWritable || dockSaving,
|
|
1494
|
+
onChange: (on) => void toggleDock("sidebar", on),
|
|
1495
|
+
label: t("displaySidebarToggle")
|
|
1496
|
+
})
|
|
1497
|
+
})
|
|
1498
|
+
})
|
|
1499
|
+
]
|
|
1500
|
+
})]
|
|
1335
1501
|
})
|
|
1336
1502
|
] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1337
1503
|
className: CodeArtsPluginCard_module_css_default.section,
|
|
@@ -1494,10 +1660,27 @@ const QUEUE_PATH = "/api/codearts/queue";
|
|
|
1494
1660
|
const REFRESH_INTERVAL_MS = 6e4;
|
|
1495
1661
|
/** 排队位置变得快:官方客户端也是 5 秒一次;这是本机路由,打不疼上游。 */
|
|
1496
1662
|
const QUEUE_INTERVAL_MS = 5e3;
|
|
1497
|
-
/**
|
|
1498
|
-
|
|
1663
|
+
/**
|
|
1664
|
+
* 弹层宽度:只放「账号 + 积分」两列,所以按同类插件(dsh-connect-trae 的
|
|
1665
|
+
* `min(248px, …)`)取一档窄宽度 —— 这一层回答的是「哪个号还有多少积分」,
|
|
1666
|
+
* 用量数字不该把它撑成一张报表。
|
|
1667
|
+
*/
|
|
1668
|
+
const PANEL_WIDTH = 260;
|
|
1499
1669
|
/** 弹层与那一行之间的缝隙。 */
|
|
1500
1670
|
const PANEL_GAP = 8;
|
|
1671
|
+
/**
|
|
1672
|
+
* 弹层里每行的列模板:账号 | 积分。
|
|
1673
|
+
*
|
|
1674
|
+
* 数字列用 `auto`:它跟着最宽的那个余额自适应,面板不必为「12,600」预留固定宽度。
|
|
1675
|
+
* 输入 / 输出 / 缓存这些用量数字不进表格,收进整行的悬浮提示({@link usageLine}),
|
|
1676
|
+
* 完整明细在设置卡片里看。
|
|
1677
|
+
*/
|
|
1678
|
+
const PANEL_ROW_COLUMNS = "minmax(0, 1fr) auto";
|
|
1679
|
+
/** 数字格统一右对齐 + 等宽数字,列才对得齐。 */
|
|
1680
|
+
const PANEL_NUM_CELL = {
|
|
1681
|
+
justifySelf: "end",
|
|
1682
|
+
fontVariantNumeric: "tabular-nums"
|
|
1683
|
+
};
|
|
1501
1684
|
/** 那一行在输入框下方,往上开才够空间;给弹层留的最小高度,不够就翻到下面。 */
|
|
1502
1685
|
const PANEL_MIN_ABOVE = 260;
|
|
1503
1686
|
function readSelection(useProjection) {
|
|
@@ -1535,6 +1718,24 @@ function formatClock(ts) {
|
|
|
1535
1718
|
return "";
|
|
1536
1719
|
}
|
|
1537
1720
|
}
|
|
1721
|
+
/**
|
|
1722
|
+
* 弹层里那行用量:`入 12.3k · 出 697(思 505)· 命中 94% · 37 条`。
|
|
1723
|
+
*
|
|
1724
|
+
* 刻意比设置卡片里的完整版短:面板只有 260px,把「缓存 11.5k」也列上就会折成
|
|
1725
|
+
* 两三行,比原来那个悬浮提示还难看。缓存值本身由命中率表达(它是输入的占比),
|
|
1726
|
+
* 思考 token 也不在这里——它是输出的子集,放在设置卡片的统计块里。上游不给缓存
|
|
1727
|
+
* 字段就不显示命中率:显示成 0% 会被当成「没命中」而不是「没数据」。
|
|
1728
|
+
*/
|
|
1729
|
+
function usageLine(usage, t) {
|
|
1730
|
+
const cached = usage.cachedTokens ?? 0;
|
|
1731
|
+
const parts = [t("usageCompact", {
|
|
1732
|
+
prompt: formatTokens(usage.promptTokens),
|
|
1733
|
+
completion: formatTokens(usage.completionTokens)
|
|
1734
|
+
})];
|
|
1735
|
+
if (cached > 0 && usage.promptTokens > 0) parts.push(t("usageCacheHit", { pct: Math.min(100, Math.round(cached / usage.promptTokens * 100)) }));
|
|
1736
|
+
parts.push(t("usageRequestCount", { n: formatNumber(usage.requests) }));
|
|
1737
|
+
return parts.join(" · ");
|
|
1738
|
+
}
|
|
1538
1739
|
/** 账号名与设置卡片同一套取法:备注 > 用户名 > id。 */
|
|
1539
1740
|
function accountName(account) {
|
|
1540
1741
|
return account.label?.trim() || account.userName?.trim() || account.id;
|
|
@@ -1566,21 +1767,20 @@ function rowsOf(data) {
|
|
|
1566
1767
|
};
|
|
1567
1768
|
});
|
|
1568
1769
|
}
|
|
1569
|
-
/**
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1770
|
+
/**
|
|
1771
|
+
* 弹层往上开还是往下开。
|
|
1772
|
+
*
|
|
1773
|
+
* 位置不在这里算:fixed 元素遇到带 transform / backdrop-filter 的祖先时,坐标会
|
|
1774
|
+
* 相对那个祖先而不是视口(工具行就长在输入框卡片里),所以真实偏移要渲染后实测
|
|
1775
|
+
* (见组件里的 layout effect),这里只决定朝哪边翻。
|
|
1776
|
+
*/
|
|
1777
|
+
function placeAbove(rect) {
|
|
1778
|
+
return rect.top > PANEL_MIN_ABOVE;
|
|
1578
1779
|
}
|
|
1579
|
-
function CodeArtsCreditDock({ useProjection, t }) {
|
|
1780
|
+
function CodeArtsCreditDock({ useProjection, t, zone = "dock" }) {
|
|
1580
1781
|
const selection = readSelection(useProjection);
|
|
1581
1782
|
const active = isCodeArts(selection);
|
|
1582
1783
|
const [remain, setRemain] = (0, react.useState)(null);
|
|
1583
|
-
const [total, setTotal] = (0, react.useState)(0);
|
|
1584
1784
|
const [rows, setRows] = (0, react.useState)([]);
|
|
1585
1785
|
/**
|
|
1586
1786
|
* 模型 id -> 目录条目(显示名 + 已格式化的倍率)。
|
|
@@ -1591,10 +1791,20 @@ function CodeArtsCreditDock({ useProjection, t }) {
|
|
|
1591
1791
|
const [modelInfo, setModelInfo] = (0, react.useState)({});
|
|
1592
1792
|
const [flags, setFlags] = (0, react.useState)({
|
|
1593
1793
|
credits: true,
|
|
1594
|
-
queue: true
|
|
1794
|
+
queue: true,
|
|
1795
|
+
sidebar: false
|
|
1595
1796
|
});
|
|
1596
1797
|
const [queued, setQueued] = (0, react.useState)(null);
|
|
1597
1798
|
const [anchor, setAnchor] = (0, react.useState)(null);
|
|
1799
|
+
/**
|
|
1800
|
+
* 弹层的包含块原点(视口坐标)。
|
|
1801
|
+
*
|
|
1802
|
+
* fixed 只有在祖先没有 transform / backdrop-filter 时才是视口坐标;工具行长在输入框
|
|
1803
|
+
* 卡片里,一旦撞上这类祖先,left/top 就会相对那个祖先算,弹层会飞到窗口外。做法是
|
|
1804
|
+
* 先按 0,0 渲染但不可见,量出面板实际落在哪(就是包含块原点),再把目标坐标减掉它;
|
|
1805
|
+
* 视口情形下量到 (0,0),等于没动。
|
|
1806
|
+
*/
|
|
1807
|
+
const [origin, setOrigin] = (0, react.useState)(null);
|
|
1598
1808
|
const [refreshing, setRefreshing] = (0, react.useState)(false);
|
|
1599
1809
|
const mounted = (0, react.useRef)(true);
|
|
1600
1810
|
const triggerRef = (0, react.useRef)(null);
|
|
@@ -1618,7 +1828,8 @@ function CodeArtsCreditDock({ useProjection, t }) {
|
|
|
1618
1828
|
if (data === void 0 || !mounted.current) return;
|
|
1619
1829
|
setFlags(data.dock ?? {
|
|
1620
1830
|
credits: true,
|
|
1621
|
-
queue: true
|
|
1831
|
+
queue: true,
|
|
1832
|
+
sidebar: false
|
|
1622
1833
|
});
|
|
1623
1834
|
setRows(rowsOf(data));
|
|
1624
1835
|
setModelInfo(Object.fromEntries((data.models ?? []).map((model) => [model.id, {
|
|
@@ -1632,7 +1843,6 @@ function CodeArtsCreditDock({ useProjection, t }) {
|
|
|
1632
1843
|
return;
|
|
1633
1844
|
}
|
|
1634
1845
|
setRemain(Math.round(pool.reduce((sum, item) => sum + item.credits.total.remain, 0)));
|
|
1635
|
-
setTotal(Math.round(pool.reduce((sum, item) => sum + item.credits.total.total, 0)));
|
|
1636
1846
|
} catch {}
|
|
1637
1847
|
}, []);
|
|
1638
1848
|
(0, react.useEffect)(() => {
|
|
@@ -1695,6 +1905,19 @@ function CodeArtsCreditDock({ useProjection, t }) {
|
|
|
1695
1905
|
window.removeEventListener("scroll", close, true);
|
|
1696
1906
|
};
|
|
1697
1907
|
}, [anchor, close]);
|
|
1908
|
+
(0, react.useLayoutEffect)(() => {
|
|
1909
|
+
if (anchor === null) {
|
|
1910
|
+
setOrigin(null);
|
|
1911
|
+
return;
|
|
1912
|
+
}
|
|
1913
|
+
const el = panelRef.current;
|
|
1914
|
+
if (el === null) return;
|
|
1915
|
+
const rect = el.getBoundingClientRect();
|
|
1916
|
+
setOrigin((prev) => prev !== null && Math.abs(prev.x - rect.left) < .5 && Math.abs(prev.y - rect.top) < .5 ? prev : {
|
|
1917
|
+
x: rect.left,
|
|
1918
|
+
y: rect.top
|
|
1919
|
+
});
|
|
1920
|
+
}, [anchor]);
|
|
1698
1921
|
(0, react.useEffect)(() => {
|
|
1699
1922
|
if (!active) return;
|
|
1700
1923
|
const self = rootRef.current;
|
|
@@ -1719,26 +1942,18 @@ function CodeArtsCreditDock({ useProjection, t }) {
|
|
|
1719
1942
|
if (!active) return null;
|
|
1720
1943
|
const showCredits = flags.credits && remain !== null;
|
|
1721
1944
|
const showQueue = flags.queue && queued !== null;
|
|
1945
|
+
if (zone === "bar" && !showCredits) return null;
|
|
1722
1946
|
const modelId = currentOf(selection)?.model;
|
|
1723
1947
|
const entry = modelId === void 0 ? void 0 : modelInfo[modelId];
|
|
1724
1948
|
const modelLabel = entry === void 0 ? modelId ?? "" : stripModelSuffixes(entry.name);
|
|
1725
1949
|
const ratio = entry?.ratio;
|
|
1726
1950
|
const line = buildDockLine({
|
|
1727
|
-
...showCredits ? { credits: t("creditsDock", { remain: formatNumber(remain ?? 0) }) } : {},
|
|
1951
|
+
...zone === "bar" && showCredits ? { credits: t("creditsDock", { remain: formatNumber(remain ?? 0) }) } : {},
|
|
1728
1952
|
provider: "CodeArts",
|
|
1729
1953
|
...modelLabel === "" ? {} : { model: modelLabel },
|
|
1730
1954
|
...ratio === void 0 ? {} : { ratio },
|
|
1731
|
-
...showQueue && queued !== null ? { queue: t("queueDock", { position: queued.position }) } : {}
|
|
1955
|
+
...zone === "dock" && showQueue && queued !== null ? { queue: t("queueDock", { position: queued.position }) } : {}
|
|
1732
1956
|
}, t);
|
|
1733
|
-
const queueTitle = queued === null ? void 0 : t("queueDockTitle", {
|
|
1734
|
-
model: queued.model,
|
|
1735
|
-
position: queued.position,
|
|
1736
|
-
length: queued.length
|
|
1737
|
-
});
|
|
1738
|
-
const creditsTitle = showCredits ? t("creditsDockTitle", {
|
|
1739
|
-
remain: remain ?? 0,
|
|
1740
|
-
total
|
|
1741
|
-
}) : void 0;
|
|
1742
1957
|
const fetchedAt = rows.reduce((latest, row) => Math.max(latest, row.fetchedAt ?? 0), 0);
|
|
1743
1958
|
const lastUpdated = fetchedAt > 0 ? formatClock(fetchedAt) : "";
|
|
1744
1959
|
const toggle = (event) => {
|
|
@@ -1746,7 +1961,13 @@ function CodeArtsCreditDock({ useProjection, t }) {
|
|
|
1746
1961
|
close();
|
|
1747
1962
|
return;
|
|
1748
1963
|
}
|
|
1749
|
-
|
|
1964
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
1965
|
+
const above = placeAbove(rect);
|
|
1966
|
+
setAnchor({
|
|
1967
|
+
left: rect.left,
|
|
1968
|
+
top: above ? rect.top - PANEL_GAP : rect.bottom + PANEL_GAP,
|
|
1969
|
+
above
|
|
1970
|
+
});
|
|
1750
1971
|
};
|
|
1751
1972
|
const forceRefresh = async () => {
|
|
1752
1973
|
setRefreshing(true);
|
|
@@ -1770,7 +1991,6 @@ function CodeArtsCreditDock({ useProjection, t }) {
|
|
|
1770
1991
|
flex: "0 0 auto",
|
|
1771
1992
|
minWidth: "max-content"
|
|
1772
1993
|
},
|
|
1773
|
-
title: queueTitle ?? creditsTitle,
|
|
1774
1994
|
children: [
|
|
1775
1995
|
line.credits !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1776
1996
|
ref: triggerRef,
|
|
@@ -1778,7 +1998,6 @@ function CodeArtsCreditDock({ useProjection, t }) {
|
|
|
1778
1998
|
"aria-haspopup": "dialog",
|
|
1779
1999
|
"aria-expanded": anchor !== null,
|
|
1780
2000
|
"aria-label": t("creditsDockPanelTitle"),
|
|
1781
|
-
title: creditsTitle,
|
|
1782
2001
|
onClick: toggle,
|
|
1783
2002
|
style: {
|
|
1784
2003
|
all: "unset",
|
|
@@ -1790,20 +2009,21 @@ function CodeArtsCreditDock({ useProjection, t }) {
|
|
|
1790
2009
|
whiteSpace: "inherit"
|
|
1791
2010
|
},
|
|
1792
2011
|
children: line.credits
|
|
1793
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2012
|
+
}), zone === "dock" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1794
2013
|
"aria-hidden": "true",
|
|
1795
2014
|
children: " · "
|
|
1796
2015
|
})] }),
|
|
1797
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: line.rest }),
|
|
2016
|
+
zone === "dock" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: line.rest }),
|
|
1798
2017
|
anchor !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1799
2018
|
ref: panelRef,
|
|
1800
2019
|
role: "dialog",
|
|
1801
2020
|
"aria-label": t("creditsDockPanelTitle"),
|
|
1802
2021
|
style: {
|
|
1803
2022
|
position: "fixed",
|
|
1804
|
-
left: anchor.left,
|
|
1805
|
-
top: anchor.top,
|
|
1806
|
-
transform: anchor.above ? "translateY(-100%)" : void 0,
|
|
2023
|
+
left: origin === null ? 0 : anchor.left - origin.x,
|
|
2024
|
+
top: origin === null ? 0 : anchor.top - origin.y,
|
|
2025
|
+
transform: anchor.above && origin !== null ? "translateY(-100%)" : void 0,
|
|
2026
|
+
visibility: origin === null ? "hidden" : "visible",
|
|
1807
2027
|
width: PANEL_WIDTH,
|
|
1808
2028
|
maxWidth: "calc(100vw - 16px)",
|
|
1809
2029
|
zIndex: 1e3,
|
|
@@ -1842,73 +2062,60 @@ function CodeArtsCreditDock({ useProjection, t }) {
|
|
|
1842
2062
|
}),
|
|
1843
2063
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1844
2064
|
style: {
|
|
1845
|
-
display: "
|
|
1846
|
-
|
|
1847
|
-
gap:
|
|
1848
|
-
alignItems: "center",
|
|
2065
|
+
display: "flex",
|
|
2066
|
+
flexDirection: "column",
|
|
2067
|
+
gap: 10,
|
|
1849
2068
|
borderTop: "0.5px solid var(--dsw-alias-border-l2, rgba(127, 127, 127, 0.22))",
|
|
1850
2069
|
paddingTop: 8,
|
|
2070
|
+
fontSize: 12,
|
|
1851
2071
|
color: "var(--dsw-alias-label-tertiary)"
|
|
1852
2072
|
},
|
|
1853
|
-
children: [
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
children: row.usage === void 0 ? "—" : formatTokens(row.usage.totalTokens)
|
|
1900
|
-
}),
|
|
1901
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1902
|
-
style: {
|
|
1903
|
-
justifySelf: "end",
|
|
1904
|
-
fontVariantNumeric: "tabular-nums"
|
|
1905
|
-
},
|
|
1906
|
-
children: row.remain === null ? "—" : formatNumber(row.remain)
|
|
1907
|
-
})
|
|
1908
|
-
]
|
|
1909
|
-
}, row.id);
|
|
1910
|
-
})
|
|
1911
|
-
]
|
|
2073
|
+
children: [rows.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("creditsDockEmpty") }), rows.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2074
|
+
style: {
|
|
2075
|
+
display: "flex",
|
|
2076
|
+
flexDirection: "column",
|
|
2077
|
+
gap: 2,
|
|
2078
|
+
minWidth: 0
|
|
2079
|
+
},
|
|
2080
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2081
|
+
style: {
|
|
2082
|
+
display: "grid",
|
|
2083
|
+
gridTemplateColumns: PANEL_ROW_COLUMNS,
|
|
2084
|
+
gap: "0 8px",
|
|
2085
|
+
alignItems: "center",
|
|
2086
|
+
minWidth: 0
|
|
2087
|
+
},
|
|
2088
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2089
|
+
style: {
|
|
2090
|
+
display: "flex",
|
|
2091
|
+
alignItems: "center",
|
|
2092
|
+
gap: 5,
|
|
2093
|
+
minWidth: 0
|
|
2094
|
+
},
|
|
2095
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: row.remain === null ? "warning" : "done" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2096
|
+
style: {
|
|
2097
|
+
overflow: "hidden",
|
|
2098
|
+
textOverflow: "ellipsis",
|
|
2099
|
+
whiteSpace: "nowrap",
|
|
2100
|
+
color: "var(--dsw-alias-label-primary)"
|
|
2101
|
+
},
|
|
2102
|
+
title: row.error === void 0 ? row.name : row.error,
|
|
2103
|
+
children: row.name
|
|
2104
|
+
})]
|
|
2105
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2106
|
+
style: PANEL_NUM_CELL,
|
|
2107
|
+
children: row.remain === null ? "—" : formatNumber(row.remain)
|
|
2108
|
+
})]
|
|
2109
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2110
|
+
style: {
|
|
2111
|
+
paddingLeft: 11,
|
|
2112
|
+
fontSize: 11,
|
|
2113
|
+
lineHeight: "15px",
|
|
2114
|
+
color: "var(--dsw-alias-label-tertiary)"
|
|
2115
|
+
},
|
|
2116
|
+
children: row.usage === void 0 ? t("creditsDockNoTokens") : `${t("usageToday")} ${usageLine(row.usage, t)}`
|
|
2117
|
+
})]
|
|
2118
|
+
}, row.id))]
|
|
1912
2119
|
}),
|
|
1913
2120
|
rows.filter((row) => row.expiring > 0).map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1914
2121
|
style: {
|
|
@@ -1930,6 +2137,84 @@ function CodeArtsCreditDock({ useProjection, t }) {
|
|
|
1930
2137
|
});
|
|
1931
2138
|
}
|
|
1932
2139
|
//#endregion
|
|
2140
|
+
//#region \0dsh-css:/home/runner/work/dsh-codearts/dsh-codearts/src/client/CodeArtsPanel.module.css.mjs
|
|
2141
|
+
const css = ".Z66cgG_page{box-sizing:border-box;height:100%;min-height:0;padding:calc(28px + var(--dsh-frame-top-clearance,0px)) clamp(24px, 4vw, 48px) 48px;color:var(--dsw-alias-label-primary);flex-direction:column;display:flex;overflow:auto}.Z66cgG_head{flex-direction:column;gap:6px;width:100%;max-width:860px;margin:0 auto;display:flex}.Z66cgG_back{appearance:none;font:inherit;cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);align-self:flex-start;align-items:center;gap:6px;margin-bottom:10px;padding:5px 12px;font-size:13px;line-height:20px;display:inline-flex}.Z66cgG_back:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.Z66cgG_backCaret{border-bottom:1.6px solid;border-left:1.6px solid;width:7px;height:7px;display:inline-block;transform:rotate(45deg)}.Z66cgG_title{margin:0;font-size:20px;font-weight:600;line-height:1.4}.Z66cgG_desc{color:var(--dsw-alias-label-tertiary);margin:0;font-size:13px;line-height:1.5}.Z66cgG_body{width:100%;max-width:860px;margin:20px auto 0}.Z66cgG_icon{flex:none;display:block}";
|
|
2142
|
+
const tagId = "dsh-codearts/CodeArtsPanel.module.css";
|
|
2143
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
2144
|
+
const tag = document.createElement("style");
|
|
2145
|
+
tag.dataset.plugin = "dsh-codearts";
|
|
2146
|
+
tag.dataset.pluginCss = tagId;
|
|
2147
|
+
tag.textContent = css;
|
|
2148
|
+
document.head.appendChild(tag);
|
|
2149
|
+
}
|
|
2150
|
+
var CodeArtsPanel_module_css_default = {
|
|
2151
|
+
"icon": "Z66cgG_icon",
|
|
2152
|
+
"backCaret": "Z66cgG_backCaret",
|
|
2153
|
+
"title": "Z66cgG_title",
|
|
2154
|
+
"head": "Z66cgG_head",
|
|
2155
|
+
"desc": "Z66cgG_desc",
|
|
2156
|
+
"back": "Z66cgG_back",
|
|
2157
|
+
"page": "Z66cgG_page",
|
|
2158
|
+
"body": "Z66cgG_body"
|
|
2159
|
+
};
|
|
2160
|
+
//#endregion
|
|
2161
|
+
//#region src/client/CodeArtsPanel.tsx
|
|
2162
|
+
/** 侧边栏按钮里的图标。宿主按 { size, active } 渲染,我们用 currentColor 跟随主题。 */
|
|
2163
|
+
function CodeArtsPanelIcon({ size }) {
|
|
2164
|
+
const px = typeof size === "number" && size > 0 ? size : 16;
|
|
2165
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
2166
|
+
className: CodeArtsPanel_module_css_default.icon,
|
|
2167
|
+
width: px,
|
|
2168
|
+
height: px,
|
|
2169
|
+
viewBox: "0 0 16 16",
|
|
2170
|
+
fill: "none",
|
|
2171
|
+
"aria-hidden": "true",
|
|
2172
|
+
focusable: "false",
|
|
2173
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
2174
|
+
d: "M9.9 2.6a1.4 1.4 0 0 1 2 0l1.5 1.5a1.4 1.4 0 0 1 0 2l-6.4 6.4-3.6.9a.6.6 0 0 1-.7-.7l.9-3.6 6.3-6.5Z",
|
|
2175
|
+
stroke: "currentColor",
|
|
2176
|
+
strokeWidth: "1.2",
|
|
2177
|
+
strokeLinejoin: "round"
|
|
2178
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
2179
|
+
d: "M8.9 3.6 12.4 7.1",
|
|
2180
|
+
stroke: "currentColor",
|
|
2181
|
+
strokeWidth: "1.2",
|
|
2182
|
+
strokeLinecap: "round"
|
|
2183
|
+
})]
|
|
2184
|
+
});
|
|
2185
|
+
}
|
|
2186
|
+
/** 侧边栏入口页:一个返回按钮 + 标题,正文直接复用设置里那张卡片。 */
|
|
2187
|
+
function CodeArtsPanelPage({ t, backToConversation }) {
|
|
2188
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2189
|
+
className: CodeArtsPanel_module_css_default.page,
|
|
2190
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2191
|
+
className: CodeArtsPanel_module_css_default.head,
|
|
2192
|
+
children: [
|
|
2193
|
+
backToConversation !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2194
|
+
type: "button",
|
|
2195
|
+
className: CodeArtsPanel_module_css_default.back,
|
|
2196
|
+
onClick: backToConversation,
|
|
2197
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2198
|
+
className: CodeArtsPanel_module_css_default.backCaret,
|
|
2199
|
+
"aria-hidden": "true"
|
|
2200
|
+
}), t("panelBack")]
|
|
2201
|
+
}),
|
|
2202
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
|
|
2203
|
+
className: CodeArtsPanel_module_css_default.title,
|
|
2204
|
+
children: t("cardTitle")
|
|
2205
|
+
}),
|
|
2206
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2207
|
+
className: CodeArtsPanel_module_css_default.desc,
|
|
2208
|
+
children: t("panelDesc")
|
|
2209
|
+
})
|
|
2210
|
+
]
|
|
2211
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2212
|
+
className: CodeArtsPanel_module_css_default.body,
|
|
2213
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeArtsPluginCard, { t })
|
|
2214
|
+
})]
|
|
2215
|
+
});
|
|
2216
|
+
}
|
|
2217
|
+
//#endregion
|
|
1933
2218
|
//#region src/client/locales.ts
|
|
1934
2219
|
const zh = {
|
|
1935
2220
|
tabLabel: "CodeArts",
|
|
@@ -1993,12 +2278,25 @@ const zh = {
|
|
|
1993
2278
|
modelsLoading: "模型勾选区加载中…(若长期不出现,请确认已登录且 DSH 已完全重启)",
|
|
1994
2279
|
usageTitle: "本机用量",
|
|
1995
2280
|
usageToday: "今日",
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
2281
|
+
usageRange: "今日 {today} 条 · 近 30 天 {last30} 条",
|
|
2282
|
+
usageStatTokens: "今日 token",
|
|
2283
|
+
usageStatIn: "输入 {n}",
|
|
2284
|
+
usageStatThinking: "思考 {n}",
|
|
2285
|
+
usageTipInput: "输入",
|
|
2286
|
+
usageTipOutput: "输出",
|
|
2287
|
+
usageTipReasoning: "思考",
|
|
2288
|
+
usageTipCached: "缓存命中",
|
|
2289
|
+
usageTipNoCache: "上游未下发",
|
|
2290
|
+
usageTipRequests: "请求",
|
|
2291
|
+
usageTipHit: "命中率",
|
|
2292
|
+
usageStatHit: "缓存命中",
|
|
2293
|
+
usageStatRequests: "今日请求",
|
|
1999
2294
|
usageRequests: "{n} 次请求",
|
|
2295
|
+
usageByAccount: "今日按账号",
|
|
2000
2296
|
usageRequestCount: "{n} 条",
|
|
2001
2297
|
usageTokens: "输入 {prompt} · 输出 {completion}",
|
|
2298
|
+
usageCompact: "入 {prompt} · 出 {completion}",
|
|
2299
|
+
usageCacheHit: "命中 {pct}%",
|
|
2002
2300
|
usageAllTime: "累计({days} 天)",
|
|
2003
2301
|
usageByModel: "今日按模型",
|
|
2004
2302
|
usageSlots: "会话槽位",
|
|
@@ -2025,9 +2323,6 @@ const zh = {
|
|
|
2025
2323
|
creditsDockPanelTitle: "CodeArts 积分",
|
|
2026
2324
|
creditsDockRefresh: "刷新积分",
|
|
2027
2325
|
creditsDockRefreshing: "刷新中…",
|
|
2028
|
-
creditsDockColAccount: "账号",
|
|
2029
|
-
creditsDockColBalance: "剩余积分",
|
|
2030
|
-
creditsDockColTokens: "今日 Token",
|
|
2031
2326
|
creditsDockNoTokens: "今天还没有经插件发出的请求",
|
|
2032
2327
|
creditsDockEmpty: "暂时没有积分数据",
|
|
2033
2328
|
creditsDockExpiring: "{account}:{expiring} 积分将在本周期结束时作废",
|
|
@@ -2036,12 +2331,15 @@ const zh = {
|
|
|
2036
2331
|
dockModel: "Model {model}",
|
|
2037
2332
|
dockNoModel: "未选择模型",
|
|
2038
2333
|
tabDisplay: "显示",
|
|
2039
|
-
displayTitle: "
|
|
2334
|
+
displayTitle: "输入框两侧显示",
|
|
2040
2335
|
displayHint: "这两项只管输入框下方那一行的积分与排队两段;中间那段「Provider CodeArts · Model 模型 · 倍率」一直显示,不受开关影响。底部那条每 60 秒读一次设置,所以关掉最多要等一分钟才见效。",
|
|
2041
|
-
displayCreditsToggle: "
|
|
2336
|
+
displayCreditsToggle: "在输入框工具行显示剩余积分(点开可看各账号明细)",
|
|
2042
2337
|
displayQueueToggle: "显示上游排队位置",
|
|
2043
2338
|
displayNotWritable: "这个宿主没给插件开配置存储,开关只能看不能改。",
|
|
2044
2339
|
displayFailed: "保存失败:{message}",
|
|
2340
|
+
displaySidebarTitle: "侧边栏图标",
|
|
2341
|
+
displaySidebarHint: "勾上以后,DSH 左侧那一列图标里会多一个 CodeArts,点它直接在中间列打开当前这一页,不必每次都绕进设置。默认不勾:这列图标是全宿主共用的,每个插件都来占一格很快就挤满了。改完立刻生效,没有保存步骤。",
|
|
2342
|
+
displaySidebarToggle: "在侧边栏图标列显示 CodeArts",
|
|
2045
2343
|
queueDock: "排队第 {position} 位",
|
|
2046
2344
|
queueDockTitle: "上游排队:{model} · 第 {position} 位 / 共 {length} 条",
|
|
2047
2345
|
claimButton: "签到领积分",
|
|
@@ -2052,7 +2350,9 @@ const zh = {
|
|
|
2052
2350
|
claimDone: "已领取 {amount} 积分",
|
|
2053
2351
|
claimAlready: "今日已领,明天再来",
|
|
2054
2352
|
claimUnavailable: "这个账号当前没有可领的签到活动",
|
|
2055
|
-
claimFailed: "领取失败:{message}"
|
|
2353
|
+
claimFailed: "领取失败:{message}",
|
|
2354
|
+
panelBack: "返回对话",
|
|
2355
|
+
panelDesc: "账号、模型开关与用量都在这一页里管,和设置 → 插件里那张卡片是同一份状态。"
|
|
2056
2356
|
};
|
|
2057
2357
|
const en = {
|
|
2058
2358
|
tabLabel: "CodeArts",
|
|
@@ -2116,12 +2416,25 @@ const en = {
|
|
|
2116
2416
|
modelsLoading: "Loading model selection… (if it never appears, make sure you are signed in and DSH was fully restarted)",
|
|
2117
2417
|
usageTitle: "Local usage",
|
|
2118
2418
|
usageToday: "Today",
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2419
|
+
usageRange: "Today {today} · last 30 days {last30}",
|
|
2420
|
+
usageStatTokens: "Today tokens",
|
|
2421
|
+
usageStatIn: "in {n}",
|
|
2422
|
+
usageStatThinking: "thinking {n}",
|
|
2423
|
+
usageTipInput: "Input",
|
|
2424
|
+
usageTipOutput: "Output",
|
|
2425
|
+
usageTipReasoning: "Reasoning",
|
|
2426
|
+
usageTipCached: "Cached",
|
|
2427
|
+
usageTipNoCache: "not reported",
|
|
2428
|
+
usageTipRequests: "Requests",
|
|
2429
|
+
usageTipHit: "Hit rate",
|
|
2430
|
+
usageStatHit: "Cache hit",
|
|
2431
|
+
usageStatRequests: "Today requests",
|
|
2122
2432
|
usageRequests: "{n} request(s)",
|
|
2433
|
+
usageByAccount: "Today by account",
|
|
2123
2434
|
usageRequestCount: "{n} reqs",
|
|
2124
2435
|
usageTokens: "in {prompt} · out {completion}",
|
|
2436
|
+
usageCompact: "in {prompt} · out {completion}",
|
|
2437
|
+
usageCacheHit: "{pct}% cached",
|
|
2125
2438
|
usageAllTime: "All time ({days} days)",
|
|
2126
2439
|
usageByModel: "Today by model",
|
|
2127
2440
|
usageSlots: "Session slots",
|
|
@@ -2148,9 +2461,6 @@ const en = {
|
|
|
2148
2461
|
creditsDockPanelTitle: "CodeArts credits",
|
|
2149
2462
|
creditsDockRefresh: "Refresh credits",
|
|
2150
2463
|
creditsDockRefreshing: "Refreshing…",
|
|
2151
|
-
creditsDockColAccount: "Account",
|
|
2152
|
-
creditsDockColBalance: "Credits left",
|
|
2153
|
-
creditsDockColTokens: "Tokens today",
|
|
2154
2464
|
creditsDockNoTokens: "No requests through the plugin today yet",
|
|
2155
2465
|
creditsDockEmpty: "No credit data yet",
|
|
2156
2466
|
creditsDockExpiring: "{account}: {expiring} credits expire when this cycle ends",
|
|
@@ -2159,12 +2469,15 @@ const en = {
|
|
|
2159
2469
|
dockModel: "Model {model}",
|
|
2160
2470
|
dockNoModel: "No model selected",
|
|
2161
2471
|
tabDisplay: "Display",
|
|
2162
|
-
displayTitle: "
|
|
2472
|
+
displayTitle: "Around the chat input box",
|
|
2163
2473
|
displayHint: "These two only control the credits and queue segments of that line under the input box; the middle “Provider CodeArts · Model … · rate” segments always show. The bar re-reads settings every 60 seconds, so hiding the rest can take up to a minute.",
|
|
2164
|
-
displayCreditsToggle: "Show remaining credits (click
|
|
2474
|
+
displayCreditsToggle: "Show remaining credits in the composer tool row (click for per-account details)",
|
|
2165
2475
|
displayQueueToggle: "Show the upstream queue position",
|
|
2166
2476
|
displayNotWritable: "This host gives the plugin nowhere to persist settings, so the switches are read-only.",
|
|
2167
2477
|
displayFailed: "Failed to save: {message}",
|
|
2478
|
+
displaySidebarTitle: "Sidebar icon",
|
|
2479
|
+
displaySidebarHint: "Once checked, a CodeArts icon joins the icon column on the left of DSH and opens this very page in the middle column, so you do not have to go through Settings each time. Off by default: that column is shared by the whole host, and it fills up quickly if every plugin claims a slot. Takes effect immediately — there is nothing to save.",
|
|
2480
|
+
displaySidebarToggle: "Show CodeArts in the sidebar icon column",
|
|
2168
2481
|
queueDock: "Queued #{position}",
|
|
2169
2482
|
queueDockTitle: "Upstream queue: {model} · position {position} of {length}",
|
|
2170
2483
|
claimButton: "Claim daily credits",
|
|
@@ -2175,13 +2488,32 @@ const en = {
|
|
|
2175
2488
|
claimDone: "Claimed {amount} credits",
|
|
2176
2489
|
claimAlready: "Already claimed today — come back tomorrow",
|
|
2177
2490
|
claimUnavailable: "No check-in campaign available for this account",
|
|
2178
|
-
claimFailed: "Claim failed: {message}"
|
|
2491
|
+
claimFailed: "Claim failed: {message}",
|
|
2492
|
+
panelBack: "Back to chat",
|
|
2493
|
+
panelDesc: "Manage accounts, model switches and usage here — same state as the card under Settings → Plugins."
|
|
2179
2494
|
};
|
|
2180
2495
|
//#endregion
|
|
2181
2496
|
//#region src/client/index.tsx
|
|
2182
2497
|
const name = "dsh-codearts-client";
|
|
2183
2498
|
const inject = ["slots", "locale"];
|
|
2499
|
+
/**
|
|
2500
|
+
* 侧边栏按钮的 id,同时也是中间列面板的 key —— 宿主靠这两个同名值把
|
|
2501
|
+
* 「点了哪一行」和「中间列画哪一页」配对。
|
|
2502
|
+
*/
|
|
2503
|
+
const PANEL_ID = "dsh-codearts";
|
|
2184
2504
|
function apply(ctx) {
|
|
2505
|
+
/**
|
|
2506
|
+
* 回对话页。软取 layout 服务:`ctx.get` 在服务没提供时返回 undefined 而不会抛,
|
|
2507
|
+
* 所以老宿主/非桌面端只是没有返回按钮,不影响整块 client 加载。
|
|
2508
|
+
* 故意不写进 `inject` —— 依赖缺失会让 apply 整个不跑。
|
|
2509
|
+
*/
|
|
2510
|
+
const backToConversation = () => {
|
|
2511
|
+
try {
|
|
2512
|
+
ctx.get("layout")?.selectPanel?.(null);
|
|
2513
|
+
} catch (error) {
|
|
2514
|
+
console.error("[dsh-codearts] failed to switch back to conversation:", error);
|
|
2515
|
+
}
|
|
2516
|
+
};
|
|
2185
2517
|
try {
|
|
2186
2518
|
const namespace = "settings.codearts";
|
|
2187
2519
|
ctx.effect(() => ctx.locale.register(namespace, {
|
|
@@ -2194,13 +2526,105 @@ function apply(ctx) {
|
|
|
2194
2526
|
key: "dsh-codearts",
|
|
2195
2527
|
locale: namespace
|
|
2196
2528
|
}, () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeArtsPluginCard, { t })));
|
|
2529
|
+
ctx.slots.inject("conversation.input.left", () => ctx.slots.register({
|
|
2530
|
+
name: "conversation.input.left",
|
|
2531
|
+
id: "codearts-credits-bar",
|
|
2532
|
+
order: 20,
|
|
2533
|
+
locale: namespace,
|
|
2534
|
+
inject: () => ({
|
|
2535
|
+
t,
|
|
2536
|
+
zone: "bar"
|
|
2537
|
+
})
|
|
2538
|
+
}, CodeArtsCreditDock));
|
|
2197
2539
|
ctx.slots.inject("conversation.composer.dock", () => ctx.slots.register({
|
|
2198
2540
|
name: "conversation.composer.dock",
|
|
2199
2541
|
id: "codearts-credits",
|
|
2200
2542
|
order: 20,
|
|
2201
2543
|
locale: namespace,
|
|
2202
|
-
inject: () => ({
|
|
2544
|
+
inject: () => ({
|
|
2545
|
+
t,
|
|
2546
|
+
zone: "dock"
|
|
2547
|
+
})
|
|
2203
2548
|
}, CodeArtsCreditDock));
|
|
2549
|
+
/** 每次 claim 拿到的 inject disposer;拆的时候逐个调用(连带注销里面的注册)。 */
|
|
2550
|
+
const panelClaims = [];
|
|
2551
|
+
const dropPanelSlots = () => {
|
|
2552
|
+
for (const dispose of panelClaims.splice(0)) try {
|
|
2553
|
+
dispose();
|
|
2554
|
+
} catch (error) {
|
|
2555
|
+
console.error("[dsh-codearts] failed to release sidebar panel:", error);
|
|
2556
|
+
}
|
|
2557
|
+
};
|
|
2558
|
+
const syncPanelRegistration = () => {
|
|
2559
|
+
dropPanelSlots();
|
|
2560
|
+
if (!sidebarPanelWanted()) return;
|
|
2561
|
+
try {
|
|
2562
|
+
panelClaims.push(ctx.slots.inject("sidebar.panellist", () => {
|
|
2563
|
+
try {
|
|
2564
|
+
return ctx.slots.register({
|
|
2565
|
+
name: "sidebar.panellist",
|
|
2566
|
+
id: PANEL_ID,
|
|
2567
|
+
order: 50,
|
|
2568
|
+
label: () => t("tabLabel"),
|
|
2569
|
+
locale: namespace
|
|
2570
|
+
}, CodeArtsPanelIcon);
|
|
2571
|
+
} catch (error) {
|
|
2572
|
+
console.error("[dsh-codearts] sidebar panel entry unavailable:", error);
|
|
2573
|
+
return () => {};
|
|
2574
|
+
}
|
|
2575
|
+
}));
|
|
2576
|
+
} catch (error) {
|
|
2577
|
+
console.error("[dsh-codearts] sidebar panel slot unavailable:", error);
|
|
2578
|
+
}
|
|
2579
|
+
try {
|
|
2580
|
+
panelClaims.push(ctx.slots.inject("main", () => {
|
|
2581
|
+
try {
|
|
2582
|
+
return ctx.slots.register({
|
|
2583
|
+
name: "main",
|
|
2584
|
+
key: PANEL_ID,
|
|
2585
|
+
locale: namespace,
|
|
2586
|
+
inject: () => ({
|
|
2587
|
+
t,
|
|
2588
|
+
backToConversation
|
|
2589
|
+
})
|
|
2590
|
+
}, CodeArtsPanelPage);
|
|
2591
|
+
} catch (error) {
|
|
2592
|
+
console.error("[dsh-codearts] main panel page unavailable:", error);
|
|
2593
|
+
return () => {};
|
|
2594
|
+
}
|
|
2595
|
+
}));
|
|
2596
|
+
} catch (error) {
|
|
2597
|
+
console.error("[dsh-codearts] main panel slot unavailable:", error);
|
|
2598
|
+
}
|
|
2599
|
+
};
|
|
2600
|
+
/**
|
|
2601
|
+
* 开关关掉时如果用户正站在那一页上,先回对话 —— 否则中间列会留在
|
|
2602
|
+
* 一个已经没了的 key 上。软取 layout:没有这个服务就跳过。
|
|
2603
|
+
*/
|
|
2604
|
+
const leavePanelIfActive = () => {
|
|
2605
|
+
try {
|
|
2606
|
+
const layout = ctx.get("layout");
|
|
2607
|
+
if (layout?.panelInfo?.getSnapshot?.()?.activePanelId === PANEL_ID) layout.selectPanel?.(null);
|
|
2608
|
+
} catch {}
|
|
2609
|
+
};
|
|
2610
|
+
ctx.effect(() => {
|
|
2611
|
+
const off = subscribeSidebarPanelWanted(() => {
|
|
2612
|
+
if (!sidebarPanelWanted()) leavePanelIfActive();
|
|
2613
|
+
syncPanelRegistration();
|
|
2614
|
+
});
|
|
2615
|
+
syncPanelRegistration();
|
|
2616
|
+
return () => {
|
|
2617
|
+
off();
|
|
2618
|
+
dropPanelSlots();
|
|
2619
|
+
};
|
|
2620
|
+
}, "dsh-codearts: sidebar panel opt-in");
|
|
2621
|
+
(async () => {
|
|
2622
|
+
try {
|
|
2623
|
+
const res = await fetch("/api/codearts/dock", { headers: { Accept: "application/json" } });
|
|
2624
|
+
if (!res.ok) return;
|
|
2625
|
+
setSidebarPanelWanted((await res.json()).dock?.sidebar === true);
|
|
2626
|
+
} catch {}
|
|
2627
|
+
})();
|
|
2204
2628
|
} catch (error) {
|
|
2205
2629
|
console.error("[dsh-codearts] client card failed to load (host provider unaffected):", error);
|
|
2206
2630
|
}
|