dsh-thinking-guard 0.1.20 → 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/lib/client.d.ts +13 -1
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +1820 -914
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -2687,7 +2687,7 @@ async function waitForMcpTools(remote, serverName, retryDelays) {
|
|
|
2687
2687
|
* second enable switch here.
|
|
2688
2688
|
*/
|
|
2689
2689
|
const CSS_ID$1 = "capability-menu-location-css";
|
|
2690
|
-
const CSS$
|
|
2690
|
+
const CSS$2 = `
|
|
2691
2691
|
.lm-block{display:flex;flex-direction:column;gap:8px}
|
|
2692
2692
|
.lm-btn{border:1px solid var(--dsw-alias-border-l2);border-radius:6px;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);font:inherit;font-size:12px;line-height:20px;padding:0 10px;cursor:pointer;white-space:nowrap}
|
|
2693
2693
|
.lm-btn:hover{border-color:var(--dsw-alias-border-l3);background:var(--dsw-alias-interactive-bg-hover)}
|
|
@@ -2731,7 +2731,7 @@ textarea.lm-input{resize:vertical;font-family:var(--dsw-font-markdown-code-block
|
|
|
2731
2731
|
if (typeof document !== "undefined" && document.querySelector(`style[data-css-id="${CSS_ID$1}"]`) === null) {
|
|
2732
2732
|
const tag = document.createElement("style");
|
|
2733
2733
|
tag.dataset.cssId = CSS_ID$1;
|
|
2734
|
-
tag.textContent = CSS$
|
|
2734
|
+
tag.textContent = CSS$2;
|
|
2735
2735
|
document.head.appendChild(tag);
|
|
2736
2736
|
}
|
|
2737
2737
|
/** Render a key/value map as `Key: Value` lines. */
|
|
@@ -3228,6 +3228,196 @@ function LocationModal(props) {
|
|
|
3228
3228
|
})]
|
|
3229
3229
|
});
|
|
3230
3230
|
}
|
|
3231
|
+
//#endregion
|
|
3232
|
+
//#region src/client/v3-ui.ts
|
|
3233
|
+
/**
|
|
3234
|
+
* v3 设计层(D-044)——设置页四个子页面共用的 token、容器脚手架与块级词汇表。
|
|
3235
|
+
*
|
|
3236
|
+
* WHY A SHARED MODULE: v3 的视觉识别来自一套统一的 token 与块(panel / stats /
|
|
3237
|
+
* board / rank / table / gitem / catstat)。四个页面各写一份必然漂移,所以跨页面
|
|
3238
|
+
* 复用的部分集中在这里;页面专属样式仍留在各自文件里(call-index.tsx 的
|
|
3239
|
+
* `CallIndexStyles()`、CapabilitySection.tsx 的 mc-* 样式块)。
|
|
3240
|
+
*
|
|
3241
|
+
* CONTAINER, NOT VIEWPORT: 设置面板是宿主写死的 800px 弹窗,内容列只有 564px,
|
|
3242
|
+
* 与视口宽度无关(D-044 实测)。因此 v3 的断点全部写成 `@container v3`,页面根
|
|
3243
|
+
* 节点加上 `v3-root` 即成为容器。用 `@media` 会在 1200px 窗口里误判成「宽」,
|
|
3244
|
+
* 画出实际放不下的双栏。
|
|
3245
|
+
*
|
|
3246
|
+
* THEME: v3 原始 CSS 写死深色;这里全部映射到宿主 `--dsw-alias-*`,深浅色跟随
|
|
3247
|
+
* 应用。卡片底色用「label-primary 的 4% 叠在 bg-layer-2 上」而不是半透明白,
|
|
3248
|
+
* 否则浅色主题下会发脏。
|
|
3249
|
+
*
|
|
3250
|
+
* 本模块只输出样式与一个 style 元素,不假设任何 DOM 结构。
|
|
3251
|
+
*/
|
|
3252
|
+
/** Every rule the v3 pages share. Class names are global like the existing mc-*. */
|
|
3253
|
+
const CSS$1 = [
|
|
3254
|
+
".v3-root{container:v3 / inline-size;--v3-bg:var(--dsw-alias-bg-layer-2,Canvas);--v3-panel:color-mix(in srgb,var(--dsw-alias-label-primary,CanvasText) 4%,var(--dsw-alias-bg-layer-2,Canvas));--v3-panel-2:color-mix(in srgb,var(--dsw-alias-label-primary,CanvasText) 8%,var(--dsw-alias-bg-layer-2,Canvas));--v3-line:color-mix(in srgb,var(--dsw-alias-label-primary,CanvasText) 10%,transparent);--v3-line-2:color-mix(in srgb,var(--dsw-alias-label-primary,CanvasText) 17%,transparent);--v3-t1:var(--dsw-alias-label-primary,CanvasText);--v3-t2:var(--dsw-alias-label-secondary,var(--dsw-alias-label-primary,CanvasText));--v3-t3:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary,CanvasText));--v3-t4:var(--dsw-alias-label-caption,var(--dsw-alias-label-tertiary,CanvasText));--v3-ok:var(--dsw-alias-state-success-primary,#18894a);--v3-bad:var(--dsw-alias-state-error-primary,#c92b2b);--v3-warn:var(--dsw-alias-state-warn-primary,#a2730a);--v3-info:var(--dsw-alias-link,var(--dsw-alias-brand-primary,#2066c4));--v3-ok-dim:color-mix(in srgb,var(--v3-ok) 16%,transparent);--v3-bad-dim:color-mix(in srgb,var(--v3-bad) 14%,transparent);--v3-warn-dim:color-mix(in srgb,var(--v3-warn) 14%,transparent);--v3-info-dim:color-mix(in srgb,var(--v3-info) 14%,transparent);--v3-r-sm:var(--dsw-radius-sm,6px);--v3-r-md:var(--dsw-radius-md,9px);--v3-r-lg:var(--dsw-radius-lg,12px);--v3-font-code:var(--dsw-font-markdown-code-font-family,ui-monospace,SFMono-Regular,Menlo,Consolas,monospace);color:var(--v3-t1);font-size:13px;line-height:20px}",
|
|
3255
|
+
".v3-num{font-variant-numeric:tabular-nums}",
|
|
3256
|
+
".v3-mono{font-family:var(--v3-font-code)}",
|
|
3257
|
+
".v3-statusline{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--v3-t3);padding:5px 10px;border-radius:999px;background:var(--v3-panel);border:1px solid var(--v3-line);min-width:0}",
|
|
3258
|
+
".v3-statusline b{color:var(--v3-t1);font-weight:600}",
|
|
3259
|
+
".v3-statusline[data-tone='bad']{background:var(--v3-bad-dim);border-color:color-mix(in srgb,var(--v3-bad) 30%,transparent)}",
|
|
3260
|
+
".v3-dot{display:inline-block;width:7px;height:7px;border-radius:50%;flex:none;background:var(--v3-t4)}",
|
|
3261
|
+
".v3-dot[data-tone='ok']{background:var(--v3-ok);box-shadow:0 0 0 3px var(--v3-ok-dim)}",
|
|
3262
|
+
".v3-dot[data-tone='bad']{background:var(--v3-bad);box-shadow:0 0 0 3px var(--v3-bad-dim)}",
|
|
3263
|
+
".v3-dot[data-tone='warn']{background:var(--v3-warn);box-shadow:0 0 0 3px var(--v3-warn-dim)}",
|
|
3264
|
+
".v3-dot[data-tone='run']{width:8px;height:8px;background:transparent;border:1.5px solid var(--v3-t3);border-top-color:transparent;animation:v3-spin .9s linear infinite;box-shadow:none}",
|
|
3265
|
+
"@keyframes v3-spin{to{transform:rotate(360deg)}}",
|
|
3266
|
+
".v3-panel{background:var(--v3-panel);border:1px solid var(--v3-line);border-radius:var(--v3-r-lg);padding:13px 15px;min-width:0}",
|
|
3267
|
+
".v3-ph{display:flex;align-items:center;gap:8px;margin-bottom:11px;min-height:18px;flex-wrap:wrap}",
|
|
3268
|
+
".v3-pt{margin:0;font-size:11px;font-weight:600;color:var(--v3-t3);letter-spacing:.07em;text-transform:uppercase}",
|
|
3269
|
+
".v3-pn{margin-left:auto;font-size:11px;color:var(--v3-t4);white-space:nowrap;text-transform:none;letter-spacing:0}",
|
|
3270
|
+
".v3-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;background:var(--v3-line);border:1px solid var(--v3-line);border-radius:var(--v3-r-lg);overflow:hidden}",
|
|
3271
|
+
".v3-stat{background:var(--v3-panel);padding:13px 15px;min-width:0}",
|
|
3272
|
+
".v3-stat-l{font-size:11px;color:var(--v3-t3);letter-spacing:.02em}",
|
|
3273
|
+
".v3-stat-v{font-size:26px;line-height:34px;font-weight:650;letter-spacing:-.025em;margin-top:3px;font-variant-numeric:tabular-nums}",
|
|
3274
|
+
".v3-stat-v small{font-size:12px;font-weight:400;color:var(--v3-t3);margin-left:4px;letter-spacing:0}",
|
|
3275
|
+
".v3-stat-d{font-size:11px;color:var(--v3-t4);margin-top:2px;display:flex;align-items:center;gap:5px}",
|
|
3276
|
+
".v3-spark{margin-top:8px;display:block;width:100%;height:22px;overflow:visible}",
|
|
3277
|
+
".v3-spark .v3-spark-ln{fill:none;stroke-width:1.4;stroke-linejoin:round;stroke-linecap:round}",
|
|
3278
|
+
".v3-spark .v3-spark-fl{opacity:.14}",
|
|
3279
|
+
".v3-board{display:grid;grid-template-columns:minmax(0,2.15fr) minmax(0,1fr);gap:12px;align-items:stretch}",
|
|
3280
|
+
".v3-chartbox{position:relative;min-width:0}",
|
|
3281
|
+
".v3-chart{display:block;width:100%;height:212px;overflow:visible}",
|
|
3282
|
+
".v3-chart .v3-grid{stroke:var(--v3-line);stroke-width:1}",
|
|
3283
|
+
".v3-chart .v3-axis{fill:var(--v3-t4);font-size:9.5px}",
|
|
3284
|
+
".v3-chart .v3-area{fill:var(--v3-info);opacity:.13}",
|
|
3285
|
+
".v3-chart .v3-line{fill:none;stroke:var(--v3-info);stroke-width:1.8;stroke-linejoin:round;stroke-linecap:round}",
|
|
3286
|
+
".v3-chart .v3-pt{fill:var(--v3-panel);stroke:var(--v3-info);stroke-width:1.6}",
|
|
3287
|
+
".v3-chart .v3-bar-er{fill:var(--v3-bad);opacity:.85}",
|
|
3288
|
+
".v3-chart .v3-hlbox{fill:var(--v3-info-dim);stroke:var(--v3-info);stroke-width:1;stroke-dasharray:3 3}",
|
|
3289
|
+
".v3-chart .v3-lbl{fill:var(--v3-t2);font-size:10px}",
|
|
3290
|
+
".v3-chart .v3-lbl-b{fill:var(--v3-t1);font-size:10.5px;font-weight:600}",
|
|
3291
|
+
".v3-legend{display:flex;gap:16px;margin-top:8px;font-size:11px;color:var(--v3-t4);flex-wrap:wrap}",
|
|
3292
|
+
".v3-legend span{display:inline-flex;align-items:center;gap:6px}",
|
|
3293
|
+
".v3-legend i{width:14px;height:2px;border-radius:1px;flex:none;background:var(--v3-info)}",
|
|
3294
|
+
".v3-legend i[data-mark='square']{width:8px;height:8px;border-radius:2px;background:var(--v3-bad)}",
|
|
3295
|
+
".v3-donut-wrap{display:flex;align-items:center;gap:14px;flex-wrap:wrap}",
|
|
3296
|
+
".v3-donut{flex:none;width:104px;height:104px;position:relative}",
|
|
3297
|
+
".v3-donut svg{width:104px;height:104px;transform:rotate(-90deg)}",
|
|
3298
|
+
".v3-donut .v3-trk{fill:none;stroke:var(--v3-panel-2);stroke-width:9}",
|
|
3299
|
+
".v3-donut .v3-seg{fill:none;stroke:var(--v3-t4);stroke-width:9}",
|
|
3300
|
+
".v3-donut .v3-mid{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;pointer-events:none}",
|
|
3301
|
+
".v3-donut .v3-mid b{font-size:17px;font-weight:650;letter-spacing:-.02em;line-height:20px}",
|
|
3302
|
+
".v3-donut .v3-mid span{font-size:9.5px;color:var(--v3-t4);line-height:12px;letter-spacing:.04em}",
|
|
3303
|
+
".v3-src-list{flex:1 1 180px;min-width:0;display:flex;flex-direction:column;gap:5px}",
|
|
3304
|
+
".v3-src{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--v3-t2);min-width:0}",
|
|
3305
|
+
".v3-src i{width:7px;height:7px;border-radius:2px;flex:none;background:var(--v3-t4);opacity:.5}",
|
|
3306
|
+
".v3-src .v3-nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}",
|
|
3307
|
+
".v3-src b{margin-left:auto;color:var(--v3-t1);font-weight:600;font-variant-numeric:tabular-nums}",
|
|
3308
|
+
".v3-src em{font-style:normal;color:var(--v3-t4);min-width:44px;text-align:right;font-variant-numeric:tabular-nums;font-size:11px}",
|
|
3309
|
+
".v3-src-note{margin:9px 0 0;padding-top:9px;border-top:1px solid var(--v3-line);font-size:11px;line-height:17px;color:var(--v3-t4)}",
|
|
3310
|
+
".v3-rank{display:flex;flex-direction:column;gap:1px;margin-top:-2px}",
|
|
3311
|
+
".v3-rank-row{display:flex;align-items:center;gap:9px;min-height:27px;font-size:12px;padding:0 2px;border-radius:4px}",
|
|
3312
|
+
".v3-rank-row:hover{background:var(--v3-panel-2)}",
|
|
3313
|
+
".v3-rank-row .v3-nm{font-family:var(--v3-font-code);font-size:11.5px;color:var(--v3-t2);width:158px;flex:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}",
|
|
3314
|
+
".v3-rank-row .v3-bar{flex:1 1 auto;min-width:30px;height:6px;background:var(--v3-panel-2);border-radius:3px;position:relative;overflow:hidden}",
|
|
3315
|
+
".v3-rank-row .v3-bar span{position:absolute;left:0;top:0;bottom:0;min-width:3px;background:var(--v3-info);opacity:.65;border-radius:3px}",
|
|
3316
|
+
".v3-rank-row .v3-bar span[data-bad='true']{background:var(--v3-bad);opacity:.85}",
|
|
3317
|
+
".v3-rank-row .v3-n{width:52px;flex:none;text-align:right;font-variant-numeric:tabular-nums;color:var(--v3-t2);white-space:nowrap}",
|
|
3318
|
+
".v3-rank-row .v3-e{flex:none;text-align:right;font-variant-numeric:tabular-nums;font-size:11px;color:var(--v3-t4);white-space:nowrap}",
|
|
3319
|
+
".v3-rank-row .v3-e[data-bad='true']{color:var(--v3-bad);font-weight:600}",
|
|
3320
|
+
".v3-ts{max-height:min(60vh,560px);overflow:auto;overscroll-behavior:contain;border-top:1px solid var(--v3-line)}",
|
|
3321
|
+
".v3-table{width:100%;border-collapse:separate;border-spacing:0;font-size:12.5px}",
|
|
3322
|
+
".v3-table thead th{position:sticky;top:0;z-index:2;background:var(--v3-panel);color:var(--v3-t4);font-weight:500;font-size:10.5px;letter-spacing:.05em;text-transform:uppercase;text-align:left;padding:0 11px;height:29px;white-space:nowrap;border-bottom:1px solid var(--v3-line)}",
|
|
3323
|
+
".v3-table thead th.v3-r{text-align:right}",
|
|
3324
|
+
".v3-table tbody td{padding:0 11px;height:32px;border-bottom:1px solid var(--v3-line);vertical-align:middle;white-space:nowrap}",
|
|
3325
|
+
".v3-table tbody tr:last-child td{border-bottom:0}",
|
|
3326
|
+
".v3-table tbody tr:hover td{background:var(--v3-panel-2)}",
|
|
3327
|
+
".v3-table td.v3-r{text-align:right;font-variant-numeric:tabular-nums;color:var(--v3-t2)}",
|
|
3328
|
+
".v3-c-tool{display:flex;align-items:center;gap:7px;min-width:0}",
|
|
3329
|
+
".v3-c-tool .v3-nm{font-family:var(--v3-font-code);font-size:11.5px;overflow:hidden;text-overflow:ellipsis}",
|
|
3330
|
+
".v3-c-tool .v3-srv{font-size:10.5px;color:var(--v3-t4)}",
|
|
3331
|
+
".v3-srcnote{flex:none;font-size:9px;line-height:13px;height:13px;padding:0 4px;border-radius:3px;color:var(--v3-t4);background:var(--v3-panel-2)}",
|
|
3332
|
+
".v3-rt{display:inline-flex;align-items:center;gap:7px;justify-content:flex-end}",
|
|
3333
|
+
".v3-rt .v3-tk{width:34px;height:3px;border-radius:2px;background:var(--v3-panel-2);overflow:hidden;flex:none}",
|
|
3334
|
+
".v3-rt .v3-fl{display:block;height:100%;background:var(--v3-ok);border-radius:2px}",
|
|
3335
|
+
".v3-rt .v3-fl[data-bad='true']{background:var(--v3-bad)}",
|
|
3336
|
+
".v3-rt b{font-weight:500;min-width:40px;text-align:right;font-variant-numeric:tabular-nums}",
|
|
3337
|
+
".v3-tfoot{display:flex;align-items:center;gap:9px;padding:9px 15px;border-top:1px solid var(--v3-line);color:var(--v3-t4);font-size:11px;flex-wrap:wrap}",
|
|
3338
|
+
".v3-empty{background:var(--v3-panel);border:1px solid var(--v3-line);border-radius:var(--v3-r-lg);padding:34px 24px;text-align:center}",
|
|
3339
|
+
".v3-empty h3{margin:0 0 5px;font-size:14px;font-weight:600;color:var(--v3-t1)}",
|
|
3340
|
+
".v3-empty p{margin:0 auto;max-width:56ch;font-size:12.5px;line-height:20px;color:var(--v3-t3)}",
|
|
3341
|
+
".v3-banner{display:flex;align-items:flex-start;gap:10px;padding:11px 13px;border-radius:var(--v3-r-md);background:var(--v3-bad-dim);border:1px solid color-mix(in srgb,var(--v3-bad) 32%,transparent);font-size:12px;line-height:19px;color:var(--v3-t2)}",
|
|
3342
|
+
".v3-banner b{display:block;font-size:12.5px;margin-bottom:2px;color:var(--v3-t1)}",
|
|
3343
|
+
".v3-banner code{font-family:var(--v3-font-code);font-size:10.5px;padding:1px 5px;border-radius:3px;background:var(--v3-panel-2);color:var(--v3-t3);margin-left:5px}",
|
|
3344
|
+
".v3-faultcard{background:var(--v3-panel);border:1px solid var(--v3-line);border-left:3px solid var(--v3-bad);border-radius:var(--v3-r-md);overflow:hidden}",
|
|
3345
|
+
".v3-faultcard .v3-fh{display:flex;align-items:center;gap:8px;padding:9px 13px}",
|
|
3346
|
+
".v3-faultcard .v3-fh b{font-size:12.5px;font-weight:600}",
|
|
3347
|
+
".v3-faultcard .v3-fh code{font-family:var(--v3-font-code);font-size:10.5px;padding:1px 5px;border-radius:3px;background:var(--v3-panel-2);color:var(--v3-t3)}",
|
|
3348
|
+
".v3-faultcard p{margin:0;padding:0 13px 9px;font-size:11.5px;line-height:18px;color:var(--v3-t3)}",
|
|
3349
|
+
".v3-gpanel{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px}",
|
|
3350
|
+
".v3-gitem{background:var(--v3-panel);border:1px solid var(--v3-line);border-radius:var(--v3-r-lg);padding:13px 15px;min-width:0}",
|
|
3351
|
+
".v3-gitem .v3-gh{display:flex;align-items:center;gap:8px;margin-bottom:7px;flex-wrap:wrap}",
|
|
3352
|
+
".v3-gitem .v3-gnm{font-size:13px;font-weight:600}",
|
|
3353
|
+
".v3-gitem .v3-gid{font-family:var(--v3-font-code);font-size:10.5px;color:var(--v3-t4)}",
|
|
3354
|
+
".v3-gitem p{margin:0;font-size:11.5px;line-height:18px;color:var(--v3-t3)}",
|
|
3355
|
+
".v3-gitem .v3-gfoot{display:flex;align-items:center;gap:6px;margin-top:9px;font-size:10.5px;color:var(--v3-t4);padding-top:9px;border-top:1px solid var(--v3-line);flex-wrap:wrap}",
|
|
3356
|
+
".v3-kbd{font-family:var(--v3-font-code);font-size:10.5px;padding:1px 5px;border-radius:3px;background:var(--v3-panel-2);color:var(--v3-t2);border:1px solid var(--v3-line)}",
|
|
3357
|
+
".v3-notebox{margin:0;padding:11px 13px;border-radius:var(--v3-r-md);background:var(--v3-panel);border:1px solid var(--v3-line);color:var(--v3-t3);font-size:11.5px;line-height:18px}",
|
|
3358
|
+
".v3-notebox b{color:var(--v3-t2);font-weight:600}",
|
|
3359
|
+
".v3-sw{position:relative;width:34px;height:19px;border:0;border-radius:999px;padding:0;cursor:pointer;flex:none;background:color-mix(in srgb,var(--dsw-alias-label-primary,CanvasText) 16%,transparent);transition:background .16s}",
|
|
3360
|
+
".v3-sw::after{content:'';position:absolute;top:2px;left:2px;width:15px;height:15px;border-radius:50%;background:var(--dsw-alias-switch-thumb,var(--v3-bg));transition:transform .16s}",
|
|
3361
|
+
".v3-sw[aria-checked='true']{background:var(--v3-ok)}",
|
|
3362
|
+
".v3-sw[aria-checked='true']::after{transform:translateX(15px)}",
|
|
3363
|
+
".v3-sw:disabled{opacity:.55;cursor:default}",
|
|
3364
|
+
".v3-sw:focus-visible{outline:2px solid var(--v3-info);outline-offset:2px}",
|
|
3365
|
+
".v3-catgrid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px}",
|
|
3366
|
+
".v3-catstat{display:flex;background:var(--v3-panel);border:1px solid var(--v3-line);border-radius:var(--v3-r-lg);overflow:hidden;margin-bottom:12px}",
|
|
3367
|
+
".v3-catstat>div{flex:1 1 0;padding:11px 14px;min-width:0}",
|
|
3368
|
+
".v3-catstat>div+div{border-left:1px solid var(--v3-line)}",
|
|
3369
|
+
".v3-catstat .v3-l{font-size:10.5px;color:var(--v3-t4);letter-spacing:.05em;text-transform:uppercase}",
|
|
3370
|
+
".v3-catstat .v3-v{font-size:19px;font-weight:650;margin-top:2px;letter-spacing:-.02em;font-variant-numeric:tabular-nums}",
|
|
3371
|
+
".v3-catstat .v3-v small{font-size:11px;font-weight:400;color:var(--v3-t3);margin-left:4px;letter-spacing:0}",
|
|
3372
|
+
".v3-group{background:var(--v3-panel);border:1px solid var(--v3-line);border-radius:var(--v3-r-md);overflow:hidden;margin-bottom:10px;min-width:0}",
|
|
3373
|
+
".v3-group:last-child{margin-bottom:0}",
|
|
3374
|
+
".v3-group>summary{display:flex;align-items:center;gap:8px;padding:9px 12px;cursor:pointer;list-style:none;min-height:36px;flex-wrap:wrap}",
|
|
3375
|
+
".v3-group>summary::-webkit-details-marker{display:none}",
|
|
3376
|
+
".v3-group>summary:hover{background:var(--v3-panel-2)}",
|
|
3377
|
+
".v3-group[open]>summary{border-bottom:1px solid var(--v3-line)}",
|
|
3378
|
+
".v3-group>summary .v3-chev{width:10px;height:10px;color:var(--v3-t4);flex:none;transition:transform .14s}",
|
|
3379
|
+
".v3-group[open]>summary .v3-chev{transform:rotate(90deg)}",
|
|
3380
|
+
".v3-group>summary .v3-gnm{font-size:12.5px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}",
|
|
3381
|
+
".v3-group>summary .v3-cnt{font-size:10.5px;color:var(--v3-t4);flex:none}",
|
|
3382
|
+
".v3-group>summary .v3-right{margin-left:auto;display:flex;gap:4px;align-items:center;flex:none}",
|
|
3383
|
+
".v3-trow{display:flex;align-items:center;gap:8px;padding:0 12px 0 29px;min-height:30px;border-top:1px solid var(--v3-line);font-size:12px;min-width:0}",
|
|
3384
|
+
".v3-trow:first-of-type{border-top:0}",
|
|
3385
|
+
".v3-trow:hover{background:var(--v3-panel-2)}",
|
|
3386
|
+
".v3-trow .v3-nm{font-family:var(--v3-font-code);font-size:11.5px;flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}",
|
|
3387
|
+
".v3-trow .v3-uses{flex:none;font-size:11px;color:var(--v3-t4);font-variant-numeric:tabular-nums;white-space:nowrap}",
|
|
3388
|
+
".v3-tag{display:inline-flex;align-items:center;gap:4px;height:17px;padding:0 6px;border-radius:4px;font-size:10px;line-height:17px;white-space:nowrap;color:var(--v3-t3);background:var(--v3-panel-2)}",
|
|
3389
|
+
".v3-tag[data-tone='info']{color:var(--v3-info);background:var(--v3-info-dim)}",
|
|
3390
|
+
".v3-tag[data-tone='warn']{color:var(--v3-warn);background:var(--v3-warn-dim)}",
|
|
3391
|
+
".v3-tag[data-tone='bad']{color:var(--v3-bad);background:var(--v3-bad-dim)}",
|
|
3392
|
+
".v3-hint{margin:0;font-size:11px;line-height:17px;color:var(--v3-t4)}",
|
|
3393
|
+
".v3-scopehint{display:flex;align-items:center;gap:7px;margin-top:9px;padding:6px 10px;border-radius:var(--v3-r-sm);background:var(--v3-panel-2);font-size:11.5px;line-height:17px;color:var(--v3-t3);flex-wrap:wrap}",
|
|
3394
|
+
".v3-scopehint .v3-id{font-family:var(--v3-font-code);font-size:11px;color:var(--v3-t2);padding:1px 5px;border-radius:3px;background:var(--v3-panel);border:1px solid var(--v3-line)}",
|
|
3395
|
+
".v3-scopehint[data-tone='warn']{background:var(--v3-warn-dim);color:var(--v3-t2)}",
|
|
3396
|
+
".v3-scan{display:flex;align-items:center;gap:10px;margin-top:9px;font-size:11.5px;color:var(--v3-t3)}",
|
|
3397
|
+
".v3-scan .v3-track{position:relative;flex:1 1 auto;height:5px;border-radius:3px;background:var(--v3-panel-2);overflow:hidden;min-width:70px}",
|
|
3398
|
+
".v3-scan .v3-fill{position:absolute;inset:0 auto 0 0;background:var(--v3-info);border-radius:3px;transition:width .3s ease}",
|
|
3399
|
+
".v3-scan[data-running='true'] .v3-fill{width:34% !important;animation:v3-indet 1.25s ease-in-out infinite}",
|
|
3400
|
+
"@keyframes v3-indet{0%{left:-34%}100%{left:100%}}",
|
|
3401
|
+
".v3-scan .v3-pct{font-variant-numeric:tabular-nums;color:var(--v3-t2);font-weight:600;min-width:38px;text-align:right}",
|
|
3402
|
+
"@container v3 (max-width:980px){.v3-board{grid-template-columns:minmax(0,1fr)}}",
|
|
3403
|
+
"@container v3 (max-width:900px){.v3-gpanel,.v3-catgrid{grid-template-columns:minmax(0,1fr)}}",
|
|
3404
|
+
"@container v3 (max-width:720px){.v3-stats{grid-template-columns:repeat(2,minmax(0,1fr))}.v3-catstat{flex-wrap:wrap}.v3-catstat>div{flex:1 1 45%}.v3-catstat>div+div{border-left:0}}",
|
|
3405
|
+
"@container v3 (max-width:620px){.v3-rank-row .v3-nm{width:104px}}",
|
|
3406
|
+
"@media (prefers-reduced-motion:reduce){.v3-dot[data-tone='run'],.v3-scan[data-running='true'] .v3-fill{animation:none}}",
|
|
3407
|
+
"[hidden]{display:none !important}"
|
|
3408
|
+
].join("");
|
|
3409
|
+
/**
|
|
3410
|
+
* Mount the shared v3 stylesheet once per document.
|
|
3411
|
+
*
|
|
3412
|
+
* React does not dedupe <style> elements across the four pages, and all four
|
|
3413
|
+
* render their own root, so the element carries a marker attribute and an
|
|
3414
|
+
* identical copy in the DOM is harmless. Kept as an element (not a singleton
|
|
3415
|
+
* side effect at import time) so the hook-free views stay pure and the test
|
|
3416
|
+
* suite can still walk the tree.
|
|
3417
|
+
*/
|
|
3418
|
+
function V3Styles() {
|
|
3419
|
+
return (0, react.createElement)("style", { "data-v3-style": "true" }, CSS$1);
|
|
3420
|
+
}
|
|
3231
3421
|
/**
|
|
3232
3422
|
* dsh's source labels for a project's own skill roots — the `project`-prefixed
|
|
3233
3423
|
* providers of `@deepseek-ai/dsh-skill-filesystem`, which scan
|
|
@@ -3717,6 +3907,18 @@ body[data-ds-dark-theme] .mc-count--disabled{color:#b8abad}
|
|
|
3717
3907
|
.mc-guard-switch--on{background:var(--dsw-alias-state-business-primary)}
|
|
3718
3908
|
.mc-guard-switch--on::after{transform:translateX(14px)}
|
|
3719
3909
|
.mc-guard-switch:disabled{opacity:.5;cursor:not-allowed}
|
|
3910
|
+
/* ---- v3 工具与技能(V3-c):仅新增,不改动上面任何 .mc-* / .mc-guard-* ---- */
|
|
3911
|
+
.v3-dot[data-tone='info']{background:var(--v3-info)}
|
|
3912
|
+
.v3-trow{cursor:pointer}
|
|
3913
|
+
.v3-trow:focus-visible{outline:2px solid var(--v3-info);outline-offset:-2px}
|
|
3914
|
+
.v3-racts{display:flex;align-items:center;gap:4px;margin-left:auto;flex:none}
|
|
3915
|
+
.v3-uses-bad{color:var(--v3-bad)}
|
|
3916
|
+
button.v3-tag.v3-tag--act{color:var(--v3-t3);background:transparent}
|
|
3917
|
+
button.v3-tag.v3-tag--act:hover{color:var(--v3-t1);background:var(--v3-panel-2)}
|
|
3918
|
+
button.v3-tag{border:0;cursor:pointer;font-family:inherit}
|
|
3919
|
+
button.v3-tag:disabled{opacity:.55;cursor:default}
|
|
3920
|
+
.v3-group>summary:focus-visible{outline:2px solid var(--v3-info);outline-offset:-2px}
|
|
3921
|
+
.v3-tools{display:flex;flex-direction:column}
|
|
3720
3922
|
`;
|
|
3721
3923
|
if (typeof document !== "undefined" && document.querySelector(`style[data-css-id="${CSS_ID}"]`) === null) {
|
|
3722
3924
|
const tag = document.createElement("style");
|
|
@@ -3794,7 +3996,7 @@ function MarkdownFilePreview(props) {
|
|
|
3794
3996
|
* `node_modules`, because the panel said nothing about itself. The value is
|
|
3795
3997
|
* inlined by `tsdown` (see `src/client/env.d.ts`).
|
|
3796
3998
|
*/
|
|
3797
|
-
const PLUGIN_VERSION = "0.1.
|
|
3999
|
+
const PLUGIN_VERSION = "0.1.21";
|
|
3798
4000
|
const PLUGIN_TITLE = `capability-menu v${PLUGIN_VERSION}`;
|
|
3799
4001
|
/**
|
|
3800
4002
|
* dsh's skill source labels, shown on rows this plugin cannot edit — so "why is
|
|
@@ -3821,6 +4023,200 @@ function sourceLabel(source, t) {
|
|
|
3821
4023
|
const key = SOURCE_LABEL_KEYS[source];
|
|
3822
4024
|
return key === void 0 ? source : t(key);
|
|
3823
4025
|
}
|
|
4026
|
+
/** Tone of a class chip / state dot, mapped to the v3 `data-tone` palette. */
|
|
4027
|
+
const CLASS_TONE = {
|
|
4028
|
+
resident: "info",
|
|
4029
|
+
"on-demand": "warn",
|
|
4030
|
+
disabled: "bad"
|
|
4031
|
+
};
|
|
4032
|
+
/** State-dot tone inside a row: resident=info, on-demand=warn, disabled=neutral. */
|
|
4033
|
+
const CLASS_DOT_TONE = {
|
|
4034
|
+
resident: "info",
|
|
4035
|
+
"on-demand": "warn",
|
|
4036
|
+
disabled: ""
|
|
4037
|
+
};
|
|
4038
|
+
/** The four-cell `.v3-catstat` strip at the top of the catalog page. */
|
|
4039
|
+
function CatalogStatStrip(props) {
|
|
4040
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4041
|
+
className: "v3-catstat",
|
|
4042
|
+
"data-v3-catstat": "true",
|
|
4043
|
+
children: props.cells.map((cell, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4044
|
+
className: "v3-l",
|
|
4045
|
+
children: cell.label
|
|
4046
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4047
|
+
className: "v3-v",
|
|
4048
|
+
children: [cell.value, cell.hint !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: cell.hint }) : null]
|
|
4049
|
+
})] }, index))
|
|
4050
|
+
});
|
|
4051
|
+
}
|
|
4052
|
+
/** Zero-call capability count when a usage map exists, else an honest dash. */
|
|
4053
|
+
function zeroCallCount(usage, rows) {
|
|
4054
|
+
if (usage === void 0) return "—";
|
|
4055
|
+
return rows.filter((row) => {
|
|
4056
|
+
const entry = usage.get(row.id);
|
|
4057
|
+
return entry === void 0 || entry.uses === 0;
|
|
4058
|
+
}).length;
|
|
4059
|
+
}
|
|
4060
|
+
/** Strip a tool’s mcp__<server>__ prefix for display, like the old row did. */
|
|
4061
|
+
function displayToolName(server, name) {
|
|
4062
|
+
const prefix = "mcp__" + server + "__";
|
|
4063
|
+
return server !== "built-in" && name.startsWith(prefix) ? name.slice(prefix.length) : name;
|
|
4064
|
+
}
|
|
4065
|
+
/**
|
|
4066
|
+
* Two-column `.v3-catgrid` of native `<details>` server groups, each summary
|
|
4067
|
+
* carrying the chevron and the class-count tags, each row a 30px `.v3-trow`.
|
|
4068
|
+
* Pure: every interaction is a callback.
|
|
4069
|
+
*/
|
|
4070
|
+
function ToolGroupsView(props) {
|
|
4071
|
+
const { t, groups, openServers, busy, usage } = props;
|
|
4072
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4073
|
+
className: "v3-catgrid",
|
|
4074
|
+
"data-v3-catgrid": "true",
|
|
4075
|
+
children: groups.map(({ server, tools }) => {
|
|
4076
|
+
const open = openServers.has(server);
|
|
4077
|
+
const counts = CLASS_KEYS.map((cls) => ({
|
|
4078
|
+
cls,
|
|
4079
|
+
count: countByClass(tools, cls)
|
|
4080
|
+
}));
|
|
4081
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
4082
|
+
className: "v3-group",
|
|
4083
|
+
open,
|
|
4084
|
+
"data-v3-group": server,
|
|
4085
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", {
|
|
4086
|
+
onClick: (e) => {
|
|
4087
|
+
e.preventDefault();
|
|
4088
|
+
props.onToggle(server);
|
|
4089
|
+
},
|
|
4090
|
+
children: [
|
|
4091
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
4092
|
+
className: "v3-chev",
|
|
4093
|
+
viewBox: "0 0 12 12",
|
|
4094
|
+
fill: "none",
|
|
4095
|
+
"aria-hidden": "true",
|
|
4096
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
4097
|
+
d: "M4.5 2.5 8 6l-3.5 3.5",
|
|
4098
|
+
stroke: "currentColor",
|
|
4099
|
+
strokeWidth: 1.4,
|
|
4100
|
+
strokeLinecap: "round",
|
|
4101
|
+
strokeLinejoin: "round"
|
|
4102
|
+
})
|
|
4103
|
+
}),
|
|
4104
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4105
|
+
className: "v3-gnm",
|
|
4106
|
+
children: server === "built-in" ? t("builtInGroup") : server
|
|
4107
|
+
}),
|
|
4108
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4109
|
+
className: "v3-cnt",
|
|
4110
|
+
children: tools.length
|
|
4111
|
+
}),
|
|
4112
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4113
|
+
className: "v3-right",
|
|
4114
|
+
children: [counts.filter(({ count }) => count > 0).map(({ cls, count }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4115
|
+
type: "button",
|
|
4116
|
+
className: "v3-tag",
|
|
4117
|
+
"data-tone": CLASS_TONE[cls],
|
|
4118
|
+
disabled: busy,
|
|
4119
|
+
title: t("cycleHint"),
|
|
4120
|
+
onClick: (e) => {
|
|
4121
|
+
e.stopPropagation();
|
|
4122
|
+
props.onCycle(tools.filter((tool) => tool.class === cls).map((tool) => tool.id), "tool");
|
|
4123
|
+
},
|
|
4124
|
+
children: [
|
|
4125
|
+
t(CLASS_SHORT_KEYS[cls]),
|
|
4126
|
+
" ",
|
|
4127
|
+
count
|
|
4128
|
+
]
|
|
4129
|
+
}, cls)), server !== "built-in" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4130
|
+
type: "button",
|
|
4131
|
+
className: "v3-tag v3-tag--act",
|
|
4132
|
+
disabled: busy,
|
|
4133
|
+
onClick: (e) => {
|
|
4134
|
+
e.stopPropagation();
|
|
4135
|
+
props.onEditServer(server);
|
|
4136
|
+
},
|
|
4137
|
+
children: t("edit")
|
|
4138
|
+
})]
|
|
4139
|
+
})
|
|
4140
|
+
]
|
|
4141
|
+
}), open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4142
|
+
className: "v3-tools",
|
|
4143
|
+
children: tools.map((tool) => {
|
|
4144
|
+
const rowUsage = usage === void 0 ? void 0 : usage.get(tool.id);
|
|
4145
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4146
|
+
className: "v3-trow",
|
|
4147
|
+
title: tool.classLabel,
|
|
4148
|
+
role: "button",
|
|
4149
|
+
tabIndex: 0,
|
|
4150
|
+
"aria-label": tool.name,
|
|
4151
|
+
onClick: () => props.onOpenDetail(tool.id),
|
|
4152
|
+
onKeyDown: (e) => {
|
|
4153
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
4154
|
+
e.preventDefault();
|
|
4155
|
+
props.onOpenDetail(tool.id);
|
|
4156
|
+
}
|
|
4157
|
+
},
|
|
4158
|
+
children: [
|
|
4159
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4160
|
+
className: "v3-dot",
|
|
4161
|
+
"data-tone": CLASS_DOT_TONE[tool.class],
|
|
4162
|
+
"aria-hidden": "true"
|
|
4163
|
+
}),
|
|
4164
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4165
|
+
className: "v3-nm",
|
|
4166
|
+
title: tool.name,
|
|
4167
|
+
children: displayToolName(server, tool.name)
|
|
4168
|
+
}),
|
|
4169
|
+
rowUsage !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4170
|
+
className: "v3-uses",
|
|
4171
|
+
children: [
|
|
4172
|
+
rowUsage.uses,
|
|
4173
|
+
" 次",
|
|
4174
|
+
rowUsage.failures !== void 0 && rowUsage.failures > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4175
|
+
className: "v3-uses-bad",
|
|
4176
|
+
children: [" · 失败 ", rowUsage.failures]
|
|
4177
|
+
}) : null
|
|
4178
|
+
]
|
|
4179
|
+
}),
|
|
4180
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4181
|
+
className: "v3-racts",
|
|
4182
|
+
children: [
|
|
4183
|
+
tool.mandatory && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4184
|
+
className: "v3-tag",
|
|
4185
|
+
children: t("mandatory")
|
|
4186
|
+
}),
|
|
4187
|
+
tool.class === "on-demand" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4188
|
+
type: "button",
|
|
4189
|
+
className: "v3-tag v3-tag--act",
|
|
4190
|
+
title: t("editSearchMetadata"),
|
|
4191
|
+
onClick: (e) => {
|
|
4192
|
+
e.stopPropagation();
|
|
4193
|
+
props.onEditSearch(tool.id);
|
|
4194
|
+
},
|
|
4195
|
+
children: t("searchMetadataButton")
|
|
4196
|
+
}),
|
|
4197
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4198
|
+
type: "button",
|
|
4199
|
+
className: "v3-tag",
|
|
4200
|
+
"data-tone": CLASS_TONE[tool.class],
|
|
4201
|
+
disabled: busy || tool.mandatory,
|
|
4202
|
+
title: tool.classLabel,
|
|
4203
|
+
"aria-label": tool.classLabel,
|
|
4204
|
+
onClick: (e) => {
|
|
4205
|
+
e.stopPropagation();
|
|
4206
|
+
props.onCycle([tool.id], "tool");
|
|
4207
|
+
},
|
|
4208
|
+
children: t(CLASS_SHORT_KEYS[tool.class])
|
|
4209
|
+
})
|
|
4210
|
+
]
|
|
4211
|
+
})
|
|
4212
|
+
]
|
|
4213
|
+
}, tool.id);
|
|
4214
|
+
})
|
|
4215
|
+
})]
|
|
4216
|
+
}, server);
|
|
4217
|
+
})
|
|
4218
|
+
});
|
|
4219
|
+
}
|
|
3824
4220
|
/**
|
|
3825
4221
|
* Whether the document is visible. A hidden settings tab does no polling and
|
|
3826
4222
|
* takes no re-reads; coming back is itself a revalidation trigger.
|
|
@@ -3836,7 +4232,7 @@ function useDocumentVisible() {
|
|
|
3836
4232
|
return visible;
|
|
3837
4233
|
}
|
|
3838
4234
|
function CapabilitySection(props) {
|
|
3839
|
-
const { remote, t, mountError, subscribeSignals } = props;
|
|
4235
|
+
const { remote, t, mountError, subscribeSignals, usage } = props;
|
|
3840
4236
|
const [state, setState] = (0, react.useState)(() => {
|
|
3841
4237
|
const cached = cachedSnapshot();
|
|
3842
4238
|
return cached === void 0 ? { status: "loading" } : {
|
|
@@ -4169,13 +4565,14 @@ function CapabilitySection(props) {
|
|
|
4169
4565
|
onCycle: cycleClass,
|
|
4170
4566
|
onRefresh: () => void refreshCatalog(),
|
|
4171
4567
|
onRefreshMcp: (serverName) => void refreshRegisteredMcp(serverName),
|
|
4172
|
-
onNotice: setNotice
|
|
4568
|
+
onNotice: setNotice,
|
|
4569
|
+
...usage === void 0 ? {} : { usage }
|
|
4173
4570
|
})
|
|
4174
4571
|
]
|
|
4175
4572
|
});
|
|
4176
4573
|
}
|
|
4177
4574
|
function ReadyBody(props) {
|
|
4178
|
-
const { remote, snapshot, diagnostics, openServers, busy, activeTab, t, onTabChange, onToggleServer, onCycle, onRefresh, onRefreshMcp, onNotice } = props;
|
|
4575
|
+
const { remote, snapshot, diagnostics, openServers, busy, activeTab, t, onTabChange, onToggleServer, onCycle, onRefresh, onRefreshMcp, onNotice, usage } = props;
|
|
4179
4576
|
const [updateStatus, setUpdateStatus] = (0, react.useState)(null);
|
|
4180
4577
|
const [updatePhase, setUpdatePhase] = (0, react.useState)("idle");
|
|
4181
4578
|
const [updateError, setUpdateError] = (0, react.useState)("");
|
|
@@ -4463,347 +4860,216 @@ function ReadyBody(props) {
|
|
|
4463
4860
|
t
|
|
4464
4861
|
]);
|
|
4465
4862
|
const skillDiagnosticCount = diagnostics === null ? 0 : diagnostics.unavailableSkills.length + diagnostics.shadowedSkills.length + diagnostics.brokenPresets.length + diagnostics.unbrowseableSkills.length + diagnostics.undocumentedSkills.length;
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
4496
|
-
size: "sm",
|
|
4497
|
-
variant: "outline",
|
|
4498
|
-
onClick: () => setRegisterOpen(true),
|
|
4499
|
-
children: t("registerCapability")
|
|
4500
|
-
}),
|
|
4501
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
4502
|
-
size: "sm",
|
|
4503
|
-
variant: "outline",
|
|
4504
|
-
onClick: () => void openCatalogDocs(),
|
|
4505
|
-
children: t("viewCatalog")
|
|
4506
|
-
}),
|
|
4507
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
4508
|
-
className: "mc-feedback-link",
|
|
4509
|
-
href: "https://github.com/PKUfudawei/dsh-capability-menu",
|
|
4510
|
-
target: "_blank",
|
|
4511
|
-
rel: "noopener noreferrer",
|
|
4512
|
-
"aria-label": t("feedback"),
|
|
4513
|
-
children: t("feedback")
|
|
4514
|
-
})
|
|
4515
|
-
]
|
|
4516
|
-
})]
|
|
4517
|
-
}),
|
|
4518
|
-
(updatePhase === "done" || updateStatus?.updateAvailable && !updateStatus.updatable && updateStatus.reason !== "local") && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4519
|
-
className: "mc-update-status",
|
|
4520
|
-
role: "status",
|
|
4521
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: updatePhase === "done" ? t(updateStatus?.reason === "local" ? "pluginSwitched" : "pluginUpdated") : t("updateAvailable", { version: updateStatus?.latest ?? "" }) }), updatePhase !== "done" && updateStatus?.updateAvailable && !updateStatus.updatable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(updateStatus.reason === "non-registry" ? "pluginNonRegistrySource" : "pluginProfileUnavailable") })]
|
|
4522
|
-
}),
|
|
4523
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4524
|
-
className: "mc-desc",
|
|
4525
|
-
children: t("desc")
|
|
4526
|
-
}),
|
|
4527
|
-
diagnostics !== null && skillDiagnosticCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
4528
|
-
className: "mc-diagnostics",
|
|
4529
|
-
children: [
|
|
4530
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: t("diagnosticTitle", { count: skillDiagnosticCount }) }),
|
|
4531
|
-
diagnostics.unavailableSkills.map((item, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: t("diagnosticUnavailable", {
|
|
4532
|
-
name: item.name,
|
|
4533
|
-
source: item.source,
|
|
4534
|
-
preset: item.preset ?? ""
|
|
4535
|
-
}) }, `unavailable-${item.name}-${item.preset ?? ""}-${index}`)),
|
|
4536
|
-
diagnostics.shadowedSkills.map((item, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: t("diagnosticShadowed", {
|
|
4537
|
-
name: item.name,
|
|
4538
|
-
winner: item.selectedFrom,
|
|
4539
|
-
hidden: item.shadowedFrom
|
|
4540
|
-
}) }, `shadowed-${item.name}-${item.shadowedFrom}-${index}`)),
|
|
4541
|
-
diagnostics.brokenPresets.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: t("diagnosticBroken", {
|
|
4542
|
-
id: item.id,
|
|
4543
|
-
reason: item.reason
|
|
4544
|
-
}) }, `broken-${item.id}`)),
|
|
4545
|
-
diagnostics.unbrowseableSkills.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: t("diagnosticUnbrowseable", {
|
|
4546
|
-
name: item.name,
|
|
4547
|
-
reason: item.reason
|
|
4548
|
-
}) }, `browse-${item.name}`)),
|
|
4549
|
-
diagnostics.undocumentedSkills.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: t("diagnosticUndocumented", {
|
|
4550
|
-
name: item.name,
|
|
4551
|
-
summary: item.summary
|
|
4552
|
-
}) }, `undocumented-${item.name}`))
|
|
4553
|
-
]
|
|
4554
|
-
}),
|
|
4555
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4556
|
-
className: "mc-tabs",
|
|
4557
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedTabs, {
|
|
4558
|
-
className: "mc-main-tabs",
|
|
4559
|
-
items: [{
|
|
4560
|
-
value: "tools",
|
|
4561
|
-
id: "mc-tab-tools",
|
|
4562
|
-
panelId: "mc-panel-tools",
|
|
4563
|
-
label: t("toolsGroup")
|
|
4564
|
-
}, {
|
|
4565
|
-
value: "skills",
|
|
4566
|
-
id: "mc-tab-skills",
|
|
4567
|
-
panelId: "mc-panel-skills",
|
|
4568
|
-
label: t("skillsGroup")
|
|
4569
|
-
}],
|
|
4570
|
-
value: activeTab,
|
|
4571
|
-
onChange: onTabChange,
|
|
4572
|
-
label: t("title")
|
|
4573
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4574
|
-
className: "mc-summary",
|
|
4575
|
-
children: summary.map(({ cls, count }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4576
|
-
className: `mc-chip mc-chip--${cls}`,
|
|
4863
|
+
const catalogUsage = usage;
|
|
4864
|
+
const classCount = (cls) => summary.find((entry) => entry.cls === cls)?.count ?? 0;
|
|
4865
|
+
const statCells = [
|
|
4866
|
+
{
|
|
4867
|
+
label: t("tierResident"),
|
|
4868
|
+
value: classCount("resident")
|
|
4869
|
+
},
|
|
4870
|
+
{
|
|
4871
|
+
label: t("tierOnDemand"),
|
|
4872
|
+
value: classCount("on-demand")
|
|
4873
|
+
},
|
|
4874
|
+
{
|
|
4875
|
+
label: t("tierDisabled"),
|
|
4876
|
+
value: classCount("disabled")
|
|
4877
|
+
},
|
|
4878
|
+
{
|
|
4879
|
+
label: t("catalogZeroCall"),
|
|
4880
|
+
value: zeroCallCount(catalogUsage, statRows),
|
|
4881
|
+
hint: t("catalogZeroCallHint")
|
|
4882
|
+
}
|
|
4883
|
+
];
|
|
4884
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4885
|
+
className: "v3-root",
|
|
4886
|
+
children: [
|
|
4887
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(V3Styles, {}),
|
|
4888
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4889
|
+
className: "mc-heading-row",
|
|
4890
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4891
|
+
className: "mc-heading-meta",
|
|
4577
4892
|
children: [
|
|
4578
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
4579
|
-
className:
|
|
4580
|
-
|
|
4893
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
4894
|
+
className: "mc-heading",
|
|
4895
|
+
children: t("title")
|
|
4581
4896
|
}),
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4897
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4898
|
+
className: "mc-version",
|
|
4899
|
+
title: PLUGIN_TITLE,
|
|
4900
|
+
children: ["v", PLUGIN_VERSION]
|
|
4901
|
+
}),
|
|
4902
|
+
updateStatus?.updateAvailable && (updateStatus.updatable || updateStatus.reason === "local") && updatePhase !== "done" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
4903
|
+
type: "button",
|
|
4904
|
+
variant: "primary",
|
|
4905
|
+
size: "sm",
|
|
4906
|
+
className: "mc-update-check",
|
|
4907
|
+
title: t("updateAvailable", { version: updateStatus.latest }),
|
|
4908
|
+
disabled: updatePhase === "installing",
|
|
4909
|
+
onClick: () => setUpdateDialogOpen(true),
|
|
4910
|
+
children: t("newVersion")
|
|
4911
|
+
})
|
|
4585
4912
|
]
|
|
4586
|
-
},
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
t(CLASS_SHORT_KEYS[cls]),
|
|
4663
|
-
" ",
|
|
4664
|
-
count
|
|
4665
|
-
]
|
|
4666
|
-
}, cls))
|
|
4667
|
-
}), server !== "built-in" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4668
|
-
type: "button",
|
|
4669
|
-
className: "mc-count mc-count--action",
|
|
4670
|
-
disabled: busy,
|
|
4671
|
-
onClick: (e) => {
|
|
4672
|
-
e.stopPropagation();
|
|
4673
|
-
openMcpEdit(server);
|
|
4674
|
-
},
|
|
4675
|
-
children: t("edit")
|
|
4676
|
-
})]
|
|
4677
|
-
})
|
|
4678
|
-
]
|
|
4679
|
-
}), open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4680
|
-
className: "mc-tools",
|
|
4681
|
-
children: tools.map((tool) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4682
|
-
className: "mc-tool",
|
|
4683
|
-
title: tool.classLabel,
|
|
4684
|
-
role: "button",
|
|
4685
|
-
tabIndex: 0,
|
|
4686
|
-
"aria-label": tool.name,
|
|
4687
|
-
onClick: () => void openToolDetail(tool.id),
|
|
4688
|
-
onKeyDown: (e) => {
|
|
4689
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
4690
|
-
e.preventDefault();
|
|
4691
|
-
openToolDetail(tool.id);
|
|
4692
|
-
}
|
|
4693
|
-
},
|
|
4694
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4695
|
-
className: "mc-tool-name",
|
|
4696
|
-
title: tool.name,
|
|
4697
|
-
children: server !== "built-in" && tool.name.startsWith(`mcp__${server}__`) ? tool.name.slice(`mcp__${server}__`.length) : tool.name
|
|
4698
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4699
|
-
className: "mc-tool-meta",
|
|
4700
|
-
children: [
|
|
4701
|
-
tool.mandatory && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("mandatory") }),
|
|
4702
|
-
tool.class === "on-demand" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
4703
|
-
size: "sm",
|
|
4704
|
-
variant: "ghost",
|
|
4705
|
-
className: "mc-count--action",
|
|
4706
|
-
title: t("editSearchMetadata"),
|
|
4707
|
-
onClick: (e) => {
|
|
4708
|
-
e.stopPropagation();
|
|
4709
|
-
openSearchEdit(tool.id, "tool");
|
|
4710
|
-
},
|
|
4711
|
-
children: t("searchMetadataButton")
|
|
4712
|
-
}),
|
|
4713
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4714
|
-
type: "button",
|
|
4715
|
-
className: `mc-dot-btn mc-count--${tool.class}`,
|
|
4716
|
-
disabled: busy || tool.mandatory,
|
|
4717
|
-
title: tool.classLabel,
|
|
4718
|
-
"aria-label": tool.classLabel,
|
|
4719
|
-
onClick: (e) => {
|
|
4720
|
-
e.stopPropagation();
|
|
4721
|
-
onCycle([tool.id], "tool");
|
|
4722
|
-
},
|
|
4723
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4724
|
-
className: `mc-dot mc-dot--${tool.class}`,
|
|
4725
|
-
"aria-hidden": "true"
|
|
4726
|
-
})
|
|
4727
|
-
})
|
|
4728
|
-
]
|
|
4729
|
-
})]
|
|
4730
|
-
}, tool.id))
|
|
4731
|
-
})]
|
|
4732
|
-
}, server);
|
|
4733
|
-
}) })
|
|
4734
|
-
})
|
|
4735
|
-
}),
|
|
4736
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4737
|
-
role: "tabpanel",
|
|
4738
|
-
id: "mc-panel-skills",
|
|
4739
|
-
"aria-labelledby": "mc-tab-skills",
|
|
4740
|
-
hidden: activeTab !== "skills",
|
|
4741
|
-
className: `mc-panel${skills.length > 0 ? " mc-panel--tight" : ""}`,
|
|
4742
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4743
|
-
className: "mc-panel-inner",
|
|
4744
|
-
children: skills.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4745
|
-
className: "mc-empty",
|
|
4746
|
-
children: needle === "" ? t("emptySkills") : t("filterNoMatch")
|
|
4747
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4748
|
-
className: "mc-subtabs",
|
|
4749
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedTabs, {
|
|
4750
|
-
items: [
|
|
4751
|
-
{
|
|
4752
|
-
value: "global",
|
|
4753
|
-
id: "mc-skill-tab-global",
|
|
4754
|
-
panelId: "mc-skill-panel-global",
|
|
4755
|
-
label: t("globalSkills")
|
|
4756
|
-
},
|
|
4757
|
-
{
|
|
4758
|
-
value: "project",
|
|
4759
|
-
id: "mc-skill-tab-project",
|
|
4760
|
-
panelId: "mc-skill-panel-project",
|
|
4761
|
-
label: t("projectSkills")
|
|
4762
|
-
},
|
|
4763
|
-
{
|
|
4764
|
-
value: "preset",
|
|
4765
|
-
id: "mc-skill-tab-preset",
|
|
4766
|
-
panelId: "mc-skill-panel-preset",
|
|
4767
|
-
label: t("presetSkills")
|
|
4768
|
-
}
|
|
4769
|
-
],
|
|
4770
|
-
value: skillTab,
|
|
4771
|
-
onChange: setSkillTab,
|
|
4913
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4914
|
+
className: "mc-heading-actions",
|
|
4915
|
+
children: [
|
|
4916
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
4917
|
+
size: "sm",
|
|
4918
|
+
variant: "outline",
|
|
4919
|
+
onClick: () => setRegisterOpen(true),
|
|
4920
|
+
children: t("registerCapability")
|
|
4921
|
+
}),
|
|
4922
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
4923
|
+
size: "sm",
|
|
4924
|
+
variant: "outline",
|
|
4925
|
+
onClick: () => void openCatalogDocs(),
|
|
4926
|
+
children: t("viewCatalog")
|
|
4927
|
+
}),
|
|
4928
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
4929
|
+
className: "mc-feedback-link",
|
|
4930
|
+
href: "https://github.com/PKUfudawei/dsh-capability-menu",
|
|
4931
|
+
target: "_blank",
|
|
4932
|
+
rel: "noopener noreferrer",
|
|
4933
|
+
"aria-label": t("feedback"),
|
|
4934
|
+
children: t("feedback")
|
|
4935
|
+
})
|
|
4936
|
+
]
|
|
4937
|
+
})]
|
|
4938
|
+
}),
|
|
4939
|
+
(updatePhase === "done" || updateStatus?.updateAvailable && !updateStatus.updatable && updateStatus.reason !== "local") && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4940
|
+
className: "mc-update-status",
|
|
4941
|
+
role: "status",
|
|
4942
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: updatePhase === "done" ? t(updateStatus?.reason === "local" ? "pluginSwitched" : "pluginUpdated") : t("updateAvailable", { version: updateStatus?.latest ?? "" }) }), updatePhase !== "done" && updateStatus?.updateAvailable && !updateStatus.updatable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(updateStatus.reason === "non-registry" ? "pluginNonRegistrySource" : "pluginProfileUnavailable") })]
|
|
4943
|
+
}),
|
|
4944
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4945
|
+
className: "mc-desc",
|
|
4946
|
+
children: t("desc")
|
|
4947
|
+
}),
|
|
4948
|
+
diagnostics !== null && skillDiagnosticCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
4949
|
+
className: "mc-diagnostics",
|
|
4950
|
+
children: [
|
|
4951
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: t("diagnosticTitle", { count: skillDiagnosticCount }) }),
|
|
4952
|
+
diagnostics.unavailableSkills.map((item, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: t("diagnosticUnavailable", {
|
|
4953
|
+
name: item.name,
|
|
4954
|
+
source: item.source,
|
|
4955
|
+
preset: item.preset ?? ""
|
|
4956
|
+
}) }, `unavailable-${item.name}-${item.preset ?? ""}-${index}`)),
|
|
4957
|
+
diagnostics.shadowedSkills.map((item, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: t("diagnosticShadowed", {
|
|
4958
|
+
name: item.name,
|
|
4959
|
+
winner: item.selectedFrom,
|
|
4960
|
+
hidden: item.shadowedFrom
|
|
4961
|
+
}) }, `shadowed-${item.name}-${item.shadowedFrom}-${index}`)),
|
|
4962
|
+
diagnostics.brokenPresets.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: t("diagnosticBroken", {
|
|
4963
|
+
id: item.id,
|
|
4964
|
+
reason: item.reason
|
|
4965
|
+
}) }, `broken-${item.id}`)),
|
|
4966
|
+
diagnostics.unbrowseableSkills.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: t("diagnosticUnbrowseable", {
|
|
4967
|
+
name: item.name,
|
|
4968
|
+
reason: item.reason
|
|
4969
|
+
}) }, `browse-${item.name}`)),
|
|
4970
|
+
diagnostics.undocumentedSkills.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: t("diagnosticUndocumented", {
|
|
4971
|
+
name: item.name,
|
|
4972
|
+
summary: item.summary
|
|
4973
|
+
}) }, `undocumented-${item.name}`))
|
|
4974
|
+
]
|
|
4975
|
+
}),
|
|
4976
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4977
|
+
className: "mc-tabs",
|
|
4978
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedTabs, {
|
|
4979
|
+
className: "mc-main-tabs",
|
|
4980
|
+
items: [{
|
|
4981
|
+
value: "tools",
|
|
4982
|
+
id: "mc-tab-tools",
|
|
4983
|
+
panelId: "mc-panel-tools",
|
|
4984
|
+
label: t("toolsGroup")
|
|
4985
|
+
}, {
|
|
4986
|
+
value: "skills",
|
|
4987
|
+
id: "mc-tab-skills",
|
|
4988
|
+
panelId: "mc-panel-skills",
|
|
4772
4989
|
label: t("skillsGroup")
|
|
4990
|
+
}],
|
|
4991
|
+
value: activeTab,
|
|
4992
|
+
onChange: onTabChange,
|
|
4993
|
+
label: t("title")
|
|
4994
|
+
})
|
|
4995
|
+
}),
|
|
4996
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CatalogStatStrip, { cells: statCells }),
|
|
4997
|
+
snapshot.rows.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4998
|
+
className: "mc-filter",
|
|
4999
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
|
|
5000
|
+
type: "search",
|
|
5001
|
+
value: filter,
|
|
5002
|
+
placeholder: t("filterByName"),
|
|
5003
|
+
"aria-label": t("filterByName"),
|
|
5004
|
+
title: t("filterHint"),
|
|
5005
|
+
onChange: (e) => setFilter(e.target.value)
|
|
5006
|
+
})
|
|
5007
|
+
}),
|
|
5008
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5009
|
+
role: "tabpanel",
|
|
5010
|
+
id: "mc-panel-tools",
|
|
5011
|
+
"aria-labelledby": "mc-tab-tools",
|
|
5012
|
+
hidden: activeTab !== "tools",
|
|
5013
|
+
className: "mc-panel",
|
|
5014
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5015
|
+
className: "mc-panel-inner",
|
|
5016
|
+
children: servers.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5017
|
+
className: "mc-empty",
|
|
5018
|
+
children: needle === "" ? t("emptyTools") : t("filterNoMatch")
|
|
5019
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolGroupsView, {
|
|
5020
|
+
t,
|
|
5021
|
+
groups: servers,
|
|
5022
|
+
openServers,
|
|
5023
|
+
busy,
|
|
5024
|
+
usage: catalogUsage,
|
|
5025
|
+
onToggle: onToggleServer,
|
|
5026
|
+
onCycle,
|
|
5027
|
+
onOpenDetail: (id) => void openToolDetail(id),
|
|
5028
|
+
onEditServer: (server) => void openMcpEdit(server),
|
|
5029
|
+
onEditSearch: (id) => void openSearchEdit(id, "tool")
|
|
4773
5030
|
})
|
|
4774
|
-
})
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
5031
|
+
})
|
|
5032
|
+
}),
|
|
5033
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5034
|
+
role: "tabpanel",
|
|
5035
|
+
id: "mc-panel-skills",
|
|
5036
|
+
"aria-labelledby": "mc-tab-skills",
|
|
5037
|
+
hidden: activeTab !== "skills",
|
|
5038
|
+
className: `mc-panel${skills.length > 0 ? " mc-panel--tight" : ""}`,
|
|
5039
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5040
|
+
className: "mc-panel-inner",
|
|
5041
|
+
children: skills.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5042
|
+
className: "mc-empty",
|
|
5043
|
+
children: needle === "" ? t("emptySkills") : t("filterNoMatch")
|
|
5044
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5045
|
+
className: "mc-subtabs",
|
|
5046
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedTabs, {
|
|
5047
|
+
items: [
|
|
5048
|
+
{
|
|
5049
|
+
value: "global",
|
|
5050
|
+
id: "mc-skill-tab-global",
|
|
5051
|
+
panelId: "mc-skill-panel-global",
|
|
5052
|
+
label: t("globalSkills")
|
|
5053
|
+
},
|
|
5054
|
+
{
|
|
5055
|
+
value: "project",
|
|
5056
|
+
id: "mc-skill-tab-project",
|
|
5057
|
+
panelId: "mc-skill-panel-project",
|
|
5058
|
+
label: t("projectSkills")
|
|
5059
|
+
},
|
|
5060
|
+
{
|
|
5061
|
+
value: "preset",
|
|
5062
|
+
id: "mc-skill-tab-preset",
|
|
5063
|
+
panelId: "mc-skill-panel-preset",
|
|
5064
|
+
label: t("presetSkills")
|
|
5065
|
+
}
|
|
5066
|
+
],
|
|
5067
|
+
value: skillTab,
|
|
5068
|
+
onChange: setSkillTab,
|
|
5069
|
+
label: t("skillsGroup")
|
|
5070
|
+
})
|
|
5071
|
+
}), skillTab === "global" ? globalSkills.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillList, {
|
|
5072
|
+
skills: globalSkills,
|
|
4807
5073
|
remote,
|
|
4808
5074
|
busy,
|
|
4809
5075
|
t,
|
|
@@ -4812,307 +5078,339 @@ function ReadyBody(props) {
|
|
|
4812
5078
|
onEditSkill: openSkillEdit,
|
|
4813
5079
|
onAdoptSkill: adoptSkill,
|
|
4814
5080
|
onEditSearch: (id) => void openSearchEdit(id, "skill")
|
|
4815
|
-
})
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
}
|
|
4852
|
-
}, null, 2)
|
|
4853
|
-
})]
|
|
5081
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5082
|
+
className: "mc-empty",
|
|
5083
|
+
children: t("emptyGlobalSkills")
|
|
5084
|
+
}) : skillTab === "project" ? projectSkills.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillList, {
|
|
5085
|
+
skills: projectSkills,
|
|
5086
|
+
remote,
|
|
5087
|
+
busy,
|
|
5088
|
+
t,
|
|
5089
|
+
onCycle,
|
|
5090
|
+
editableSkills,
|
|
5091
|
+
onEditSkill: openSkillEdit,
|
|
5092
|
+
onAdoptSkill: adoptSkill,
|
|
5093
|
+
onEditSearch: (id) => void openSearchEdit(id, "skill")
|
|
5094
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5095
|
+
className: "mc-empty",
|
|
5096
|
+
children: t("emptyProjectSkills")
|
|
5097
|
+
}) : presetGroups.length > 0 ? presetGroups.map(([preset, group]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5098
|
+
className: "mc-skill-group",
|
|
5099
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5100
|
+
className: "mc-skill-group-title",
|
|
5101
|
+
children: preset
|
|
5102
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillList, {
|
|
5103
|
+
skills: group,
|
|
5104
|
+
remote,
|
|
5105
|
+
busy,
|
|
5106
|
+
t,
|
|
5107
|
+
onCycle,
|
|
5108
|
+
editableSkills,
|
|
5109
|
+
onEditSkill: openSkillEdit,
|
|
5110
|
+
onAdoptSkill: adoptSkill,
|
|
5111
|
+
onEditSearch: (id) => void openSearchEdit(id, "skill")
|
|
5112
|
+
})]
|
|
5113
|
+
}, preset)) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5114
|
+
className: "mc-empty",
|
|
5115
|
+
children: t("emptyPresetSkills")
|
|
5116
|
+
})] })
|
|
4854
5117
|
})
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
closeLabel: t("previewClose"),
|
|
4862
|
-
className: "mc-update-dialog",
|
|
4863
|
-
footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4864
|
-
className: "mc-confirm-actions mc-update-actions",
|
|
5118
|
+
}),
|
|
5119
|
+
toolDetail !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
5120
|
+
open: true,
|
|
5121
|
+
onClose: () => setToolDetail(null),
|
|
5122
|
+
title: toolDetail.detail?.name ?? toolDetail.id,
|
|
5123
|
+
closeLabel: t("previewClose"),
|
|
4865
5124
|
children: [
|
|
4866
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
size: "sm",
|
|
4870
|
-
className: "mc-update-cancel",
|
|
4871
|
-
disabled: updatePhase === "installing",
|
|
4872
|
-
onClick: closeUpdateDialog,
|
|
4873
|
-
children: t("cancel")
|
|
5125
|
+
toolDetail.status === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5126
|
+
className: "mc-preview-hint",
|
|
5127
|
+
children: "…"
|
|
4874
5128
|
}),
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
size: "sm",
|
|
4879
|
-
disabled: updatePhase === "installing",
|
|
4880
|
-
onClick: () => setSourceStepsOpen((value) => !value),
|
|
4881
|
-
children: t(sourceStepsOpen ? "updateSourceStepsHide" : "updateSourceSteps")
|
|
5129
|
+
toolDetail.status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5130
|
+
className: "mc-preview-hint",
|
|
5131
|
+
children: toolDetail.message
|
|
4882
5132
|
}),
|
|
4883
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
5133
|
+
toolDetail.status === "ready" && toolDetail.detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5134
|
+
className: "mc-preview-body",
|
|
5135
|
+
children: [toolDetail.detail.description.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5136
|
+
className: "mc-tool-description",
|
|
5137
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MarkdownPreview, {
|
|
5138
|
+
text: toolDetail.detail.description,
|
|
5139
|
+
t
|
|
5140
|
+
})
|
|
5141
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
5142
|
+
className: "mc-preview-plain",
|
|
5143
|
+
children: JSON.stringify({
|
|
5144
|
+
type: "function",
|
|
5145
|
+
function: {
|
|
5146
|
+
name: toolDetail.detail.name,
|
|
5147
|
+
parameters: toolDetail.detail.parameters
|
|
5148
|
+
}
|
|
5149
|
+
}, null, 2)
|
|
5150
|
+
})]
|
|
4890
5151
|
})
|
|
4891
5152
|
]
|
|
4892
5153
|
}),
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
className: "mc-update-
|
|
4901
|
-
children: [
|
|
4902
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("updateSourceStepsIntro") }),
|
|
4903
|
-
updateStatus.sourcePath && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4904
|
-
className: "mc-confirm-path",
|
|
4905
|
-
children: updateStatus.sourcePath
|
|
4906
|
-
}),
|
|
4907
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { children: "git pull\npnpm install\npnpm run build" }),
|
|
4908
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("updateSourceStepsRestart") })
|
|
4909
|
-
]
|
|
4910
|
-
}),
|
|
4911
|
-
updatePhase === "installing" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4912
|
-
role: "status",
|
|
4913
|
-
children: t("updatingPlugin")
|
|
4914
|
-
}),
|
|
4915
|
-
updatePhase === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
4916
|
-
className: "mc-error",
|
|
4917
|
-
role: "alert",
|
|
5154
|
+
updateDialogOpen && updateStatus?.updateAvailable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
5155
|
+
open: true,
|
|
5156
|
+
onClose: closeUpdateDialog,
|
|
5157
|
+
title: t("updateDialogTitle"),
|
|
5158
|
+
closeLabel: t("previewClose"),
|
|
5159
|
+
className: "mc-update-dialog",
|
|
5160
|
+
footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5161
|
+
className: "mc-confirm-actions mc-update-actions",
|
|
4918
5162
|
children: [
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
open: true,
|
|
4928
|
-
onClose: () => setSearchEdit(null),
|
|
4929
|
-
title: `${t("editSearchMetadata")} · ${searchEdit.id}`,
|
|
4930
|
-
closeLabel: t("previewClose"),
|
|
4931
|
-
className: "mc-search-dialog",
|
|
4932
|
-
children: [
|
|
4933
|
-
searchEdit.status === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4934
|
-
className: "mc-preview-hint",
|
|
4935
|
-
children: "…"
|
|
4936
|
-
}),
|
|
4937
|
-
searchEdit.status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4938
|
-
className: "mc-preview-hint",
|
|
4939
|
-
children: searchEdit.message
|
|
4940
|
-
}),
|
|
4941
|
-
searchEdit.status === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4942
|
-
className: "mc-confirm-body",
|
|
4943
|
-
children: [
|
|
4944
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4945
|
-
className: "mc-search-field",
|
|
4946
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4947
|
-
className: "mc-search-label-row",
|
|
4948
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
4949
|
-
htmlFor: "mc-search-description",
|
|
4950
|
-
children: t("searchDescription")
|
|
4951
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4952
|
-
id: "mc-search-description-note",
|
|
4953
|
-
children: t("searchMetadataNote")
|
|
4954
|
-
})]
|
|
4955
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
4956
|
-
id: "mc-search-description",
|
|
4957
|
-
"aria-describedby": "mc-search-description-note",
|
|
4958
|
-
value: searchDescription,
|
|
4959
|
-
maxLength: searchEdit.metadata?.maxChars,
|
|
4960
|
-
disabled: searchSaving,
|
|
4961
|
-
onChange: (e) => setSearchDescription(e.target.value)
|
|
4962
|
-
})]
|
|
4963
|
-
}),
|
|
4964
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4965
|
-
className: "mc-search-hint",
|
|
4966
|
-
children: [
|
|
4967
|
-
searchDescription.length,
|
|
4968
|
-
"/",
|
|
4969
|
-
searchEdit.metadata?.maxChars
|
|
4970
|
-
]
|
|
4971
|
-
}),
|
|
4972
|
-
searchEdit.message !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4973
|
-
className: "mc-error",
|
|
4974
|
-
children: searchEdit.message
|
|
5163
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5164
|
+
type: "button",
|
|
5165
|
+
variant: "outline",
|
|
5166
|
+
size: "sm",
|
|
5167
|
+
className: "mc-update-cancel",
|
|
5168
|
+
disabled: updatePhase === "installing",
|
|
5169
|
+
onClick: closeUpdateDialog,
|
|
5170
|
+
children: t("cancel")
|
|
4975
5171
|
}),
|
|
4976
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
]
|
|
4994
|
-
})
|
|
4995
|
-
]
|
|
4996
|
-
}),
|
|
4997
|
-
(registerOpen || editMcp !== void 0 || editSkill !== void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LocationModal, {
|
|
4998
|
-
remote,
|
|
4999
|
-
t,
|
|
5000
|
-
defaultKind: activeTab === "skills" ? "skill" : "mcp",
|
|
5001
|
-
...editMcp !== void 0 ? { editMcp } : {},
|
|
5002
|
-
...editSkill !== void 0 ? { editSkill } : {},
|
|
5003
|
-
onClose: () => {
|
|
5004
|
-
setRegisterOpen(false);
|
|
5005
|
-
setEditMcp(void 0);
|
|
5006
|
-
setEditSkill(void 0);
|
|
5007
|
-
},
|
|
5008
|
-
onChanged: (notice, refreshMcpServer) => {
|
|
5009
|
-
if (refreshMcpServer !== void 0) onRefreshMcp(refreshMcpServer);
|
|
5010
|
-
else onRefresh();
|
|
5011
|
-
if (notice !== void 0) onNotice(notice);
|
|
5012
|
-
}
|
|
5013
|
-
}),
|
|
5014
|
-
catalogDocs !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
5015
|
-
open: true,
|
|
5016
|
-
onClose: () => setCatalogDocs(null),
|
|
5017
|
-
title: t("viewCatalog"),
|
|
5018
|
-
closeLabel: t("previewClose"),
|
|
5019
|
-
children: [
|
|
5020
|
-
catalogDocs.status === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5021
|
-
className: "mc-preview-hint",
|
|
5022
|
-
children: "…"
|
|
5023
|
-
}),
|
|
5024
|
-
catalogDocs.status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5025
|
-
className: "mc-preview-hint",
|
|
5026
|
-
children: catalogDocs.message
|
|
5172
|
+
updateStatus.reason === "local" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5173
|
+
type: "button",
|
|
5174
|
+
variant: "outline",
|
|
5175
|
+
size: "sm",
|
|
5176
|
+
disabled: updatePhase === "installing",
|
|
5177
|
+
onClick: () => setSourceStepsOpen((value) => !value),
|
|
5178
|
+
children: t(sourceStepsOpen ? "updateSourceStepsHide" : "updateSourceSteps")
|
|
5179
|
+
}),
|
|
5180
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5181
|
+
type: "button",
|
|
5182
|
+
variant: "primary",
|
|
5183
|
+
size: "sm",
|
|
5184
|
+
disabled: updatePhase === "installing",
|
|
5185
|
+
onClick: () => void installUpdate(updateStatus.reason === "local" ? "local" : "registry"),
|
|
5186
|
+
children: t(updateStatus.reason === "local" ? "switchAndInstall" : "installUpdate")
|
|
5187
|
+
})
|
|
5188
|
+
]
|
|
5027
5189
|
}),
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5190
|
+
children: [
|
|
5191
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("updateVersionComparison", {
|
|
5192
|
+
current: updateStatus.current,
|
|
5193
|
+
latest: updateStatus.latest
|
|
5194
|
+
}) }),
|
|
5195
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t(updateStatus.reason === "local" ? "updateLocalNote" : "updateNpmNote") }),
|
|
5196
|
+
updateStatus.reason === "local" && sourceStepsOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5197
|
+
className: "mc-update-steps",
|
|
5198
|
+
children: [
|
|
5199
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("updateSourceStepsIntro") }),
|
|
5200
|
+
updateStatus.sourcePath && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5201
|
+
className: "mc-confirm-path",
|
|
5202
|
+
children: updateStatus.sourcePath
|
|
5203
|
+
}),
|
|
5204
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { children: "git pull\npnpm install\npnpm run build" }),
|
|
5205
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("updateSourceStepsRestart") })
|
|
5206
|
+
]
|
|
5207
|
+
}),
|
|
5208
|
+
updatePhase === "installing" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5209
|
+
role: "status",
|
|
5210
|
+
children: t("updatingPlugin")
|
|
5211
|
+
}),
|
|
5212
|
+
updatePhase === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
5213
|
+
className: "mc-error",
|
|
5214
|
+
role: "alert",
|
|
5215
|
+
children: [
|
|
5216
|
+
t("pluginUpdateFailed"),
|
|
5217
|
+
" ",
|
|
5218
|
+
updateError
|
|
5219
|
+
]
|
|
5045
5220
|
})
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
5078
|
-
|
|
5221
|
+
]
|
|
5222
|
+
}),
|
|
5223
|
+
searchEdit !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
5224
|
+
open: true,
|
|
5225
|
+
onClose: () => setSearchEdit(null),
|
|
5226
|
+
title: `${t("editSearchMetadata")} · ${searchEdit.id}`,
|
|
5227
|
+
closeLabel: t("previewClose"),
|
|
5228
|
+
className: "mc-search-dialog",
|
|
5229
|
+
children: [
|
|
5230
|
+
searchEdit.status === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5231
|
+
className: "mc-preview-hint",
|
|
5232
|
+
children: "…"
|
|
5233
|
+
}),
|
|
5234
|
+
searchEdit.status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5235
|
+
className: "mc-preview-hint",
|
|
5236
|
+
children: searchEdit.message
|
|
5237
|
+
}),
|
|
5238
|
+
searchEdit.status === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5239
|
+
className: "mc-confirm-body",
|
|
5240
|
+
children: [
|
|
5241
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5242
|
+
className: "mc-search-field",
|
|
5243
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5244
|
+
className: "mc-search-label-row",
|
|
5245
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
5246
|
+
htmlFor: "mc-search-description",
|
|
5247
|
+
children: t("searchDescription")
|
|
5248
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5249
|
+
id: "mc-search-description-note",
|
|
5250
|
+
children: t("searchMetadataNote")
|
|
5251
|
+
})]
|
|
5252
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
5253
|
+
id: "mc-search-description",
|
|
5254
|
+
"aria-describedby": "mc-search-description-note",
|
|
5255
|
+
value: searchDescription,
|
|
5256
|
+
maxLength: searchEdit.metadata?.maxChars,
|
|
5257
|
+
disabled: searchSaving,
|
|
5258
|
+
onChange: (e) => setSearchDescription(e.target.value)
|
|
5259
|
+
})]
|
|
5260
|
+
}),
|
|
5261
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5262
|
+
className: "mc-search-hint",
|
|
5263
|
+
children: [
|
|
5264
|
+
searchDescription.length,
|
|
5265
|
+
"/",
|
|
5266
|
+
searchEdit.metadata?.maxChars
|
|
5267
|
+
]
|
|
5268
|
+
}),
|
|
5269
|
+
searchEdit.message !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5270
|
+
className: "mc-error",
|
|
5271
|
+
children: searchEdit.message
|
|
5272
|
+
}),
|
|
5273
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5274
|
+
className: "mc-confirm-actions",
|
|
5275
|
+
children: [searchDescription !== searchEdit.metadata?.defaultDescription && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5276
|
+
size: "sm",
|
|
5277
|
+
variant: "ghost",
|
|
5278
|
+
disabled: searchSaving,
|
|
5279
|
+
title: t("searchMetadataRestoreHint"),
|
|
5280
|
+
onClick: () => setSearchDescription(searchEdit.metadata?.defaultDescription ?? ""),
|
|
5281
|
+
children: t("searchMetadataRestore")
|
|
5282
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5079
5283
|
size: "sm",
|
|
5080
5284
|
variant: "primary",
|
|
5081
|
-
disabled:
|
|
5082
|
-
onClick: () => void
|
|
5285
|
+
disabled: searchSaving,
|
|
5286
|
+
onClick: () => void saveSearchEdit(),
|
|
5083
5287
|
children: t("searchMetadataSave")
|
|
5084
|
-
})
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5288
|
+
})]
|
|
5289
|
+
})
|
|
5290
|
+
]
|
|
5291
|
+
})
|
|
5292
|
+
]
|
|
5293
|
+
}),
|
|
5294
|
+
(registerOpen || editMcp !== void 0 || editSkill !== void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LocationModal, {
|
|
5295
|
+
remote,
|
|
5296
|
+
t,
|
|
5297
|
+
defaultKind: activeTab === "skills" ? "skill" : "mcp",
|
|
5298
|
+
...editMcp !== void 0 ? { editMcp } : {},
|
|
5299
|
+
...editSkill !== void 0 ? { editSkill } : {},
|
|
5300
|
+
onClose: () => {
|
|
5301
|
+
setRegisterOpen(false);
|
|
5302
|
+
setEditMcp(void 0);
|
|
5303
|
+
setEditSkill(void 0);
|
|
5304
|
+
},
|
|
5305
|
+
onChanged: (notice, refreshMcpServer) => {
|
|
5306
|
+
if (refreshMcpServer !== void 0) onRefreshMcp(refreshMcpServer);
|
|
5307
|
+
else onRefresh();
|
|
5308
|
+
if (notice !== void 0) onNotice(notice);
|
|
5309
|
+
}
|
|
5310
|
+
}),
|
|
5311
|
+
catalogDocs !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
5312
|
+
open: true,
|
|
5313
|
+
onClose: () => setCatalogDocs(null),
|
|
5314
|
+
title: t("viewCatalog"),
|
|
5315
|
+
closeLabel: t("previewClose"),
|
|
5316
|
+
children: [
|
|
5317
|
+
catalogDocs.status === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5318
|
+
className: "mc-preview-hint",
|
|
5319
|
+
children: "…"
|
|
5088
5320
|
}),
|
|
5089
|
-
|
|
5090
|
-
className: "mc-
|
|
5091
|
-
children:
|
|
5321
|
+
catalogDocs.status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5322
|
+
className: "mc-preview-hint",
|
|
5323
|
+
children: catalogDocs.message
|
|
5092
5324
|
}),
|
|
5093
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5325
|
+
catalogDocs.status === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5326
|
+
className: "mc-subtabs mc-catalog-tabs",
|
|
5327
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedTabs, {
|
|
5328
|
+
items: [{
|
|
5329
|
+
value: "policy",
|
|
5330
|
+
id: "mc-cat-tab-policy",
|
|
5331
|
+
panelId: "mc-cat-panel-policy",
|
|
5332
|
+
label: t("catalogPolicy")
|
|
5333
|
+
}, {
|
|
5334
|
+
value: "catalog",
|
|
5335
|
+
id: "mc-cat-tab-catalog",
|
|
5336
|
+
panelId: "mc-cat-panel-catalog",
|
|
5337
|
+
label: t("catalogOnDemand")
|
|
5338
|
+
}],
|
|
5339
|
+
value: catalogTab,
|
|
5340
|
+
onChange: setCatalogTab,
|
|
5341
|
+
label: t("viewCatalog")
|
|
5342
|
+
})
|
|
5343
|
+
}), catalogTab === "policy" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5344
|
+
className: "mc-catalog-path",
|
|
5345
|
+
children: t("catalogPolicyNote")
|
|
5346
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
5094
5347
|
className: "mc-preview-body",
|
|
5095
|
-
children:
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5348
|
+
children: catalogDocs.docs.policyYaml
|
|
5349
|
+
})] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
5350
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5351
|
+
className: "mc-catalog-toolbar",
|
|
5352
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5353
|
+
className: "mc-catalog-path",
|
|
5354
|
+
children: t("catalogSearchNote", { count: catalogDocs.docs.onDemand.length })
|
|
5355
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5356
|
+
className: "mc-summary-setting",
|
|
5357
|
+
children: [
|
|
5358
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
5359
|
+
htmlFor: "mc-summary-limit",
|
|
5360
|
+
children: t("summaryLimit")
|
|
5361
|
+
}),
|
|
5362
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5363
|
+
id: "mc-summary-limit",
|
|
5364
|
+
type: "number",
|
|
5365
|
+
min: 20,
|
|
5366
|
+
step: 1,
|
|
5367
|
+
value: summaryLimitDraft,
|
|
5368
|
+
disabled: !catalogDocs.docs.searchSettingsEnabled || summaryLimitSaving,
|
|
5369
|
+
onChange: (e) => {
|
|
5370
|
+
setSummaryLimitDraft(e.target.value);
|
|
5371
|
+
setSummaryLimitError(void 0);
|
|
5372
|
+
}
|
|
5373
|
+
}),
|
|
5374
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("summaryLimitUnit") }),
|
|
5375
|
+
catalogDocs.docs.searchSettingsEnabled && summaryLimitDraft !== String(catalogDocs.docs.summaryMaxChars) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5376
|
+
size: "sm",
|
|
5377
|
+
variant: "primary",
|
|
5378
|
+
disabled: summaryLimitSaving,
|
|
5379
|
+
onClick: () => void saveSummaryLimit(),
|
|
5380
|
+
children: t("searchMetadataSave")
|
|
5381
|
+
}),
|
|
5382
|
+
!catalogDocs.docs.searchSettingsEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("summaryLimitDisabled") })
|
|
5383
|
+
]
|
|
5109
5384
|
})]
|
|
5110
|
-
},
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5385
|
+
}),
|
|
5386
|
+
summaryLimitError !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5387
|
+
className: "mc-error mc-catalog-limit-error",
|
|
5388
|
+
children: summaryLimitError
|
|
5389
|
+
}),
|
|
5390
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5391
|
+
className: "mc-preview-body",
|
|
5392
|
+
children: [catalogDocs.docs.onDemand.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5393
|
+
className: "mc-preview-hint",
|
|
5394
|
+
children: t("catalogEmpty")
|
|
5395
|
+
}), catalogDocs.docs.onDemand.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5396
|
+
className: "mc-search-result",
|
|
5397
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5398
|
+
className: "mc-search-result-head",
|
|
5399
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: row.kind === "tool" ? "Tool" : "Skill" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5400
|
+
className: "mc-search-result-id",
|
|
5401
|
+
children: row.id
|
|
5402
|
+
})]
|
|
5403
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5404
|
+
className: "mc-search-result-summary",
|
|
5405
|
+
children: row.summary
|
|
5406
|
+
})]
|
|
5407
|
+
}, `${row.kind}:${row.id}`))]
|
|
5408
|
+
})
|
|
5409
|
+
] })] })
|
|
5410
|
+
]
|
|
5411
|
+
})
|
|
5412
|
+
]
|
|
5413
|
+
});
|
|
5116
5414
|
}
|
|
5117
5415
|
function projectRootForSkill(path) {
|
|
5118
5416
|
return path.match(/^(.*)\/(?:\.dsh|\.agents)\/skills(?:\/.*)?$/)?.[1] ?? path;
|
|
@@ -5298,111 +5596,118 @@ function SkillList(props) {
|
|
|
5298
5596
|
show the directory the click will link. */
|
|
5299
5597
|
const confirmAdoptRow = confirmAdopt === null ? void 0 : skills.find((row) => row.id === confirmAdopt);
|
|
5300
5598
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
className: "
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
"
|
|
5310
|
-
|
|
5311
|
-
onKeyDown: (e) => {
|
|
5312
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
5599
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5600
|
+
className: "v3-catgrid",
|
|
5601
|
+
children: skills.map((skill) => {
|
|
5602
|
+
const open = openSkill === skill.id;
|
|
5603
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
5604
|
+
className: "v3-group",
|
|
5605
|
+
open,
|
|
5606
|
+
"data-v3-skill": skill.id,
|
|
5607
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", {
|
|
5608
|
+
onClick: (e) => {
|
|
5313
5609
|
e.preventDefault();
|
|
5314
5610
|
toggleSkill(skill.id);
|
|
5315
|
-
}
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
title: skill.path,
|
|
5329
|
-
children: t("projectRootLabel", { path: projectRootForSkill(skill.path) })
|
|
5330
|
-
}),
|
|
5331
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5332
|
-
className: "mc-skill-meta",
|
|
5333
|
-
children: [
|
|
5334
|
-
skill.mandatory && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tag, { children: t("mandatory") }),
|
|
5335
|
-
skill.class === "on-demand" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5336
|
-
size: "sm",
|
|
5337
|
-
variant: "ghost",
|
|
5338
|
-
className: "mc-count--action",
|
|
5339
|
-
title: t("editSearchMetadata"),
|
|
5340
|
-
onClick: (e) => {
|
|
5341
|
-
e.stopPropagation();
|
|
5342
|
-
onEditSearch(skill.id);
|
|
5343
|
-
},
|
|
5344
|
-
children: t("searchMetadataButton")
|
|
5345
|
-
}),
|
|
5346
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
5347
|
-
type: "button",
|
|
5348
|
-
className: `mc-count mc-count--${skill.class}`,
|
|
5349
|
-
disabled: busy || skill.mandatory,
|
|
5350
|
-
title: skill.classLabel,
|
|
5351
|
-
onClick: (e) => {
|
|
5352
|
-
e.stopPropagation();
|
|
5353
|
-
onCycle([skill.id], "skill");
|
|
5354
|
-
},
|
|
5355
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5356
|
-
className: `mc-dot mc-dot--${skill.class}`,
|
|
5357
|
-
"aria-hidden": "true"
|
|
5358
|
-
}), t(CLASS_SHORT_KEYS[skill.class])]
|
|
5359
|
-
}),
|
|
5360
|
-
!editableSkills.has(skill.id) && (skill.preset !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5361
|
-
className: "mc-source",
|
|
5362
|
-
title: t("skillFromPresetHint"),
|
|
5363
|
-
children: t("skillFromPreset", { preset: skill.preset })
|
|
5364
|
-
}) : ADOPTABLE_SKILL_SOURCES.has(skill.source ?? "") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5365
|
-
type: "button",
|
|
5366
|
-
className: "mc-count mc-count--action",
|
|
5367
|
-
disabled: busy,
|
|
5368
|
-
title: t("adoptSkillHint"),
|
|
5369
|
-
onClick: (e) => {
|
|
5370
|
-
e.stopPropagation();
|
|
5371
|
-
setConfirmAdopt(skill.id);
|
|
5372
|
-
},
|
|
5373
|
-
children: t("adoptSkill")
|
|
5374
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5375
|
-
className: "mc-source",
|
|
5376
|
-
title: t("skillSourceHint"),
|
|
5377
|
-
children: t("skillSource", { source: sourceLabel(skill.source, t) })
|
|
5378
|
-
})),
|
|
5379
|
-
editableSkills.has(skill.id) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5380
|
-
type: "button",
|
|
5381
|
-
className: "mc-count mc-count--action",
|
|
5382
|
-
disabled: busy,
|
|
5383
|
-
onClick: (e) => {
|
|
5384
|
-
e.stopPropagation();
|
|
5385
|
-
onEditSkill(skill.id, skill.source);
|
|
5386
|
-
},
|
|
5387
|
-
children: t("edit")
|
|
5611
|
+
},
|
|
5612
|
+
children: [
|
|
5613
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
5614
|
+
className: "v3-chev",
|
|
5615
|
+
viewBox: "0 0 12 12",
|
|
5616
|
+
fill: "none",
|
|
5617
|
+
"aria-hidden": "true",
|
|
5618
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
5619
|
+
d: "M4.5 2.5 8 6l-3.5 3.5",
|
|
5620
|
+
stroke: "currentColor",
|
|
5621
|
+
strokeWidth: 1.4,
|
|
5622
|
+
strokeLinecap: "round",
|
|
5623
|
+
strokeLinejoin: "round"
|
|
5388
5624
|
})
|
|
5389
|
-
|
|
5625
|
+
}),
|
|
5626
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5627
|
+
className: "v3-gnm",
|
|
5628
|
+
children: skill.name
|
|
5629
|
+
}),
|
|
5630
|
+
PROJECT_SKILL_SOURCES.has(skill.source ?? "") && skill.path !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5631
|
+
className: "v3-cnt",
|
|
5632
|
+
title: skill.path,
|
|
5633
|
+
children: t("projectRootLabel", { path: projectRootForSkill(skill.path) })
|
|
5634
|
+
}),
|
|
5635
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5636
|
+
className: "v3-right",
|
|
5637
|
+
children: [
|
|
5638
|
+
skill.mandatory && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5639
|
+
className: "v3-tag",
|
|
5640
|
+
children: t("mandatory")
|
|
5641
|
+
}),
|
|
5642
|
+
skill.class === "on-demand" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5643
|
+
type: "button",
|
|
5644
|
+
className: "v3-tag v3-tag--act",
|
|
5645
|
+
title: t("editSearchMetadata"),
|
|
5646
|
+
onClick: (e) => {
|
|
5647
|
+
e.stopPropagation();
|
|
5648
|
+
onEditSearch(skill.id);
|
|
5649
|
+
},
|
|
5650
|
+
children: t("searchMetadataButton")
|
|
5651
|
+
}),
|
|
5652
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5653
|
+
type: "button",
|
|
5654
|
+
className: "v3-tag",
|
|
5655
|
+
"data-tone": CLASS_TONE[skill.class],
|
|
5656
|
+
disabled: busy || skill.mandatory,
|
|
5657
|
+
title: skill.classLabel,
|
|
5658
|
+
onClick: (e) => {
|
|
5659
|
+
e.stopPropagation();
|
|
5660
|
+
onCycle([skill.id], "skill");
|
|
5661
|
+
},
|
|
5662
|
+
children: t(CLASS_SHORT_KEYS[skill.class])
|
|
5663
|
+
}),
|
|
5664
|
+
!editableSkills.has(skill.id) && (skill.preset !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5665
|
+
className: "v3-tag",
|
|
5666
|
+
title: t("skillFromPresetHint"),
|
|
5667
|
+
children: t("skillFromPreset", { preset: skill.preset })
|
|
5668
|
+
}) : ADOPTABLE_SKILL_SOURCES.has(skill.source ?? "") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5669
|
+
type: "button",
|
|
5670
|
+
className: "v3-tag v3-tag--act",
|
|
5671
|
+
disabled: busy,
|
|
5672
|
+
title: t("adoptSkillHint"),
|
|
5673
|
+
onClick: (e) => {
|
|
5674
|
+
e.stopPropagation();
|
|
5675
|
+
setConfirmAdopt(skill.id);
|
|
5676
|
+
},
|
|
5677
|
+
children: t("adoptSkill")
|
|
5678
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5679
|
+
className: "v3-tag",
|
|
5680
|
+
title: t("skillSourceHint"),
|
|
5681
|
+
children: t("skillSource", { source: sourceLabel(skill.source, t) })
|
|
5682
|
+
})),
|
|
5683
|
+
editableSkills.has(skill.id) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5684
|
+
type: "button",
|
|
5685
|
+
className: "v3-tag v3-tag--act",
|
|
5686
|
+
disabled: busy,
|
|
5687
|
+
onClick: (e) => {
|
|
5688
|
+
e.stopPropagation();
|
|
5689
|
+
onEditSkill(skill.id, skill.source);
|
|
5690
|
+
},
|
|
5691
|
+
children: t("edit")
|
|
5692
|
+
})
|
|
5693
|
+
]
|
|
5694
|
+
})
|
|
5695
|
+
]
|
|
5696
|
+
}), open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5697
|
+
className: "mc-skill-body",
|
|
5698
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5699
|
+
className: "mc-tree",
|
|
5700
|
+
children: [browseErrors[`${skill.id}:`] !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5701
|
+
className: "mc-preview-hint",
|
|
5702
|
+
children: browseErrors[`${skill.id}:`]
|
|
5703
|
+
}), renderEntries(tree.dirs[`${skill.id}:`], skill.id, "") ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5704
|
+
className: "mc-tree-row",
|
|
5705
|
+
children: "…"
|
|
5706
|
+
})]
|
|
5390
5707
|
})
|
|
5391
|
-
]
|
|
5392
|
-
}
|
|
5393
|
-
|
|
5394
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5395
|
-
className: "mc-tree",
|
|
5396
|
-
children: [browseErrors[`${skill.id}:`] !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5397
|
-
className: "mc-preview-hint",
|
|
5398
|
-
children: browseErrors[`${skill.id}:`]
|
|
5399
|
-
}), renderEntries(tree.dirs[`${skill.id}:`], skill.id, "") ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5400
|
-
className: "mc-tree-row",
|
|
5401
|
-
children: "…"
|
|
5402
|
-
})]
|
|
5403
|
-
})
|
|
5404
|
-
})]
|
|
5405
|
-
}, skill.id);
|
|
5708
|
+
})]
|
|
5709
|
+
}, skill.id);
|
|
5710
|
+
})
|
|
5406
5711
|
}),
|
|
5407
5712
|
confirmAdopt !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
5408
5713
|
open: true,
|
|
@@ -6708,14 +7013,211 @@ function shortCallIndexSessionId(sessionId) {
|
|
|
6708
7013
|
}
|
|
6709
7014
|
/** Inline stylesheet; a `<style>` element keeps this file dependency-free. */
|
|
6710
7015
|
function CallIndexStyles() {
|
|
6711
|
-
return (0, react.createElement)("style", { "data-call-index-style": "true" }, ".mc-ci-filter{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin:8px 0}.mc-ci-filter label{display:flex;gap:4px;align-items:center;font-size:12px}.mc-ci-table-scroll{width:100%;overflow:auto;max-height:min(60vh,560px);overscroll-behavior:contain}.mc-ci-table{width:100%;border-collapse:collapse;font-size:12px}.mc-ci-table thead th{position:sticky;top:0;z-index:1;background:var(--mc-surface,Canvas);box-shadow:inset 0 -1px 0 color-mix(in srgb,currentColor 12%,transparent)}.mc-ci-progress{display:flex;flex-direction:column;gap:4px;margin:8px 0}.mc-ci-progress-track{height:6px;border-radius:999px;overflow:hidden;background:color-mix(in srgb,currentColor 12%,transparent)}.mc-ci-progress-fill{height:100%;border-radius:999px;background:color-mix(in srgb,currentColor 55%,transparent);transition:width .3s ease}.mc-ci-progress-fill.is-indeterminate{animation:mc-ci-indeterminate 1.1s ease-in-out infinite}@keyframes mc-ci-indeterminate{0%{transform:translateX(-60%)}100%{transform:translateX(340%)}}@media (prefers-reduced-motion:reduce){.mc-ci-progress-fill{transition:none}.mc-ci-progress-fill.is-indeterminate{animation:none;width:100%!important;opacity:.4}}.mc-ci-session-picker{display:inline-flex;align-items:center;gap:6px;font-size:12px}.mc-ci-session-picker-label{opacity:.7}.mc-ci-session-select{max-width:280px;padding:3px 6px;border-radius:6px;font-size:12px;border:1px solid color-mix(in srgb,currentColor 22%,transparent);background:transparent;color:inherit}.mc-ci-session-select:disabled{opacity:.5}.mc-ci-progress-meta{display:flex;gap:8px;align-items:baseline;font-size:12px}.mc-ci-progress-value{font-variant-numeric:tabular-nums;font-weight:600}.mc-ci-progress-detail{opacity:.72}.mc-ci-table th,.mc-ci-table td{padding:4px 6px;text-align:left;border-bottom:1px solid color-mix(in srgb,currentColor 12%,transparent);white-space:nowrap}.mc-ci-table tbody tr{cursor:pointer}.mc-ci-table tbody tr[aria-selected=\"true\"]{background:color-mix(in srgb,currentColor 8%,transparent)}.mc-ci-table td:nth-child(2),.mc-ci-table td:nth-child(4){max-width:220px;overflow:hidden;text-overflow:ellipsis}.mc-ci-table th:nth-child(2),.mc-ci-table th:nth-child(4){max-width:220px}.mc-ci-num{font-variant-numeric:tabular-nums}.mc-ci-bar{display:flex;height:8px;gap:1px;margin:4px 0}.mc-ci-bar > span{display:block;height:100%;min-width:2px}.mc-ci-aside{border-left:1px solid color-mix(in srgb,currentColor 15%,transparent);padding-left:12px;min-width:240px;font-size:12px}.mc-ci-metric{display:inline-flex;flex-direction:column;margin-right:18px;min-width:110px;vertical-align:top}.mc-ci-metric-label{font-size:11px;opacity:.7}.mc-ci-metric-value{font-size:18px;font-variant-numeric:tabular-nums}.mc-ci-metric-hint{font-size:11px;opacity:.75}.mc-ci-trend svg{width:100%;max-width:640px;height:auto}");
|
|
7016
|
+
return (0, react.createElement)("style", { "data-call-index-style": "true" }, ".mc-ci-filter{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin:8px 0}.mc-ci-filter label{display:flex;gap:4px;align-items:center;font-size:12px}.mc-ci-table-scroll{width:100%;overflow:auto;max-height:min(60vh,560px);overscroll-behavior:contain}.mc-ci-table{width:100%;border-collapse:collapse;font-size:12px}.mc-ci-table thead th{position:sticky;top:0;z-index:1;background:var(--mc-surface,Canvas);box-shadow:inset 0 -1px 0 color-mix(in srgb,currentColor 12%,transparent)}.mc-ci-progress{display:flex;flex-direction:column;gap:4px;margin:8px 0}.mc-ci-progress-track{height:6px;border-radius:999px;overflow:hidden;background:color-mix(in srgb,currentColor 12%,transparent)}.mc-ci-progress-fill{height:100%;border-radius:999px;background:color-mix(in srgb,currentColor 55%,transparent);transition:width .3s ease}.mc-ci-progress-fill.is-indeterminate{animation:mc-ci-indeterminate 1.1s ease-in-out infinite}@keyframes mc-ci-indeterminate{0%{transform:translateX(-60%)}100%{transform:translateX(340%)}}@media (prefers-reduced-motion:reduce){.mc-ci-progress-fill{transition:none}.mc-ci-progress-fill.is-indeterminate{animation:none;width:100%!important;opacity:.4}}.mc-ci-session-picker{display:inline-flex;align-items:center;gap:6px;font-size:12px}.mc-ci-session-picker-label{opacity:.7}.mc-ci-session-select{max-width:280px;padding:3px 6px;border-radius:6px;font-size:12px;border:1px solid color-mix(in srgb,currentColor 22%,transparent);background:transparent;color:inherit}.mc-ci-session-select:disabled{opacity:.5}.mc-ci-progress-meta{display:flex;gap:8px;align-items:baseline;font-size:12px}.mc-ci-progress-value{font-variant-numeric:tabular-nums;font-weight:600}.mc-ci-progress-detail{opacity:.72}.mc-ci-table th,.mc-ci-table td{padding:4px 6px;text-align:left;border-bottom:1px solid color-mix(in srgb,currentColor 12%,transparent);white-space:nowrap}.mc-ci-table tbody tr{cursor:pointer}.mc-ci-table tbody tr[aria-selected=\"true\"]{background:color-mix(in srgb,currentColor 8%,transparent)}.mc-ci-table td:nth-child(2),.mc-ci-table td:nth-child(4){max-width:220px;overflow:hidden;text-overflow:ellipsis}.mc-ci-table th:nth-child(2),.mc-ci-table th:nth-child(4){max-width:220px}.mc-ci-num{font-variant-numeric:tabular-nums}.mc-ci-bar{display:flex;height:8px;gap:1px;margin:4px 0}.mc-ci-bar > span{display:block;height:100%;min-width:2px}.mc-ci-aside{border-left:1px solid color-mix(in srgb,currentColor 15%,transparent);padding-left:12px;min-width:240px;font-size:12px}.mc-ci-metric{display:inline-flex;flex-direction:column;margin-right:18px;min-width:110px;vertical-align:top}.mc-ci-metric-label{font-size:11px;opacity:.7}.mc-ci-metric-value{font-size:18px;font-variant-numeric:tabular-nums}.mc-ci-metric-hint{font-size:11px;opacity:.75}.mc-ci-trend svg{width:100%;max-width:640px;height:auto}.v3-status-pills{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-bottom:12px}.v3-statusline.v3-status-dash{border-style:dashed;color:var(--v3-t4)}.v3-filtercard{padding:11px 14px 13px}.v3-filter-row{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-bottom:9px}.v3-search{display:flex;align-items:center;gap:6px;height:26px;padding:0 8px;border:1px solid var(--v3-line);border-radius:var(--v3-r-sm);background:var(--v3-panel-2);min-width:150px;flex:1 1 150px}.v3-search input{border:0;background:transparent;color:var(--v3-t1);font:inherit;font-size:12px;width:100%;outline:0;min-width:0}.v3-search input::placeholder{color:var(--v3-t4)}.v3-kv{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px}.v3-kv-l{font-size:11px;color:var(--v3-t4)}.v3-kv-v{font-size:12px;color:var(--v3-t2);margin-top:2px;overflow-wrap:anywhere}.v3-ts.v3-ts--h330{max-height:330px}.v3-src i[data-zero=\"true\"]{background:var(--v3-panel-2)}");
|
|
6712
7017
|
}
|
|
6713
|
-
/**
|
|
6714
|
-
function
|
|
7018
|
+
/** One v3 `.v3-stat` cell: label, big value, optional hint line, optional sparkline. */
|
|
7019
|
+
function V3Stat(props) {
|
|
6715
7020
|
return (0, react.createElement)("div", {
|
|
6716
|
-
className: "
|
|
6717
|
-
"data-call-index-metric": label
|
|
6718
|
-
}, (0, react.createElement)("div", { className: "
|
|
7021
|
+
className: "v3-stat",
|
|
7022
|
+
"data-call-index-metric": props.label
|
|
7023
|
+
}, (0, react.createElement)("div", { className: "v3-stat-l" }, props.label), (0, react.createElement)("div", { className: "v3-stat-v v3-num" }, props.value), props.hint === void 0 ? null : (0, react.createElement)("div", { className: "v3-stat-d" }, props.hint), props.spark ?? null);
|
|
7024
|
+
}
|
|
7025
|
+
/** Values → `x,y` points inside a 100×22 viewBox, baselined at 0. */
|
|
7026
|
+
function sparkPoints(values) {
|
|
7027
|
+
const W = 100, H = 22;
|
|
7028
|
+
const max = values.reduce((m, v) => Math.max(m, v), 0);
|
|
7029
|
+
const scale = max > 0 ? max : 1;
|
|
7030
|
+
const xAt = (i) => values.length <= 1 ? W / 2 : i * W / (values.length - 1);
|
|
7031
|
+
const yAt = (v) => 20 - v / scale * 18;
|
|
7032
|
+
const pts = values.map((v, i) => `${xAt(i).toFixed(1)},${yAt(v).toFixed(1)}`);
|
|
7033
|
+
return {
|
|
7034
|
+
line: pts.join(" "),
|
|
7035
|
+
area: `0,${H} ${pts.join(" ")} ${W},${H}`
|
|
7036
|
+
};
|
|
7037
|
+
}
|
|
7038
|
+
/** 22px trend sparkline: a line plus a translucent area fill, coloured by tone. */
|
|
7039
|
+
function Sparkline(props) {
|
|
7040
|
+
if (props.values.length < 2) return null;
|
|
7041
|
+
const points = sparkPoints(props.values);
|
|
7042
|
+
const colour = props.tone === "ok" ? "var(--v3-ok)" : props.tone === "bad" ? "var(--v3-bad)" : "var(--v3-info)";
|
|
7043
|
+
return (0, react.createElement)("svg", {
|
|
7044
|
+
className: "v3-spark",
|
|
7045
|
+
viewBox: "0 0 100 22",
|
|
7046
|
+
preserveAspectRatio: "none",
|
|
7047
|
+
"aria-hidden": "true",
|
|
7048
|
+
"data-call-index-spark": props.tone
|
|
7049
|
+
}, (0, react.createElement)("polygon", {
|
|
7050
|
+
className: "v3-spark-fl",
|
|
7051
|
+
points: points.area,
|
|
7052
|
+
fill: colour
|
|
7053
|
+
}), (0, react.createElement)("polyline", {
|
|
7054
|
+
className: "v3-spark-ln",
|
|
7055
|
+
points: points.line,
|
|
7056
|
+
stroke: colour
|
|
7057
|
+
}));
|
|
7058
|
+
}
|
|
7059
|
+
/** `server · tool` for an `mcp__` name, otherwise the bare tool name. */
|
|
7060
|
+
function toolDisplayLabel(toolName) {
|
|
7061
|
+
if (toolName.startsWith("mcp__")) {
|
|
7062
|
+
const parts = toolName.split("__");
|
|
7063
|
+
return parts.length >= 3 ? `${parts[1]} · ${parts.slice(2).join("__")}` : toolName;
|
|
7064
|
+
}
|
|
7065
|
+
return toolName;
|
|
7066
|
+
}
|
|
7067
|
+
/**
|
|
7068
|
+
* The v3 overview trend: a 720×212 line + area (calls), failure底柱 (error), a
|
|
7069
|
+
* dashed "recent week" band and a peak label. Drawn from `callIndexTrend`'s bars
|
|
7070
|
+
* so its numbers are the same ones the caption quotes — no second data path.
|
|
7071
|
+
*/
|
|
7072
|
+
function OverviewTrendSvg(props) {
|
|
7073
|
+
const { chart } = props, W = 720, H = 212, padL = 34, padT = 12;
|
|
7074
|
+
const plotW = 676;
|
|
7075
|
+
const plotH = 174;
|
|
7076
|
+
const bars = chart.bars;
|
|
7077
|
+
const n = bars.length;
|
|
7078
|
+
const maxV = chart.maxCalls > 0 ? Math.ceil(chart.maxCalls / 10) * 10 : 1;
|
|
7079
|
+
const xAt = (i) => padL + (n <= 1 ? plotW / 2 : i * plotW / (n - 1));
|
|
7080
|
+
const yAt = (v) => 186 - v / maxV * plotH;
|
|
7081
|
+
const points = bars.map((bar, i) => `${xAt(i).toFixed(1)},${yAt(bar.calls).toFixed(1)}`);
|
|
7082
|
+
let peak = 0;
|
|
7083
|
+
for (let i = 1; i < n; i++) if (bars[i].calls > bars[peak].calls) peak = i;
|
|
7084
|
+
const children = [];
|
|
7085
|
+
if (n > 0) {
|
|
7086
|
+
const start = Math.max(0, n - 7);
|
|
7087
|
+
const slot = n > 1 ? plotW / (n - 1) : plotW;
|
|
7088
|
+
const left = Math.max(padL, xAt(start) - slot / 2);
|
|
7089
|
+
const right = Math.min(710, xAt(n - 1) + slot / 2);
|
|
7090
|
+
children.push((0, react.createElement)("rect", {
|
|
7091
|
+
key: "hl",
|
|
7092
|
+
className: "v3-hlbox",
|
|
7093
|
+
x: left.toFixed(1),
|
|
7094
|
+
y: padT,
|
|
7095
|
+
width: Math.max(0, right - left).toFixed(1),
|
|
7096
|
+
height: plotH.toFixed(1),
|
|
7097
|
+
rx: 4
|
|
7098
|
+
}));
|
|
7099
|
+
}
|
|
7100
|
+
for (let g = 0; g <= 4; g++) {
|
|
7101
|
+
const value = maxV * g / 4;
|
|
7102
|
+
const y = yAt(value);
|
|
7103
|
+
children.push((0, react.createElement)("line", {
|
|
7104
|
+
key: `grid-${g}`,
|
|
7105
|
+
className: "v3-grid",
|
|
7106
|
+
x1: padL,
|
|
7107
|
+
y1: y.toFixed(1),
|
|
7108
|
+
x2: 710,
|
|
7109
|
+
y2: y.toFixed(1)
|
|
7110
|
+
}));
|
|
7111
|
+
children.push((0, react.createElement)("text", {
|
|
7112
|
+
key: `tick-${g}`,
|
|
7113
|
+
className: "v3-axis",
|
|
7114
|
+
x: 27,
|
|
7115
|
+
y: (y + 3.5).toFixed(1),
|
|
7116
|
+
"text-anchor": "end"
|
|
7117
|
+
}, String(Math.round(value))));
|
|
7118
|
+
}
|
|
7119
|
+
const barWidth = Math.max(4, plotW / Math.max(1, n) - 8);
|
|
7120
|
+
bars.forEach((bar, i) => {
|
|
7121
|
+
if (bar.error <= 0) return;
|
|
7122
|
+
const errH = Math.max(2.5, bar.error / maxV * plotH);
|
|
7123
|
+
children.push((0, react.createElement)("rect", {
|
|
7124
|
+
key: `err-${bar.day}`,
|
|
7125
|
+
className: "v3-bar-er",
|
|
7126
|
+
x: (xAt(i) - barWidth / 2).toFixed(1),
|
|
7127
|
+
y: (186 - errH).toFixed(1),
|
|
7128
|
+
width: barWidth.toFixed(1),
|
|
7129
|
+
height: errH.toFixed(1),
|
|
7130
|
+
rx: 1.5
|
|
7131
|
+
}, (0, react.createElement)("title", null, `${bar.day}:失败 ${bar.error} 次`)));
|
|
7132
|
+
});
|
|
7133
|
+
children.push((0, react.createElement)("polygon", {
|
|
7134
|
+
key: "area",
|
|
7135
|
+
className: "v3-area",
|
|
7136
|
+
points: `${padL},186 ${points.join(" ")} 710,186`
|
|
7137
|
+
}));
|
|
7138
|
+
children.push((0, react.createElement)("polyline", {
|
|
7139
|
+
key: "line",
|
|
7140
|
+
className: "v3-line",
|
|
7141
|
+
points: points.join(" ")
|
|
7142
|
+
}));
|
|
7143
|
+
bars.forEach((bar, i) => {
|
|
7144
|
+
if (i % 4 !== 0 && i !== n - 1 && i !== peak) return;
|
|
7145
|
+
children.push((0, react.createElement)("circle", {
|
|
7146
|
+
key: `pt-${bar.day}`,
|
|
7147
|
+
className: "v3-pt",
|
|
7148
|
+
cx: xAt(i).toFixed(1),
|
|
7149
|
+
cy: yAt(bar.calls).toFixed(1),
|
|
7150
|
+
r: 2.6
|
|
7151
|
+
}, (0, react.createElement)("title", null, `${bar.day}:${bar.calls} 次调用,失败 ${bar.error} 次`)));
|
|
7152
|
+
});
|
|
7153
|
+
if (n > 0) {
|
|
7154
|
+
children.push((0, react.createElement)("text", {
|
|
7155
|
+
key: "peak",
|
|
7156
|
+
className: "v3-lbl-b",
|
|
7157
|
+
x: (xAt(peak) - 8).toFixed(1),
|
|
7158
|
+
y: (yAt(bars[peak].calls) - 9).toFixed(1),
|
|
7159
|
+
"text-anchor": "end"
|
|
7160
|
+
}, `峰值 ${bars[peak].calls}`));
|
|
7161
|
+
for (let m = 0; m < n; m += 5) children.push((0, react.createElement)("text", {
|
|
7162
|
+
key: `xl-${m}`,
|
|
7163
|
+
className: "v3-axis",
|
|
7164
|
+
x: xAt(m).toFixed(1),
|
|
7165
|
+
y: 204,
|
|
7166
|
+
"text-anchor": "middle"
|
|
7167
|
+
}, bars[m].day.slice(5)));
|
|
7168
|
+
children.push((0, react.createElement)("text", {
|
|
7169
|
+
key: "xl-last",
|
|
7170
|
+
className: "v3-axis",
|
|
7171
|
+
x: 710,
|
|
7172
|
+
y: 204,
|
|
7173
|
+
"text-anchor": "end"
|
|
7174
|
+
}, bars[n - 1].day.slice(5)));
|
|
7175
|
+
}
|
|
7176
|
+
return (0, react.createElement)("svg", {
|
|
7177
|
+
className: "v3-chart",
|
|
7178
|
+
viewBox: `0 0 ${W} ${H}`,
|
|
7179
|
+
preserveAspectRatio: "none",
|
|
7180
|
+
role: "img",
|
|
7181
|
+
"aria-label": `每日调用与失败数:${n} 天,峰值 ${chart.maxCalls} 次`,
|
|
7182
|
+
"data-call-index-svg": "trend"
|
|
7183
|
+
}, ...children);
|
|
7184
|
+
}
|
|
7185
|
+
/** 来源构成: a one-segment donut (未解析) + five-source list + an honesty note. */
|
|
7186
|
+
function OverviewSourcePanel(props) {
|
|
7187
|
+
if (props.bySource === void 0) return (0, react.createElement)("div", { className: "v3-panel" }, (0, react.createElement)("div", { className: "v3-ph" }, (0, react.createElement)("span", { className: "v3-pt" }, "来源构成")), (0, react.createElement)("p", {
|
|
7188
|
+
className: "v3-hint",
|
|
7189
|
+
"data-call-index-missing": "by-source"
|
|
7190
|
+
}, "Host 未返回来源分布(bySource);这不是「全部为 0」。"));
|
|
7191
|
+
const data = callIndexSourceData(props.bySource);
|
|
7192
|
+
const total = data.reduce((sum, item) => sum + item.count, 0);
|
|
7193
|
+
const unknownCount = data.find((item) => item.kind === "unknown")?.count ?? 0;
|
|
7194
|
+
const share = total > 0 ? unknownCount / total : 0;
|
|
7195
|
+
const percent = Math.round(share * 100);
|
|
7196
|
+
const radius = 43;
|
|
7197
|
+
const circumference = 2 * Math.PI * radius;
|
|
7198
|
+
const segment = share * circumference;
|
|
7199
|
+
const allUnresolved = total > 0 && unknownCount === total;
|
|
7200
|
+
return (0, react.createElement)("div", { className: "v3-panel" }, (0, react.createElement)("div", { className: "v3-ph" }, (0, react.createElement)("span", { className: "v3-pt" }, "来源构成"), (0, react.createElement)("span", { className: "v3-pn" }, `${formatCallIndexCount(total, props.totalExact)} 次`)), (0, react.createElement)("div", { className: "v3-donut-wrap" }, (0, react.createElement)("div", { className: "v3-donut" }, (0, react.createElement)("svg", {
|
|
7201
|
+
viewBox: "0 0 104 104",
|
|
7202
|
+
"aria-hidden": "true"
|
|
7203
|
+
}, (0, react.createElement)("circle", {
|
|
7204
|
+
className: "v3-trk",
|
|
7205
|
+
cx: 52,
|
|
7206
|
+
cy: 52,
|
|
7207
|
+
r: radius
|
|
7208
|
+
}), (0, react.createElement)("circle", {
|
|
7209
|
+
className: "v3-seg",
|
|
7210
|
+
cx: 52,
|
|
7211
|
+
cy: 52,
|
|
7212
|
+
r: radius,
|
|
7213
|
+
"data-seg": "unknown",
|
|
7214
|
+
strokeDasharray: `${segment.toFixed(1)} ${(circumference - segment).toFixed(1)}`,
|
|
7215
|
+
strokeDashoffset: 0
|
|
7216
|
+
})), (0, react.createElement)("div", { className: "v3-mid" }, (0, react.createElement)("b", { className: "v3-num" }, `${percent}%`), (0, react.createElement)("span", null, "未解析"))), (0, react.createElement)("div", { className: "v3-src-list" }, ...data.map((item) => (0, react.createElement)("div", {
|
|
7217
|
+
key: item.kind,
|
|
7218
|
+
className: "v3-src",
|
|
7219
|
+
"data-source-row": item.kind
|
|
7220
|
+
}, (0, react.createElement)("i", item.count === 0 ? { "data-zero": "true" } : {}), (0, react.createElement)("span", { className: "v3-nm" }, item.label), (0, react.createElement)("b", null, formatCallIndexCount(item.count, props.totalExact)), (0, react.createElement)("em", null, total > 0 ? `${Math.round(item.share * 100)}%` : "0%"))))), (0, react.createElement)("p", { className: "v3-src-note" }, allUnresolved ? `Host 无法证明插件 owner,非 mcp__ 前缀的调用也不带归属证据,所以 ${formatCallIndexCount(total, props.totalExact)} 次调用全部落在「来源未解析」——这是当前唯一真实的分布形态,不是抽样。` : "Host 无法证明插件 owner,非 mcp__ 前缀的调用也不带归属证据;未解析出归属的调用单列为「来源未解析」,其余按 Host 能证明的 kind 归类。", (0, react.createElement)("b", { style: { color: "var(--v3-t3)" } }, " 0 在这里不等于未使用")));
|
|
6719
7221
|
}
|
|
6720
7222
|
function callIndexDiagnostics(input) {
|
|
6721
7223
|
const items = [];
|
|
@@ -6775,96 +7277,6 @@ function StateNotice({ state, failure }) {
|
|
|
6775
7277
|
"data-call-index-state": state.kind
|
|
6776
7278
|
}, (0, react.createElement)("strong", null, state.title), state.detail === "" ? null : (0, react.createElement)("p", { className: "mc-desc" }, state.detail), failure?.retryable === true && state.canRetry ? (0, react.createElement)("p", { className: "mc-desc" }, "这是一个可重试的错误;重试会重新读取,不会重放旧游标。") : null);
|
|
6777
7279
|
}
|
|
6778
|
-
/** Source distribution bars (bySource). */
|
|
6779
|
-
function CallIndexSourceBars(props) {
|
|
6780
|
-
const data = callIndexSourceData(props.bySource);
|
|
6781
|
-
const present = data.filter((item) => item.count > 0);
|
|
6782
|
-
return (0, react.createElement)("div", {
|
|
6783
|
-
className: "mc-ci-sources",
|
|
6784
|
-
"data-call-index-block": "by-source"
|
|
6785
|
-
}, (0, react.createElement)("h4", {
|
|
6786
|
-
className: "mc-heading",
|
|
6787
|
-
style: { fontSize: 13 }
|
|
6788
|
-
}, "来源分布"), props.bySource === void 0 ? (0, react.createElement)("p", {
|
|
6789
|
-
className: "mc-empty",
|
|
6790
|
-
"data-call-index-missing": "by-source"
|
|
6791
|
-
}, "Host 未返回来源分布(bySource);这不是「全部为 0」。") : (0, react.createElement)("div", {
|
|
6792
|
-
className: "mc-ci-bar",
|
|
6793
|
-
role: "img",
|
|
6794
|
-
"aria-label": "来源分布条"
|
|
6795
|
-
}, ...present.map((item) => (0, react.createElement)("span", {
|
|
6796
|
-
key: item.kind,
|
|
6797
|
-
"data-source-kind": item.kind,
|
|
6798
|
-
title: `${item.label}:${formatCallIndexCount(item.count, props.totalExact)}`,
|
|
6799
|
-
style: {
|
|
6800
|
-
flexGrow: item.count,
|
|
6801
|
-
background: `var(--mc-source-${item.kind}, currentColor)`,
|
|
6802
|
-
opacity: .65
|
|
6803
|
-
}
|
|
6804
|
-
}))), ...data.map((item) => (0, react.createElement)("div", {
|
|
6805
|
-
className: "mc-ci-source-row",
|
|
6806
|
-
key: item.kind,
|
|
6807
|
-
"data-source-row": item.kind
|
|
6808
|
-
}, (0, react.createElement)("span", { className: "mc-source" }, item.label), (0, react.createElement)("span", { className: "mc-ci-num" }, formatCallIndexCount(item.count, props.totalExact)), item.zeroNote === void 0 ? null : (0, react.createElement)("span", {
|
|
6809
|
-
className: "mc-desc",
|
|
6810
|
-
"data-call-index-zero": item.kind
|
|
6811
|
-
}, item.zeroNote))));
|
|
6812
|
-
}
|
|
6813
|
-
/** Self-drawn SVG trend: no chart library, deterministic geometry. */
|
|
6814
|
-
function CallIndexTrendChart(props) {
|
|
6815
|
-
const chart = callIndexTrend(props.aggregates?.byDay);
|
|
6816
|
-
const geometry = CALL_INDEX_TREND_GEOMETRY;
|
|
6817
|
-
if (props.aggregates === void 0) return (0, react.createElement)("div", {
|
|
6818
|
-
className: "mc-ci-trend",
|
|
6819
|
-
"data-call-index-block": "trend"
|
|
6820
|
-
}, (0, react.createElement)("h4", {
|
|
6821
|
-
className: "mc-heading",
|
|
6822
|
-
style: { fontSize: 13 }
|
|
6823
|
-
}, "按日趋势"), (0, react.createElement)("p", {
|
|
6824
|
-
className: "mc-empty",
|
|
6825
|
-
"data-call-index-missing": "aggregates"
|
|
6826
|
-
}, "Host 未返回按日聚合(aggregates);这不是「没有调用」,趋势不可用。"));
|
|
6827
|
-
if (!chart.available) return (0, react.createElement)("div", {
|
|
6828
|
-
className: "mc-ci-trend",
|
|
6829
|
-
"data-call-index-block": "trend"
|
|
6830
|
-
}, (0, react.createElement)("h4", {
|
|
6831
|
-
className: "mc-heading",
|
|
6832
|
-
style: { fontSize: 13 }
|
|
6833
|
-
}, "按日趋势"), (0, react.createElement)("p", {
|
|
6834
|
-
className: "mc-empty",
|
|
6835
|
-
"data-call-index-missing": "by-day"
|
|
6836
|
-
}, "该筛选在所选范围内没有任何按日桶,趋势为空;单个日粒度为 0 不参与绘制。"));
|
|
6837
|
-
return (0, react.createElement)("div", {
|
|
6838
|
-
className: "mc-ci-trend",
|
|
6839
|
-
"data-call-index-block": "trend"
|
|
6840
|
-
}, (0, react.createElement)("h4", {
|
|
6841
|
-
className: "mc-heading",
|
|
6842
|
-
style: { fontSize: 13 }
|
|
6843
|
-
}, "按日趋势"), (0, react.createElement)("svg", {
|
|
6844
|
-
viewBox: `0 0 ${geometry.width} ${geometry.height}`,
|
|
6845
|
-
role: "img",
|
|
6846
|
-
"aria-label": `按日调用趋势(已索引部分):${chart.bars.length} 天,峰值 ${chart.maxCalls} 次`,
|
|
6847
|
-
"data-call-index-svg": "trend"
|
|
6848
|
-
}, ...chart.bars.map((bar) => (0, react.createElement)("rect", {
|
|
6849
|
-
key: bar.day,
|
|
6850
|
-
x: bar.x,
|
|
6851
|
-
y: bar.y,
|
|
6852
|
-
width: bar.width,
|
|
6853
|
-
height: bar.height,
|
|
6854
|
-
"data-day": bar.day,
|
|
6855
|
-
"data-calls": bar.calls,
|
|
6856
|
-
fill: bar.error > 0 ? "var(--mc-trend-error, currentColor)" : "currentColor",
|
|
6857
|
-
opacity: bar.error > 0 ? .85 : .55
|
|
6858
|
-
})), ...chart.bars.map((bar) => (0, react.createElement)("text", {
|
|
6859
|
-
key: `label-${bar.day}`,
|
|
6860
|
-
x: bar.x + bar.width / 2,
|
|
6861
|
-
y: geometry.height - 6,
|
|
6862
|
-
"font-size": 9,
|
|
6863
|
-
"text-anchor": "middle",
|
|
6864
|
-
fill: "currentColor",
|
|
6865
|
-
opacity: .7
|
|
6866
|
-
}, bar.day.slice(5)))), (0, react.createElement)("p", { className: "mc-desc" }, `图上 ${chart.bars.length} 天、${chart.totalCalls} 次调用;峰值 ${chart.maxCalls} 次/天。柱高按峰值归一。趋势只统计已索引部分,覆盖不完整时右侧天数与总数都可能偏少。`));
|
|
6867
|
-
}
|
|
6868
7280
|
/**
|
|
6869
7281
|
* Turn the index census into a progress percentage.
|
|
6870
7282
|
*
|
|
@@ -7033,26 +7445,73 @@ function callIndexToolRows(page) {
|
|
|
7033
7445
|
...entry.durationCount === 0 ? {} : { averageDurationMs: entry.durationSum / entry.durationCount }
|
|
7034
7446
|
})).sort((a, b) => b.calls - a.calls || a.toolName.localeCompare(b.toolName));
|
|
7035
7447
|
}
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7448
|
+
/** Short source marker for the tool cell: MCP / 技能 / 插件 / 来源未解析. */
|
|
7449
|
+
function sourceNoteForKind(kind) {
|
|
7450
|
+
switch (kind) {
|
|
7451
|
+
case "mcp": return "MCP";
|
|
7452
|
+
case "skill": return "技能";
|
|
7453
|
+
case "plugin-tool": return "插件";
|
|
7454
|
+
case "unknown": return "来源未解析";
|
|
7455
|
+
default: return;
|
|
7456
|
+
}
|
|
7457
|
+
}
|
|
7458
|
+
/**
|
|
7459
|
+
* The v3 "完整工具表": one sticky-header row per TOOL, inside a bounded
|
|
7460
|
+
* `.v3-ts` scroller (330px here — the two charts above it already tell the big
|
|
7461
|
+
* picture). Takes pre-computed rows so the same filtered set feeds the charts.
|
|
7462
|
+
*/
|
|
7463
|
+
function CallIndexToolTable(props) {
|
|
7464
|
+
return (0, react.createElement)("div", { className: "v3-ts v3-ts--h330" }, (0, react.createElement)("table", {
|
|
7465
|
+
className: "v3-table",
|
|
7041
7466
|
"data-call-index-table": "tools"
|
|
7042
7467
|
}, (0, react.createElement)("thead", null, (0, react.createElement)("tr", null, ...[
|
|
7043
|
-
|
|
7044
|
-
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
|
|
7054
|
-
|
|
7055
|
-
|
|
7468
|
+
{
|
|
7469
|
+
label: "工具",
|
|
7470
|
+
right: false
|
|
7471
|
+
},
|
|
7472
|
+
{
|
|
7473
|
+
label: "调用",
|
|
7474
|
+
right: true
|
|
7475
|
+
},
|
|
7476
|
+
{
|
|
7477
|
+
label: "失败",
|
|
7478
|
+
right: true
|
|
7479
|
+
},
|
|
7480
|
+
{
|
|
7481
|
+
label: "成功率",
|
|
7482
|
+
right: true
|
|
7483
|
+
},
|
|
7484
|
+
{
|
|
7485
|
+
label: "平均耗时",
|
|
7486
|
+
right: true
|
|
7487
|
+
},
|
|
7488
|
+
{
|
|
7489
|
+
label: "最近调用",
|
|
7490
|
+
right: true
|
|
7491
|
+
}
|
|
7492
|
+
].map((col) => (0, react.createElement)("th", {
|
|
7493
|
+
key: col.label,
|
|
7494
|
+
scope: "col",
|
|
7495
|
+
...col.right ? { className: "v3-r" } : {}
|
|
7496
|
+
}, col.label)))), (0, react.createElement)("tbody", null, ...props.rows.map((row) => {
|
|
7497
|
+
const known = row.success + row.error;
|
|
7498
|
+
const rate = known > 0 ? row.success / known : void 0;
|
|
7499
|
+
const bad = row.error > 0 && row.error / row.calls >= .2;
|
|
7500
|
+
const note = sourceNoteForKind(row.sourceKind);
|
|
7501
|
+
const server = row.toolName.startsWith("mcp__") ? row.toolName.split("__")[1] : void 0;
|
|
7502
|
+
const shortName = row.sourceKind === "mcp" && row.toolName.startsWith("mcp__") ? row.toolName.split("__").slice(2).join("__") : row.toolName;
|
|
7503
|
+
return (0, react.createElement)("tr", {
|
|
7504
|
+
key: row.toolName + "::" + row.sourceKind,
|
|
7505
|
+
"data-call-index-tool": row.toolName
|
|
7506
|
+
}, (0, react.createElement)("td", null, (0, react.createElement)("div", { className: "v3-c-tool" }, note === void 0 ? null : (0, react.createElement)("span", { className: "v3-srcnote" }, note), (0, react.createElement)("span", {
|
|
7507
|
+
className: "v3-nm",
|
|
7508
|
+
title: row.toolName
|
|
7509
|
+
}, shortName), server === void 0 ? null : (0, react.createElement)("span", { className: "v3-srv" }, server))), (0, react.createElement)("td", { className: "v3-r" }, String(row.calls)), (0, react.createElement)("td", { className: "v3-r" }, String(row.error)), (0, react.createElement)("td", { className: "v3-r" }, (0, react.createElement)("span", { className: "v3-rt" }, (0, react.createElement)("span", { className: "v3-tk" }, (0, react.createElement)("span", {
|
|
7510
|
+
className: "v3-fl",
|
|
7511
|
+
...bad ? { "data-bad": "true" } : {},
|
|
7512
|
+
style: { width: `${Math.round((rate ?? 0) * 100)}%` }
|
|
7513
|
+
})), (0, react.createElement)("b", null, formatCallIndexRate(rate)))), (0, react.createElement)("td", { className: "v3-r" }, formatCallIndexDuration(row.averageDurationMs)), (0, react.createElement)("td", { className: "v3-r" }, formatCallIndexTime(row.lastAt)));
|
|
7514
|
+
}))));
|
|
7056
7515
|
}
|
|
7057
7516
|
function callIndexRates(summary) {
|
|
7058
7517
|
if (summary === void 0) return {};
|
|
@@ -7084,7 +7543,7 @@ function formatCallIndexRate(value) {
|
|
|
7084
7543
|
* Modal; the container decides it from a media query, so this stays pure.
|
|
7085
7544
|
*/
|
|
7086
7545
|
function CallIndexDetailPanelView(props) {
|
|
7087
|
-
const { query, status, page, loading, loadingMore, failure, onQueryChange, onResolveScope, catalog, moreFailure, startFailure, startTask } = props;
|
|
7546
|
+
const { query, status, page, loading, loadingMore, failure, onQueryChange, onResolveScope, catalog, moreFailure, startFailure, startTask, search, onSearchChange } = props;
|
|
7088
7547
|
const state = callIndexDetailState({
|
|
7089
7548
|
status,
|
|
7090
7549
|
page,
|
|
@@ -7093,74 +7552,250 @@ function CallIndexDetailPanelView(props) {
|
|
|
7093
7552
|
...failure === void 0 ? {} : { failure }
|
|
7094
7553
|
});
|
|
7095
7554
|
const totalText = page === void 0 ? void 0 : formatCallIndexCount(page.total ?? page.summary.total, page.totalExact);
|
|
7096
|
-
const
|
|
7555
|
+
const coverageLabel = page === void 0 ? void 0 : COVERAGE_LABELS[page.coverage];
|
|
7556
|
+
const scanning = status !== void 0 && (status.phase === "running" || (status.sessions?.pending ?? 0) > 0 || (status.sessions?.pendingLive ?? 0) > 0);
|
|
7557
|
+
const statusText = page === void 0 ? loading === true ? "正在读取调用明细…" : "尚未读取调用明细" : `快照代 ${page.generation} · 覆盖 ${coverageLabel ?? "未知"} · 按工具聚合`;
|
|
7097
7558
|
const rates = callIndexRates(page?.summary);
|
|
7098
7559
|
const successStats = rates.success;
|
|
7099
7560
|
const failureStats = rates.failure;
|
|
7100
7561
|
const rateText = (value) => formatCallIndexRate(value);
|
|
7101
7562
|
const rateHint = (stats) => stats === void 0 ? "没有已知结果的调用,无法计算比例" : `${stats.numerator} / ${stats.denominator} 次已知结果`;
|
|
7102
7563
|
const suggestionCount = page === void 0 ? void 0 : (page.summary.unresolved ?? 0) + page.summary.error;
|
|
7103
|
-
const suggestionText = () => suggestionCount === void 0 ? "—" : String(suggestionCount);
|
|
7104
7564
|
const suggestionHint = () => page === void 0 ? "尚未读取" : `失败 ${page.summary.error} + 未配对 ${page.summary.unresolved ?? 0};未配对表示没有捕获到结果,不等于失败`;
|
|
7565
|
+
const allRows = page === void 0 ? [] : callIndexToolRows(page);
|
|
7566
|
+
const term = (search ?? "").trim().toLowerCase();
|
|
7567
|
+
const rows = term === "" ? allRows : allRows.filter((row) => row.toolName.toLowerCase().includes(term));
|
|
7568
|
+
const durations = page === void 0 ? [] : page.items.map((item) => item.durationMs).filter((ms) => ms !== void 0 && Number.isFinite(ms));
|
|
7569
|
+
const averageDuration = durations.length > 0 ? durations.reduce((sum, ms) => sum + ms, 0) / durations.length : void 0;
|
|
7570
|
+
const readCalls = rows.reduce((sum, row) => sum + row.calls, 0);
|
|
7571
|
+
const totalCalls = page === void 0 ? void 0 : page.total ?? page.summary.total;
|
|
7572
|
+
const readIsPartial = totalCalls !== void 0 && readCalls < totalCalls;
|
|
7573
|
+
const rankRows = rows.slice(0, 12);
|
|
7574
|
+
const rankMax = rankRows.length > 0 ? rankRows[0].calls : 1;
|
|
7575
|
+
const failingRows = rows.filter((row) => row.error > 0).slice().sort((a, b) => b.error - a.error);
|
|
7576
|
+
const failMax = failingRows.length > 0 ? failingRows[0].error : 1;
|
|
7577
|
+
const searchInput = (0, react.createElement)("label", { className: "v3-search" }, (0, react.createElement)("svg", {
|
|
7578
|
+
width: 12,
|
|
7579
|
+
height: 12,
|
|
7580
|
+
viewBox: "0 0 14 14",
|
|
7581
|
+
fill: "none",
|
|
7582
|
+
"aria-hidden": "true",
|
|
7583
|
+
style: {
|
|
7584
|
+
color: "var(--v3-t4)",
|
|
7585
|
+
flex: "none"
|
|
7586
|
+
}
|
|
7587
|
+
}, (0, react.createElement)("circle", {
|
|
7588
|
+
cx: 6.2,
|
|
7589
|
+
cy: 6.2,
|
|
7590
|
+
r: 4.4,
|
|
7591
|
+
stroke: "currentColor",
|
|
7592
|
+
"stroke-width": 1.3
|
|
7593
|
+
}), (0, react.createElement)("path", {
|
|
7594
|
+
d: "m9.6 9.6 3 3",
|
|
7595
|
+
stroke: "currentColor",
|
|
7596
|
+
"stroke-width": 1.3,
|
|
7597
|
+
"stroke-linecap": "round"
|
|
7598
|
+
})), (0, react.createElement)("input", onSearchChange === void 0 ? {
|
|
7599
|
+
type: "search",
|
|
7600
|
+
placeholder: "筛选工具名…",
|
|
7601
|
+
"aria-label": "筛选工具名",
|
|
7602
|
+
defaultValue: search ?? "",
|
|
7603
|
+
"data-call-index-search": "true"
|
|
7604
|
+
} : {
|
|
7605
|
+
type: "search",
|
|
7606
|
+
placeholder: "筛选工具名…",
|
|
7607
|
+
"aria-label": "筛选工具名",
|
|
7608
|
+
value: search ?? "",
|
|
7609
|
+
"data-call-index-search": "true",
|
|
7610
|
+
onChange: (event) => onSearchChange(event.target.value)
|
|
7611
|
+
}));
|
|
7105
7612
|
const indexBlockedReason = status === void 0 ? "尚未收到索引状态,无法判断索引进度(Host 未应答或回复被拒绝)" : status.scope.status !== "ready" ? "索引范围未启用,插件不会自动索引历史会话" : void 0;
|
|
7106
7613
|
return (0, react.createElement)("section", {
|
|
7107
|
-
className: "mc-section",
|
|
7614
|
+
className: "v3-root mc-section",
|
|
7108
7615
|
"aria-label": "调用明细",
|
|
7109
7616
|
"aria-busy": loading === true
|
|
7110
|
-
}, CallIndexStyles(), (
|
|
7111
|
-
className: "
|
|
7112
|
-
"data-
|
|
7113
|
-
|
|
7114
|
-
|
|
7617
|
+
}, CallIndexStyles(), V3Styles(), (0, react.createElement)("div", { className: "v3-status-pills" }, (0, react.createElement)("span", {
|
|
7618
|
+
className: "v3-statusline",
|
|
7619
|
+
...state.kind === "failure" || state.kind === "disconnected" ? { "data-tone": "bad" } : {}
|
|
7620
|
+
}, (0, react.createElement)("span", {
|
|
7621
|
+
className: "v3-dot",
|
|
7622
|
+
"data-tone": state.kind === "failure" || state.kind === "disconnected" ? "bad" : scanning ? "run" : "ok",
|
|
7623
|
+
"aria-hidden": "true"
|
|
7624
|
+
}), statusText), (0, react.createElement)("span", { className: "v3-statusline v3-status-dash" }, `${rows.length} 个工具 · ${formatCallIndexCount(readCalls, page?.totalExact)} 次调用${readIsPartial ? `(全部 ${formatCallIndexCount(totalCalls, page?.totalExact)} 次)` : ""}`)), (0, react.createElement)("div", { className: "v3-panel v3-filtercard" }, (0, react.createElement)("div", { className: "v3-filter-row" }, CallIndexFilters({
|
|
7115
7625
|
query,
|
|
7116
7626
|
...onQueryChange === void 0 ? {} : { onChange: onQueryChange },
|
|
7117
7627
|
...onResolveScope === void 0 ? {} : { onResolveScope },
|
|
7118
7628
|
...catalog === void 0 ? {} : { catalog }
|
|
7119
|
-
}), CallIndexScanBar({ ...status === void 0 ? {} : { status } }), (0, react.createElement)(StateNotice, {
|
|
7629
|
+
}), searchInput), CallIndexScanBar({ ...status === void 0 ? {} : { status } })), (0, react.createElement)(StateNotice, {
|
|
7120
7630
|
state,
|
|
7121
7631
|
...failure === void 0 ? {} : { failure }
|
|
7122
7632
|
}), startFailure === void 0 ? null : (0, react.createElement)("p", {
|
|
7123
|
-
className: "
|
|
7633
|
+
className: "v3-hint",
|
|
7124
7634
|
"data-call-index-note": "start-failure",
|
|
7125
7635
|
role: "status"
|
|
7126
7636
|
}, `自动索引失败:${callIndexFailureText(startFailure)}`), startTask === void 0 ? null : (0, react.createElement)("p", {
|
|
7127
|
-
className: "
|
|
7637
|
+
className: "v3-hint",
|
|
7128
7638
|
"data-call-index-note": "start-task"
|
|
7129
|
-
}, `自动索引:${startTask.phase}${startTask.mode === "full" ? "(全量)" : "(增量)"} · 任务 ${startTask.taskId.slice(0, 8)}`),
|
|
7639
|
+
}, `自动索引:${startTask.phase}${startTask.mode === "full" ? "(全量)" : "(增量)"} · 任务 ${startTask.taskId.slice(0, 8)}`), indexBlockedReason === void 0 ? null : (0, react.createElement)("p", {
|
|
7640
|
+
className: "v3-hint",
|
|
7641
|
+
"data-call-index-note": "index-blocked",
|
|
7642
|
+
role: "status"
|
|
7643
|
+
}, `自动索引不可用:${indexBlockedReason}`), CallIndexDiagnostics({
|
|
7130
7644
|
...status === void 0 ? {} : { status },
|
|
7131
7645
|
...page === void 0 ? {} : { page },
|
|
7132
7646
|
...failure === void 0 ? {} : { failure },
|
|
7133
7647
|
...startFailure === void 0 ? {} : { startFailure },
|
|
7134
7648
|
...moreFailure === void 0 ? {} : { moreFailure }
|
|
7135
7649
|
}), (0, react.createElement)("div", {
|
|
7136
|
-
className: "
|
|
7650
|
+
className: "v3-stats",
|
|
7137
7651
|
"data-call-index-summary": "rates"
|
|
7138
|
-
},
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7652
|
+
}, V3Stat({
|
|
7653
|
+
label: "成功率",
|
|
7654
|
+
value: rateText(successStats?.rate),
|
|
7655
|
+
hint: totalText === void 0 ? rateHint(successStats) : `${rateHint(successStats)} · 本页合计 ${totalText}`
|
|
7656
|
+
}), V3Stat({
|
|
7657
|
+
label: "失败率",
|
|
7658
|
+
value: rateText(failureStats?.rate),
|
|
7659
|
+
hint: rateHint(failureStats)
|
|
7660
|
+
}), V3Stat({
|
|
7661
|
+
label: "需要关注",
|
|
7662
|
+
value: suggestionCount === void 0 ? "—" : String(suggestionCount),
|
|
7663
|
+
hint: suggestionHint()
|
|
7664
|
+
}), V3Stat({
|
|
7665
|
+
label: "平均耗时",
|
|
7666
|
+
value: formatCallIndexDuration(averageDuration),
|
|
7667
|
+
hint: "按有耗时的调用平均"
|
|
7668
|
+
})), page !== void 0 && page.droppedItems > 0 ? (0, react.createElement)("p", {
|
|
7669
|
+
className: "v3-hint",
|
|
7670
|
+
"data-call-index-note": "dropped",
|
|
7671
|
+
style: { marginTop: 8 }
|
|
7672
|
+
}, `本页有 ${page.droppedItems} 行未通过白名单投影(字段不合法),已丢弃,未计入合计。`) : null, (0, react.createElement)("div", {
|
|
7673
|
+
className: "v3-board",
|
|
7674
|
+
style: { marginTop: 12 }
|
|
7675
|
+
}, (0, react.createElement)("div", { className: "v3-panel" }, (0, react.createElement)("div", { className: "v3-ph" }, (0, react.createElement)("span", { className: "v3-pt" }, "调用量分布(本范围工具)"), (0, react.createElement)("span", { className: "v3-pn" }, term === "" ? "前 12 名" : "筛选结果")), rankRows.length === 0 ? (0, react.createElement)("p", { className: "v3-hint" }, term === "" ? "当前范围没有工具调用。" : "没有匹配的工具。") : (0, react.createElement)("div", { className: "v3-rank" }, ...rankRows.map((row) => {
|
|
7676
|
+
const bad = row.error > 0 && row.error / row.calls >= .2;
|
|
7677
|
+
return (0, react.createElement)("div", {
|
|
7678
|
+
key: row.toolName + "::" + row.sourceKind,
|
|
7679
|
+
className: "v3-rank-row",
|
|
7680
|
+
title: row.toolName
|
|
7681
|
+
}, (0, react.createElement)("span", { className: "v3-nm" }, toolDisplayLabel(row.toolName)), (0, react.createElement)("span", { className: "v3-bar" }, (0, react.createElement)("span", {
|
|
7682
|
+
...bad ? { "data-bad": "true" } : {},
|
|
7683
|
+
style: { width: `${Math.max(3, Math.round(row.calls / rankMax * 100))}%` }
|
|
7684
|
+
})), (0, react.createElement)("span", { className: "v3-n" }, String(row.calls)));
|
|
7685
|
+
})), (0, react.createElement)("p", {
|
|
7686
|
+
className: "v3-hint",
|
|
7687
|
+
style: { marginTop: 9 }
|
|
7688
|
+
}, `条长 = 调用量,按最大值归一;失败率 ≥ 20% 的条变红。${readIsPartial ? `本页已读取 ${formatCallIndexCount(readCalls, page?.totalExact)} 次调用,全部共 ${formatCallIndexCount(totalCalls, page?.totalExact)} 次,未读取部分不参与排行。` : ""}`)), (0, react.createElement)("div", { className: "v3-panel" }, (0, react.createElement)("div", { className: "v3-ph" }, (0, react.createElement)("span", { className: "v3-pt" }, "失败与耗时"), (0, react.createElement)("span", { className: "v3-pn" }, "按失败数排序")), failingRows.length === 0 ? (0, react.createElement)("p", { className: "v3-hint" }, "当前范围没有失败调用。") : (0, react.createElement)("div", { className: "v3-rank" }, ...failingRows.slice(0, 8).map((row) => {
|
|
7689
|
+
const perTool = Math.round(row.error / row.calls * 100);
|
|
7690
|
+
return (0, react.createElement)("div", {
|
|
7691
|
+
key: "fail-" + row.toolName + "::" + row.sourceKind,
|
|
7692
|
+
className: "v3-rank-row",
|
|
7693
|
+
title: row.toolName
|
|
7694
|
+
}, (0, react.createElement)("span", { className: "v3-nm" }, toolDisplayLabel(row.toolName)), (0, react.createElement)("span", { className: "v3-bar" }, (0, react.createElement)("span", {
|
|
7695
|
+
"data-bad": "true",
|
|
7696
|
+
style: { width: `${Math.max(4, Math.round(row.error / failMax * 100))}%` }
|
|
7697
|
+
})), (0, react.createElement)("span", {
|
|
7698
|
+
className: "v3-n",
|
|
7699
|
+
style: {
|
|
7700
|
+
color: "var(--v3-bad)",
|
|
7701
|
+
fontWeight: 600
|
|
7702
|
+
}
|
|
7703
|
+
}, `${row.error} 次`), (0, react.createElement)("span", {
|
|
7704
|
+
className: "v3-e",
|
|
7705
|
+
"data-bad": "true"
|
|
7706
|
+
}, `占该工具 ${perTool}%`));
|
|
7707
|
+
})), (0, react.createElement)("p", {
|
|
7708
|
+
className: "v3-hint",
|
|
7709
|
+
style: { marginTop: 9 }
|
|
7710
|
+
}, `条长 = 失败次数(不是失败率)。共 ${failingRows.length} 个工具出现过失败。`))), (0, react.createElement)("div", {
|
|
7711
|
+
className: "v3-panel",
|
|
7712
|
+
style: { marginTop: 12 }
|
|
7713
|
+
}, (0, react.createElement)("div", { className: "v3-ph" }, (0, react.createElement)("span", { className: "v3-pt" }, "完整工具表"), (0, react.createElement)("span", { className: "v3-pn" }, `${rows.length} 行 · 表内滚动`)), (0, react.createElement)(CallIndexToolTable, { rows }), (0, react.createElement)("div", { className: "v3-tfoot" }, (0, react.createElement)("span", null, `${rows.length} 个工具 · 表内滚动`), page === void 0 ? null : (0, react.createElement)("span", { style: { marginLeft: "auto" } }, `快照代 ${page.generation} · 覆盖 ${coverageLabel ?? "未知"}`))), page?.nextCursor !== void 0 && loadingMore === true ? (0, react.createElement)("p", {
|
|
7714
|
+
className: "v3-hint",
|
|
7715
|
+
"data-call-index-note": "loading-more",
|
|
7716
|
+
style: { marginTop: 8 }
|
|
7144
7717
|
}, "正在加载其余工具…") : null, moreFailure === void 0 ? null : (0, react.createElement)("p", {
|
|
7145
|
-
className: "
|
|
7718
|
+
className: "v3-hint",
|
|
7146
7719
|
"data-call-index-note": "more-failure",
|
|
7147
|
-
role: "status"
|
|
7148
|
-
|
|
7720
|
+
role: "status",
|
|
7721
|
+
style: { marginTop: 8 }
|
|
7722
|
+
}, `加载失败:${callIndexFailureText(moreFailure)}`));
|
|
7149
7723
|
}
|
|
7150
|
-
/** Pure view for
|
|
7724
|
+
/** Pure view for 总览 (v3 看板). */
|
|
7151
7725
|
function CallIndexOverviewPanelView(props) {
|
|
7152
|
-
const { status, overview, loading, failure, onRefresh } = props;
|
|
7726
|
+
const { status, overview, loading, failure, onRefresh, tools, toolsLoading, toolsFailure } = props;
|
|
7153
7727
|
const metrics = callIndexOverviewMetrics(overview, status);
|
|
7154
7728
|
const rangeLabel = callIndexRangeLabel("all");
|
|
7155
7729
|
const exact = metrics.callsTotalExact;
|
|
7156
7730
|
const mix = callIndexOutcomeMix(overview?.summary);
|
|
7157
7731
|
const aggregates = metrics.aggregates;
|
|
7158
7732
|
const notice = failure === void 0 ? void 0 : failure.disconnected ? `与 Host 断连:${callIndexFailureText(failure)}${failure.hostCode === void 0 ? "" : `(${failure.hostCode})`}` : callIndexFailureText(failure);
|
|
7733
|
+
const coverageLabel = status === void 0 ? "未知" : COVERAGE_LABELS[status.coverage];
|
|
7734
|
+
const scanning = status !== void 0 && (status.phase === "running" || (status.sessions?.pending ?? 0) > 0 || (status.sessions?.pendingLive ?? 0) > 0);
|
|
7735
|
+
const sessionsText = metrics.sessionsListed === void 0 ? "Session 未读取" : `${metrics.sessionsListed} 列出 / ${metrics.sessionsVisible ?? "—"} 可见`;
|
|
7736
|
+
const coverageHint = exact === true ? (0, react.createElement)("span", { style: {
|
|
7737
|
+
display: "inline-flex",
|
|
7738
|
+
alignItems: "center",
|
|
7739
|
+
gap: 5
|
|
7740
|
+
} }, (0, react.createElement)("span", {
|
|
7741
|
+
className: "v3-dot",
|
|
7742
|
+
"data-tone": "ok",
|
|
7743
|
+
"aria-hidden": "true"
|
|
7744
|
+
}), "覆盖完整,计数精确") : (0, react.createElement)("span", { style: {
|
|
7745
|
+
display: "inline-flex",
|
|
7746
|
+
alignItems: "center",
|
|
7747
|
+
gap: 5
|
|
7748
|
+
} }, (0, react.createElement)("span", {
|
|
7749
|
+
className: "v3-dot",
|
|
7750
|
+
"data-tone": "warn",
|
|
7751
|
+
"aria-hidden": "true"
|
|
7752
|
+
}), "覆盖部分,实际更多");
|
|
7753
|
+
const failHint = (0, react.createElement)("span", { style: {
|
|
7754
|
+
display: "inline-flex",
|
|
7755
|
+
alignItems: "center",
|
|
7756
|
+
gap: 5
|
|
7757
|
+
} }, (0, react.createElement)("span", {
|
|
7758
|
+
className: "v3-dot",
|
|
7759
|
+
"data-tone": "bad",
|
|
7760
|
+
"aria-hidden": "true"
|
|
7761
|
+
}), `另有 ${formatCallIndexCount(mix?.unresolved, exact)} 次未配对`);
|
|
7762
|
+
const rates = callIndexRates(overview?.summary);
|
|
7763
|
+
const rateHint = (stats) => stats === void 0 ? "没有已知结果的调用" : `${stats.numerator} / ${stats.denominator} 次已知结果`;
|
|
7764
|
+
const trend = callIndexTrend(aggregates?.byDay);
|
|
7765
|
+
const callSpark = aggregates?.byDay === void 0 ? void 0 : aggregates.byDay.map((bucket) => bucket.calls);
|
|
7766
|
+
const successSpark = aggregates?.byDay === void 0 ? void 0 : aggregates.byDay.map((bucket) => bucket.calls > 0 ? bucket.success / bucket.calls : 0);
|
|
7767
|
+
const errorSpark = aggregates?.byDay === void 0 ? void 0 : aggregates.byDay.map((bucket) => bucket.error);
|
|
7768
|
+
const totalToolCalls = tools === void 0 ? 0 : tools.reduce((sum, row) => sum + row.calls, 0);
|
|
7769
|
+
const topRows = tools === void 0 ? void 0 : tools.slice(0, 12);
|
|
7770
|
+
const rankMax = topRows !== void 0 && topRows.length > 0 ? topRows[0].calls : 1;
|
|
7771
|
+
const topCoverage = topRows === void 0 || totalToolCalls === 0 ? void 0 : Math.round(topRows.reduce((sum, row) => sum + row.calls, 0) / totalToolCalls * 100);
|
|
7772
|
+
const failingRows = tools === void 0 ? void 0 : tools.filter((row) => row.error > 0).slice().sort((a, b) => b.error - a.error);
|
|
7773
|
+
const failingTop = failingRows === void 0 ? [] : failingRows.slice(0, 3);
|
|
7774
|
+
const failingRest = failingRows === void 0 ? [] : failingRows.slice(3);
|
|
7775
|
+
const failingRestErrors = failingRest.reduce((sum, row) => sum + row.error, 0);
|
|
7776
|
+
const failingReadErrors = failingRows === void 0 ? 0 : failingRows.reduce((sum, row) => sum + row.error, 0);
|
|
7777
|
+
const failDenominator = metrics.failed !== void 0 && metrics.failed > 0 ? metrics.failed : failingReadErrors;
|
|
7778
|
+
const readCalls = tools === void 0 ? 0 : totalToolCalls;
|
|
7779
|
+
const readIsPartial = metrics.calls !== void 0 && readCalls < metrics.calls;
|
|
7780
|
+
const worstRateTool = failingRows === void 0 || failingRows.length === 0 ? void 0 : failingRows.slice().sort((a, b) => b.error / b.calls - a.error / a.calls)[0];
|
|
7781
|
+
const toolsNotice = tools === void 0 ? (0, react.createElement)("p", {
|
|
7782
|
+
className: "v3-hint",
|
|
7783
|
+
"data-call-index-note": "tools"
|
|
7784
|
+
}, toolsFailure !== void 0 ? `逐工具明细读取失败:${callIndexFailureText(toolsFailure)}` : toolsLoading === true ? "正在读取逐工具明细…" : "尚未读取逐工具明细;上方调用总量与趋势来自总览快照,排行需要逐工具数据。") : tools.length === 0 ? (0, react.createElement)("p", {
|
|
7785
|
+
className: "v3-hint",
|
|
7786
|
+
"data-call-index-note": "tools"
|
|
7787
|
+
}, "该范围没有逐工具调用记录。") : null;
|
|
7788
|
+
const sessionInfo = status?.sessions;
|
|
7789
|
+
const taskNote = metrics.tasks === void 0 ? null : (0, react.createElement)("p", {
|
|
7790
|
+
className: "v3-hint",
|
|
7791
|
+
"data-call-index-note": "task",
|
|
7792
|
+
style: { marginTop: 9 }
|
|
7793
|
+
}, `最近一次扫描:${metrics.tasks.mode} / ${metrics.tasks.phase}(开始 ${formatCallIndexTime(metrics.tasks.startedAt)})`);
|
|
7159
7794
|
return (0, react.createElement)("section", {
|
|
7160
|
-
className: "mc-section",
|
|
7795
|
+
className: "v3-root mc-section",
|
|
7161
7796
|
"aria-label": "调用统计总览",
|
|
7162
7797
|
"aria-busy": loading === true
|
|
7163
|
-
}, CallIndexStyles(), (0, react.createElement)("header", { className: "mc-heading-row" }, (0, react.createElement)("div", { className: "mc-heading-meta" }, (0, react.createElement)("h2", { className: "mc-heading" }, "总览"), (0, react.createElement)("span", { className: "mc-version" }, loading === true ? "正在读取…" : rangeLabel === "全部" ? "范围:全部已索引会话" : `范围:最近 ${rangeLabel}`)), (0, react.createElement)("div", { className: "mc-heading-actions" }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
7798
|
+
}, CallIndexStyles(), V3Styles(), (0, react.createElement)("header", { className: "mc-heading-row" }, (0, react.createElement)("div", { className: "mc-heading-meta" }, (0, react.createElement)("h2", { className: "mc-heading" }, "总览"), (0, react.createElement)("span", { className: "mc-version" }, loading === true ? "正在读取…" : rangeLabel === "全部" ? "范围:全部已索引会话" : `范围:最近 ${rangeLabel}`)), (0, react.createElement)("div", { className: "mc-heading-actions" }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
7164
7799
|
size: "sm",
|
|
7165
7800
|
variant: "outline",
|
|
7166
7801
|
disabled: loading === true || onRefresh === void 0,
|
|
@@ -7169,19 +7804,152 @@ function CallIndexOverviewPanelView(props) {
|
|
|
7169
7804
|
className: "mc-notice",
|
|
7170
7805
|
role: failure?.disconnected === true ? "alert" : "status",
|
|
7171
7806
|
"data-call-index-state": failure?.disconnected === true ? "disconnected" : "failure"
|
|
7172
|
-
}, notice), (0, react.createElement)("div", {
|
|
7173
|
-
className: "
|
|
7807
|
+
}, notice), (0, react.createElement)("div", { className: "v3-status-pills" }, (0, react.createElement)("span", { className: "v3-statusline" }, (0, react.createElement)("span", {
|
|
7808
|
+
className: "v3-dot",
|
|
7809
|
+
"data-tone": coverageLabel === "完整" ? "ok" : "warn",
|
|
7810
|
+
"aria-hidden": "true"
|
|
7811
|
+
}), (0, react.createElement)("span", null, "覆盖 ", (0, react.createElement)("b", null, coverageLabel), ` · ${sessionsText}${exact === true ? "" : " · 所有总量为下界"}`)), (0, react.createElement)("span", { className: "v3-statusline" }, (0, react.createElement)("span", {
|
|
7812
|
+
className: "v3-dot",
|
|
7813
|
+
"data-tone": scanning ? "run" : "ok",
|
|
7814
|
+
"aria-hidden": "true"
|
|
7815
|
+
}), scanning ? "正在扫描" : "扫描已结束", ` · ${formatCallIndexCount(sessionInfo?.pending, true)} 个待处理`), (0, react.createElement)("span", { className: "v3-statusline v3-status-dash" }, `口径:${overview?.corpus === "persisted-plus-observed-live" ? "已持久化 + 挂载后实时观测" : "Host 未声明 corpus"}`)), (0, react.createElement)("div", {
|
|
7816
|
+
className: "v3-stats",
|
|
7174
7817
|
"data-call-index-metrics": "overview"
|
|
7175
|
-
},
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7818
|
+
}, V3Stat({
|
|
7819
|
+
label: "调用次数",
|
|
7820
|
+
value: formatCallIndexCount(metrics.calls, exact),
|
|
7821
|
+
hint: coverageHint,
|
|
7822
|
+
...callSpark === void 0 ? {} : { spark: Sparkline({
|
|
7823
|
+
values: callSpark,
|
|
7824
|
+
tone: "info"
|
|
7825
|
+
}) }
|
|
7826
|
+
}), V3Stat({
|
|
7827
|
+
label: "成功率",
|
|
7828
|
+
value: formatCallIndexRate(rates.success?.rate),
|
|
7829
|
+
hint: rateHint(rates.success),
|
|
7830
|
+
...successSpark === void 0 ? {} : { spark: Sparkline({
|
|
7831
|
+
values: successSpark,
|
|
7832
|
+
tone: "ok"
|
|
7833
|
+
}) }
|
|
7834
|
+
}), V3Stat({
|
|
7835
|
+
label: "失败",
|
|
7836
|
+
value: formatCallIndexCount(metrics.failed, exact),
|
|
7837
|
+
hint: failHint,
|
|
7838
|
+
...errorSpark === void 0 ? {} : { spark: Sparkline({
|
|
7839
|
+
values: errorSpark,
|
|
7840
|
+
tone: "bad"
|
|
7841
|
+
}) }
|
|
7842
|
+
}), V3Stat({
|
|
7843
|
+
label: "不同工具",
|
|
7844
|
+
value: formatCallIndexCount(metrics.distinctTools, exact),
|
|
7845
|
+
hint: "按 toolName 去重"
|
|
7846
|
+
})), callIndexHasUnexplainedSources(aggregates) ? (0, react.createElement)("p", {
|
|
7847
|
+
className: "v3-hint",
|
|
7848
|
+
"data-call-index-note": "unexplained-sources",
|
|
7849
|
+
style: { marginTop: 10 }
|
|
7850
|
+
}, "插件工具与技能执行入口的归属目前都解析为 0:Host 无法证明插件 owner,技能执行归属也未验证,所以这两个 0 表示「未解析出」,不表示「未使用」。") : null, (0, react.createElement)("div", {
|
|
7851
|
+
className: "v3-board",
|
|
7852
|
+
style: { marginTop: 12 }
|
|
7853
|
+
}, (0, react.createElement)("div", { className: "v3-panel" }, (0, react.createElement)("div", { className: "v3-ph" }, (0, react.createElement)("span", { className: "v3-pt" }, "按日调用趋势"), (0, react.createElement)("span", { className: "v3-pn" }, aggregates === void 0 ? "趋势不可用" : `合计 ${trend.totalCalls} 次 · 峰值 ${trend.maxCalls} 次`)), aggregates === void 0 ? (0, react.createElement)("p", {
|
|
7854
|
+
className: "v3-hint",
|
|
7855
|
+
"data-call-index-missing": "aggregates"
|
|
7856
|
+
}, "Host 未返回按日聚合(aggregates);这不是「没有调用」,趋势不可用。") : !trend.available ? (0, react.createElement)("p", {
|
|
7857
|
+
className: "v3-hint",
|
|
7858
|
+
"data-call-index-missing": "by-day"
|
|
7859
|
+
}, "该筛选在所选范围内没有任何按日桶,趋势为空;单个日粒度为 0 不参与绘制。") : (0, react.createElement)(OverviewTrendSvg, { chart: trend }), aggregates === void 0 || !trend.available ? null : (0, react.createElement)("div", { className: "v3-legend" }, (0, react.createElement)("span", null, (0, react.createElement)("i", { style: { background: "var(--v3-info)" } }), "每日调用量(折线 + 面积)"), (0, react.createElement)("span", null, (0, react.createElement)("i", {
|
|
7860
|
+
"data-mark": "square",
|
|
7861
|
+
style: { background: "var(--v3-bad)" }
|
|
7862
|
+
}), "每日失败数(底柱)"), (0, react.createElement)("span", null, (0, react.createElement)("i", { style: {
|
|
7863
|
+
background: "var(--v3-info)",
|
|
7864
|
+
opacity: .3,
|
|
7865
|
+
height: 8,
|
|
7866
|
+
borderRadius: 2
|
|
7867
|
+
} }), "最近一周"))), OverviewSourcePanel({
|
|
7868
|
+
...aggregates?.bySource === void 0 ? {} : { bySource: aggregates.bySource },
|
|
7180
7869
|
...exact === void 0 ? {} : { totalExact: exact }
|
|
7181
|
-
}),
|
|
7182
|
-
className: "
|
|
7183
|
-
|
|
7184
|
-
},
|
|
7870
|
+
})), (0, react.createElement)("div", {
|
|
7871
|
+
className: "v3-board",
|
|
7872
|
+
style: { marginTop: 12 }
|
|
7873
|
+
}, (0, react.createElement)("div", { className: "v3-panel" }, (0, react.createElement)("div", { className: "v3-ph" }, (0, react.createElement)("span", { className: "v3-pt" }, "工具调用排行"), (0, react.createElement)("span", { className: "v3-pn" }, topRows === void 0 ? "前 12 名" : `前 12 名${topCoverage === void 0 ? "" : ` · 占已读取调用的 ${topCoverage}%`}` + (metrics.calls !== void 0 && totalToolCalls < metrics.calls ? ` · 已读取 ${formatCallIndexCount(totalToolCalls, exact)} / 共 ${formatCallIndexCount(metrics.calls, exact)} 次` : ""))), toolsNotice !== null ? toolsNotice : (0, react.createElement)("div", { className: "v3-rank" }, ...topRows.map((row) => {
|
|
7874
|
+
const bad = row.error > 0 && row.error / row.calls >= .2;
|
|
7875
|
+
return (0, react.createElement)("div", {
|
|
7876
|
+
key: "rank-" + row.toolName + "::" + row.sourceKind,
|
|
7877
|
+
className: "v3-rank-row",
|
|
7878
|
+
title: row.toolName
|
|
7879
|
+
}, (0, react.createElement)("span", { className: "v3-nm" }, toolDisplayLabel(row.toolName)), (0, react.createElement)("span", { className: "v3-bar" }, (0, react.createElement)("span", {
|
|
7880
|
+
...bad ? { "data-bad": "true" } : {},
|
|
7881
|
+
style: { width: `${Math.max(3, Math.round(row.calls / rankMax * 100))}%` }
|
|
7882
|
+
})), (0, react.createElement)("span", { className: "v3-n" }, String(row.calls)), (0, react.createElement)("span", {
|
|
7883
|
+
className: "v3-e",
|
|
7884
|
+
...bad ? { "data-bad": "true" } : {},
|
|
7885
|
+
...row.error === 0 ? { "data-zero": "true" } : {}
|
|
7886
|
+
}, `失败 ${row.error}`));
|
|
7887
|
+
}))), (0, react.createElement)("div", { className: "v3-panel" }, (0, react.createElement)("div", { className: "v3-ph" }, (0, react.createElement)("span", { className: "v3-pt" }, "异常集中度"), (0, react.createElement)("span", { className: "v3-pn" }, tools === void 0 ? "按失败数排序" : `${formatCallIndexCount(metrics.failed, exact)} 次失败`)), toolsNotice !== null ? toolsNotice : failingRows === void 0 || failingRows.length === 0 ? (0, react.createElement)("p", { className: "v3-hint" }, "当前范围没有失败调用。") : (0, react.createElement)("div", null, (0, react.createElement)("div", { className: "v3-rank" }, ...failingTop.map((row) => (0, react.createElement)("div", {
|
|
7888
|
+
key: "fc-" + row.toolName + "::" + row.sourceKind,
|
|
7889
|
+
className: "v3-rank-row"
|
|
7890
|
+
}, (0, react.createElement)("span", {
|
|
7891
|
+
className: "v3-nm",
|
|
7892
|
+
style: {
|
|
7893
|
+
width: "auto",
|
|
7894
|
+
flex: "1 1 auto"
|
|
7895
|
+
}
|
|
7896
|
+
}, toolDisplayLabel(row.toolName)), (0, react.createElement)("span", {
|
|
7897
|
+
className: "v3-n",
|
|
7898
|
+
style: {
|
|
7899
|
+
color: "var(--v3-bad)",
|
|
7900
|
+
fontWeight: 600
|
|
7901
|
+
}
|
|
7902
|
+
}, String(row.error)))), ...failingRest.length === 0 ? [] : [(0, react.createElement)("div", {
|
|
7903
|
+
key: "fc-rest",
|
|
7904
|
+
className: "v3-rank-row"
|
|
7905
|
+
}, (0, react.createElement)("span", {
|
|
7906
|
+
className: "v3-nm",
|
|
7907
|
+
style: {
|
|
7908
|
+
width: "auto",
|
|
7909
|
+
flex: "1 1 auto"
|
|
7910
|
+
}
|
|
7911
|
+
}, `其余 ${failingRest.length} 个工具合计`), (0, react.createElement)("span", {
|
|
7912
|
+
className: "v3-n",
|
|
7913
|
+
style: { color: "var(--v3-t2)" }
|
|
7914
|
+
}, String(failingRestErrors)))]), failDenominator > 0 ? (0, react.createElement)("p", {
|
|
7915
|
+
className: "v3-hint",
|
|
7916
|
+
style: { marginTop: 9 }
|
|
7917
|
+
}, `这些失败合计占全部失败的 ${Math.round(failingTop.reduce((sum, row) => sum + row.error, 0) / failDenominator * 100)}%(占全部失败,不是占单个工具)${readIsPartial ? ";分母是全部失败数,分子只含已读取的逐工具行" : ""}。`) : null, worstRateTool === void 0 ? null : (0, react.createElement)("div", { style: {
|
|
7918
|
+
marginTop: 11,
|
|
7919
|
+
paddingTop: 11,
|
|
7920
|
+
borderTop: "1px solid var(--v3-line)"
|
|
7921
|
+
} }, (0, react.createElement)("div", {
|
|
7922
|
+
className: "v3-src",
|
|
7923
|
+
style: { fontSize: 11.5 }
|
|
7924
|
+
}, (0, react.createElement)("span", {
|
|
7925
|
+
className: "v3-nm",
|
|
7926
|
+
style: {
|
|
7927
|
+
color: "var(--v3-t4)",
|
|
7928
|
+
flex: "1 1 auto"
|
|
7929
|
+
}
|
|
7930
|
+
}, "失败率最高的工具"), (0, react.createElement)("b", { style: { color: "var(--v3-bad)" } }, `${Math.round(worstRateTool.error / worstRateTool.calls * 100)}%`)), (0, react.createElement)("p", {
|
|
7931
|
+
className: "v3-hint",
|
|
7932
|
+
style: { marginTop: 4 }
|
|
7933
|
+
}, `${worstRateTool.toolName} ${worstRateTool.error} / ${worstRateTool.calls}(占该工具失败率,不是占全部失败)。`)), (0, react.createElement)("div", { style: {
|
|
7934
|
+
marginTop: 11,
|
|
7935
|
+
paddingTop: 11,
|
|
7936
|
+
borderTop: "1px solid var(--v3-line)"
|
|
7937
|
+
} }, (0, react.createElement)("div", {
|
|
7938
|
+
className: "v3-src",
|
|
7939
|
+
style: { fontSize: 11.5 }
|
|
7940
|
+
}, (0, react.createElement)("span", {
|
|
7941
|
+
className: "v3-nm",
|
|
7942
|
+
style: {
|
|
7943
|
+
color: "var(--v3-t4)",
|
|
7944
|
+
flex: "1 1 auto"
|
|
7945
|
+
}
|
|
7946
|
+
}, "未配对结果"), (0, react.createElement)("b", { style: { color: "var(--v3-warn)" } }, formatCallIndexCount(mix?.unresolved, exact))), (0, react.createElement)("p", {
|
|
7947
|
+
className: "v3-hint",
|
|
7948
|
+
style: { marginTop: 4 }
|
|
7949
|
+
}, "没有捕获到结果,不计入成功率分母,也不等于失败。"))))), (0, react.createElement)("div", {
|
|
7950
|
+
className: "v3-panel",
|
|
7951
|
+
style: { marginTop: 12 }
|
|
7952
|
+
}, (0, react.createElement)("div", { className: "v3-ph" }, (0, react.createElement)("span", { className: "v3-pt" }, "索引状态"), (0, react.createElement)("span", { className: "v3-pn" }, metrics.tasks === void 0 ? "最近扫描未记录" : `最近扫描 ${metrics.tasks.mode} · ${metrics.tasks.phase}`)), (0, react.createElement)("div", { className: "v3-kv" }, (0, react.createElement)("div", null, (0, react.createElement)("div", { className: "v3-kv-l" }, "数据范围"), (0, react.createElement)("div", { className: "v3-kv-v" }, overview?.corpus === "persisted-plus-observed-live" ? "已持久化 + 挂载后实时观测" : "Host 未声明")), (0, react.createElement)("div", null, (0, react.createElement)("div", { className: "v3-kv-l" }, "Session 列出 / 可见"), (0, react.createElement)("div", { className: "v3-kv-v v3-num" }, sessionInfo === void 0 ? "—" : `${sessionInfo.listed} / ${sessionInfo.visible}`)), (0, react.createElement)("div", null, (0, react.createElement)("div", { className: "v3-kv-l" }, "待处理 / 失败"), (0, react.createElement)("div", { className: "v3-kv-v v3-num" }, sessionInfo === void 0 ? "—" : `${sessionInfo.pending} / ${sessionInfo.failed}`)), (0, react.createElement)("div", null, (0, react.createElement)("div", { className: "v3-kv-l" }, "覆盖(事件 / 枚举 / 语义)"), (0, react.createElement)("div", { className: "v3-kv-v" }, status === void 0 ? "—" : `${COVERAGE_LABELS[status.eventCoverage]} / ${COVERAGE_LABELS[status.enumerationCoverage]} / ${COVERAGE_LABELS[status.coverage]}`))), taskNote));
|
|
7185
7953
|
}
|
|
7186
7954
|
function useNarrowViewport() {
|
|
7187
7955
|
const [narrow, setNarrow] = (0, react.useState)(false);
|
|
@@ -7252,6 +8020,7 @@ function CallIndexDetailPanel({ api, initialQuery, resolveScopeTarget, resolveSe
|
|
|
7252
8020
|
loadingDetail: false
|
|
7253
8021
|
});
|
|
7254
8022
|
const [refreshToken, setRefreshToken] = (0, react.useState)(0);
|
|
8023
|
+
const [search, setSearch] = (0, react.useState)("");
|
|
7255
8024
|
const generation = (0, react.useRef)(0);
|
|
7256
8025
|
const pageAnchor = (0, react.useRef)(void 0);
|
|
7257
8026
|
/** How many extra pages 加载更多 has appended; 0 means only the first page. */
|
|
@@ -7488,6 +8257,8 @@ function CallIndexDetailPanel({ api, initialQuery, resolveScopeTarget, resolveSe
|
|
|
7488
8257
|
loadingMore: state.loadingMore,
|
|
7489
8258
|
loadingDetail: state.loadingDetail,
|
|
7490
8259
|
narrow,
|
|
8260
|
+
search,
|
|
8261
|
+
onSearchChange: setSearch,
|
|
7491
8262
|
onQueryChange: setQuery,
|
|
7492
8263
|
onRefresh: () => setRefreshToken((value) => value + 1),
|
|
7493
8264
|
onStartIndex: startIndex,
|
|
@@ -7498,8 +8269,12 @@ function CallIndexDetailPanel({ api, initialQuery, resolveScopeTarget, resolveSe
|
|
|
7498
8269
|
});
|
|
7499
8270
|
}
|
|
7500
8271
|
/**
|
|
7501
|
-
* Container for 总览. Reads the status once
|
|
7502
|
-
*
|
|
8272
|
+
* Container for 总览. Reads the status once, one all-time summary, AND one
|
|
8273
|
+
* `listCalls` snapshot — because the overview reply carries no per-tool counts,
|
|
8274
|
+
* and the v3 ranking / fault panels need them. The per-tool read fills up to
|
|
8275
|
+
* `MAX_AUTO_PAGES` pages (same bound the detail page uses) then aggregates with
|
|
8276
|
+
* the shared pure `callIndexToolRows`. Failing to read rows never blocks the
|
|
8277
|
+
* headline numbers; it only shows an honest empty state in the two panels.
|
|
7503
8278
|
*/
|
|
7504
8279
|
function CallIndexOverviewPanel({ api }) {
|
|
7505
8280
|
const [state, setState] = (0, react.useState)({ loading: true });
|
|
@@ -7511,15 +8286,44 @@ function CallIndexOverviewPanel({ api }) {
|
|
|
7511
8286
|
loading: true
|
|
7512
8287
|
}));
|
|
7513
8288
|
const query = { range: "all" };
|
|
8289
|
+
const anchor = Date.now();
|
|
7514
8290
|
(async () => {
|
|
7515
|
-
const [statusResult, overviewResult] = await Promise.all([
|
|
8291
|
+
const [statusResult, overviewResult, callsResult] = await Promise.all([
|
|
8292
|
+
api.getStatus(),
|
|
8293
|
+
api.getOverview(query),
|
|
8294
|
+
api.listCalls(query, void 0, anchor)
|
|
8295
|
+
]);
|
|
7516
8296
|
if (!active) return;
|
|
7517
8297
|
const failure = overviewResult.ok ? statusResult.ok ? void 0 : statusResult : overviewResult;
|
|
8298
|
+
let tools;
|
|
8299
|
+
let toolsFailure;
|
|
8300
|
+
if (callsResult.ok) {
|
|
8301
|
+
const items = [...callsResult.value.items];
|
|
8302
|
+
let cursor = callsResult.value.nextCursor;
|
|
8303
|
+
let pages = 0;
|
|
8304
|
+
while (cursor !== void 0 && pages < 20) {
|
|
8305
|
+
const next = await api.listCalls(query, cursor, anchor);
|
|
8306
|
+
if (!next.ok) {
|
|
8307
|
+
toolsFailure = next;
|
|
8308
|
+
break;
|
|
8309
|
+
}
|
|
8310
|
+
items.push(...next.value.items);
|
|
8311
|
+
cursor = next.value.nextCursor;
|
|
8312
|
+
pages += 1;
|
|
8313
|
+
}
|
|
8314
|
+
tools = callIndexToolRows({
|
|
8315
|
+
...callsResult.value,
|
|
8316
|
+
items
|
|
8317
|
+
});
|
|
8318
|
+
} else toolsFailure = callsResult;
|
|
8319
|
+
if (!active) return;
|
|
7518
8320
|
setState({
|
|
7519
8321
|
loading: false,
|
|
7520
8322
|
...statusResult.ok ? { status: statusResult.value } : {},
|
|
7521
8323
|
...overviewResult.ok ? { overview: overviewResult.value } : {},
|
|
7522
|
-
...failure === void 0 ? {} : { failure }
|
|
8324
|
+
...failure === void 0 ? {} : { failure },
|
|
8325
|
+
...tools === void 0 ? {} : { tools },
|
|
8326
|
+
...toolsFailure === void 0 ? {} : { toolsFailure }
|
|
7523
8327
|
});
|
|
7524
8328
|
})();
|
|
7525
8329
|
return () => {
|
|
@@ -7529,8 +8333,11 @@ function CallIndexOverviewPanel({ api }) {
|
|
|
7529
8333
|
return (0, react.createElement)(CallIndexOverviewPanelView, {
|
|
7530
8334
|
...state.status === void 0 ? {} : { status: state.status },
|
|
7531
8335
|
...state.overview === void 0 ? {} : { overview: state.overview },
|
|
8336
|
+
...state.tools === void 0 ? {} : { tools: state.tools },
|
|
8337
|
+
...state.toolsFailure === void 0 ? {} : { toolsFailure: state.toolsFailure },
|
|
7532
8338
|
...state.failure === void 0 ? {} : { failure: state.failure },
|
|
7533
8339
|
loading: state.loading,
|
|
8340
|
+
toolsLoading: state.loading,
|
|
7534
8341
|
onRefresh: () => setRefreshToken((value) => value + 1)
|
|
7535
8342
|
});
|
|
7536
8343
|
}
|
|
@@ -7659,18 +8466,29 @@ function OverviewContainer(props) {
|
|
|
7659
8466
|
//#endregion
|
|
7660
8467
|
//#region src/client/GuardPanel.tsx
|
|
7661
8468
|
/**
|
|
7662
|
-
* 思考限制 — the Guard configuration surface.
|
|
8469
|
+
* 思考限制 — the Guard configuration surface (v3 · 数据看板, D-044).
|
|
7663
8470
|
*
|
|
7664
8471
|
* Three sections, in the order the product specified: repeated identical calls,
|
|
7665
8472
|
* alternating cycles, no-progress protection. Each carries a model-side
|
|
7666
|
-
* identifier (
|
|
8473
|
+
* identifier ('duplicate_call' / 'alternating_cycle' / 'no_progress') shown as
|
|
7667
8474
|
* plain text, because the reminder text injected into the conversation is
|
|
7668
8475
|
* English while the label a user reads here is Chinese. The identifier is what
|
|
7669
8476
|
* ties the two together, so it is displayed rather than hidden.
|
|
7670
8477
|
*
|
|
7671
|
-
*
|
|
7672
|
-
*
|
|
7673
|
-
*
|
|
8478
|
+
* v3 SHAPE: the switches are no longer a single-column stack of .mc-guard-card.
|
|
8479
|
+
* They become a two-column grid of .v3-gitem cards (>900px two columns, auto
|
|
8480
|
+
* single column via the container query already in v3-ui.ts). Each card has a
|
|
8481
|
+
* StateDot + title + model id + switch head, a compact body, and a thin
|
|
8482
|
+
* supplementary foot. The fourth grid cell is the 「生效范围」 explanation, not
|
|
8483
|
+
* a switch, so the grid fills evenly.
|
|
8484
|
+
*
|
|
8485
|
+
* DOM CONTRACT kept for the shared test suite: nine <li class="mc-guard-point">
|
|
8486
|
+
* whose text still comes from t(); the three data-guard-section values in order;
|
|
8487
|
+
* exactly one threshold <input> (value '3, 5, 8', readOnly tracks onChange); the
|
|
8488
|
+
* four data-guard-stat cells and data-guard-stats / data-guard-stats-since; and
|
|
8489
|
+
* three role="switch" buttons whose aria-checked follows the props. No Chinese
|
|
8490
|
+
* colon (':') is introduced by this file — spacing and full-width spaces do
|
|
8491
|
+
* the separating instead.
|
|
7674
8492
|
*
|
|
7675
8493
|
* Kept hook-free and prop-driven so the settings test suite (no DOM harness) can
|
|
7676
8494
|
* walk the returned tree.
|
|
@@ -7681,6 +8499,10 @@ function OverviewContainer(props) {
|
|
|
7681
8499
|
* The descriptions are part of the contract, not decoration: a bare switch does
|
|
7682
8500
|
* not tell a reader whether turning it off stops reminders only or also stops
|
|
7683
8501
|
* local denials. Each bullet states the real behaviour the detector implements.
|
|
8502
|
+
*
|
|
8503
|
+
* v3 keeps all three bullets (nine <li class="mc-guard-point"> in total, as the
|
|
8504
|
+
* shared suite asserts) but lays them out as one compact wrapped row per card,
|
|
8505
|
+
* so the paragraph reads like a sentence rather than a three-line list.
|
|
7684
8506
|
*/
|
|
7685
8507
|
const SECTIONS = [
|
|
7686
8508
|
{
|
|
@@ -7711,43 +8533,66 @@ const SECTIONS = [
|
|
|
7711
8533
|
]
|
|
7712
8534
|
}
|
|
7713
8535
|
];
|
|
7714
|
-
/**
|
|
8536
|
+
/**
|
|
8537
|
+
* Page-specific rules for the v3 Guard grid. Everything else comes from
|
|
8538
|
+
* v3-ui.ts; the only local vocabulary here is the compact bullet row and the
|
|
8539
|
+
* threshold editor chrome. Colours are always v3 semantic variables — nothing
|
|
8540
|
+
* is hard-coded, so light and dark themes both track the host.
|
|
8541
|
+
*/
|
|
8542
|
+
const GUARD_CSS = [
|
|
8543
|
+
".mc-section.v3-root{display:flex;flex-direction:column;gap:12px}",
|
|
8544
|
+
".v3-gpoints{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;align-items:baseline;gap:0 5px}",
|
|
8545
|
+
".v3-gpoints>.mc-guard-point{font-size:11.5px;line-height:18px;color:var(--v3-t3)}",
|
|
8546
|
+
".v3-gpoints>.mc-guard-point+.mc-guard-point::before{content:'·';margin-right:5px;color:var(--v3-t4)}",
|
|
8547
|
+
".v3-gitem--info{background:var(--v3-panel-2)}",
|
|
8548
|
+
".v3-gitem .v3-gh .v3-sw{margin-left:auto}",
|
|
8549
|
+
".v3-gfoot-edit{margin-top:9px}",
|
|
8550
|
+
".v3-guard-stats{margin:12px 0}",
|
|
8551
|
+
".mc-guard-threshold-edit{display:flex;align-items:center;gap:8px;flex-wrap:wrap}",
|
|
8552
|
+
".mc-guard-threshold-edit-label{font-size:11.5px;color:var(--v3-t3)}",
|
|
8553
|
+
".mc-guard-threshold-edit-input{width:150px;padding:3px 7px;border-radius:var(--v3-r-sm);font-size:12px;font-family:var(--v3-font-code);color:var(--v3-t1);background:var(--v3-panel-2);border:1px solid var(--v3-line)}",
|
|
8554
|
+
".mc-guard-threshold-edit-input:focus-visible{outline:2px solid var(--v3-info);outline-offset:1px}",
|
|
8555
|
+
".mc-guard-threshold-edit-input:disabled{opacity:.6}",
|
|
8556
|
+
".mc-guard-threshold-edit-hint{font-size:10.5px;color:var(--v3-t4)}"
|
|
8557
|
+
].join("");
|
|
8558
|
+
/** '—' for a counter the Host did not report; never a fabricated 0. */
|
|
7715
8559
|
function statText(value) {
|
|
7716
8560
|
return value === void 0 || !Number.isFinite(value) ? "—" : String(value);
|
|
7717
8561
|
}
|
|
7718
8562
|
/**
|
|
7719
|
-
* The Guard's real activity board.
|
|
8563
|
+
* The Guard's real activity board, restyled as a v3 stat strip.
|
|
7720
8564
|
*
|
|
7721
8565
|
* Answers the two questions the page previously could not: 「它是否在工作」
|
|
7722
8566
|
* (observations / since) and 「调用成功还是失败」 (outcome split). Every number
|
|
7723
|
-
* comes from the Host; a missing counter renders
|
|
7724
|
-
* "unknown" rather than "zero".
|
|
8567
|
+
* comes from the Host; a missing counter renders '—', so an older Host reads as
|
|
8568
|
+
* "unknown" rather than "zero". The four data-guard-stat cells and the
|
|
8569
|
+
* data-guard-stats / data-guard-stats-since hooks are the published contract.
|
|
7725
8570
|
*/
|
|
7726
8571
|
function GuardStatsBoard(props) {
|
|
7727
8572
|
const { t, stats } = props;
|
|
7728
8573
|
const outcomes = stats?.outcomes;
|
|
7729
8574
|
const reminders = stats?.reminders;
|
|
7730
8575
|
const cell = (label, value, hint) => (0, react.createElement)("div", {
|
|
7731
|
-
className: "
|
|
8576
|
+
className: "v3-stat",
|
|
7732
8577
|
"data-guard-stat": label
|
|
7733
|
-
}, (0, react.createElement)("div", { className: "
|
|
7734
|
-
return (0, react.createElement)("div", {
|
|
7735
|
-
className: "
|
|
8578
|
+
}, (0, react.createElement)("div", { className: "v3-stat-l" }, label), (0, react.createElement)("div", { className: "v3-stat-v" }, value), hint === void 0 ? null : (0, react.createElement)("div", { className: "v3-stat-d" }, hint));
|
|
8579
|
+
return (0, react.createElement)("div", { className: "v3-guard-stats" }, (0, react.createElement)("div", { className: "v3-ph" }, (0, react.createElement)("h3", { className: "v3-pt" }, t("guardStatsTitle"))), (0, react.createElement)("div", {
|
|
8580
|
+
className: "v3-stats",
|
|
7736
8581
|
"data-guard-stats": "true",
|
|
7737
8582
|
role: "group",
|
|
7738
8583
|
"aria-label": t("guardStatsTitle")
|
|
7739
|
-
}, cell(t("guardStatObservations"), statText(stats?.observations), t("guardStatObservationsHint")), cell(t("guardStatOutcomes"),
|
|
7740
|
-
className: "
|
|
8584
|
+
}, cell(t("guardStatObservations"), statText(stats?.observations), t("guardStatObservationsHint")), cell(t("guardStatOutcomes"), statText(outcomes?.success) + " / " + statText(outcomes?.error), t("guardStatOutcomesHint")), cell(t("guardStatReminders"), statText(reminders?.repeat) + " / " + statText(reminders?.cycle), t("guardStatRemindersHint")), cell(t("guardStatDenials"), statText(stats?.denials), t("guardStatDenialsHint"))), stats?.since === void 0 ? null : (0, react.createElement)("p", {
|
|
8585
|
+
className: "v3-src-note",
|
|
7741
8586
|
"data-guard-stats-since": "true"
|
|
7742
|
-
},
|
|
8587
|
+
}, t("guardStatsSince") + " " + formatGuardTime(stats.since)));
|
|
7743
8588
|
}
|
|
7744
|
-
/**
|
|
8589
|
+
/** 'YYYY-MM-DD HH:mm' in the browser zone; '—' when unknown. */
|
|
7745
8590
|
function formatGuardTime(time) {
|
|
7746
8591
|
if (time === void 0 || !Number.isFinite(time)) return "—";
|
|
7747
8592
|
const date = new Date(time);
|
|
7748
8593
|
if (Number.isNaN(date.getTime())) return "—";
|
|
7749
8594
|
const pad = (value) => String(value).padStart(2, "0");
|
|
7750
|
-
return
|
|
8595
|
+
return date.getFullYear() + "-" + pad(date.getMonth() + 1) + "-" + pad(date.getDate()) + " " + pad(date.getHours()) + ":" + pad(date.getMinutes());
|
|
7751
8596
|
}
|
|
7752
8597
|
/**
|
|
7753
8598
|
* Editable reminder thresholds.
|
|
@@ -7757,6 +8602,9 @@ function formatGuardTime(time) {
|
|
|
7757
8602
|
* field: the list is short, order matters, and a number-per-input row would be
|
|
7758
8603
|
* more chrome than content. Invalid input is refused by the Host and reported
|
|
7759
8604
|
* back, so this input never claims a value the detector rejected.
|
|
8605
|
+
*
|
|
8606
|
+
* Kept as its own component so the shared suite's expanding walk can reach the
|
|
8607
|
+
* single <input> (data-guard-thresholds marks the wrapper).
|
|
7760
8608
|
*/
|
|
7761
8609
|
function GuardThresholdEditor(props) {
|
|
7762
8610
|
const { t, thresholds, onChange } = props;
|
|
@@ -7786,9 +8634,9 @@ function GuardThresholdEditor(props) {
|
|
|
7786
8634
|
}), (0, react.createElement)("span", { className: "mc-guard-threshold-edit-hint" }, editable ? t("guardThresholdsEditableHint") : t("guardThresholdsFixedHint")));
|
|
7787
8635
|
}
|
|
7788
8636
|
/**
|
|
7789
|
-
* Parse
|
|
8637
|
+
* Parse '3, 5, 8' into a threshold list.
|
|
7790
8638
|
*
|
|
7791
|
-
* Returns
|
|
8639
|
+
* Returns 'undefined' for anything the Host would reject (empty, non-integer,
|
|
7792
8640
|
* out of range, not strictly increasing). Parsing here as well as on the Host is
|
|
7793
8641
|
* deliberate: it keeps an invalid keystroke from round-tripping through the
|
|
7794
8642
|
* remote and flickering the field.
|
|
@@ -7806,40 +8654,61 @@ function parseGuardThresholds(text) {
|
|
|
7806
8654
|
}
|
|
7807
8655
|
return parsed;
|
|
7808
8656
|
}
|
|
8657
|
+
/** The supplementary foot line for a section, per the v3 design copy. */
|
|
8658
|
+
function sectionFoot(id, t) {
|
|
8659
|
+
if (id === "alternating_cycle") return (0, react.createElement)("div", { className: "v3-gfoot" }, (0, react.createElement)("span", null, t("guardFootCycle")));
|
|
8660
|
+
if (id === "no_progress") return (0, react.createElement)("div", { className: "v3-gfoot" }, (0, react.createElement)("span", null, t("guardFootNoProgress")));
|
|
8661
|
+
return (0, react.createElement)("div", { className: "v3-gfoot" });
|
|
8662
|
+
}
|
|
7809
8663
|
function GuardPanel(props) {
|
|
7810
8664
|
const { t, enabled, duplicateThresholds, onToggle, onThresholdsChange, stats, onReset } = props;
|
|
7811
8665
|
const section = (entry) => {
|
|
7812
8666
|
const isOn = enabled?.[entry.id] ?? false;
|
|
7813
8667
|
const canToggle = onToggle !== void 0;
|
|
8668
|
+
const dot = isOn ? (0, react.createElement)("span", {
|
|
8669
|
+
className: "v3-dot",
|
|
8670
|
+
"data-tone": "ok",
|
|
8671
|
+
"aria-hidden": "true"
|
|
8672
|
+
}) : (0, react.createElement)("span", {
|
|
8673
|
+
className: "v3-dot",
|
|
8674
|
+
"aria-hidden": "true"
|
|
8675
|
+
});
|
|
7814
8676
|
return (0, react.createElement)("div", {
|
|
7815
8677
|
key: entry.id,
|
|
7816
|
-
className: "
|
|
8678
|
+
className: "v3-gitem",
|
|
7817
8679
|
"data-guard-section": entry.id
|
|
7818
|
-
}, (0, react.createElement)("div", { className: "
|
|
8680
|
+
}, (0, react.createElement)("div", { className: "v3-gh" }, dot, (0, react.createElement)("span", { className: "v3-gnm" }, t(entry.titleKey)), (0, react.createElement)("span", { className: "v3-gid" }, entry.id), (0, react.createElement)("button", {
|
|
7819
8681
|
type: "button",
|
|
7820
8682
|
role: "switch",
|
|
7821
8683
|
"aria-checked": isOn ? "true" : "false",
|
|
7822
8684
|
"aria-label": t(entry.titleKey),
|
|
7823
|
-
className:
|
|
8685
|
+
className: "v3-sw",
|
|
7824
8686
|
disabled: !canToggle,
|
|
7825
8687
|
onClick: () => canToggle && onToggle(entry.id, !isOn)
|
|
7826
|
-
})), (0, react.createElement)("
|
|
8688
|
+
})), (0, react.createElement)("ul", { className: "v3-gpoints" }, ...entry.bodyKeys.map((key) => (0, react.createElement)("li", {
|
|
7827
8689
|
key,
|
|
7828
8690
|
className: "mc-guard-point"
|
|
7829
|
-
}, t(key)))), entry.id === "duplicate_call"
|
|
8691
|
+
}, t(key)))), entry.id === "duplicate_call" ? (0, react.createElement)("div", { className: "v3-gfoot" }, (0, react.createElement)("span", null, t("guardThresholds")), ...(duplicateThresholds ?? []).map((value, index) => (0, react.createElement)("span", {
|
|
8692
|
+
key: index,
|
|
8693
|
+
className: "v3-kbd"
|
|
8694
|
+
}, String(value)))) : sectionFoot(entry.id, t), entry.id === "duplicate_call" && duplicateThresholds !== void 0 ? (0, react.createElement)("div", { className: "v3-gfoot-edit" }, (0, react.createElement)(GuardThresholdEditor, {
|
|
7830
8695
|
t,
|
|
7831
8696
|
thresholds: duplicateThresholds,
|
|
7832
8697
|
...onThresholdsChange === void 0 ? {} : { onChange: onThresholdsChange }
|
|
7833
|
-
})))
|
|
8698
|
+
})) : null);
|
|
7834
8699
|
};
|
|
7835
|
-
|
|
8700
|
+
const scopeCell = (0, react.createElement)("div", {
|
|
8701
|
+
key: "scope",
|
|
8702
|
+
className: "v3-gitem v3-gitem--info"
|
|
8703
|
+
}, (0, react.createElement)("div", { className: "v3-gh" }, (0, react.createElement)("span", { className: "v3-gnm" }, t("guardScopeTitle"))), (0, react.createElement)("p", null, t("guardScopeBody")), (0, react.createElement)("div", { className: "v3-gfoot" }, (0, react.createElement)("span", null, t("guardScopeFoot"))));
|
|
8704
|
+
return (0, react.createElement)("section", { className: "mc-section v3-root" }, V3Styles(), (0, react.createElement)("style", { "data-guard-style": "true" }, GUARD_CSS), (0, react.createElement)("header", { className: "mc-heading-row" }, (0, react.createElement)("h2", { className: "mc-heading" }, t("guardTitle")), (0, react.createElement)("div", { className: "mc-heading-actions" }, onReset !== void 0 && (0, react.createElement)("button", {
|
|
7836
8705
|
type: "button",
|
|
7837
8706
|
className: "mc-count mc-count--action",
|
|
7838
8707
|
onClick: onReset
|
|
7839
|
-
}, t("guardReset")))), (0, react.createElement)("p", { className: "
|
|
8708
|
+
}, t("guardReset")))), (0, react.createElement)("p", { className: "v3-notebox" }, (0, react.createElement)("b", null, t("guardBoundaryLabel")), " ", t("guardBoundary")), (0, react.createElement)(GuardStatsBoard, {
|
|
7840
8709
|
t,
|
|
7841
8710
|
...stats === void 0 ? {} : { stats }
|
|
7842
|
-
}), ...SECTIONS.map(section));
|
|
8711
|
+
}), (0, react.createElement)("div", { className: "v3-gpanel" }, ...SECTIONS.map(section), scopeCell));
|
|
7843
8712
|
}
|
|
7844
8713
|
//#endregion
|
|
7845
8714
|
//#region src/client/GuardContainer.tsx
|
|
@@ -8136,6 +9005,7 @@ function PluginSection(props) {
|
|
|
8136
9005
|
const [active, setActive] = (0, react.useState)("overview");
|
|
8137
9006
|
const callIndexApi = callIndexApiFor(props.callIndexRemote);
|
|
8138
9007
|
const [diagnostics, setDiagnostics] = (0, react.useState)(void 0);
|
|
9008
|
+
const [catalogUsage, setCatalogUsage] = (0, react.useState)(void 0);
|
|
8139
9009
|
(0, react.useEffect)(() => {
|
|
8140
9010
|
let live = true;
|
|
8141
9011
|
(async () => {
|
|
@@ -8147,6 +9017,22 @@ function PluginSection(props) {
|
|
|
8147
9017
|
live = false;
|
|
8148
9018
|
};
|
|
8149
9019
|
}, [callIndexApi]);
|
|
9020
|
+
(0, react.useEffect)(() => {
|
|
9021
|
+
let live = true;
|
|
9022
|
+
(async () => {
|
|
9023
|
+
const result = await callIndexApi.listCalls({ range: "all" });
|
|
9024
|
+
if (!live || !result.ok) return;
|
|
9025
|
+
const map = /* @__PURE__ */ new Map();
|
|
9026
|
+
for (const row of callIndexToolRows(result.value)) map.set(row.toolName, {
|
|
9027
|
+
uses: row.calls,
|
|
9028
|
+
failures: row.error
|
|
9029
|
+
});
|
|
9030
|
+
setCatalogUsage(map);
|
|
9031
|
+
})();
|
|
9032
|
+
return () => {
|
|
9033
|
+
live = false;
|
|
9034
|
+
};
|
|
9035
|
+
}, [callIndexApi]);
|
|
8150
9036
|
return (0, react.createElement)(PluginSectionView, {
|
|
8151
9037
|
capability: props.capability,
|
|
8152
9038
|
usageApi: props.usageApi,
|
|
@@ -8157,7 +9043,8 @@ function PluginSection(props) {
|
|
|
8157
9043
|
t: props.t,
|
|
8158
9044
|
active,
|
|
8159
9045
|
onSelect: setActive,
|
|
8160
|
-
...diagnostics === void 0 ? {} : { diagnostics }
|
|
9046
|
+
...diagnostics === void 0 ? {} : { diagnostics },
|
|
9047
|
+
...catalogUsage === void 0 ? {} : { catalogUsage }
|
|
8161
9048
|
});
|
|
8162
9049
|
}
|
|
8163
9050
|
/**
|
|
@@ -8166,7 +9053,7 @@ function PluginSection(props) {
|
|
|
8166
9053
|
* `UsagePanelView`.
|
|
8167
9054
|
*/
|
|
8168
9055
|
function PluginSectionView(props) {
|
|
8169
|
-
const { capability, usageApi, callIndexRemote, scopeTarget, sessionCatalog, guardRemote, t, active, onSelect, diagnostics } = props;
|
|
9056
|
+
const { capability, usageApi, callIndexRemote, scopeTarget, sessionCatalog, guardRemote, t, active, onSelect, diagnostics, catalogUsage } = props;
|
|
8170
9057
|
const callIndexApi = callIndexApiFor(callIndexRemote);
|
|
8171
9058
|
const panel = (category, children) => (0, react.createElement)("div", {
|
|
8172
9059
|
role: "tabpanel",
|
|
@@ -8199,7 +9086,10 @@ function PluginSectionView(props) {
|
|
|
8199
9086
|
5,
|
|
8200
9087
|
8
|
|
8201
9088
|
]
|
|
8202
|
-
})), panel("catalog", (0, react.createElement)(CapabilitySection,
|
|
9089
|
+
})), panel("catalog", (0, react.createElement)(CapabilitySection, {
|
|
9090
|
+
...capability,
|
|
9091
|
+
...catalogUsage === void 0 ? {} : { usage: catalogUsage }
|
|
9092
|
+
})), panel("usage", callIndexRemote === void 0 && usageApi !== void 0 ? (0, react.createElement)(UsagePanel, { api: usageApi }) : (0, react.createElement)(CallIndexDetailPanel, {
|
|
8203
9093
|
api: callIndexApi,
|
|
8204
9094
|
...scopeTarget === void 0 ? {} : { resolveScopeTarget: scopeTarget },
|
|
8205
9095
|
...sessionCatalog === void 0 ? {} : { resolveSessionCatalog: sessionCatalog }
|
|
@@ -8279,6 +9169,12 @@ async function apply(ctx) {
|
|
|
8279
9169
|
guardDesc: "只针对有证据的重复与无进展拦截具体操作;不因总步数、工具总次数或任务时长终止任务。",
|
|
8280
9170
|
guardBoundary: "统计与限制是两件事:Step、工具调用次数、任务时长只用于统计与诊断,不构成硬停止条件。Quick / Normal / Deep 三档里的 Step、工具次数、时长阈值(soft* / hard*)是兼容字段与统计口径,只参与配置校验与计数,不产生提醒,也不停止任务。单个工具自身的超时另由宿主或该工具负责。",
|
|
8281
9171
|
guardReset: "恢复默认",
|
|
9172
|
+
guardScopeTitle: "生效范围",
|
|
9173
|
+
guardScopeBody: "三个开关按 Agent / Turn 隔离,不跨 Session 继承;关闭只停止对应的提醒与局部拒绝,不改动任何配置或历史。",
|
|
9174
|
+
guardScopeFoot: "恢复默认只写回开关值,不重写其他配置",
|
|
9175
|
+
guardBoundaryLabel: "边界",
|
|
9176
|
+
guardFootCycle: "命中后只给出说明,不阻断调用",
|
|
9177
|
+
guardFootNoProgress: "降级条件 日志缺失 · 结果不可比较 · 识别不确定",
|
|
8282
9178
|
guardSectionA: "A · 相同调用重复提醒",
|
|
8283
9179
|
guardSectionB: "B · 交替循环识别",
|
|
8284
9180
|
guardSectionC: "C · 无进展保护",
|
|
@@ -8336,6 +9232,8 @@ async function apply(ctx) {
|
|
|
8336
9232
|
residentShort: "常驻",
|
|
8337
9233
|
onDemandShort: "按需",
|
|
8338
9234
|
disabledShort: "禁用",
|
|
9235
|
+
catalogZeroCall: "零调用",
|
|
9236
|
+
catalogZeroCallHint: "按已索引调用统计",
|
|
8339
9237
|
cycleHint: "点击标签切换分类(按需 → 禁用 → 常驻)",
|
|
8340
9238
|
notPreviewable: "该文件不是可预览的文本文件",
|
|
8341
9239
|
previewClose: "关闭",
|
|
@@ -8477,6 +9375,12 @@ async function apply(ctx) {
|
|
|
8477
9375
|
guardDesc: "Blocks specific operations only when there is evidence of repetition or no progress; never stops a task for step count, tool count or duration.",
|
|
8478
9376
|
guardBoundary: "Counting and limiting are separate: steps, tool calls and task duration are statistics and diagnostics only, never hard-stop conditions. The per-level (Quick / Normal / Deep) step, tool-call and duration thresholds (soft* / hard*) are compatibility fields and counting units: they only take part in config validation and tallies, never producing a reminder or stopping a task. A single tool timeout stays with the host or that tool.",
|
|
8479
9377
|
guardReset: "Restore defaults",
|
|
9378
|
+
guardScopeTitle: "Scope",
|
|
9379
|
+
guardScopeBody: "The three switches are isolated per Agent / turn and never inherited across Sessions; turning one off stops only its reminders and local denials, and changes no configuration or history.",
|
|
9380
|
+
guardScopeFoot: "Restoring defaults writes only the switch values; no other configuration is rewritten.",
|
|
9381
|
+
guardBoundaryLabel: "Boundary",
|
|
9382
|
+
guardFootCycle: "Fires an explanation only; it never blocks the call.",
|
|
9383
|
+
guardFootNoProgress: "Degrades when: logs missing · results incomparable · match uncertain",
|
|
8480
9384
|
guardSectionA: "A · Repeated identical calls",
|
|
8481
9385
|
guardSectionB: "B · Alternating cycle detection",
|
|
8482
9386
|
guardSectionC: "C · No-progress protection",
|
|
@@ -8534,6 +9438,8 @@ async function apply(ctx) {
|
|
|
8534
9438
|
residentShort: "Resident",
|
|
8535
9439
|
onDemandShort: "On-demand",
|
|
8536
9440
|
disabledShort: "Disabled",
|
|
9441
|
+
catalogZeroCall: "No calls",
|
|
9442
|
+
catalogZeroCallHint: "Based on indexed calls",
|
|
8537
9443
|
cycleHint: "Click a tag to cycle its classification (On-demand → Disabled → Resident)",
|
|
8538
9444
|
notPreviewable: "This file is not a previewable text file",
|
|
8539
9445
|
previewClose: "Close",
|