dsh-prime-memory 0.21.0 → 0.22.2
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/dist/client.js +1581 -1150
- package/dist/config.d.ts +149 -0
- package/dist/config.js +35 -0
- package/dist/conflict-service.d.ts +8 -0
- package/dist/conflict-service.js +19 -0
- package/dist/contract.d.ts +131 -0
- package/dist/domain-gate.d.ts +8 -0
- package/dist/domain-gate.js +30 -0
- package/dist/graph/constraints.d.ts +4 -2
- package/dist/graph/constraints.js +4 -2
- package/dist/hooks/recall.d.ts +2 -0
- package/dist/hooks/recall.js +21 -2
- package/dist/hooks/skill-recall.d.ts +25 -0
- package/dist/hooks/skill-recall.js +72 -0
- package/dist/index.d.ts +98 -0
- package/dist/index.js +26 -1
- package/dist/memport/format.d.ts +70 -0
- package/dist/memport/format.js +305 -0
- package/dist/memport/prefilter.d.ts +62 -0
- package/dist/memport/prefilter.js +132 -0
- package/dist/memport/scan.d.ts +13 -0
- package/dist/memport/scan.js +100 -0
- package/dist/metadata-validators.d.ts +22 -0
- package/dist/metadata-validators.js +45 -0
- package/dist/pipeline/l1.js +16 -2
- package/dist/pipeline/ruminate.d.ts +3 -0
- package/dist/pipeline/ruminate.js +50 -1
- package/dist/pipeline/slot-migrate.d.ts +45 -0
- package/dist/pipeline/slot-migrate.js +45 -0
- package/dist/projection/recall.d.ts +74 -0
- package/dist/projection/recall.js +148 -0
- package/dist/projection/slots.d.ts +5 -0
- package/dist/projection/slots.js +9 -2
- package/dist/prompts/graph-projection.js +3 -0
- package/dist/prompts/l1-extraction.d.ts +4 -1
- package/dist/prompts/l1-extraction.js +27 -4
- package/dist/settings.js +106 -11
- package/dist/skills/crystallize.d.ts +41 -0
- package/dist/skills/crystallize.js +75 -0
- package/dist/stats.d.ts +18 -1
- package/dist/stats.js +184 -5
- package/dist/store/file-versions.d.ts +2 -0
- package/dist/store/file-versions.js +2 -0
- package/dist/store/l1.d.ts +2 -0
- package/dist/store/l1.js +4 -0
- package/dist/store/memory-sources.d.ts +59 -0
- package/dist/store/memory-sources.js +214 -0
- package/dist/store/session-recalled.d.ts +25 -0
- package/dist/store/session-recalled.js +163 -0
- package/dist/store/skill-store.d.ts +99 -0
- package/dist/store/skill-store.js +330 -0
- package/dist/store/sqlite.d.ts +5 -0
- package/dist/store/sqlite.js +30 -4
- package/dist/tools/index.d.ts +0 -13
- package/dist/tools/index.js +58 -7
- package/dist/tools/skills.d.ts +13 -0
- package/dist/tools/skills.js +130 -0
- package/dist/types.d.ts +6 -0
- package/dist/util/maturity.d.ts +27 -0
- package/dist/util/maturity.js +26 -0
- package/dist/wing-backfill.js +7 -4
- package/dsh.plugin.json +2 -2
- package/package.json +14 -14
package/dist/client.js
CHANGED
|
@@ -32,7 +32,7 @@ var __defProp = Object.defineProperty;
|
|
|
32
32
|
module.exports = __toCommonJS(entry_exports);
|
|
33
33
|
|
|
34
34
|
// client/src/panel.tsx
|
|
35
|
-
var
|
|
35
|
+
var import_react21 = require("react");
|
|
36
36
|
|
|
37
37
|
// client/src/sidebar-icon.ts
|
|
38
38
|
var BOOK_ICON_SVG = '<svg data-mem-icon="1" viewBox="0 0 16 16" width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg" style="flex-shrink:0"><path d="M8 3.4C6.6 2.5 4.6 2.4 2.9 3.1v9.3c1.7-.7 3.7-.6 5.1.3 1.4-.9 3.4-1 5.1-.3V3.1C11.4 2.4 9.4 2.5 8 3.4Z" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/><path d="M8 3.4v9.3" stroke="currentColor" stroke-width="1.2"/></svg>';
|
|
@@ -68,12 +68,70 @@ var __defProp = Object.defineProperty;
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
// client/src/skin.ts
|
|
72
|
+
var SKIN_KEY = "dsh-mem-skin";
|
|
73
|
+
function rootEl() {
|
|
74
|
+
return document.documentElement;
|
|
75
|
+
}
|
|
76
|
+
function lsGet() {
|
|
77
|
+
try {
|
|
78
|
+
return localStorage.getItem(SKIN_KEY);
|
|
79
|
+
} catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function lsSet(v) {
|
|
84
|
+
try {
|
|
85
|
+
localStorage.setItem(SKIN_KEY, v);
|
|
86
|
+
} catch {
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function hostDark() {
|
|
90
|
+
return typeof document !== "undefined" && document.body.hasAttribute("data-ds-dark-theme");
|
|
91
|
+
}
|
|
92
|
+
function sysDark() {
|
|
93
|
+
try {
|
|
94
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
95
|
+
} catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function effectiveSkin(skin) {
|
|
100
|
+
if (skin === "light") return "light";
|
|
101
|
+
if (skin === "dark") return "dark";
|
|
102
|
+
return hostDark() || sysDark() ? "dark" : "light";
|
|
103
|
+
}
|
|
104
|
+
function getSkin() {
|
|
105
|
+
const v = lsGet();
|
|
106
|
+
return v === "light" || v === "dark" ? v : "auto";
|
|
107
|
+
}
|
|
108
|
+
function setSkin(skin) {
|
|
109
|
+
lsSet(skin);
|
|
110
|
+
}
|
|
111
|
+
function commit(skin) {
|
|
112
|
+
rootEl().setAttribute("data-dsh-mem-skin", effectiveSkin(skin));
|
|
113
|
+
}
|
|
114
|
+
var hostWatched = false;
|
|
115
|
+
function ensureHostWatch() {
|
|
116
|
+
if (hostWatched) return;
|
|
117
|
+
hostWatched = true;
|
|
118
|
+
const obs = new MutationObserver(() => {
|
|
119
|
+
if (getSkin() === "auto") commit("auto");
|
|
120
|
+
});
|
|
121
|
+
obs.observe(document.body, { attributes: true, attributeFilter: ["data-ds-dark-theme"] });
|
|
122
|
+
}
|
|
123
|
+
function applySkin(skin) {
|
|
124
|
+
commit(skin);
|
|
125
|
+
ensureHostWatch();
|
|
126
|
+
return effectiveSkin(skin);
|
|
127
|
+
}
|
|
128
|
+
|
|
71
129
|
// client/src/styles.ts
|
|
72
130
|
var S = {
|
|
73
131
|
section: { padding: "0 4px" },
|
|
74
132
|
heading: { fontSize: 16, fontWeight: 600, margin: "0 0 4px", color: "var(--dsh-mem-text-1)" },
|
|
75
133
|
intro: { fontSize: 13, color: "var(--dsh-mem-text-3)", margin: "0 0 12px" },
|
|
76
|
-
tabbar: { display: "flex", gap:
|
|
134
|
+
tabbar: { display: "flex", gap: 1, flexWrap: "nowrap", overflowX: "auto", borderBottom: "1px solid var(--dsh-mem-border)", marginBottom: 14 },
|
|
77
135
|
error: {
|
|
78
136
|
marginTop: 10,
|
|
79
137
|
fontSize: 13,
|
|
@@ -208,272 +266,295 @@ var __defProp = Object.defineProperty;
|
|
|
208
266
|
|
|
209
267
|
// client/src/theme.ts
|
|
210
268
|
var THEME_STYLE_ID = "dsh-mem-theme-style";
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
269
|
+
var LIGHT_TOK = [
|
|
270
|
+
" --dsh-mem-accent: #4d6bfe;",
|
|
271
|
+
" --dsh-mem-accent-text: #3d5be0;",
|
|
272
|
+
" --dsh-mem-accent-fill: #3d5be0;",
|
|
273
|
+
" --dsh-mem-accent-weak: rgba(77,107,254,0.10);",
|
|
274
|
+
" --dsh-mem-bg-card: var(--dsw-alias-bg-layer-2, #ffffff);",
|
|
275
|
+
" --dsh-mem-bg-inset: var(--dsw-alias-bg-overlay, #e9ecf2);",
|
|
276
|
+
" --dsh-mem-bg-hover: var(--dsw-alias-interactive-bg-hover, rgba(38,49,72,0.06));",
|
|
277
|
+
" --dsh-mem-bg-pop: var(--dsw-alias-bg-layer-3, #ffffff);",
|
|
278
|
+
" --dsh-mem-bg-pop-base: var(--dsw-alias-bg-primary, #ffffff);",
|
|
279
|
+
" --dsh-mem-border: var(--dsw-alias-border-l2, rgba(0,0,0,0.10));",
|
|
280
|
+
" --dsh-mem-border-strong: var(--dsw-alias-border-l3, rgba(0,0,0,0.12));",
|
|
281
|
+
" --dsh-mem-border-pop: var(--dsw-alias-border-inverted, rgba(0,0,0,0));",
|
|
282
|
+
" --dsh-mem-text-1: var(--dsw-alias-label-primary, #0f1115);",
|
|
283
|
+
" --dsh-mem-text-2: var(--dsw-alias-label-secondary, #61666b);",
|
|
284
|
+
" --dsh-mem-text-3: var(--dsw-alias-label-tertiary, #6e7781);",
|
|
285
|
+
" --dsh-mem-danger: var(--dsw-alias-state-error-primary, #d0403f);",
|
|
286
|
+
// 成本折线图系列色:8 档固定色;PALETTE 只引用 var(),1 档锚品牌蓝、8 档中性"其他"
|
|
287
|
+
" --dsh-mem-chart-1: #4d6bfe;",
|
|
288
|
+
" --dsh-mem-chart-2: #0e9c8f;",
|
|
289
|
+
" --dsh-mem-chart-3: #1f9d55;",
|
|
290
|
+
" --dsh-mem-chart-4: #a8821c;",
|
|
291
|
+
" --dsh-mem-chart-5: #d97a0d;",
|
|
292
|
+
" --dsh-mem-chart-6: #d64570;",
|
|
293
|
+
" --dsh-mem-chart-7: #7c5cff;",
|
|
294
|
+
" --dsh-mem-chart-8: #61666b;",
|
|
295
|
+
// 档位色 = 灰 → 品牌蓝的渐变阶(chat/work 过渡蓝、auto 品牌蓝);
|
|
296
|
+
// 文字对比度按 pill 实际底色(流光内底 = bg-card 97% + 档位色 3%)复算 AA 达标
|
|
297
|
+
" --dsh-mem-mode-chat: #5a69b0;",
|
|
298
|
+
" --dsh-mem-mode-work: #5263ca;",
|
|
299
|
+
" --dsh-mem-mode-auto: #3d5be0;",
|
|
300
|
+
// 开关旋钮 / 进度条底(滑轨已随 ModeSlider 删除,填充渐变与停点令牌一并移除)
|
|
301
|
+
" --dsh-mem-thumb: #ffffff;",
|
|
302
|
+
" --dsh-mem-track: rgba(128,140,150,0.32);",
|
|
303
|
+
// wing 八边形令牌(WingWheel):连线 / 角默认 / 角选中 / 空角与未打标态;
|
|
304
|
+
// 全部引用既有中性色与品牌蓝体系,双主题各自声明,无裸色溢出
|
|
305
|
+
" --dsh-mem-wing-line: rgba(128,140,150,0.35);",
|
|
306
|
+
" --dsh-mem-wing-corner: var(--dsh-mem-text-2);",
|
|
307
|
+
" --dsh-mem-wing-corner-on: var(--dsh-mem-accent);",
|
|
308
|
+
" --dsh-mem-wing-empty: var(--dsh-mem-text-3);",
|
|
309
|
+
" --dsh-mem-shadow-card: var(--dsw-shadow-lv1, 0 2px 4px 0 rgba(0,0,0,0.05));",
|
|
310
|
+
" --dsh-mem-shadow-pop: var(--dsw-shadow-lv3, 0 0 1px 0 rgba(0,0,0,.2), 0 0 4px 0 rgba(0,0,0,.02), 0 12px 32px 0 rgba(0,0,0,0.08));"
|
|
311
|
+
];
|
|
312
|
+
var DARK_TOK = [
|
|
313
|
+
" --dsh-mem-accent: #6e85ff;",
|
|
314
|
+
" --dsh-mem-accent-text: #7b90ff;",
|
|
315
|
+
" --dsh-mem-accent-fill: #465ce8;",
|
|
316
|
+
" --dsh-mem-accent-weak: rgba(110,133,255,0.14);",
|
|
317
|
+
" --dsh-mem-bg-card: var(--dsw-alias-bg-layer-2, #2c2c2e);",
|
|
318
|
+
" --dsh-mem-bg-inset: var(--dsw-alias-bg-layer-1, #232324);",
|
|
319
|
+
" --dsh-mem-bg-hover: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,0.08));",
|
|
320
|
+
" --dsh-mem-bg-pop: var(--dsw-alias-bg-layer-3, #353638);",
|
|
321
|
+
" --dsh-mem-bg-pop-base: var(--dsw-alias-bg-primary, #1b1c1e);",
|
|
322
|
+
" --dsh-mem-border: var(--dsw-alias-border-l2, rgba(255,255,255,0.12));",
|
|
323
|
+
" --dsh-mem-border-strong: var(--dsw-alias-border-l3, rgba(255,255,255,0.16));",
|
|
324
|
+
" --dsh-mem-border-pop: var(--dsw-alias-border-inverted, rgba(255,255,255,0.06));",
|
|
325
|
+
" --dsh-mem-text-1: var(--dsw-alias-label-primary, #f9fafb);",
|
|
326
|
+
" --dsh-mem-text-2: var(--dsw-alias-label-secondary, #cfd3d6);",
|
|
327
|
+
" --dsh-mem-text-3: var(--dsw-alias-label-tertiary, #8892a6);",
|
|
328
|
+
" --dsh-mem-danger: var(--dsw-alias-state-error-primary, #f4707b);",
|
|
329
|
+
" --dsh-mem-chart-1: #6e85ff;",
|
|
330
|
+
" --dsh-mem-chart-2: #35c4b5;",
|
|
331
|
+
" --dsh-mem-chart-3: #52c98d;",
|
|
332
|
+
" --dsh-mem-chart-4: #d9b23e;",
|
|
333
|
+
" --dsh-mem-chart-5: #f59e5b;",
|
|
334
|
+
" --dsh-mem-chart-6: #f47ba2;",
|
|
335
|
+
" --dsh-mem-chart-7: #a78bfa;",
|
|
336
|
+
" --dsh-mem-chart-8: #8892a6;",
|
|
337
|
+
" --dsh-mem-mode-chat: #97a4ff;",
|
|
338
|
+
" --dsh-mem-mode-work: #8295ff;",
|
|
339
|
+
" --dsh-mem-mode-auto: #7b90ff;",
|
|
340
|
+
" --dsh-mem-thumb: #e8ebf5;",
|
|
341
|
+
" --dsh-mem-track: rgba(148,160,180,0.30);",
|
|
342
|
+
" --dsh-mem-wing-line: rgba(148,160,180,0.32);",
|
|
343
|
+
" --dsh-mem-wing-corner: var(--dsh-mem-text-2);",
|
|
344
|
+
" --dsh-mem-wing-corner-on: var(--dsh-mem-accent);",
|
|
345
|
+
" --dsh-mem-wing-empty: var(--dsh-mem-text-3);",
|
|
346
|
+
" --dsh-mem-shadow-card: var(--dsw-shadow-lv1, 0 2px 4px 0 rgba(0,0,0,0.3));",
|
|
347
|
+
" --dsh-mem-shadow-pop: var(--dsw-shadow-lv3, 0 0 1px 0 rgba(0,0,0,.2), 0 0 4px 0 rgba(0,0,0,.02), 0 12px 32px 0 rgba(0,0,0,0.08));"
|
|
348
|
+
];
|
|
349
|
+
var COMPONENT_CSS = [
|
|
350
|
+
// conic 角度要 @property 注册才能插值动画;不支持 @property 的浏览器里
|
|
351
|
+
// var(--dsh-mem-angle) 无定义 → conic 层失效 → background 整条退化为无背景
|
|
352
|
+
//(光带边框与内底一起消失,只剩文字色)。2026 常青浏览器均已支持,仅作记录。
|
|
353
|
+
"@property --dsh-mem-angle { syntax: '<angle>'; initial-value: 0deg; inherits: false; }",
|
|
354
|
+
"@keyframes dshMemFlow { to { --dsh-mem-angle: 360deg; } }",
|
|
355
|
+
// ── 主题切换过渡:只过渡颜色/阴影(不碰 transform),明暗翻转不生硬 ──
|
|
356
|
+
".dsh-mem-root, .dsh-mem-root * { transition: background-color .18s ease, border-color .18s ease, color .18s ease, box-shadow .18s ease; }",
|
|
357
|
+
// ── 控件:按钮(次级)── 圆角体系:控件 8 / 卡片 10 / 浮层 12 / 胶囊 999
|
|
358
|
+
".dsh-mem-btn {",
|
|
359
|
+
" padding: 5px 14px; font-size: 13px; line-height: 20px; border-radius: 8px; cursor: pointer;",
|
|
360
|
+
" border: 1px solid var(--dsh-mem-border); background: var(--dsh-mem-bg-card); color: var(--dsh-mem-text-1);",
|
|
361
|
+
" transition: background-color .15s ease, border-color .15s ease, transform .08s ease;",
|
|
362
|
+
"}",
|
|
363
|
+
".dsh-mem-btn:hover:not(:disabled) { border-color: var(--dsh-mem-border-strong); background: var(--dsh-mem-bg-hover); }",
|
|
364
|
+
".dsh-mem-btn:active:not(:disabled) { transform: scale(0.98); }",
|
|
365
|
+
".dsh-mem-btn:focus-visible { outline: 2px solid var(--dsh-mem-accent); outline-offset: 1px; }",
|
|
366
|
+
".dsh-mem-btn:disabled { opacity: 0.45; cursor: not-allowed; }",
|
|
367
|
+
// ── 控件:输入框 / 下拉 ──
|
|
368
|
+
".dsh-mem-input {",
|
|
369
|
+
" padding: 5px 10px; font-size: 13px; border-radius: 8px; color: var(--dsh-mem-text-1);",
|
|
370
|
+
" border: 1px solid var(--dsh-mem-border); background: var(--dsh-mem-bg-card);",
|
|
371
|
+
" transition: border-color .15s ease, box-shadow .15s ease;",
|
|
372
|
+
"}",
|
|
373
|
+
".dsh-mem-input:focus {",
|
|
374
|
+
" outline: none; border-color: var(--dsh-mem-accent);",
|
|
375
|
+
" box-shadow: 0 0 0 3px var(--dsh-mem-accent-weak);",
|
|
376
|
+
"}",
|
|
377
|
+
// ── 下拉触发钮(NSel):观感与输入框一致(8px 圆角/同令牌边框底色),
|
|
378
|
+
// 文字 ellipsis + CSS 描边 chevron(展开旋转 180°);弹出面板见 .dsh-mem-pop ──
|
|
379
|
+
".dsh-mem-select {",
|
|
380
|
+
" display: inline-flex; align-items: center; justify-content: space-between; gap: 8px;",
|
|
381
|
+
" width: 100%; min-width: 0; padding: 5px 10px; font: inherit; font-size: 13px; line-height: 20px;",
|
|
382
|
+
" text-align: left; border-radius: 8px; cursor: pointer; color: var(--dsh-mem-text-1);",
|
|
383
|
+
" border: 1px solid var(--dsh-mem-border); background: var(--dsh-mem-bg-card);",
|
|
384
|
+
" transition: border-color .15s ease, box-shadow .15s ease;",
|
|
385
|
+
"}",
|
|
386
|
+
".dsh-mem-select:focus-visible {",
|
|
387
|
+
" outline: none; border-color: var(--dsh-mem-accent);",
|
|
388
|
+
" box-shadow: 0 0 0 3px var(--dsh-mem-accent-weak);",
|
|
389
|
+
"}",
|
|
390
|
+
".dsh-mem-select:disabled { opacity: 0.45; cursor: not-allowed; }",
|
|
391
|
+
".dsh-mem-select-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }",
|
|
392
|
+
// 下拉弹出面板:dsh MenuDropdown 同款——浮层 12 圆角 + menu 底 + lv3 投影;
|
|
393
|
+
// 选项行 10 圆角 + hover 底色 + 选中打勾(active 由 data-active 标记)
|
|
394
|
+
".dsh-mem-sel { position: relative; display: inline-flex; min-width: 0; vertical-align: top; }",
|
|
395
|
+
".dsh-mem-sel-chev {",
|
|
396
|
+
" width: 8px; height: 8px; flex: none; margin-right: 2px;",
|
|
397
|
+
" border-right: 1.5px solid var(--dsh-mem-text-3); border-bottom: 1.5px solid var(--dsh-mem-text-3);",
|
|
398
|
+
" transform: rotate(45deg); transition: transform .12s ease;",
|
|
399
|
+
"}",
|
|
400
|
+
".dsh-mem-sel-chev-open { transform: rotate(225deg); }",
|
|
401
|
+
".dsh-mem-pop {",
|
|
402
|
+
" position: absolute; top: calc(100% + 6px); left: 0; z-index: 30;",
|
|
403
|
+
" min-width: 100%; width: max-content; max-width: 340px; max-height: 264px;",
|
|
404
|
+
" overflow-y: auto; overscroll-behavior: contain; padding: 4px;",
|
|
405
|
+
// 不透明实底:基色垫底+别名色整层叠印(别名即使带 alpha 也被垫死),2026-10-09 用户修复
|
|
406
|
+
" background: linear-gradient(var(--dsh-mem-bg-pop), var(--dsh-mem-bg-pop)) , var(--dsh-mem-bg-pop-base); border: 1px solid var(--dsh-mem-border-pop);",
|
|
407
|
+
" border-radius: 12px; box-shadow: var(--dsh-mem-shadow-pop);",
|
|
408
|
+
"}",
|
|
409
|
+
".dsh-mem-pop-opt {",
|
|
410
|
+
" display: flex; align-items: center; gap: 8px; width: 100%; box-sizing: border-box;",
|
|
411
|
+
" min-height: 32px; padding: 5px 10px; font: inherit; font-size: 13px; line-height: 20px;",
|
|
412
|
+
" text-align: left; color: var(--dsh-mem-text-1); cursor: pointer;",
|
|
413
|
+
" background: none; border: none; outline: none; border-radius: 10px;",
|
|
414
|
+
"}",
|
|
415
|
+
'.dsh-mem-pop-opt:hover, .dsh-mem-pop-opt[data-active="1"] { background: var(--dsh-mem-bg-hover); }',
|
|
416
|
+
".dsh-mem-pop-opt-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }",
|
|
417
|
+
".dsh-mem-pop-check { flex: none; font-size: 12px; color: var(--dsh-mem-text-1); }",
|
|
418
|
+
".dsh-mem-pop-empty { padding: 10px; font-size: 13px; color: var(--dsh-mem-text-3); }",
|
|
419
|
+
// ── Tab(下划线式):active 品牌蓝下划线 + 主文字色 ──
|
|
420
|
+
".dsh-mem-tab {",
|
|
421
|
+
" padding: 6px 6px; font-size: 13px; cursor: pointer; background: none; border: none; white-space: nowrap;",
|
|
422
|
+
" color: var(--dsh-mem-text-2); border-bottom: 2px solid transparent; margin-bottom: -1px;",
|
|
423
|
+
"}",
|
|
424
|
+
".dsh-mem-tab:hover { color: var(--dsh-mem-text-1); }",
|
|
425
|
+
".dsh-mem-tab-on { font-weight: 600; color: var(--dsh-mem-text-1); border-bottom-color: var(--dsh-mem-accent); }",
|
|
426
|
+
".dsh-mem-tab:focus-visible { outline: 2px solid var(--dsh-mem-accent); outline-offset: -2px; }",
|
|
427
|
+
// ── 卡片:hover 微抬(边框加深),只给可交互卡片用 ──
|
|
428
|
+
".dsh-mem-card {",
|
|
429
|
+
" border: 1px solid var(--dsh-mem-border); border-radius: 10px; background: var(--dsh-mem-bg-card);",
|
|
430
|
+
" box-shadow: var(--dsh-mem-shadow-card);",
|
|
431
|
+
"}",
|
|
432
|
+
".dsh-mem-card-hover:hover { border-color: var(--dsh-mem-border-strong); }",
|
|
433
|
+
// ── 场景卡折叠箭头:展开态旋转 90°(进 reduced-motion 压制名单) ──
|
|
434
|
+
".dsh-mem-scene-chev { display: inline-block; transition: transform .15s ease; color: var(--dsh-mem-text-3); }",
|
|
435
|
+
// ── 记忆类型标签:tint 风格(彩底淡色 + 彩字),--dsh-mem-tag-c 由类型类给定 ──
|
|
436
|
+
".dsh-mem-tag {",
|
|
437
|
+
" display: inline-block; padding: 1px 8px; border-radius: 999px;",
|
|
438
|
+
" font-size: 11px; font-weight: 600; line-height: 18px; white-space: nowrap;",
|
|
439
|
+
" color: var(--dsh-mem-tag-c, var(--dsh-mem-text-2));",
|
|
440
|
+
" background: color-mix(in srgb, var(--dsh-mem-tag-c, #8a93a1) 12%, transparent);",
|
|
441
|
+
" border: 1px solid color-mix(in srgb, var(--dsh-mem-tag-c, #8a93a1) 28%, transparent);",
|
|
442
|
+
"}",
|
|
443
|
+
".dsh-mem-tag-persona { --dsh-mem-tag-c: #6f42c1; }",
|
|
444
|
+
".dsh-mem-tag-episodic { --dsh-mem-tag-c: #0757b4; }",
|
|
445
|
+
".dsh-mem-tag-instruction, .dsh-mem-tag-work-artifact { --dsh-mem-tag-c: #8a5a00; }",
|
|
446
|
+
".dsh-mem-tag-work-fact { --dsh-mem-tag-c: #0757b4; }",
|
|
447
|
+
".dsh-mem-tag-work-task { --dsh-mem-tag-c: #116629; }",
|
|
448
|
+
".dsh-mem-tag-work-method { --dsh-mem-tag-c: #6f42c1; }",
|
|
449
|
+
"body[data-ds-dark-theme] .dsh-mem-tag-persona { --dsh-mem-tag-c: #c297ff; }",
|
|
450
|
+
"body[data-ds-dark-theme] .dsh-mem-tag-episodic { --dsh-mem-tag-c: #6cb2ff; }",
|
|
451
|
+
"body[data-ds-dark-theme] .dsh-mem-tag-instruction, body[data-ds-dark-theme] .dsh-mem-tag-work-artifact { --dsh-mem-tag-c: #e3b341; }",
|
|
452
|
+
"body[data-ds-dark-theme] .dsh-mem-tag-work-fact { --dsh-mem-tag-c: #6cb2ff; }",
|
|
453
|
+
"body[data-ds-dark-theme] .dsh-mem-tag-work-task { --dsh-mem-tag-c: #6fca74; }",
|
|
454
|
+
"body[data-ds-dark-theme] .dsh-mem-tag-work-method { --dsh-mem-tag-c: #c297ff; }",
|
|
455
|
+
// ── pill 边缘流光(品牌蓝族,chat/work/auto 三档共用;off 无):border 区画旋转
|
|
456
|
+
// conic 光带;内部必须用【不透明】底色盖住光带——半透明内层会让 conic 透进按钮
|
|
457
|
+
// 内部干扰文字(实测事故)。不透明底 = 主题底混 3% 档位色(--dsh-mem-pill-tint
|
|
458
|
+
// 由 pill inline 给定;3% 保证档位色文字 AA,暗色智能档余量 4.63:1)
|
|
459
|
+
".dsh-mem-flow {",
|
|
460
|
+
" border: 1px solid transparent;",
|
|
461
|
+
" background:",
|
|
462
|
+
" linear-gradient(",
|
|
463
|
+
" color-mix(in srgb, var(--dsh-mem-bg-card, #ffffff) 97%, var(--dsh-mem-pill-tint, #4d6bfe)),",
|
|
464
|
+
" color-mix(in srgb, var(--dsh-mem-bg-card, #ffffff) 97%, var(--dsh-mem-pill-tint, #4d6bfe))",
|
|
465
|
+
" ) padding-box,",
|
|
466
|
+
" conic-gradient(from var(--dsh-mem-angle),",
|
|
467
|
+
" rgba(61,91,224,0.9), rgba(77,107,254,0.95), rgba(147,168,255,1),",
|
|
468
|
+
" rgba(110,133,255,0.9), rgba(61,91,224,0.9)) border-box;",
|
|
469
|
+
" animation: dshMemFlow 3s linear infinite;",
|
|
470
|
+
"}",
|
|
471
|
+
// ── off 档 pill:dsh 透明按钮——无底无边框只留文字,hover 才出 interactive 淡底
|
|
472
|
+
//(裸 button 会露 UA 默认灰底+描边,必须显式压掉) ──
|
|
473
|
+
".dsh-mem-pill-off { border: none; background: transparent; }",
|
|
474
|
+
".dsh-mem-pill-off:hover { background: var(--dsh-mem-bg-hover); }",
|
|
475
|
+
".dsh-mem-pill-off:focus-visible { outline: 2px solid var(--dsh-mem-accent); outline-offset: 1px; }",
|
|
476
|
+
// 流光态焦点环(同一物理按钮的两态焦点反馈对称,配方同 .dsh-mem-btn)
|
|
477
|
+
".dsh-mem-flow:focus-visible { outline: 2px solid var(--dsh-mem-accent); outline-offset: 1px; }",
|
|
478
|
+
// ── 触屏隐形热区(手机端适配):触点目标补足 44px 标准(iOS HIG)。
|
|
479
|
+
// 伪元素不参与布局(浮层/输入栏几何零变化),指针事件落在宿主元素上。
|
|
480
|
+
// 全端统一不做 pointer:coarse 分端(桌面点中目标变大是纯收益)。
|
|
481
|
+
// pill:视觉高 24px,::after 上下各外扩 10px;只上下不左右——左右是宿主输入栏
|
|
482
|
+
// 邻位控件(模式选择器),外扩会制造误触重叠带 ──
|
|
483
|
+
".dsh-mem-pill-hit::after {",
|
|
484
|
+
" content: ''; position: absolute; left: 0; right: 0; top: -10px; bottom: -10px;",
|
|
485
|
+
"}",
|
|
486
|
+
// ── 浮层(dsh 原生菜单同配方:不透明实底 + inverted 描边(浅色不可见)+ lv3 阴影) ──
|
|
487
|
+
".dsh-mem-popover {",
|
|
488
|
+
" border-radius: 12px;",
|
|
489
|
+
" border: 1px solid var(--dsh-mem-border-pop);",
|
|
490
|
+
" background: linear-gradient(var(--dsh-mem-bg-pop), var(--dsh-mem-bg-pop)) , var(--dsh-mem-bg-pop-base);",
|
|
491
|
+
" box-shadow: var(--dsh-mem-shadow-pop);",
|
|
492
|
+
" color: var(--dsh-mem-text-1);",
|
|
493
|
+
"}",
|
|
494
|
+
// ── 重建面板 ──(模态本体走 NModal:原生 Modal 优先,回退 rb-overlay/rb-modal)
|
|
495
|
+
".dsh-mem-rb-card {",
|
|
496
|
+
" border: 1px solid var(--dsh-mem-border); border-radius: 10px; background: var(--dsh-mem-bg-card);",
|
|
497
|
+
" box-shadow: var(--dsh-mem-shadow-card); padding: 12px 14px; margin-bottom: 14px; font-size: 13px;",
|
|
498
|
+
// 剪掉行内溢出的固定宽控件(如维度输入框),防其顶破卡片圆角边界
|
|
499
|
+
" overflow: hidden;",
|
|
500
|
+
"}",
|
|
501
|
+
".dsh-mem-rb-bar { height: 8px; border-radius: 4px; overflow: hidden; flex: 1; background: var(--dsh-mem-track); }",
|
|
502
|
+
".dsh-mem-rb-fill { height: 100%; border-radius: 4px; background: var(--dsh-mem-accent-fill); transition: width .4s ease; }",
|
|
503
|
+
// 无位移阶段(单次 LLM 调用可达分钟级)的呼吸进度条:宽度满格,透明度呼吸表达"在跑"
|
|
504
|
+
"@keyframes dshMemRbBreath { 0%,100% { opacity: 1; } 50% { opacity: .35; } }",
|
|
505
|
+
".dsh-mem-rb-fill-indet { animation: dshMemRbBreath 1.6s ease-in-out infinite; transition: none; }",
|
|
506
|
+
".dsh-mem-rb-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.35);",
|
|
507
|
+
" display: flex; align-items: center; justify-content: center; z-index: 2000; }",
|
|
508
|
+
".dsh-mem-rb-modal { width: 440px; max-width: calc(100vw - 48px); border-radius: 12px;",
|
|
509
|
+
" padding: 18px 20px; font-size: 13px; line-height: 1.6;",
|
|
510
|
+
" border: 1px solid var(--dsh-mem-border); background: var(--dsh-mem-bg-card); color: var(--dsh-mem-text-1);",
|
|
511
|
+
" box-shadow: 0 16px 48px rgba(0,0,0,0.24); }",
|
|
512
|
+
"body[data-ds-dark-theme] .dsh-mem-rb-modal { box-shadow: 0 16px 48px rgba(0,0,0,0.6); }",
|
|
513
|
+
".dsh-mem-rb-muted { font-size: 12px; color: var(--dsh-mem-text-3); }",
|
|
514
|
+
// ── 会话信息区(悬浮卡下半部):分隔线 + 2×2 指标 + 状态行;纯静态 DOM,
|
|
515
|
+
// 不挂 rAF 循环,轮询数据到达才触发本组件小树 re-render ──
|
|
516
|
+
".dsh-mem-sinfo { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--dsh-mem-border); }",
|
|
517
|
+
".dsh-mem-sinfo-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 10px; }",
|
|
518
|
+
".dsh-mem-sinfo-val { font-size: 13px; font-weight: 600; color: var(--dsh-mem-text-1); line-height: 18px; font-variant-numeric: tabular-nums; }",
|
|
519
|
+
".dsh-mem-sinfo-label { font-size: 11px; color: var(--dsh-mem-text-3); line-height: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }",
|
|
520
|
+
".dsh-mem-sinfo-warn { font-size: 11px; color: var(--dsh-mem-danger); line-height: 16px; margin-bottom: 6px; }",
|
|
521
|
+
".dsh-mem-sinfo-note { font-size: 11px; color: var(--dsh-mem-text-3); line-height: 16px; margin-top: 8px; }",
|
|
522
|
+
".dsh-mem-sinfo-sum { font-size: 11px; color: var(--dsh-mem-text-3); line-height: 16px; margin-top: 8px; }",
|
|
523
|
+
// reduced-motion 兜底放样式表末尾:同特异性下后置声明才能压过上面的组件类
|
|
524
|
+
"@media (prefers-reduced-motion: reduce) {",
|
|
525
|
+
" .dsh-mem-root, .dsh-mem-root *, .dsh-mem-btn, .dsh-mem-input, .dsh-mem-select, .dsh-mem-rb-fill, .dsh-mem-scene-chev, .dsh-mem-sel-chev { transition: none; }",
|
|
526
|
+
" .dsh-mem-flow { animation: none; }",
|
|
527
|
+
"}"
|
|
528
|
+
];
|
|
529
|
+
function buildStyleSheet() {
|
|
530
|
+
return [
|
|
531
|
+
// auto/跟随宿主的兜底:浅色在 :root,暗色在 body[data-ds-dark-theme]
|
|
224
532
|
":root {",
|
|
225
|
-
|
|
226
|
-
" --dsh-mem-accent-text: #3d5be0;",
|
|
227
|
-
" --dsh-mem-accent-fill: #3d5be0;",
|
|
228
|
-
" --dsh-mem-accent-weak: rgba(77,107,254,0.10);",
|
|
229
|
-
" --dsh-mem-bg-card: var(--dsw-alias-bg-layer-2, #ffffff);",
|
|
230
|
-
" --dsh-mem-bg-inset: var(--dsw-alias-bg-overlay, #e9ecf2);",
|
|
231
|
-
" --dsh-mem-bg-hover: var(--dsw-alias-interactive-bg-hover, rgba(38,49,72,0.06));",
|
|
232
|
-
" --dsh-mem-bg-pop: var(--dsw-specific-menu, var(--dsw-alias-bg-layer-3, #ffffff));",
|
|
233
|
-
" --dsh-mem-border: var(--dsw-alias-border-l2, rgba(0,0,0,0.10));",
|
|
234
|
-
" --dsh-mem-border-strong: var(--dsw-alias-border-l3, rgba(0,0,0,0.12));",
|
|
235
|
-
" --dsh-mem-border-pop: var(--dsw-alias-border-inverted, rgba(0,0,0,0));",
|
|
236
|
-
" --dsh-mem-text-1: var(--dsw-alias-label-primary, #0f1115);",
|
|
237
|
-
" --dsh-mem-text-2: var(--dsw-alias-label-secondary, #61666b);",
|
|
238
|
-
" --dsh-mem-text-3: var(--dsw-alias-label-tertiary, #6e7781);",
|
|
239
|
-
" --dsh-mem-danger: var(--dsw-alias-state-error-primary, #d0403f);",
|
|
240
|
-
// 成本折线图系列色:8 档固定色;PALETTE 只引用 var(),1 档锚品牌蓝、8 档中性"其他"
|
|
241
|
-
" --dsh-mem-chart-1: #4d6bfe;",
|
|
242
|
-
" --dsh-mem-chart-2: #0e9c8f;",
|
|
243
|
-
" --dsh-mem-chart-3: #1f9d55;",
|
|
244
|
-
" --dsh-mem-chart-4: #a8821c;",
|
|
245
|
-
" --dsh-mem-chart-5: #d97a0d;",
|
|
246
|
-
" --dsh-mem-chart-6: #d64570;",
|
|
247
|
-
" --dsh-mem-chart-7: #7c5cff;",
|
|
248
|
-
" --dsh-mem-chart-8: #61666b;",
|
|
249
|
-
// 档位色 = 灰 → 品牌蓝的渐变阶(chat/work 过渡蓝、auto 品牌蓝);
|
|
250
|
-
// 文字对比度按 pill 实际底色(流光内底 = bg-card 97% + 档位色 3%)复算 AA 达标
|
|
251
|
-
" --dsh-mem-mode-chat: #5a69b0;",
|
|
252
|
-
" --dsh-mem-mode-work: #5263ca;",
|
|
253
|
-
" --dsh-mem-mode-auto: #3d5be0;",
|
|
254
|
-
// 开关旋钮 / 进度条底(滑轨已随 ModeSlider 删除,填充渐变与停点令牌一并移除)
|
|
255
|
-
" --dsh-mem-thumb: #ffffff;",
|
|
256
|
-
" --dsh-mem-track: rgba(128,140,150,0.32);",
|
|
257
|
-
// wing 八边形令牌(WingWheel):连线 / 角默认 / 角选中 / 空角与未打标态;
|
|
258
|
-
// 全部引用既有中性色与品牌蓝体系,双主题各自声明,无裸色溢出
|
|
259
|
-
" --dsh-mem-wing-line: rgba(128,140,150,0.35);",
|
|
260
|
-
" --dsh-mem-wing-corner: var(--dsh-mem-text-2);",
|
|
261
|
-
" --dsh-mem-wing-corner-on: var(--dsh-mem-accent);",
|
|
262
|
-
" --dsh-mem-wing-empty: var(--dsh-mem-text-3);",
|
|
263
|
-
" --dsh-mem-shadow-card: var(--dsw-shadow-lv1, 0 2px 4px 0 rgba(0,0,0,0.05));",
|
|
264
|
-
" --dsh-mem-shadow-pop: var(--dsw-shadow-lv3, 0 0 1px 0 rgba(0,0,0,.2), 0 0 4px 0 rgba(0,0,0,.02), 0 12px 32px 0 rgba(0,0,0,0.08));",
|
|
533
|
+
...LIGHT_TOK,
|
|
265
534
|
"}",
|
|
266
|
-
// ── 令牌(暗色:body[data-ds-dark-theme] 是 dsh 前端的暗色开关) ──
|
|
267
535
|
"body[data-ds-dark-theme] {",
|
|
268
|
-
|
|
269
|
-
" --dsh-mem-accent-text: #7b90ff;",
|
|
270
|
-
" --dsh-mem-accent-fill: #465ce8;",
|
|
271
|
-
" --dsh-mem-accent-weak: rgba(110,133,255,0.14);",
|
|
272
|
-
" --dsh-mem-bg-card: var(--dsw-alias-bg-layer-2, #2c2c2e);",
|
|
273
|
-
" --dsh-mem-bg-inset: var(--dsw-alias-bg-layer-1, #232324);",
|
|
274
|
-
" --dsh-mem-bg-hover: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,0.08));",
|
|
275
|
-
" --dsh-mem-bg-pop: var(--dsw-specific-menu, var(--dsw-alias-bg-layer-3, #353638));",
|
|
276
|
-
" --dsh-mem-border: var(--dsw-alias-border-l2, rgba(255,255,255,0.12));",
|
|
277
|
-
" --dsh-mem-border-strong: var(--dsw-alias-border-l3, rgba(255,255,255,0.16));",
|
|
278
|
-
" --dsh-mem-border-pop: var(--dsw-alias-border-inverted, rgba(255,255,255,0.06));",
|
|
279
|
-
" --dsh-mem-text-1: var(--dsw-alias-label-primary, #f9fafb);",
|
|
280
|
-
" --dsh-mem-text-2: var(--dsw-alias-label-secondary, #cfd3d6);",
|
|
281
|
-
" --dsh-mem-text-3: var(--dsw-alias-label-tertiary, #8892a6);",
|
|
282
|
-
" --dsh-mem-danger: var(--dsw-alias-state-error-primary, #f4707b);",
|
|
283
|
-
" --dsh-mem-chart-1: #6e85ff;",
|
|
284
|
-
" --dsh-mem-chart-2: #35c4b5;",
|
|
285
|
-
" --dsh-mem-chart-3: #52c98d;",
|
|
286
|
-
" --dsh-mem-chart-4: #d9b23e;",
|
|
287
|
-
" --dsh-mem-chart-5: #f59e5b;",
|
|
288
|
-
" --dsh-mem-chart-6: #f47ba2;",
|
|
289
|
-
" --dsh-mem-chart-7: #a78bfa;",
|
|
290
|
-
" --dsh-mem-chart-8: #8892a6;",
|
|
291
|
-
" --dsh-mem-mode-chat: #97a4ff;",
|
|
292
|
-
" --dsh-mem-mode-work: #8295ff;",
|
|
293
|
-
" --dsh-mem-mode-auto: #7b90ff;",
|
|
294
|
-
" --dsh-mem-thumb: #e8ebf5;",
|
|
295
|
-
" --dsh-mem-track: rgba(148,160,180,0.30);",
|
|
296
|
-
" --dsh-mem-wing-line: rgba(148,160,180,0.32);",
|
|
297
|
-
" --dsh-mem-wing-corner: var(--dsh-mem-text-2);",
|
|
298
|
-
" --dsh-mem-wing-corner-on: var(--dsh-mem-accent);",
|
|
299
|
-
" --dsh-mem-wing-empty: var(--dsh-mem-text-3);",
|
|
300
|
-
" --dsh-mem-shadow-card: var(--dsw-shadow-lv1, 0 2px 4px 0 rgba(0,0,0,0.3));",
|
|
301
|
-
" --dsh-mem-shadow-pop: var(--dsw-shadow-lv3, 0 0 1px 0 rgba(0,0,0,.2), 0 0 4px 0 rgba(0,0,0,.02), 0 12px 32px 0 rgba(0,0,0,0.08));",
|
|
536
|
+
...DARK_TOK,
|
|
302
537
|
"}",
|
|
303
|
-
//
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
" padding: 5px 14px; font-size: 13px; line-height: 20px; border-radius: 8px; cursor: pointer;",
|
|
308
|
-
" border: 1px solid var(--dsh-mem-border); background: var(--dsh-mem-bg-card); color: var(--dsh-mem-text-1);",
|
|
309
|
-
" transition: background-color .15s ease, border-color .15s ease, transform .08s ease;",
|
|
538
|
+
// 皮肤显式覆写:html[data-dsh-mem-skin] 由 skin.ts 始终写成具体 light|dark。
|
|
539
|
+
// 与宿主暗色块同特异度(元素+属性),但后置声明胜出,从而能压过宿主强切明暗。
|
|
540
|
+
'html[data-dsh-mem-skin="light"] {',
|
|
541
|
+
...LIGHT_TOK,
|
|
310
542
|
"}",
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
".dsh-mem-btn:focus-visible { outline: 2px solid var(--dsh-mem-accent); outline-offset: 1px; }",
|
|
314
|
-
".dsh-mem-btn:disabled { opacity: 0.45; cursor: not-allowed; }",
|
|
315
|
-
// ── 控件:输入框 / 下拉 ──
|
|
316
|
-
".dsh-mem-input {",
|
|
317
|
-
" padding: 5px 10px; font-size: 13px; border-radius: 8px; color: var(--dsh-mem-text-1);",
|
|
318
|
-
" border: 1px solid var(--dsh-mem-border); background: var(--dsh-mem-bg-card);",
|
|
319
|
-
" transition: border-color .15s ease, box-shadow .15s ease;",
|
|
543
|
+
'html[data-dsh-mem-skin="dark"] {',
|
|
544
|
+
...DARK_TOK,
|
|
320
545
|
"}",
|
|
321
|
-
|
|
322
|
-
" outline: none; border-color: var(--dsh-mem-accent);",
|
|
323
|
-
" box-shadow: 0 0 0 3px var(--dsh-mem-accent-weak);",
|
|
324
|
-
"}",
|
|
325
|
-
// ── 下拉触发钮(NSel):观感与输入框一致(8px 圆角/同令牌边框底色),
|
|
326
|
-
// 文字 ellipsis + CSS 描边 chevron(展开旋转 180°);弹出面板见 .dsh-mem-pop ──
|
|
327
|
-
".dsh-mem-select {",
|
|
328
|
-
" display: inline-flex; align-items: center; justify-content: space-between; gap: 8px;",
|
|
329
|
-
" width: 100%; min-width: 0; padding: 5px 10px; font: inherit; font-size: 13px; line-height: 20px;",
|
|
330
|
-
" text-align: left; border-radius: 8px; cursor: pointer; color: var(--dsh-mem-text-1);",
|
|
331
|
-
" border: 1px solid var(--dsh-mem-border); background: var(--dsh-mem-bg-card);",
|
|
332
|
-
" transition: border-color .15s ease, box-shadow .15s ease;",
|
|
333
|
-
"}",
|
|
334
|
-
".dsh-mem-select:focus-visible {",
|
|
335
|
-
" outline: none; border-color: var(--dsh-mem-accent);",
|
|
336
|
-
" box-shadow: 0 0 0 3px var(--dsh-mem-accent-weak);",
|
|
337
|
-
"}",
|
|
338
|
-
".dsh-mem-select:disabled { opacity: 0.45; cursor: not-allowed; }",
|
|
339
|
-
".dsh-mem-select-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }",
|
|
340
|
-
// 下拉弹出面板:dsh MenuDropdown 同款——浮层 12 圆角 + menu 底 + lv3 投影;
|
|
341
|
-
// 选项行 10 圆角 + hover 底色 + 选中打勾(active 由 data-active 标记)
|
|
342
|
-
".dsh-mem-sel { position: relative; display: inline-flex; min-width: 0; vertical-align: top; }",
|
|
343
|
-
".dsh-mem-sel-chev {",
|
|
344
|
-
" width: 8px; height: 8px; flex: none; margin-right: 2px;",
|
|
345
|
-
" border-right: 1.5px solid var(--dsh-mem-text-3); border-bottom: 1.5px solid var(--dsh-mem-text-3);",
|
|
346
|
-
" transform: rotate(45deg); transition: transform .12s ease;",
|
|
347
|
-
"}",
|
|
348
|
-
".dsh-mem-sel-chev-open { transform: rotate(225deg); }",
|
|
349
|
-
".dsh-mem-pop {",
|
|
350
|
-
" position: absolute; top: calc(100% + 6px); left: 0; z-index: 30;",
|
|
351
|
-
" min-width: 100%; width: max-content; max-width: 340px; max-height: 264px;",
|
|
352
|
-
" overflow-y: auto; overscroll-behavior: contain; padding: 4px;",
|
|
353
|
-
" background: var(--dsh-mem-bg-pop); border: 1px solid var(--dsh-mem-border-pop);",
|
|
354
|
-
" border-radius: 12px; box-shadow: var(--dsh-mem-shadow-pop);",
|
|
355
|
-
"}",
|
|
356
|
-
".dsh-mem-pop-opt {",
|
|
357
|
-
" display: flex; align-items: center; gap: 8px; width: 100%; box-sizing: border-box;",
|
|
358
|
-
" min-height: 32px; padding: 5px 10px; font: inherit; font-size: 13px; line-height: 20px;",
|
|
359
|
-
" text-align: left; color: var(--dsh-mem-text-1); cursor: pointer;",
|
|
360
|
-
" background: none; border: none; outline: none; border-radius: 10px;",
|
|
361
|
-
"}",
|
|
362
|
-
'.dsh-mem-pop-opt:hover, .dsh-mem-pop-opt[data-active="1"] { background: var(--dsh-mem-bg-hover); }',
|
|
363
|
-
".dsh-mem-pop-opt-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }",
|
|
364
|
-
".dsh-mem-pop-check { flex: none; font-size: 12px; color: var(--dsh-mem-text-1); }",
|
|
365
|
-
".dsh-mem-pop-empty { padding: 10px; font-size: 13px; color: var(--dsh-mem-text-3); }",
|
|
366
|
-
// ── Tab(下划线式):active 品牌蓝下划线 + 主文字色 ──
|
|
367
|
-
".dsh-mem-tab {",
|
|
368
|
-
" padding: 6px 12px; font-size: 13px; cursor: pointer; background: none; border: none;",
|
|
369
|
-
" color: var(--dsh-mem-text-2); border-bottom: 2px solid transparent; margin-bottom: -1px;",
|
|
370
|
-
"}",
|
|
371
|
-
".dsh-mem-tab:hover { color: var(--dsh-mem-text-1); }",
|
|
372
|
-
".dsh-mem-tab-on { font-weight: 600; color: var(--dsh-mem-text-1); border-bottom-color: var(--dsh-mem-accent); }",
|
|
373
|
-
".dsh-mem-tab:focus-visible { outline: 2px solid var(--dsh-mem-accent); outline-offset: -2px; }",
|
|
374
|
-
// ── 卡片:hover 微抬(边框加深),只给可交互卡片用 ──
|
|
375
|
-
".dsh-mem-card {",
|
|
376
|
-
" border: 1px solid var(--dsh-mem-border); border-radius: 10px; background: var(--dsh-mem-bg-card);",
|
|
377
|
-
" box-shadow: var(--dsh-mem-shadow-card);",
|
|
378
|
-
"}",
|
|
379
|
-
".dsh-mem-card-hover:hover { border-color: var(--dsh-mem-border-strong); }",
|
|
380
|
-
// ── 场景卡折叠箭头:展开态旋转 90°(进 reduced-motion 压制名单) ──
|
|
381
|
-
".dsh-mem-scene-chev { display: inline-block; transition: transform .15s ease; color: var(--dsh-mem-text-3); }",
|
|
382
|
-
// ── 记忆类型标签:tint 风格(彩底淡色 + 彩字),--dsh-mem-tag-c 由类型类给定 ──
|
|
383
|
-
".dsh-mem-tag {",
|
|
384
|
-
" display: inline-block; padding: 1px 8px; border-radius: 999px;",
|
|
385
|
-
" font-size: 11px; font-weight: 600; line-height: 18px; white-space: nowrap;",
|
|
386
|
-
" color: var(--dsh-mem-tag-c, var(--dsh-mem-text-2));",
|
|
387
|
-
" background: color-mix(in srgb, var(--dsh-mem-tag-c, #8a93a1) 12%, transparent);",
|
|
388
|
-
" border: 1px solid color-mix(in srgb, var(--dsh-mem-tag-c, #8a93a1) 28%, transparent);",
|
|
389
|
-
"}",
|
|
390
|
-
".dsh-mem-tag-persona { --dsh-mem-tag-c: #6f42c1; }",
|
|
391
|
-
".dsh-mem-tag-episodic { --dsh-mem-tag-c: #0757b4; }",
|
|
392
|
-
".dsh-mem-tag-instruction, .dsh-mem-tag-work-artifact { --dsh-mem-tag-c: #8a5a00; }",
|
|
393
|
-
".dsh-mem-tag-work-fact { --dsh-mem-tag-c: #0757b4; }",
|
|
394
|
-
".dsh-mem-tag-work-task { --dsh-mem-tag-c: #116629; }",
|
|
395
|
-
".dsh-mem-tag-work-method { --dsh-mem-tag-c: #6f42c1; }",
|
|
396
|
-
"body[data-ds-dark-theme] .dsh-mem-tag-persona { --dsh-mem-tag-c: #c297ff; }",
|
|
397
|
-
"body[data-ds-dark-theme] .dsh-mem-tag-episodic { --dsh-mem-tag-c: #6cb2ff; }",
|
|
398
|
-
"body[data-ds-dark-theme] .dsh-mem-tag-instruction, body[data-ds-dark-theme] .dsh-mem-tag-work-artifact { --dsh-mem-tag-c: #e3b341; }",
|
|
399
|
-
"body[data-ds-dark-theme] .dsh-mem-tag-work-fact { --dsh-mem-tag-c: #6cb2ff; }",
|
|
400
|
-
"body[data-ds-dark-theme] .dsh-mem-tag-work-task { --dsh-mem-tag-c: #6fca74; }",
|
|
401
|
-
"body[data-ds-dark-theme] .dsh-mem-tag-work-method { --dsh-mem-tag-c: #c297ff; }",
|
|
402
|
-
// ── pill 边缘流光(品牌蓝族,chat/work/auto 三档共用;off 无):border 区画旋转
|
|
403
|
-
// conic 光带;内部必须用【不透明】底色盖住光带——半透明内层会让 conic 透进按钮
|
|
404
|
-
// 内部干扰文字(实测事故)。不透明底 = 主题底混 3% 档位色(--dsh-mem-pill-tint
|
|
405
|
-
// 由 pill inline 给定;3% 保证档位色文字 AA,暗色智能档余量 4.63:1)
|
|
406
|
-
".dsh-mem-flow {",
|
|
407
|
-
" border: 1px solid transparent;",
|
|
408
|
-
" background:",
|
|
409
|
-
" linear-gradient(",
|
|
410
|
-
" color-mix(in srgb, var(--dsh-mem-bg-card, #ffffff) 97%, var(--dsh-mem-pill-tint, #4d6bfe)),",
|
|
411
|
-
" color-mix(in srgb, var(--dsh-mem-bg-card, #ffffff) 97%, var(--dsh-mem-pill-tint, #4d6bfe))",
|
|
412
|
-
" ) padding-box,",
|
|
413
|
-
" conic-gradient(from var(--dsh-mem-angle),",
|
|
414
|
-
" rgba(61,91,224,0.9), rgba(77,107,254,0.95), rgba(147,168,255,1),",
|
|
415
|
-
" rgba(110,133,255,0.9), rgba(61,91,224,0.9)) border-box;",
|
|
416
|
-
" animation: dshMemFlow 3s linear infinite;",
|
|
417
|
-
"}",
|
|
418
|
-
// ── off 档 pill:dsh 透明按钮——无底无边框只留文字,hover 才出 interactive 淡底
|
|
419
|
-
//(裸 button 会露 UA 默认灰底+描边,必须显式压掉) ──
|
|
420
|
-
".dsh-mem-pill-off { border: none; background: transparent; }",
|
|
421
|
-
".dsh-mem-pill-off:hover { background: var(--dsh-mem-bg-hover); }",
|
|
422
|
-
".dsh-mem-pill-off:focus-visible { outline: 2px solid var(--dsh-mem-accent); outline-offset: 1px; }",
|
|
423
|
-
// 流光态焦点环(同一物理按钮的两态焦点反馈对称,配方同 .dsh-mem-btn)
|
|
424
|
-
".dsh-mem-flow:focus-visible { outline: 2px solid var(--dsh-mem-accent); outline-offset: 1px; }",
|
|
425
|
-
// ── 触屏隐形热区(手机端适配):触点目标补足 44px 标准(iOS HIG)。
|
|
426
|
-
// 伪元素不参与布局(浮层/输入栏几何零变化),指针事件落在宿主元素上。
|
|
427
|
-
// 全端统一不做 pointer:coarse 分端(桌面点中目标变大是纯收益)。
|
|
428
|
-
// pill:视觉高 24px,::after 上下各外扩 10px;只上下不左右——左右是宿主输入栏
|
|
429
|
-
// 邻位控件(模式选择器),外扩会制造误触重叠带 ──
|
|
430
|
-
".dsh-mem-pill-hit::after {",
|
|
431
|
-
" content: ''; position: absolute; left: 0; right: 0; top: -10px; bottom: -10px;",
|
|
432
|
-
"}",
|
|
433
|
-
// ── 浮层(dsh 原生菜单同配方:不透明实底 + inverted 描边(浅色不可见)+ lv3 阴影) ──
|
|
434
|
-
".dsh-mem-popover {",
|
|
435
|
-
" border-radius: 12px;",
|
|
436
|
-
" border: 1px solid var(--dsh-mem-border-pop);",
|
|
437
|
-
" background: var(--dsh-mem-bg-pop);",
|
|
438
|
-
" box-shadow: var(--dsh-mem-shadow-pop);",
|
|
439
|
-
" color: var(--dsh-mem-text-1);",
|
|
440
|
-
"}",
|
|
441
|
-
// ── 重建面板 ──(模态本体走 NModal:原生 Modal 优先,回退 rb-overlay/rb-modal)
|
|
442
|
-
".dsh-mem-rb-card {",
|
|
443
|
-
" border: 1px solid var(--dsh-mem-border); border-radius: 10px; background: var(--dsh-mem-bg-card);",
|
|
444
|
-
" box-shadow: var(--dsh-mem-shadow-card); padding: 12px 14px; margin-bottom: 14px; font-size: 13px;",
|
|
445
|
-
// 剪掉行内溢出的固定宽控件(如维度输入框),防其顶破卡片圆角边界
|
|
446
|
-
" overflow: hidden;",
|
|
447
|
-
"}",
|
|
448
|
-
".dsh-mem-rb-bar { height: 8px; border-radius: 4px; overflow: hidden; flex: 1; background: var(--dsh-mem-track); }",
|
|
449
|
-
".dsh-mem-rb-fill { height: 100%; border-radius: 4px; background: var(--dsh-mem-accent-fill); transition: width .4s ease; }",
|
|
450
|
-
// 无位移阶段(单次 LLM 调用可达分钟级)的呼吸进度条:宽度满格,透明度呼吸表达"在跑"
|
|
451
|
-
"@keyframes dshMemRbBreath { 0%,100% { opacity: 1; } 50% { opacity: .35; } }",
|
|
452
|
-
".dsh-mem-rb-fill-indet { animation: dshMemRbBreath 1.6s ease-in-out infinite; transition: none; }",
|
|
453
|
-
".dsh-mem-rb-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.35);",
|
|
454
|
-
" display: flex; align-items: center; justify-content: center; z-index: 2000; }",
|
|
455
|
-
".dsh-mem-rb-modal { width: 440px; max-width: calc(100vw - 48px); border-radius: 12px;",
|
|
456
|
-
" padding: 18px 20px; font-size: 13px; line-height: 1.6;",
|
|
457
|
-
" border: 1px solid var(--dsh-mem-border); background: var(--dsh-mem-bg-card); color: var(--dsh-mem-text-1);",
|
|
458
|
-
" box-shadow: 0 16px 48px rgba(0,0,0,0.24); }",
|
|
459
|
-
"body[data-ds-dark-theme] .dsh-mem-rb-modal { box-shadow: 0 16px 48px rgba(0,0,0,0.6); }",
|
|
460
|
-
".dsh-mem-rb-muted { font-size: 12px; color: var(--dsh-mem-text-3); }",
|
|
461
|
-
// ── 会话信息区(悬浮卡下半部):分隔线 + 2×2 指标 + 状态行;纯静态 DOM,
|
|
462
|
-
// 不挂 rAF 循环,轮询数据到达才触发本组件小树 re-render ──
|
|
463
|
-
".dsh-mem-sinfo { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--dsh-mem-border); }",
|
|
464
|
-
".dsh-mem-sinfo-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 10px; }",
|
|
465
|
-
".dsh-mem-sinfo-val { font-size: 13px; font-weight: 600; color: var(--dsh-mem-text-1); line-height: 18px; font-variant-numeric: tabular-nums; }",
|
|
466
|
-
".dsh-mem-sinfo-label { font-size: 11px; color: var(--dsh-mem-text-3); line-height: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }",
|
|
467
|
-
".dsh-mem-sinfo-warn { font-size: 11px; color: var(--dsh-mem-danger); line-height: 16px; margin-bottom: 6px; }",
|
|
468
|
-
".dsh-mem-sinfo-note { font-size: 11px; color: var(--dsh-mem-text-3); line-height: 16px; margin-top: 8px; }",
|
|
469
|
-
".dsh-mem-sinfo-sum { font-size: 11px; color: var(--dsh-mem-text-3); line-height: 16px; margin-top: 8px; }",
|
|
470
|
-
// reduced-motion 兜底放样式表末尾:同特异性下后置声明才能压过上面的组件类
|
|
471
|
-
"@media (prefers-reduced-motion: reduce) {",
|
|
472
|
-
" .dsh-mem-root, .dsh-mem-root *, .dsh-mem-btn, .dsh-mem-input, .dsh-mem-select, .dsh-mem-rb-fill, .dsh-mem-scene-chev, .dsh-mem-sel-chev { transition: none; }",
|
|
473
|
-
" .dsh-mem-flow { animation: none; }",
|
|
474
|
-
"}"
|
|
546
|
+
...COMPONENT_CSS
|
|
475
547
|
].join("\n");
|
|
476
|
-
|
|
548
|
+
}
|
|
549
|
+
function ensureThemeStyle(skin) {
|
|
550
|
+
const eff = effectiveSkin(skin ?? getSkin());
|
|
551
|
+
if (!document.getElementById(THEME_STYLE_ID)) {
|
|
552
|
+
const el = document.createElement("style");
|
|
553
|
+
el.id = THEME_STYLE_ID;
|
|
554
|
+
el.textContent = buildStyleSheet();
|
|
555
|
+
document.head.appendChild(el);
|
|
556
|
+
}
|
|
557
|
+
document.documentElement.setAttribute("data-dsh-mem-skin", eff);
|
|
477
558
|
}
|
|
478
559
|
|
|
479
560
|
// client/src/tabs/ConflictsTab.tsx
|
|
@@ -805,46 +886,243 @@ var __defProp = Object.defineProperty;
|
|
|
805
886
|
}
|
|
806
887
|
function Side(props) {
|
|
807
888
|
const axis = props.pair && props.side ? axisText(props.pair, props.side) : "";
|
|
889
|
+
const mt = props.pair && props.side ? props.side === "winner" ? props.pair.winner_maturity : props.pair.loser_maturity : void 0;
|
|
808
890
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: 6 }, children: [
|
|
809
891
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...S.muted, fontWeight: props.accent ? 600 : void 0 }, children: props.label }),
|
|
810
892
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: S.content, children: props.content || GONE }),
|
|
811
893
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...S.muted, fontFamily: "ui-monospace, Consolas, monospace" }, children: props.id }),
|
|
812
|
-
axis ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...S.muted, marginTop: 2, fontSize: 11 }, children: axis }) : null
|
|
894
|
+
axis ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...S.muted, marginTop: 2, fontSize: 11 }, children: axis }) : null,
|
|
895
|
+
mt ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...S.muted, marginTop: 2, fontSize: 11 }, children: "成熟度 · " + (mt === "high" ? "高" : mt === "mid" ? "中" : "低") }) : null
|
|
813
896
|
] });
|
|
814
897
|
}
|
|
815
898
|
|
|
816
|
-
// client/src/tabs/
|
|
899
|
+
// client/src/tabs/ConnectTab.tsx
|
|
817
900
|
var import_react3 = require("react");
|
|
901
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
902
|
+
function errMsg(r) {
|
|
903
|
+
return r && r.error && r.error.message ? r.error.message : "RPC 错误";
|
|
904
|
+
}
|
|
905
|
+
function SourceCard(props) {
|
|
906
|
+
const { src, rpc, onChanged, onErr } = props;
|
|
907
|
+
const retire = (active) => {
|
|
908
|
+
rpc("dsh-memory/memory-sources-retire", { id: src.id, active }).then((r) => {
|
|
909
|
+
if (r && r.ok) onChanged();
|
|
910
|
+
else onErr(errMsg(r));
|
|
911
|
+
}).catch((e) => onErr(String(e?.message || e)));
|
|
912
|
+
};
|
|
913
|
+
const retired = src.status === "retired";
|
|
914
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dsh-mem-card", style: S.card, children: [
|
|
915
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: S.cardHead, children: [
|
|
916
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: src.label || src.id }),
|
|
917
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: S.muted, children: "· " + src.kind + (retired ? " · 已退役" : src.disabled ? " · 已停用" : "") }),
|
|
918
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: S.grow }),
|
|
919
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(NButton, { onClick: () => retire(!retired), children: retired ? "恢复" : "退役" })
|
|
920
|
+
] }),
|
|
921
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...S.detail }, children: src.path }),
|
|
922
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...S.muted, marginTop: 4 }, children: "上次扫描 " + (src.lastScanAt || "—") + " · 上次导入 " + (src.lastImportAt || "—") })
|
|
923
|
+
] });
|
|
924
|
+
}
|
|
925
|
+
function ConnectTab(props) {
|
|
926
|
+
const rpc = props.rpc;
|
|
927
|
+
const [data, setData] = (0, import_react3.useState)(null);
|
|
928
|
+
const [scan, setScan] = (0, import_react3.useState)(null);
|
|
929
|
+
const [error, setError] = (0, import_react3.useState)(null);
|
|
930
|
+
const [busy, setBusy] = (0, import_react3.useState)(false);
|
|
931
|
+
const [form, setForm] = (0, import_react3.useState)({ id: "", kind: "file", path: "", label: "" });
|
|
932
|
+
const load = (0, import_react3.useCallback)(() => {
|
|
933
|
+
rpc("dsh-memory/memory-sources-list", {}).then((r) => {
|
|
934
|
+
if (r && r.ok) {
|
|
935
|
+
setData(r.value);
|
|
936
|
+
setError(null);
|
|
937
|
+
} else setError(errMsg(r));
|
|
938
|
+
}).catch((e) => setError(String(e?.message || e)));
|
|
939
|
+
}, [rpc]);
|
|
940
|
+
(0, import_react3.useEffect)(() => {
|
|
941
|
+
load();
|
|
942
|
+
}, [load]);
|
|
943
|
+
const add = () => {
|
|
944
|
+
if (!form.id.trim() || !form.path.trim()) {
|
|
945
|
+
setError("登记来源需要 id 与绝对路径 path");
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
rpc("dsh-memory/memory-sources-add", { id: form.id.trim(), kind: form.kind, path: form.path.trim(), label: form.label.trim() || void 0 }).then((r) => {
|
|
949
|
+
if (r && r.ok) {
|
|
950
|
+
setError(null);
|
|
951
|
+
setForm({ ...form, id: "", path: "", label: "" });
|
|
952
|
+
load();
|
|
953
|
+
} else setError(errMsg(r));
|
|
954
|
+
}).catch((e) => setError(String(e?.message || e)));
|
|
955
|
+
};
|
|
956
|
+
const runScan = () => {
|
|
957
|
+
setBusy(true);
|
|
958
|
+
rpc("dsh-memory/memport-scan", {}).then((r) => {
|
|
959
|
+
if (r && r.ok) {
|
|
960
|
+
setScan(r.value);
|
|
961
|
+
setError(null);
|
|
962
|
+
load();
|
|
963
|
+
} else setError(errMsg(r));
|
|
964
|
+
}).catch((e) => setError(String(e?.message || e))).finally(() => setBusy(false));
|
|
965
|
+
};
|
|
966
|
+
const input = (key, placeholder) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
967
|
+
"input",
|
|
968
|
+
{
|
|
969
|
+
className: "dsh-mem-input",
|
|
970
|
+
style: { flex: key === "path" ? 2 : 1, minWidth: 120 },
|
|
971
|
+
value: form[key],
|
|
972
|
+
placeholder,
|
|
973
|
+
onChange: (e) => setForm({ ...form, [key]: e.target.value })
|
|
974
|
+
}
|
|
975
|
+
);
|
|
976
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
977
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { style: S.intro, children: [
|
|
978
|
+
"登记外部 AI 工具的记忆来源(仅存路径指针,正文不复制入库)。扫描为只读预览;实际导入由「memport 导入」经 memory_import 完成。整面需在设置开启",
|
|
979
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("code", { children: " memport.enabled" }),
|
|
980
|
+
"。"
|
|
981
|
+
] }),
|
|
982
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: S.toolbar, children: [
|
|
983
|
+
input("id", "来源 id(小写-连字符)"),
|
|
984
|
+
input("kind", "kind: claude/codex/workbuddy/file…"),
|
|
985
|
+
input("path", "绝对路径(目录或 .mem)"),
|
|
986
|
+
input("label", "显示名(可选)"),
|
|
987
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(NButton, { onClick: add, children: "登记来源" })
|
|
988
|
+
] }),
|
|
989
|
+
!data?.memoryMutate ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: S.hint, children: "提示:登记/退役需先在面板开启「高权限模式」。" }) : null,
|
|
990
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { ...S.flexRow, margin: "8px 0 12px" }, children: [
|
|
991
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: S.muted, children: data ? data.sources.length ? data.sources.length + " 个来源" : "暂无来源" : "加载中…" }),
|
|
992
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: S.grow }),
|
|
993
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(NButton, { onClick: runScan, disabled: busy, children: busy ? "扫描中…" : "扫描全部来源" }),
|
|
994
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(NButton, { onClick: load, children: "刷新" })
|
|
995
|
+
] }),
|
|
996
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: S.error, children: error }) : null,
|
|
997
|
+
(data?.sources || []).map((src) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SourceCard, { rpc, src, onChanged: load, onErr: setError }, src.id)),
|
|
998
|
+
scan ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginTop: 12 }, children: [
|
|
999
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: S.heading, children: [
|
|
1000
|
+
"扫描预览",
|
|
1001
|
+
scan.notice ? `(${scan.notice})` : ""
|
|
1002
|
+
] }),
|
|
1003
|
+
scan.sources.map((s) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dsh-mem-card", style: S.card, children: [
|
|
1004
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: S.cardHead, children: [
|
|
1005
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: s.label || s.sourceId }),
|
|
1006
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: S.muted, children: ":新 " + s.counts.new + " · 近重复 " + s.counts["near-dup"] + " · 疑似冲突 " + s.counts["conflict-candidate"] + " · 重复 " + s.counts.dup }),
|
|
1007
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: S.grow }),
|
|
1008
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: S.muted, children: s.files + " 包 · " + s.total + " 条" })
|
|
1009
|
+
] }),
|
|
1010
|
+
s.errors.length ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...S.error, whiteSpace: "pre-wrap" }, children: s.errors.join("\n") }) : null,
|
|
1011
|
+
s.sampleNew.length ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { ...S.detail }, children: s.sampleNew.map((n) => `[${n.type}] ${n.content}`).join("\n") }) : s.counts.new > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: S.muted, children: "有新记录(样本省略)。" }) : null
|
|
1012
|
+
] }, s.sourceId)),
|
|
1013
|
+
scan.enabled && scan.sources.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: S.muted, children: "无启用来源,或来源下未发现 .mem。" }) : null
|
|
1014
|
+
] }) : null
|
|
1015
|
+
] });
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
// client/src/tabs/SkillsTab.tsx
|
|
1019
|
+
var import_react4 = require("react");
|
|
1020
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1021
|
+
function errMsg2(r) {
|
|
1022
|
+
return r && r.error && r.error.message ? r.error.message : "RPC 错误";
|
|
1023
|
+
}
|
|
1024
|
+
var TITLES = { candidate: "候选", active: "活跃", archived: "已归档" };
|
|
1025
|
+
function SkillsTab(props) {
|
|
1026
|
+
const rpc = props.rpc;
|
|
1027
|
+
const [data, setData] = (0, import_react4.useState)(null);
|
|
1028
|
+
const [error, setError] = (0, import_react4.useState)(null);
|
|
1029
|
+
const [busy, setBusy] = (0, import_react4.useState)(false);
|
|
1030
|
+
const load = (0, import_react4.useCallback)(() => {
|
|
1031
|
+
rpc("dsh-memory/skills-list", {}).then((r) => {
|
|
1032
|
+
if (r && r.ok) {
|
|
1033
|
+
setData(r.value);
|
|
1034
|
+
setError(null);
|
|
1035
|
+
} else setError(errMsg2(r));
|
|
1036
|
+
}).catch((e) => setError(String(e?.message || e)));
|
|
1037
|
+
}, [rpc]);
|
|
1038
|
+
(0, import_react4.useEffect)(() => {
|
|
1039
|
+
load();
|
|
1040
|
+
}, [load]);
|
|
1041
|
+
const act = (id, action, tier) => {
|
|
1042
|
+
if (busy) return;
|
|
1043
|
+
setBusy(true);
|
|
1044
|
+
rpc("dsh-memory/skills-action", { id, action, tier }).then((r) => {
|
|
1045
|
+
if (r && r.ok) {
|
|
1046
|
+
setError(r.value.changed ? null : r.value.notice || null);
|
|
1047
|
+
load();
|
|
1048
|
+
} else setError(errMsg2(r));
|
|
1049
|
+
}).catch((e) => setError(String(e?.message || e))).finally(() => setBusy(false));
|
|
1050
|
+
};
|
|
1051
|
+
if (data && !data.enabled) {
|
|
1052
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: S.intro, children: "技能结晶(程序性记忆)未启用。到「概览」页开启「技能」开关(或部署配置 skills.enabled),重复工作流会固化为技能候选,在此审阅晋升。" });
|
|
1053
|
+
}
|
|
1054
|
+
const mutateHint = data && !data.memoryMutate ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: S.hint, children: "提示:晋升/归档/固定需在面板开启「高权限模式」。" }) : null;
|
|
1055
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1056
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...S.flexRow, marginBottom: 10 }, children: [
|
|
1057
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: S.muted, children: data ? `${data.skills.length} 个技能 · 自动晋升${data.allowPromote ? "开" : "关(人工审阅)"} · 需证据会话达阈` : "加载中…" }),
|
|
1058
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: S.grow }),
|
|
1059
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(NButton, { onClick: load, children: "刷新" })
|
|
1060
|
+
] }),
|
|
1061
|
+
mutateHint,
|
|
1062
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: S.error, children: error }) : null,
|
|
1063
|
+
data && data.skills.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: S.intro, children: '暂无技能。技能从重复出现的"工作方法"记忆结晶而来。' }) : null,
|
|
1064
|
+
(data?.skills || []).map((s) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-mem-card", style: S.card, children: [
|
|
1065
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: S.cardHead, children: [
|
|
1066
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: s.title }),
|
|
1067
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-mem-tag", style: { marginLeft: 6 }, children: TITLES[s.status] }),
|
|
1068
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: S.muted, children: ` · 档:${s.tier}${s.pinned ? " · 已固定" : ""} · 覆盖 ${s.sessionCount} 会话` }),
|
|
1069
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: S.grow })
|
|
1070
|
+
] }),
|
|
1071
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap", marginTop: 6 }, children: [
|
|
1072
|
+
s.status === "candidate" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(NButton, { onClick: () => act(s.id, "promote"), disabled: busy, children: "晋升" }) : null,
|
|
1073
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1074
|
+
"select",
|
|
1075
|
+
{
|
|
1076
|
+
className: "dsh-mem-select",
|
|
1077
|
+
style: { width: "auto", padding: "5px 10px" },
|
|
1078
|
+
value: s.tier,
|
|
1079
|
+
onChange: (e) => act(s.id, "set-tier", e.target.value),
|
|
1080
|
+
children: [
|
|
1081
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "full", children: "全文档" }),
|
|
1082
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "excerpt", children: "摘录档" }),
|
|
1083
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "hint", children: "提示档" })
|
|
1084
|
+
]
|
|
1085
|
+
}
|
|
1086
|
+
),
|
|
1087
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(NButton, { onClick: () => act(s.id, s.pinned ? "unpin" : "pin"), disabled: busy, children: s.pinned ? "取消固定" : "固定" }),
|
|
1088
|
+
s.status !== "archived" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(NButton, { onClick: () => act(s.id, "archive"), disabled: busy, children: "归档" }) : null
|
|
1089
|
+
] })
|
|
1090
|
+
] }, s.id))
|
|
1091
|
+
] });
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
// client/src/tabs/CostTab.tsx
|
|
1095
|
+
var import_react5 = require("react");
|
|
818
1096
|
|
|
819
1097
|
// client/src/ui/controls.tsx
|
|
820
|
-
var
|
|
1098
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
821
1099
|
function Switch(props) {
|
|
822
1100
|
const on = !!props.checked;
|
|
823
1101
|
const disabled = !!props.disabled;
|
|
824
1102
|
const base = { ...S.switch, ...on ? S.switchOn : S.switchOff, ...disabled ? S.switchDisabled : null };
|
|
825
|
-
return /* @__PURE__ */ (0,
|
|
1103
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
826
1104
|
"div",
|
|
827
1105
|
{
|
|
828
1106
|
style: base,
|
|
829
1107
|
onClick: () => {
|
|
830
1108
|
if (!disabled && props.onChange) props.onChange(!on);
|
|
831
1109
|
},
|
|
832
|
-
children: /* @__PURE__ */ (0,
|
|
1110
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { ...S.knob, left: on ? 18 : 2 } })
|
|
833
1111
|
}
|
|
834
1112
|
);
|
|
835
1113
|
}
|
|
836
1114
|
function SwitchRow(props) {
|
|
837
|
-
return /* @__PURE__ */ (0,
|
|
838
|
-
/* @__PURE__ */ (0,
|
|
839
|
-
/* @__PURE__ */ (0,
|
|
840
|
-
/* @__PURE__ */ (0,
|
|
841
|
-
/* @__PURE__ */ (0,
|
|
1115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: S.switchRow, children: [
|
|
1116
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Switch, { checked: props.checked, disabled: props.disabled, onChange: props.onChange }),
|
|
1117
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
|
|
1118
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: S.switchLabel, children: props.label }),
|
|
1119
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: S.switchDesc, children: props.desc || "" })
|
|
842
1120
|
] })
|
|
843
1121
|
] });
|
|
844
1122
|
}
|
|
845
1123
|
function ActionButton(props) {
|
|
846
1124
|
const disabled = !!props.disabled;
|
|
847
|
-
return /* @__PURE__ */ (0,
|
|
1125
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
848
1126
|
"button",
|
|
849
1127
|
{
|
|
850
1128
|
type: "button",
|
|
@@ -868,10 +1146,10 @@ var __defProp = Object.defineProperty;
|
|
|
868
1146
|
function Segmented(props) {
|
|
869
1147
|
const value = props.value;
|
|
870
1148
|
const disabled = !!props.disabled;
|
|
871
|
-
return /* @__PURE__ */ (0,
|
|
1149
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { ...S.seg, ...disabled ? S.switchDisabled : null }, children: props.options.map((opt, i) => {
|
|
872
1150
|
const on = opt.key === value;
|
|
873
1151
|
const optDisabled = disabled || !!opt.disabled;
|
|
874
|
-
return /* @__PURE__ */ (0,
|
|
1152
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
875
1153
|
"span",
|
|
876
1154
|
{
|
|
877
1155
|
title: opt.disabledTitle || opt.title || "",
|
|
@@ -892,7 +1170,7 @@ var __defProp = Object.defineProperty;
|
|
|
892
1170
|
}
|
|
893
1171
|
|
|
894
1172
|
// client/src/tabs/CostTab.tsx
|
|
895
|
-
var
|
|
1173
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
896
1174
|
function renderCostChart(buckets, models, maxY, fmtDate, fmtInt, palette) {
|
|
897
1175
|
const W = 600;
|
|
898
1176
|
const H = 200;
|
|
@@ -907,17 +1185,17 @@ var __defProp = Object.defineProperty;
|
|
|
907
1185
|
const y = (v) => T + ih - v / maxY * ih;
|
|
908
1186
|
const yTicks = [0, maxY / 2, maxY];
|
|
909
1187
|
const xIdx = n > 2 ? [0, Math.floor((n - 1) / 2), n - 1] : n === 2 ? [0, 1] : [0];
|
|
910
|
-
return /* @__PURE__ */ (0,
|
|
911
|
-
/* @__PURE__ */ (0,
|
|
1188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { viewBox: "0 0 " + W + " " + H, style: { width: "100%", height: "auto", display: "block" }, children: [
|
|
1189
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: L, y1: y(0), x2: W - R2, y2: y(0), stroke: "var(--dsh-mem-border)", strokeWidth: 1 }),
|
|
912
1190
|
yTicks.map((v) => {
|
|
913
|
-
return /* @__PURE__ */ (0,
|
|
1191
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("text", { x: L - 6, y: y(v) + 4, textAnchor: "end", fontSize: 10, fill: "var(--dsh-mem-text-3)", children: fmtInt(v) }, "yt" + v);
|
|
914
1192
|
}),
|
|
915
1193
|
xIdx.map((i) => {
|
|
916
|
-
return /* @__PURE__ */ (0,
|
|
1194
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("text", { x: x(i), y: H - 8, textAnchor: "middle", fontSize: 10, fill: "var(--dsh-mem-text-3)", children: fmtDate(buckets[i] ? buckets[i].ts : 0) }, "xt" + i);
|
|
917
1195
|
}),
|
|
918
1196
|
models.map((m, mi) => {
|
|
919
1197
|
const pts = buckets.map((b, i) => x(i) + "," + y(b.byModel[m] || 0)).join(" ");
|
|
920
|
-
return /* @__PURE__ */ (0,
|
|
1198
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
921
1199
|
"polyline",
|
|
922
1200
|
{
|
|
923
1201
|
points: pts,
|
|
@@ -961,13 +1239,13 @@ var __defProp = Object.defineProperty;
|
|
|
961
1239
|
var tdStyle = { fontSize: 12.5, color: "var(--dsh-mem-text-1)", textAlign: "right", padding: "4px 10px", fontFamily: "ui-monospace, Consolas, monospace" };
|
|
962
1240
|
function CostTab(props) {
|
|
963
1241
|
const rpc = props.rpc;
|
|
964
|
-
const [data, setData] = (0,
|
|
965
|
-
const [error, setError] = (0,
|
|
966
|
-
const [granularity, setGranularity] = (0,
|
|
967
|
-
const [layer, setLayer] = (0,
|
|
968
|
-
const [rangeDays, setRangeDays] = (0,
|
|
969
|
-
const [rangeOpen, setRangeOpen] = (0,
|
|
970
|
-
const load = (0,
|
|
1242
|
+
const [data, setData] = (0, import_react5.useState)(null);
|
|
1243
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
1244
|
+
const [granularity, setGranularity] = (0, import_react5.useState)("day");
|
|
1245
|
+
const [layer, setLayer] = (0, import_react5.useState)("");
|
|
1246
|
+
const [rangeDays, setRangeDays] = (0, import_react5.useState)(0);
|
|
1247
|
+
const [rangeOpen, setRangeOpen] = (0, import_react5.useState)(false);
|
|
1248
|
+
const load = (0, import_react5.useCallback)(() => {
|
|
971
1249
|
setError(null);
|
|
972
1250
|
rpc("dsh-memory/token-cost", {
|
|
973
1251
|
granularity,
|
|
@@ -979,7 +1257,7 @@ var __defProp = Object.defineProperty;
|
|
|
979
1257
|
setError(String(e && e.message || e));
|
|
980
1258
|
});
|
|
981
1259
|
}, [rpc, granularity, rangeDays]);
|
|
982
|
-
(0,
|
|
1260
|
+
(0, import_react5.useEffect)(() => {
|
|
983
1261
|
load();
|
|
984
1262
|
const timer = setInterval(load, 5e3);
|
|
985
1263
|
return () => {
|
|
@@ -1052,13 +1330,13 @@ var __defProp = Object.defineProperty;
|
|
|
1052
1330
|
});
|
|
1053
1331
|
const cell = (lc, r, pick) => {
|
|
1054
1332
|
const w = lc.win[r];
|
|
1055
|
-
return /* @__PURE__ */ (0,
|
|
1333
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { style: tdStyle, children: w ? fmtInt(pick(w)) : "0" }, r);
|
|
1056
1334
|
};
|
|
1057
|
-
return /* @__PURE__ */ (0,
|
|
1058
|
-
/* @__PURE__ */ (0,
|
|
1059
|
-
/* @__PURE__ */ (0,
|
|
1060
|
-
/* @__PURE__ */ (0,
|
|
1061
|
-
/* @__PURE__ */ (0,
|
|
1335
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
1336
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { ...S.flexRow, marginBottom: 10 }, children: [
|
|
1337
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Segmented, { value: layer, options: LAYER_OPTS, onChange: setLayer }),
|
|
1338
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Segmented, { value: granularity, options: GRAN_OPTS, onChange: setGranularity }),
|
|
1339
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1062
1340
|
NButton,
|
|
1063
1341
|
{
|
|
1064
1342
|
onClick: () => {
|
|
@@ -1067,12 +1345,12 @@ var __defProp = Object.defineProperty;
|
|
|
1067
1345
|
children: rangeDays > 0 ? "近 " + rangeDays + " 天" : "近N天"
|
|
1068
1346
|
}
|
|
1069
1347
|
),
|
|
1070
|
-
/* @__PURE__ */ (0,
|
|
1071
|
-
/* @__PURE__ */ (0,
|
|
1348
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: S.grow }),
|
|
1349
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(NButton, { onClick: load, children: "刷新" })
|
|
1072
1350
|
] }),
|
|
1073
|
-
rangeOpen ? /* @__PURE__ */ (0,
|
|
1074
|
-
/* @__PURE__ */ (0,
|
|
1075
|
-
/* @__PURE__ */ (0,
|
|
1351
|
+
rangeOpen ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { ...S.flexRow, marginBottom: 10 }, children: [
|
|
1352
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: S.muted, children: "展示近 N 天(正整数,清空=默认窗口;超出保留期后端自动回退)" }),
|
|
1353
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1076
1354
|
NInput,
|
|
1077
1355
|
{
|
|
1078
1356
|
value: rangeDays === 0 ? "" : String(rangeDays),
|
|
@@ -1090,94 +1368,94 @@ var __defProp = Object.defineProperty;
|
|
|
1090
1368
|
}
|
|
1091
1369
|
)
|
|
1092
1370
|
] }) : null,
|
|
1093
|
-
error ? /* @__PURE__ */ (0,
|
|
1094
|
-
/* @__PURE__ */ (0,
|
|
1095
|
-
buckets.length > 0 ? /* @__PURE__ */ (0,
|
|
1371
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: S.error, children: "成本读取失败:" + error }) : null,
|
|
1372
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: S.panelLabel, children: "成本趋势(按模型)" }),
|
|
1373
|
+
buckets.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
1096
1374
|
renderCostChart(buckets, models, maxY, fmtDate, fmtInt, PALETTE),
|
|
1097
|
-
/* @__PURE__ */ (0,
|
|
1098
|
-
return /* @__PURE__ */ (0,
|
|
1375
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: "4px 12px", margin: "6px 0 14px" }, children: models.map((m, mi) => {
|
|
1376
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1099
1377
|
"span",
|
|
1100
1378
|
{
|
|
1101
1379
|
style: { display: "inline-flex", alignItems: "center", gap: 4, fontSize: 12, color: "var(--dsh-mem-text-2)" },
|
|
1102
1380
|
children: [
|
|
1103
|
-
/* @__PURE__ */ (0,
|
|
1381
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { width: 10, height: 10, borderRadius: 4, background: PALETTE[mi % PALETTE.length], display: "inline-block" } }),
|
|
1104
1382
|
m
|
|
1105
1383
|
]
|
|
1106
1384
|
},
|
|
1107
1385
|
"lg" + m
|
|
1108
1386
|
);
|
|
1109
1387
|
}) })
|
|
1110
|
-
] }) : /* @__PURE__ */ (0,
|
|
1111
|
-
/* @__PURE__ */ (0,
|
|
1112
|
-
/* @__PURE__ */ (0,
|
|
1113
|
-
/* @__PURE__ */ (0,
|
|
1114
|
-
/* @__PURE__ */ (0,
|
|
1388
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { style: S.muted, children: data ? "暂无成本数据(触发一次蒸馏后这里会出现趋势)。" : "加载中…" }),
|
|
1389
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: S.panelLabel, children: "层级成本(输出 token)" }),
|
|
1390
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { style: { width: "100%", borderCollapse: "collapse", marginBottom: 14 }, children: [
|
|
1391
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { children: [
|
|
1392
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { style: thFirst, children: "层级" }),
|
|
1115
1393
|
RANGES.map((r) => {
|
|
1116
|
-
return /* @__PURE__ */ (0,
|
|
1394
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { style: thStyle, children: RANGE_LABELS[r] }, r);
|
|
1117
1395
|
})
|
|
1118
1396
|
] }) }),
|
|
1119
|
-
/* @__PURE__ */ (0,
|
|
1120
|
-
return /* @__PURE__ */ (0,
|
|
1121
|
-
/* @__PURE__ */ (0,
|
|
1397
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tbody", { children: layerTable.map((lc) => {
|
|
1398
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { children: [
|
|
1399
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { style: tdFirst, children: lc.layer.toUpperCase() }),
|
|
1122
1400
|
RANGES.map((r) => cell(lc, r, (w) => w.outputTokens))
|
|
1123
1401
|
] }, lc.layer);
|
|
1124
1402
|
}) })
|
|
1125
1403
|
] }),
|
|
1126
|
-
/* @__PURE__ */ (0,
|
|
1127
|
-
/* @__PURE__ */ (0,
|
|
1128
|
-
/* @__PURE__ */ (0,
|
|
1129
|
-
/* @__PURE__ */ (0,
|
|
1404
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: S.panelLabel, children: "层级成本(单次 avg)" }),
|
|
1405
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { style: { width: "100%", borderCollapse: "collapse", marginBottom: 14 }, children: [
|
|
1406
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { children: [
|
|
1407
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { style: thFirst, children: "层级" }),
|
|
1130
1408
|
RANGES.map((r) => {
|
|
1131
|
-
return /* @__PURE__ */ (0,
|
|
1409
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { style: thStyle, children: RANGE_LABELS[r] + "-avg" }, r);
|
|
1132
1410
|
})
|
|
1133
1411
|
] }) }),
|
|
1134
|
-
/* @__PURE__ */ (0,
|
|
1135
|
-
return /* @__PURE__ */ (0,
|
|
1136
|
-
/* @__PURE__ */ (0,
|
|
1412
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tbody", { children: layerTable.map((lc) => {
|
|
1413
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { children: [
|
|
1414
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { style: tdFirst, children: lc.layer.toUpperCase() }),
|
|
1137
1415
|
RANGES.map((r) => cell(lc, r, (w) => w.avgOutputTokens))
|
|
1138
1416
|
] }, lc.layer);
|
|
1139
1417
|
}) })
|
|
1140
1418
|
] }),
|
|
1141
|
-
/* @__PURE__ */ (0,
|
|
1142
|
-
/* @__PURE__ */ (0,
|
|
1143
|
-
/* @__PURE__ */ (0,
|
|
1144
|
-
/* @__PURE__ */ (0,
|
|
1419
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: S.panelLabel, children: "层级成本(单次 median)" }),
|
|
1420
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { style: { width: "100%", borderCollapse: "collapse", marginBottom: 14 }, children: [
|
|
1421
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { children: [
|
|
1422
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { style: thFirst, children: "层级" }),
|
|
1145
1423
|
RANGES.map((r) => {
|
|
1146
|
-
return /* @__PURE__ */ (0,
|
|
1424
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { style: thStyle, children: RANGE_LABELS[r] + "-median" }, r);
|
|
1147
1425
|
})
|
|
1148
1426
|
] }) }),
|
|
1149
|
-
/* @__PURE__ */ (0,
|
|
1150
|
-
return /* @__PURE__ */ (0,
|
|
1151
|
-
/* @__PURE__ */ (0,
|
|
1427
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tbody", { children: layerTable.map((lc) => {
|
|
1428
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { children: [
|
|
1429
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { style: tdFirst, children: lc.layer.toUpperCase() }),
|
|
1152
1430
|
RANGES.map((r) => cell(lc, r, (w) => w.medianOutputTokens))
|
|
1153
1431
|
] }, lc.layer);
|
|
1154
1432
|
}) })
|
|
1155
1433
|
] }),
|
|
1156
|
-
/* @__PURE__ */ (0,
|
|
1157
|
-
/* @__PURE__ */ (0,
|
|
1158
|
-
return /* @__PURE__ */ (0,
|
|
1159
|
-
/* @__PURE__ */ (0,
|
|
1160
|
-
/* @__PURE__ */ (0,
|
|
1161
|
-
/* @__PURE__ */ (0,
|
|
1434
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: S.panelLabel, children: "时间窗口总览" }),
|
|
1435
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: S.statGrid, children: windows.map((w) => {
|
|
1436
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "dsh-mem-card", style: S.statTile, children: [
|
|
1437
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: S.statNum, children: fmtInt(w.outputTokens + w.reasoningTokens) }),
|
|
1438
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: S.statLabel, children: RANGE_LABELS[w.range] + " · 总输出 token" }),
|
|
1439
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: S.muted, children: "文字 " + fmtInt(w.outputTokens) + " · 思考 " + fmtInt(w.reasoningTokens) + " · " + w.calls + " 次调用" })
|
|
1162
1440
|
] }, w.range);
|
|
1163
1441
|
}) }),
|
|
1164
|
-
byModel.length > 0 ? /* @__PURE__ */ (0,
|
|
1165
|
-
/* @__PURE__ */ (0,
|
|
1442
|
+
byModel.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
1443
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: S.panelLabel, children: "按模型(累计)" }),
|
|
1166
1444
|
byModel.map((m) => {
|
|
1167
1445
|
const label = fmtModel(m.provider, m.model);
|
|
1168
|
-
return /* @__PURE__ */ (0,
|
|
1169
|
-
/* @__PURE__ */ (0,
|
|
1170
|
-
/* @__PURE__ */ (0,
|
|
1446
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: S.infoRow, children: [
|
|
1447
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: S.infoKey, children: label }),
|
|
1448
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: S.infoVal, children: m.calls + " 次 · 输出 " + fmtInt(m.outputTokens) + " · 思考 " + fmtInt(m.reasoningTokens) })
|
|
1171
1449
|
] }, "m-" + label);
|
|
1172
1450
|
})
|
|
1173
1451
|
] }) : null,
|
|
1174
|
-
data ? /* @__PURE__ */ (0,
|
|
1452
|
+
data ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { style: S.hint, children: "输入按字符、输出/思考按 token 计;趋势图 Y 轴为输出 token,上方可切换层级与颗粒度。" }) : null
|
|
1175
1453
|
] });
|
|
1176
1454
|
}
|
|
1177
1455
|
|
|
1178
1456
|
// client/src/tabs/LogTab.tsx
|
|
1179
|
-
var
|
|
1180
|
-
var
|
|
1457
|
+
var import_react6 = require("react");
|
|
1458
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1181
1459
|
var SOURCES = [
|
|
1182
1460
|
{ id: "", label: "系统日志" },
|
|
1183
1461
|
{ id: "recall_turn", label: "召回追踪" },
|
|
@@ -1200,11 +1478,11 @@ var __defProp = Object.defineProperty;
|
|
|
1200
1478
|
}
|
|
1201
1479
|
function LogTab(props) {
|
|
1202
1480
|
const rpc = props.rpc;
|
|
1203
|
-
const [source, setSource] = (0,
|
|
1204
|
-
const [lines, setLines] = (0,
|
|
1205
|
-
const [error, setError] = (0,
|
|
1206
|
-
const preRef = (0,
|
|
1207
|
-
const load = (0,
|
|
1481
|
+
const [source, setSource] = (0, import_react6.useState)("");
|
|
1482
|
+
const [lines, setLines] = (0, import_react6.useState)(null);
|
|
1483
|
+
const [error, setError] = (0, import_react6.useState)(null);
|
|
1484
|
+
const preRef = (0, import_react6.useRef)(null);
|
|
1485
|
+
const load = (0, import_react6.useCallback)(() => {
|
|
1208
1486
|
setError(null);
|
|
1209
1487
|
if (source === "") {
|
|
1210
1488
|
rpc("dsh-memory/log-tail", { lines: 200 }).then((r) => {
|
|
@@ -1218,25 +1496,25 @@ var __defProp = Object.defineProperty;
|
|
|
1218
1496
|
else setError(r && r.error ? r.error.message : "RPC error");
|
|
1219
1497
|
}).catch((e) => setError(String(e && e.message || e)));
|
|
1220
1498
|
}, [rpc, source]);
|
|
1221
|
-
(0,
|
|
1499
|
+
(0, import_react6.useEffect)(() => {
|
|
1222
1500
|
load();
|
|
1223
1501
|
}, [load]);
|
|
1224
|
-
(0,
|
|
1502
|
+
(0, import_react6.useEffect)(() => {
|
|
1225
1503
|
if (lines && preRef.current) preRef.current.scrollTop = preRef.current.scrollHeight;
|
|
1226
1504
|
}, [lines]);
|
|
1227
|
-
return /* @__PURE__ */ (0,
|
|
1228
|
-
/* @__PURE__ */ (0,
|
|
1229
|
-
SOURCES.map((s) => /* @__PURE__ */ (0,
|
|
1230
|
-
/* @__PURE__ */ (0,
|
|
1231
|
-
/* @__PURE__ */ (0,
|
|
1505
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
|
|
1506
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { ...S.flexRow, marginBottom: 10, gap: 8 }, children: [
|
|
1507
|
+
SOURCES.map((s) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NButton, { onClick: () => setSource(s.id), children: source === s.id ? "● " + s.label : s.label }, s.id)),
|
|
1508
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: S.grow }),
|
|
1509
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NButton, { onClick: load, children: "刷新" })
|
|
1232
1510
|
] }),
|
|
1233
|
-
/* @__PURE__ */ (0,
|
|
1234
|
-
error ? /* @__PURE__ */ (0,
|
|
1511
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { ...S.muted, marginBottom: 10 }, children: error ? "加载失败" : lines === null ? "加载中…" : `最近 ${lines.length} 条(${SOURCES.find((s) => s.id === source)?.label})` }),
|
|
1512
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { ...S.error, marginBottom: 10 }, children: "读取失败:" + error + "(点右上“刷新”重试)" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { style: S.pre, ref: preRef, children: (lines || []).join("\n") || "(暂无记录)" })
|
|
1235
1513
|
] });
|
|
1236
1514
|
}
|
|
1237
1515
|
|
|
1238
1516
|
// client/src/tabs/OverviewTab.tsx
|
|
1239
|
-
var
|
|
1517
|
+
var import_react15 = require("react");
|
|
1240
1518
|
|
|
1241
1519
|
// client/src/pill/modes.ts
|
|
1242
1520
|
var MODES = [
|
|
@@ -1256,11 +1534,11 @@ var __defProp = Object.defineProperty;
|
|
|
1256
1534
|
}
|
|
1257
1535
|
|
|
1258
1536
|
// client/src/tabs/DistillSettings.tsx
|
|
1259
|
-
var
|
|
1537
|
+
var import_react11 = require("react");
|
|
1260
1538
|
|
|
1261
1539
|
// client/src/tabs/BudgetInputs.tsx
|
|
1262
|
-
var
|
|
1263
|
-
var
|
|
1540
|
+
var import_react7 = require("react");
|
|
1541
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1264
1542
|
var LAYERS = [
|
|
1265
1543
|
["extract", "抽取"],
|
|
1266
1544
|
["dedup", "去重"],
|
|
@@ -1281,7 +1559,7 @@ var __defProp = Object.defineProperty;
|
|
|
1281
1559
|
const onError = props.onError;
|
|
1282
1560
|
const scope = props.scope ?? "all";
|
|
1283
1561
|
const layers = scope === "all" || scope === "input" ? LAYERS : LAYERS.filter((l) => SCOPE_KEYS[scope].includes(l[0]));
|
|
1284
|
-
const [draft, setDraft] = (0,
|
|
1562
|
+
const [draft, setDraft] = (0, import_react7.useState)(null);
|
|
1285
1563
|
if (!data || !data.budgets) return null;
|
|
1286
1564
|
const cur = data.budgets.current || {};
|
|
1287
1565
|
const def = data.budgets.defaults || {};
|
|
@@ -1377,7 +1655,7 @@ var __defProp = Object.defineProperty;
|
|
|
1377
1655
|
return false;
|
|
1378
1656
|
};
|
|
1379
1657
|
const inputBox = (key, _label, title, width, placeholder, onCommit) => {
|
|
1380
|
-
return /* @__PURE__ */ (0,
|
|
1658
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1381
1659
|
NInput,
|
|
1382
1660
|
{
|
|
1383
1661
|
type: "number",
|
|
@@ -1408,10 +1686,10 @@ var __defProp = Object.defineProperty;
|
|
|
1408
1686
|
const showInput = scope === "all" || scope === "input";
|
|
1409
1687
|
const effNote = layers.map((l) => eff[l[0]] || "?").join(" / ");
|
|
1410
1688
|
const rowLabel = (key) => key === "extract" ? "抽取输出" : key === "dedup" ? "去重输出" : key === "l2" ? "L2 输出" : "L3 输出";
|
|
1411
|
-
const
|
|
1412
|
-
return /* @__PURE__ */ (0,
|
|
1413
|
-
showOutputs ? /* @__PURE__ */ (0,
|
|
1414
|
-
/* @__PURE__ */ (0,
|
|
1689
|
+
const rowStyle2 = { display: "flex", alignItems: "center", gap: 8 };
|
|
1690
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
|
|
1691
|
+
showOutputs ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { marginTop: 12 }, children: [
|
|
1692
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1415
1693
|
"div",
|
|
1416
1694
|
{
|
|
1417
1695
|
style: S.switchLabel,
|
|
@@ -1419,8 +1697,8 @@ var __defProp = Object.defineProperty;
|
|
|
1419
1697
|
children: "输出预算"
|
|
1420
1698
|
}
|
|
1421
1699
|
),
|
|
1422
|
-
/* @__PURE__ */ (0,
|
|
1423
|
-
/* @__PURE__ */ (0,
|
|
1700
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 6, marginTop: 4 }, children: layers.map((l) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: rowStyle2, children: [
|
|
1701
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { width: 68, flexShrink: 0, fontSize: 12, color: "var(--dsh-mem-text-2)" }, children: rowLabel(l[0]) }),
|
|
1424
1702
|
inputBox(
|
|
1425
1703
|
l[0],
|
|
1426
1704
|
l[1],
|
|
@@ -1429,11 +1707,11 @@ var __defProp = Object.defineProperty;
|
|
|
1429
1707
|
def[l[0]],
|
|
1430
1708
|
commitOutputs
|
|
1431
1709
|
),
|
|
1432
|
-
/* @__PURE__ */ (0,
|
|
1710
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: 11, color: "var(--dsh-mem-text-3)" }, children: "token" })
|
|
1433
1711
|
] }, l[0])) })
|
|
1434
1712
|
] }) : null,
|
|
1435
|
-
showInput ? /* @__PURE__ */ (0,
|
|
1436
|
-
/* @__PURE__ */ (0,
|
|
1713
|
+
showInput ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { marginTop: 12 }, children: [
|
|
1714
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1437
1715
|
"div",
|
|
1438
1716
|
{
|
|
1439
1717
|
style: S.switchLabel,
|
|
@@ -1441,8 +1719,8 @@ var __defProp = Object.defineProperty;
|
|
|
1441
1719
|
children: "输入预算"
|
|
1442
1720
|
}
|
|
1443
1721
|
),
|
|
1444
|
-
/* @__PURE__ */ (0,
|
|
1445
|
-
/* @__PURE__ */ (0,
|
|
1722
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 6, marginTop: 4 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: rowStyle2, children: [
|
|
1723
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { width: 68, flexShrink: 0, fontSize: 12, color: "var(--dsh-mem-text-2)" }, children: "单次输入" }),
|
|
1446
1724
|
inputBox(
|
|
1447
1725
|
"input",
|
|
1448
1726
|
"输入",
|
|
@@ -1451,15 +1729,15 @@ var __defProp = Object.defineProperty;
|
|
|
1451
1729
|
ib.fallback,
|
|
1452
1730
|
commitInput
|
|
1453
1731
|
),
|
|
1454
|
-
/* @__PURE__ */ (0,
|
|
1732
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: 11, color: "var(--dsh-mem-text-3)" }, children: "字符" })
|
|
1455
1733
|
] }) })
|
|
1456
1734
|
] }) : null
|
|
1457
1735
|
] });
|
|
1458
1736
|
}
|
|
1459
1737
|
|
|
1460
1738
|
// client/src/tabs/ChannelEditor.tsx
|
|
1461
|
-
var
|
|
1462
|
-
var
|
|
1739
|
+
var import_react8 = require("react");
|
|
1740
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1463
1741
|
var STY = {
|
|
1464
1742
|
block: { marginTop: 10, paddingTop: 10, borderTop: "1px solid var(--dsh-mem-border)" },
|
|
1465
1743
|
head: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", marginBottom: 6 },
|
|
@@ -1490,15 +1768,15 @@ var __defProp = Object.defineProperty;
|
|
|
1490
1768
|
];
|
|
1491
1769
|
function ChannelEditor(props) {
|
|
1492
1770
|
const { channel, rpc, disabled } = props;
|
|
1493
|
-
const [baseText, setBaseText] = (0,
|
|
1494
|
-
const [keyText, setKeyText] = (0,
|
|
1495
|
-
const baseTimer = (0,
|
|
1496
|
-
const dirty = (0,
|
|
1497
|
-
(0,
|
|
1771
|
+
const [baseText, setBaseText] = (0, import_react8.useState)(channel.runtimeBaseURL);
|
|
1772
|
+
const [keyText, setKeyText] = (0, import_react8.useState)("");
|
|
1773
|
+
const baseTimer = (0, import_react8.useRef)(void 0);
|
|
1774
|
+
const dirty = (0, import_react8.useRef)(false);
|
|
1775
|
+
(0, import_react8.useEffect)(() => {
|
|
1498
1776
|
if (!dirty.current) setBaseText(channel.runtimeBaseURL);
|
|
1499
1777
|
}, [channel.runtimeBaseURL]);
|
|
1500
|
-
(0,
|
|
1501
|
-
const
|
|
1778
|
+
(0, import_react8.useEffect)(() => () => clearTimeout(baseTimer.current), []);
|
|
1779
|
+
const commit2 = (patch) => {
|
|
1502
1780
|
rpc("dsh-memory/settings-set", patch).catch(() => {
|
|
1503
1781
|
});
|
|
1504
1782
|
};
|
|
@@ -1508,14 +1786,14 @@ var __defProp = Object.defineProperty;
|
|
|
1508
1786
|
clearTimeout(baseTimer.current);
|
|
1509
1787
|
baseTimer.current = setTimeout(() => {
|
|
1510
1788
|
dirty.current = false;
|
|
1511
|
-
|
|
1789
|
+
commit2({ directBaseURL: v.trim() });
|
|
1512
1790
|
}, 600);
|
|
1513
1791
|
};
|
|
1514
1792
|
const commitKey = () => {
|
|
1515
1793
|
const v = keyText.trim();
|
|
1516
1794
|
if (v) {
|
|
1517
1795
|
dirty.current = true;
|
|
1518
|
-
|
|
1796
|
+
commit2({ directApiKey: v });
|
|
1519
1797
|
dirty.current = false;
|
|
1520
1798
|
}
|
|
1521
1799
|
setKeyText("");
|
|
@@ -1526,29 +1804,29 @@ var __defProp = Object.defineProperty;
|
|
|
1526
1804
|
const deployedDirect = channel.deployed === "direct";
|
|
1527
1805
|
const apiKeySet = channel.runtimeApiKeySet || channel.deployedApiKeySet;
|
|
1528
1806
|
const showWarn = isDirect && !channel.directReady;
|
|
1529
|
-
return /* @__PURE__ */ (0,
|
|
1530
|
-
/* @__PURE__ */ (0,
|
|
1531
|
-
/* @__PURE__ */ (0,
|
|
1532
|
-
/* @__PURE__ */ (0,
|
|
1533
|
-
/* @__PURE__ */ (0,
|
|
1807
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: STY.block, children: [
|
|
1808
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: STY.head, children: [
|
|
1809
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: STY.title, children: "蒸馏通道" }),
|
|
1810
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: isDirect ? STY.chipAccent : STY.chipMuted, children: isDirect ? "直连端点" : "复用宿主" }),
|
|
1811
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { title: "direct = 插件原生直连 OpenAI 兼容端点,与付费 API 解耦;失败自动回退宿主路由链。", style: { marginLeft: "auto", fontSize: 11, color: "var(--dsh-mem-text-3)" }, children: [
|
|
1534
1812
|
"生效:",
|
|
1535
1813
|
runtime ? runtime === "direct" ? "运行时直连" : "运行时宿主" : "跟随部署配置"
|
|
1536
1814
|
] })
|
|
1537
1815
|
] }),
|
|
1538
|
-
/* @__PURE__ */ (0,
|
|
1539
|
-
/* @__PURE__ */ (0,
|
|
1816
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: STY.desc, children: "direct 通道走插件原生 HTTP,不依赖宿主 provider 注册表;direct 失败自动回退宿主路由链作兜底安全网。" }),
|
|
1817
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1540
1818
|
Segmented,
|
|
1541
1819
|
{
|
|
1542
1820
|
value: runtime,
|
|
1543
1821
|
disabled,
|
|
1544
1822
|
options: MODE_OPTIONS.map((m) => ({ key: m.key, label: m.label, title: m.title })),
|
|
1545
|
-
onChange: (k) =>
|
|
1823
|
+
onChange: (k) => commit2({ distillMode: k })
|
|
1546
1824
|
}
|
|
1547
1825
|
),
|
|
1548
|
-
editing ? /* @__PURE__ */ (0,
|
|
1549
|
-
/* @__PURE__ */ (0,
|
|
1550
|
-
/* @__PURE__ */ (0,
|
|
1551
|
-
/* @__PURE__ */ (0,
|
|
1826
|
+
editing ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
|
|
1827
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: STY.fieldRow, children: [
|
|
1828
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: STY.fieldLabel, children: "端点 URL" }),
|
|
1829
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1552
1830
|
NInput,
|
|
1553
1831
|
{
|
|
1554
1832
|
style: STY.input,
|
|
@@ -1560,19 +1838,19 @@ var __defProp = Object.defineProperty;
|
|
|
1560
1838
|
if (e.key === "Enter") {
|
|
1561
1839
|
clearTimeout(baseTimer.current);
|
|
1562
1840
|
dirty.current = false;
|
|
1563
|
-
|
|
1841
|
+
commit2({ directBaseURL: baseText.trim() });
|
|
1564
1842
|
}
|
|
1565
1843
|
}
|
|
1566
1844
|
}
|
|
1567
1845
|
),
|
|
1568
|
-
deployedDirect && !channel.runtimeBaseURL ? /* @__PURE__ */ (0,
|
|
1846
|
+
deployedDirect && !channel.runtimeBaseURL ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { style: { fontSize: 11, color: "var(--dsh-mem-text-3)" }, children: [
|
|
1569
1847
|
"部署基线:",
|
|
1570
1848
|
channel.deployedBaseURL || "(空)"
|
|
1571
1849
|
] }) : null
|
|
1572
1850
|
] }),
|
|
1573
|
-
/* @__PURE__ */ (0,
|
|
1574
|
-
/* @__PURE__ */ (0,
|
|
1575
|
-
/* @__PURE__ */ (0,
|
|
1851
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: STY.fieldRow, children: [
|
|
1852
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: STY.fieldLabel, children: "API Key" }),
|
|
1853
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1576
1854
|
NInput,
|
|
1577
1855
|
{
|
|
1578
1856
|
style: STY.input,
|
|
@@ -1588,41 +1866,41 @@ var __defProp = Object.defineProperty;
|
|
|
1588
1866
|
onBlur: commitKey
|
|
1589
1867
|
}
|
|
1590
1868
|
),
|
|
1591
|
-
apiKeySet ? /* @__PURE__ */ (0,
|
|
1592
|
-
/* @__PURE__ */ (0,
|
|
1869
|
+
apiKeySet ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: STY.chipAccent, children: "已配置" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: STY.chipMuted, children: "未配置" }),
|
|
1870
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1593
1871
|
NButton,
|
|
1594
1872
|
{
|
|
1595
1873
|
disabled,
|
|
1596
1874
|
title: "写入空串清除运行时密钥(部署 .yml 的密钥不受影响)",
|
|
1597
|
-
onClick: () =>
|
|
1875
|
+
onClick: () => commit2({ directApiKey: "" }),
|
|
1598
1876
|
children: "清除"
|
|
1599
1877
|
}
|
|
1600
1878
|
)
|
|
1601
1879
|
] }),
|
|
1602
|
-
showWarn ? /* @__PURE__ */ (0,
|
|
1603
|
-
] }) : /* @__PURE__ */ (0,
|
|
1880
|
+
showWarn ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: STY.warn, children: "⚠ direct 未配置完整:需同时有端点 URL 与模型(llm.model / 全局链主路由),否则会回退宿主路由。" }) : null
|
|
1881
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: STY.preview, children: isDirect ? "当前将直连端点:" + (channel.runtimeBaseURL || channel.deployedBaseURL || "(未配置端点)") + (apiKeySet ? " · 密钥已配置" : " · 未配置密钥") : "当前复用宿主 ctx.llm(" + (runtime === "host" ? "运行时锁定" : "跟随部署配置") + ")" })
|
|
1604
1882
|
] });
|
|
1605
1883
|
}
|
|
1606
1884
|
|
|
1607
1885
|
// client/src/tabs/RouteChainEditor.tsx
|
|
1608
|
-
var
|
|
1886
|
+
var import_react10 = require("react");
|
|
1609
1887
|
|
|
1610
1888
|
// client/src/ui/NSel.tsx
|
|
1611
|
-
var
|
|
1612
|
-
var
|
|
1889
|
+
var import_react9 = require("react");
|
|
1890
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1613
1891
|
function NSel(props) {
|
|
1614
1892
|
const options = props.options || [];
|
|
1615
1893
|
const value = props.value || "";
|
|
1616
1894
|
const disabled = !!props.disabled;
|
|
1617
|
-
const [open, setOpen] = (0,
|
|
1618
|
-
const [idx, setIdx] = (0,
|
|
1619
|
-
const wrapRef = (0,
|
|
1620
|
-
const listRef = (0,
|
|
1895
|
+
const [open, setOpen] = (0, import_react9.useState)(false);
|
|
1896
|
+
const [idx, setIdx] = (0, import_react9.useState)(-1);
|
|
1897
|
+
const wrapRef = (0, import_react9.useRef)(null);
|
|
1898
|
+
const listRef = (0, import_react9.useRef)(null);
|
|
1621
1899
|
let selectedLabel = "";
|
|
1622
1900
|
for (let si = 0; si < options.length; si++) {
|
|
1623
1901
|
if (options[si].id === value) selectedLabel = options[si].label;
|
|
1624
1902
|
}
|
|
1625
|
-
(0,
|
|
1903
|
+
(0, import_react9.useEffect)(() => {
|
|
1626
1904
|
if (!open) return void 0;
|
|
1627
1905
|
const onDown = (e) => {
|
|
1628
1906
|
if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
|
|
@@ -1632,7 +1910,7 @@ var __defProp = Object.defineProperty;
|
|
|
1632
1910
|
document.removeEventListener("mousedown", onDown);
|
|
1633
1911
|
};
|
|
1634
1912
|
}, [open]);
|
|
1635
|
-
(0,
|
|
1913
|
+
(0, import_react9.useEffect)(() => {
|
|
1636
1914
|
if (!open || !listRef.current) return;
|
|
1637
1915
|
const el = listRef.current.querySelector('[data-active="1"]');
|
|
1638
1916
|
if (el && el.scrollIntoView) el.scrollIntoView({ block: "nearest" });
|
|
@@ -1695,8 +1973,8 @@ var __defProp = Object.defineProperty;
|
|
|
1695
1973
|
const to = e.relatedTarget;
|
|
1696
1974
|
if (!to || wrapRef.current && !wrapRef.current.contains(to)) setOpen(false);
|
|
1697
1975
|
};
|
|
1698
|
-
return /* @__PURE__ */ (0,
|
|
1699
|
-
/* @__PURE__ */ (0,
|
|
1976
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "dsh-mem-sel", style: props.style, ref: wrapRef, onKeyDown: onKey, onBlur, children: [
|
|
1977
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1700
1978
|
"button",
|
|
1701
1979
|
{
|
|
1702
1980
|
type: "button",
|
|
@@ -1712,13 +1990,13 @@ var __defProp = Object.defineProperty;
|
|
|
1712
1990
|
}
|
|
1713
1991
|
},
|
|
1714
1992
|
children: [
|
|
1715
|
-
/* @__PURE__ */ (0,
|
|
1716
|
-
/* @__PURE__ */ (0,
|
|
1993
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "dsh-mem-select-label", children: selectedLabel || props.placeholder || "(请选择)" }),
|
|
1994
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "dsh-mem-sel-chev" + (open ? " dsh-mem-sel-chev-open" : ""), "aria-hidden": true })
|
|
1717
1995
|
]
|
|
1718
1996
|
}
|
|
1719
1997
|
),
|
|
1720
|
-
open && !disabled ? /* @__PURE__ */ (0,
|
|
1721
|
-
return /* @__PURE__ */ (0,
|
|
1998
|
+
open && !disabled ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "dsh-mem-pop", ref: listRef, role: "listbox", children: options.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "dsh-mem-pop-empty", children: "无选项" }) : options.map((o, i) => {
|
|
1999
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1722
2000
|
"button",
|
|
1723
2001
|
{
|
|
1724
2002
|
type: "button",
|
|
@@ -1736,8 +2014,8 @@ var __defProp = Object.defineProperty;
|
|
|
1736
2014
|
if (idx !== i) setIdx(i);
|
|
1737
2015
|
},
|
|
1738
2016
|
children: [
|
|
1739
|
-
/* @__PURE__ */ (0,
|
|
1740
|
-
o.id === value ? /* @__PURE__ */ (0,
|
|
2017
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "dsh-mem-pop-opt-label", children: o.label }),
|
|
2018
|
+
o.id === value ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "dsh-mem-pop-check", children: "✓" }) : null
|
|
1741
2019
|
]
|
|
1742
2020
|
},
|
|
1743
2021
|
o.id
|
|
@@ -1747,7 +2025,7 @@ var __defProp = Object.defineProperty;
|
|
|
1747
2025
|
}
|
|
1748
2026
|
|
|
1749
2027
|
// client/src/tabs/RouteChainEditor.tsx
|
|
1750
|
-
var
|
|
2028
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1751
2029
|
var modelsCache = {};
|
|
1752
2030
|
var EFFORT_VOCAB = ["", "off", "none", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
1753
2031
|
var STY2 = {
|
|
@@ -1776,26 +2054,26 @@ var __defProp = Object.defineProperty;
|
|
|
1776
2054
|
const disabled = !!props.disabled;
|
|
1777
2055
|
const scope = props.scope ?? "global";
|
|
1778
2056
|
const isLayer = scope !== "global";
|
|
1779
|
-
const [info, setInfo] = (0,
|
|
1780
|
-
const [rows, setRows] = (0,
|
|
1781
|
-
const [rowErrs, setRowErrs] = (0,
|
|
1782
|
-
const [err, setErr] = (0,
|
|
1783
|
-
const [manual, setManual] = (0,
|
|
1784
|
-
const pendingWrites = (0,
|
|
2057
|
+
const [info, setInfo] = (0, import_react10.useState)(null);
|
|
2058
|
+
const [rows, setRows] = (0, import_react10.useState)(null);
|
|
2059
|
+
const [rowErrs, setRowErrs] = (0, import_react10.useState)({});
|
|
2060
|
+
const [err, setErr] = (0, import_react10.useState)(null);
|
|
2061
|
+
const [manual, setManual] = (0, import_react10.useState)({ idx: -1, text: "" });
|
|
2062
|
+
const pendingWrites = (0, import_react10.useRef)(0);
|
|
1785
2063
|
function refreshInfo() {
|
|
1786
2064
|
rpc("dsh-memory/llm-providers", {}).then((r) => {
|
|
1787
2065
|
if (r && r.ok && pendingWrites.current === 0) setInfo(r.value);
|
|
1788
2066
|
}).catch(() => {
|
|
1789
2067
|
});
|
|
1790
2068
|
}
|
|
1791
|
-
(0,
|
|
2069
|
+
(0, import_react10.useEffect)(() => {
|
|
1792
2070
|
refreshInfo();
|
|
1793
2071
|
const timer = setInterval(refreshInfo, 5e3);
|
|
1794
2072
|
return () => {
|
|
1795
2073
|
clearInterval(timer);
|
|
1796
2074
|
};
|
|
1797
2075
|
}, [rpc]);
|
|
1798
|
-
(0,
|
|
2076
|
+
(0, import_react10.useEffect)(() => {
|
|
1799
2077
|
if (!info || !info.providers) return;
|
|
1800
2078
|
info.providers.forEach((p) => {
|
|
1801
2079
|
if (!p.id || modelsCache[p.id]) return;
|
|
@@ -1807,7 +2085,7 @@ var __defProp = Object.defineProperty;
|
|
|
1807
2085
|
}, [rpc, info]);
|
|
1808
2086
|
const layerView = isLayer && info && info.layerChains ? info.layerChains[scope] : null;
|
|
1809
2087
|
const savedRows = isLayer ? layerView?.runtime ?? [] : info && info.chain ? info.chain.current : [];
|
|
1810
|
-
(0,
|
|
2088
|
+
(0, import_react10.useEffect)(() => {
|
|
1811
2089
|
if (rows === null && info && savedRows.length) {
|
|
1812
2090
|
setRows(savedRows.map(copyRow));
|
|
1813
2091
|
}
|
|
@@ -1955,17 +2233,17 @@ var __defProp = Object.defineProperty;
|
|
|
1955
2233
|
providersById[p.id] = p;
|
|
1956
2234
|
});
|
|
1957
2235
|
function roRow(e, i) {
|
|
1958
|
-
return /* @__PURE__ */ (0,
|
|
1959
|
-
/* @__PURE__ */ (0,
|
|
1960
|
-
/* @__PURE__ */ (0,
|
|
1961
|
-
/* @__PURE__ */ (0,
|
|
2236
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: STY2.roRow, children: [
|
|
2237
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: STY2.badge, children: i === 0 ? "主" : String(i + 1) }),
|
|
2238
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { ...STY2.mono, color: "var(--dsh-mem-text-2)" }, children: e.provider + " / " + e.model }),
|
|
2239
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { marginLeft: "auto", flexShrink: 0, fontSize: 11, color: "var(--dsh-mem-text-3)" }, children: e.effort ? "档位 " + e.effort : "跟随部署配置" })
|
|
1962
2240
|
] }, "ro" + i);
|
|
1963
2241
|
}
|
|
1964
2242
|
if (info.pinned) {
|
|
1965
2243
|
const effPin = isLayer ? layerView?.effectiveChain ?? [] : info.chain && info.chain.effectiveChain || [];
|
|
1966
|
-
return /* @__PURE__ */ (0,
|
|
2244
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: STY2.wrap, children: [
|
|
1967
2245
|
effPin.map(roRow),
|
|
1968
|
-
/* @__PURE__ */ (0,
|
|
2246
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: STY2.note, children: "部署已锁定路由(pin),调整请修改 cordis.patch.yml 中 llm 的配置。" })
|
|
1969
2247
|
] });
|
|
1970
2248
|
}
|
|
1971
2249
|
if (rows === null) {
|
|
@@ -1973,21 +2251,21 @@ var __defProp = Object.defineProperty;
|
|
|
1973
2251
|
const lv = layerView;
|
|
1974
2252
|
const src = lv?.source ?? "global";
|
|
1975
2253
|
if (src === "static" && lv) {
|
|
1976
|
-
return /* @__PURE__ */ (0,
|
|
2254
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: STY2.wrap, children: [
|
|
1977
2255
|
lv.static.map((e, i) => roRow({ provider: e.provider, model: e.model, effort: e.reasoningEffort || "" }, i)),
|
|
1978
|
-
/* @__PURE__ */ (0,
|
|
2256
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { marginTop: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(NButton, { onClick: forkStatic, disabled, children: "自定义本层链" }) })
|
|
1979
2257
|
] });
|
|
1980
2258
|
}
|
|
1981
2259
|
const previewRows = lv?.effectiveChain ?? [];
|
|
1982
|
-
return /* @__PURE__ */ (0,
|
|
1983
|
-
previewRows.length === 0 ? /* @__PURE__ */ (0,
|
|
1984
|
-
/* @__PURE__ */ (0,
|
|
2260
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: STY2.wrap, children: [
|
|
2261
|
+
previewRows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: S.switchDesc, children: "本层跟随全局链,暂无可用路由。" }) : previewRows.map(roRow),
|
|
2262
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { marginTop: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(NButton, { onClick: forkStatic, disabled, children: "自定义本层链" }) })
|
|
1985
2263
|
] });
|
|
1986
2264
|
}
|
|
1987
2265
|
const effFollow = info.chain && info.chain.effectiveChain || [];
|
|
1988
|
-
return /* @__PURE__ */ (0,
|
|
1989
|
-
effFollow.length === 0 ? /* @__PURE__ */ (0,
|
|
1990
|
-
/* @__PURE__ */ (0,
|
|
2266
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: STY2.wrap, children: [
|
|
2267
|
+
effFollow.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: S.switchDesc, children: "蒸馏跟随默认模型,未配置回退链。" }) : effFollow.map(roRow),
|
|
2268
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { marginTop: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(NButton, { onClick: forkStatic, disabled, children: "编辑为运行时链" }) })
|
|
1991
2269
|
] });
|
|
1992
2270
|
}
|
|
1993
2271
|
const capped = rows.length >= 8;
|
|
@@ -2028,10 +2306,10 @@ var __defProp = Object.defineProperty;
|
|
|
2028
2306
|
const effortOptions = [{ id: "", label: "跟随部署配置" }].concat(
|
|
2029
2307
|
curEfforts.filter((k) => EFFORT_VOCAB.indexOf(k) >= 0).map((k) => ({ id: k, label: k }))
|
|
2030
2308
|
);
|
|
2031
|
-
return /* @__PURE__ */ (0,
|
|
2032
|
-
/* @__PURE__ */ (0,
|
|
2033
|
-
/* @__PURE__ */ (0,
|
|
2034
|
-
/* @__PURE__ */ (0,
|
|
2309
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { ...STY2.row, ...rowErrs[i] ? STY2.rowErr : null }, children: [
|
|
2310
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: STY2.line, children: [
|
|
2311
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: STY2.badge, children: isPrimary ? "主" : String(i + 1) }),
|
|
2312
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2035
2313
|
NSel,
|
|
2036
2314
|
{
|
|
2037
2315
|
style: { flex: 1, minWidth: 150 },
|
|
@@ -2044,7 +2322,7 @@ var __defProp = Object.defineProperty;
|
|
|
2044
2322
|
}
|
|
2045
2323
|
}
|
|
2046
2324
|
),
|
|
2047
|
-
!row2.provider ? null : manualInput ? /* @__PURE__ */ (0,
|
|
2325
|
+
!row2.provider ? null : manualInput ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2048
2326
|
NInput,
|
|
2049
2327
|
{
|
|
2050
2328
|
style: { flex: 1, minWidth: 150 },
|
|
@@ -2063,7 +2341,7 @@ var __defProp = Object.defineProperty;
|
|
|
2063
2341
|
}
|
|
2064
2342
|
}
|
|
2065
2343
|
}
|
|
2066
|
-
) : /* @__PURE__ */ (0,
|
|
2344
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2067
2345
|
NSel,
|
|
2068
2346
|
{
|
|
2069
2347
|
style: { flex: 1, minWidth: 150 },
|
|
@@ -2076,7 +2354,7 @@ var __defProp = Object.defineProperty;
|
|
|
2076
2354
|
}
|
|
2077
2355
|
}
|
|
2078
2356
|
),
|
|
2079
|
-
/* @__PURE__ */ (0,
|
|
2357
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2080
2358
|
NSel,
|
|
2081
2359
|
{
|
|
2082
2360
|
style: { flexShrink: 0, width: 118 },
|
|
@@ -2090,8 +2368,8 @@ var __defProp = Object.defineProperty;
|
|
|
2090
2368
|
}
|
|
2091
2369
|
)
|
|
2092
2370
|
] }),
|
|
2093
|
-
/* @__PURE__ */ (0,
|
|
2094
|
-
/* @__PURE__ */ (0,
|
|
2371
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: STY2.actions, children: [
|
|
2372
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2095
2373
|
NButton,
|
|
2096
2374
|
{
|
|
2097
2375
|
style: STY2.ico,
|
|
@@ -2103,7 +2381,7 @@ var __defProp = Object.defineProperty;
|
|
|
2103
2381
|
children: "↑"
|
|
2104
2382
|
}
|
|
2105
2383
|
),
|
|
2106
|
-
/* @__PURE__ */ (0,
|
|
2384
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2107
2385
|
NButton,
|
|
2108
2386
|
{
|
|
2109
2387
|
style: STY2.ico,
|
|
@@ -2115,7 +2393,7 @@ var __defProp = Object.defineProperty;
|
|
|
2115
2393
|
children: "↓"
|
|
2116
2394
|
}
|
|
2117
2395
|
),
|
|
2118
|
-
/* @__PURE__ */ (0,
|
|
2396
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2119
2397
|
NButton,
|
|
2120
2398
|
{
|
|
2121
2399
|
style: STY2.ico,
|
|
@@ -2128,14 +2406,14 @@ var __defProp = Object.defineProperty;
|
|
|
2128
2406
|
}
|
|
2129
2407
|
)
|
|
2130
2408
|
] }),
|
|
2131
|
-
isPrimary && !row2.provider ? /* @__PURE__ */ (0,
|
|
2132
|
-
!known ? /* @__PURE__ */ (0,
|
|
2133
|
-
rowErrs[i] ? /* @__PURE__ */ (0,
|
|
2409
|
+
isPrimary && !row2.provider ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: STY2.note, children: "跟随默认模型" + (info.default ? ":" + info.default.provider + " / " + info.default.model : "") + "(档位跟随部署配置,选定模型后可单独设置)" }) : null,
|
|
2410
|
+
!known ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: STY2.warn, children: "⚠ 供应商 " + row2.provider + " 已不在已注册路由中:该路由调用会失败并被链跳过(不阻止保存)。" }) : null,
|
|
2411
|
+
rowErrs[i] ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: STY2.warn, children: "✕ " + rowErrs[i] }) : null
|
|
2134
2412
|
] }, "row" + i);
|
|
2135
2413
|
});
|
|
2136
2414
|
const effChain = isLayer ? layerView?.effectiveChain ?? [] : info.chain && info.chain.effectiveChain || [];
|
|
2137
|
-
return /* @__PURE__ */ (0,
|
|
2138
|
-
/* @__PURE__ */ (0,
|
|
2415
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: STY2.wrap, children: [
|
|
2416
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2139
2417
|
"div",
|
|
2140
2418
|
{
|
|
2141
2419
|
style: { ...S.switchDesc, marginBottom: 8 },
|
|
@@ -2144,9 +2422,9 @@ var __defProp = Object.defineProperty;
|
|
|
2144
2422
|
}
|
|
2145
2423
|
),
|
|
2146
2424
|
rowEls,
|
|
2147
|
-
/* @__PURE__ */ (0,
|
|
2148
|
-
/* @__PURE__ */ (0,
|
|
2149
|
-
/* @__PURE__ */ (0,
|
|
2425
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(NButton, { style: STY2.add, disabled: disabled || capped, onClick: addRow, children: capped ? "已达上限(8 条)" : "+ 添加回退路由" }),
|
|
2426
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, marginTop: 10 }, children: [
|
|
2427
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2150
2428
|
NButton,
|
|
2151
2429
|
{
|
|
2152
2430
|
style: isLayer ? { ...STY2.ghost, color: "var(--dsh-mem-danger)", border: "1px solid var(--dsh-mem-danger)" } : STY2.ghost,
|
|
@@ -2155,13 +2433,13 @@ var __defProp = Object.defineProperty;
|
|
|
2155
2433
|
children: isLayer ? "清除自定义 · 跟随全局" : "清空并跟随部署配置"
|
|
2156
2434
|
}
|
|
2157
2435
|
),
|
|
2158
|
-
/* @__PURE__ */ (0,
|
|
2159
|
-
/* @__PURE__ */ (0,
|
|
2436
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: S.grow }),
|
|
2437
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(NButton, { variant: "primary", disabled, onClick: save, children: "保存" })
|
|
2160
2438
|
] }),
|
|
2161
|
-
err ? /* @__PURE__ */ (0,
|
|
2162
|
-
/* @__PURE__ */ (0,
|
|
2163
|
-
/* @__PURE__ */ (0,
|
|
2164
|
-
/* @__PURE__ */ (0,
|
|
2439
|
+
err ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { ...STY2.warn, marginTop: 8 }, children: "✕ " + err }) : null,
|
|
2440
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { marginTop: 10, paddingTop: 10, borderTop: "1px solid var(--dsh-mem-border)" }, children: [
|
|
2441
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { fontSize: 11, color: "var(--dsh-mem-text-3)", marginBottom: 4 }, children: "实际链" + (dirty ? "(保存后更新;当前显示已保存值)" : "") }),
|
|
2442
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2165
2443
|
"div",
|
|
2166
2444
|
{
|
|
2167
2445
|
style: { fontSize: 12, color: "var(--dsh-mem-text-2)", wordBreak: "break-all", fontFamily: "ui-monospace, SFMono-Regular, Consolas, monospace" },
|
|
@@ -2173,7 +2451,7 @@ var __defProp = Object.defineProperty;
|
|
|
2173
2451
|
}
|
|
2174
2452
|
|
|
2175
2453
|
// client/src/tabs/DistillSettings.tsx
|
|
2176
|
-
var
|
|
2454
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2177
2455
|
var STY3 = {
|
|
2178
2456
|
hint: { fontSize: 11, color: "var(--dsh-mem-text-3)", margin: "0 0 8px" },
|
|
2179
2457
|
panelHead: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", marginBottom: 8 },
|
|
@@ -2202,9 +2480,9 @@ var __defProp = Object.defineProperty;
|
|
|
2202
2480
|
verticalAlign: "middle",
|
|
2203
2481
|
flexShrink: 0
|
|
2204
2482
|
};
|
|
2205
|
-
if (props.kind === "runtime") return /* @__PURE__ */ (0,
|
|
2206
|
-
if (props.kind === "static") return /* @__PURE__ */ (0,
|
|
2207
|
-
return /* @__PURE__ */ (0,
|
|
2483
|
+
if (props.kind === "runtime") return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { ...base, background: "var(--dsh-mem-accent)" } });
|
|
2484
|
+
if (props.kind === "static") return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { ...base, background: "transparent", border: "1.5px solid var(--dsh-mem-text-3)" } });
|
|
2485
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { ...base, background: "var(--dsh-mem-track)" } });
|
|
2208
2486
|
}
|
|
2209
2487
|
var LAYER_META = {
|
|
2210
2488
|
l1: { seg: "L1", title: "L1 · 抽取 / 去重" },
|
|
@@ -2214,9 +2492,9 @@ var __defProp = Object.defineProperty;
|
|
|
2214
2492
|
function DistillSettings(props) {
|
|
2215
2493
|
const rpc = props.rpc;
|
|
2216
2494
|
const disabled = !!props.disabled;
|
|
2217
|
-
const [info, setInfo] = (0,
|
|
2218
|
-
const [tab, setTab] = (0,
|
|
2219
|
-
(0,
|
|
2495
|
+
const [info, setInfo] = (0, import_react11.useState)(null);
|
|
2496
|
+
const [tab, setTab] = (0, import_react11.useState)("g");
|
|
2497
|
+
(0, import_react11.useEffect)(() => {
|
|
2220
2498
|
let alive = true;
|
|
2221
2499
|
const refresh = () => {
|
|
2222
2500
|
rpc("dsh-memory/llm-providers", {}).then((r) => {
|
|
@@ -2239,46 +2517,46 @@ var __defProp = Object.defineProperty;
|
|
|
2239
2517
|
...["l1", "l2", "l3"].map((k) => ({
|
|
2240
2518
|
key: k,
|
|
2241
2519
|
title: LAYER_META[k].title + " · " + (dotOf(k) === "runtime" ? "运行时自定义" : dotOf(k) === "static" ? "部署 YAML 层链(只读)" : "跟随全局"),
|
|
2242
|
-
label: /* @__PURE__ */ (0,
|
|
2243
|
-
/* @__PURE__ */ (0,
|
|
2520
|
+
label: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { children: [
|
|
2521
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Dot, { kind: dotOf(k) }),
|
|
2244
2522
|
LAYER_META[k].seg
|
|
2245
2523
|
] })
|
|
2246
2524
|
}))
|
|
2247
2525
|
];
|
|
2248
2526
|
const chipTitle = (k) => dotOf(k) === "runtime" ? "本层走设置页自定义链" : dotOf(k) === "static" ? "本层走部署 YAML 层链(UI 只读,自定义可覆盖)" : "本层未单独配置,走全局默认链";
|
|
2249
|
-
return /* @__PURE__ */ (0,
|
|
2250
|
-
/* @__PURE__ */ (0,
|
|
2251
|
-
/* @__PURE__ */ (0,
|
|
2252
|
-
/* @__PURE__ */ (0,
|
|
2527
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
|
|
2528
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Segmented, { value: tab, options: segOptions, onChange: (k) => setTab(k) }),
|
|
2529
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: STY3.hint, children: [
|
|
2530
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Dot, { kind: "runtime" }),
|
|
2253
2531
|
" 自定义 · ",
|
|
2254
|
-
/* @__PURE__ */ (0,
|
|
2532
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Dot, { kind: "static" }),
|
|
2255
2533
|
" 部署 YAML · ",
|
|
2256
|
-
/* @__PURE__ */ (0,
|
|
2534
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Dot, { kind: "global" }),
|
|
2257
2535
|
" 跟随全局",
|
|
2258
|
-
/* @__PURE__ */ (0,
|
|
2536
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { title: "每层实际链:运行时自定义 → 部署 YAML 层链 → 全局默认链,逐级兜底;部署 pin 时运行时编辑只读", children: "(层链优先于全局)" })
|
|
2259
2537
|
] }),
|
|
2260
|
-
tab === "g" ? /* @__PURE__ */ (0,
|
|
2261
|
-
/* @__PURE__ */ (0,
|
|
2262
|
-
/* @__PURE__ */ (0,
|
|
2263
|
-
/* @__PURE__ */ (0,
|
|
2264
|
-
/* @__PURE__ */ (0,
|
|
2538
|
+
tab === "g" ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
|
|
2539
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: STY3.panelHead, children: [
|
|
2540
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: STY3.panelTitle, children: "全局默认链" }),
|
|
2541
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { ...STY3.chip, ...STY3.chipAccent }, children: "运行时 · 可编辑" }),
|
|
2542
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { ...STY3.inUse, marginLeft: "auto" }, children: users.length ? "在用:" + users.map((k) => LAYER_META[k].seg).join("、") : "当前无层使用" })
|
|
2265
2543
|
] }),
|
|
2266
|
-
/* @__PURE__ */ (0,
|
|
2267
|
-
/* @__PURE__ */ (0,
|
|
2268
|
-
info?.channel ? /* @__PURE__ */ (0,
|
|
2269
|
-
] }) : /* @__PURE__ */ (0,
|
|
2270
|
-
/* @__PURE__ */ (0,
|
|
2271
|
-
/* @__PURE__ */ (0,
|
|
2272
|
-
/* @__PURE__ */ (0,
|
|
2544
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(RouteChainEditor, { rpc, disabled }, "g"),
|
|
2545
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(BudgetInputs, { rpc, disabled, data: props.data, setData: props.setData, onError: props.onError, scope: "input" }, "g-budget"),
|
|
2546
|
+
info?.channel ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ChannelEditor, { channel: info.channel, rpc, disabled }) : null
|
|
2547
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
|
|
2548
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: STY3.panelHead, children: [
|
|
2549
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: STY3.panelTitle, children: LAYER_META[tab].title }),
|
|
2550
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { ...STY3.chip, ...dotOf(tab) === "runtime" ? STY3.chipAccent : STY3.chipMuted }, title: chipTitle(tab), children: dotOf(tab) === "runtime" ? "运行时自定义" : dotOf(tab) === "static" ? "静态 · YAML" : "跟随全局" })
|
|
2273
2551
|
] }),
|
|
2274
|
-
/* @__PURE__ */ (0,
|
|
2275
|
-
/* @__PURE__ */ (0,
|
|
2552
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(RouteChainEditor, { rpc, disabled, scope: tab }, tab),
|
|
2553
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(BudgetInputs, { rpc, disabled, data: props.data, setData: props.setData, onError: props.onError, scope: tab }, tab + "-budget")
|
|
2276
2554
|
] })
|
|
2277
2555
|
] });
|
|
2278
2556
|
}
|
|
2279
2557
|
|
|
2280
2558
|
// client/src/tabs/EmbeddingSection.tsx
|
|
2281
|
-
var
|
|
2559
|
+
var import_react12 = require("react");
|
|
2282
2560
|
|
|
2283
2561
|
// client/src/dimensions.ts
|
|
2284
2562
|
var DIMS_MIN = 1;
|
|
@@ -2326,7 +2604,7 @@ var __defProp = Object.defineProperty;
|
|
|
2326
2604
|
}
|
|
2327
2605
|
|
|
2328
2606
|
// client/src/tabs/EmbeddingSection.tsx
|
|
2329
|
-
var
|
|
2607
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2330
2608
|
var RSTY = {
|
|
2331
2609
|
block: { marginTop: 10, paddingTop: 10, borderTop: "1px solid var(--dsh-mem-border)" },
|
|
2332
2610
|
title: { fontSize: 12, fontWeight: 600, color: "var(--dsh-mem-text-3)", margin: "0 0 2px" },
|
|
@@ -2350,17 +2628,17 @@ var __defProp = Object.defineProperty;
|
|
|
2350
2628
|
function EmbeddingSection(props) {
|
|
2351
2629
|
const rpc = props.rpc;
|
|
2352
2630
|
const loose = asLoose(rpc);
|
|
2353
|
-
const [st, setSt] = (0,
|
|
2354
|
-
const [err, setErr] = (0,
|
|
2355
|
-
const busyPollRef = (0,
|
|
2356
|
-
const [rBase, setRBase] = (0,
|
|
2357
|
-
const [rModel, setRModel] = (0,
|
|
2358
|
-
const [rDims, setRDims] = (0,
|
|
2359
|
-
const [rKey, setRKey] = (0,
|
|
2360
|
-
const remoteDirty = (0,
|
|
2361
|
-
const baseTimer = (0,
|
|
2362
|
-
const modelTimer = (0,
|
|
2363
|
-
const load = (0,
|
|
2631
|
+
const [st, setSt] = (0, import_react12.useState)(null);
|
|
2632
|
+
const [err, setErr] = (0, import_react12.useState)(null);
|
|
2633
|
+
const busyPollRef = (0, import_react12.useRef)(null);
|
|
2634
|
+
const [rBase, setRBase] = (0, import_react12.useState)("");
|
|
2635
|
+
const [rModel, setRModel] = (0, import_react12.useState)("");
|
|
2636
|
+
const [rDims, setRDims] = (0, import_react12.useState)("");
|
|
2637
|
+
const [rKey, setRKey] = (0, import_react12.useState)("");
|
|
2638
|
+
const remoteDirty = (0, import_react12.useRef)({ base: false, model: false, dims: false });
|
|
2639
|
+
const baseTimer = (0, import_react12.useRef)(void 0);
|
|
2640
|
+
const modelTimer = (0, import_react12.useRef)(void 0);
|
|
2641
|
+
const load = (0, import_react12.useCallback)(() => {
|
|
2364
2642
|
rpc("dsh-memory/embedding-state-get", {}).then((r) => {
|
|
2365
2643
|
if (r && r.ok && r.value && r.value.supported !== false) {
|
|
2366
2644
|
const v = r.value;
|
|
@@ -2379,10 +2657,10 @@ var __defProp = Object.defineProperty;
|
|
|
2379
2657
|
setErr(String(e && e.message || e));
|
|
2380
2658
|
});
|
|
2381
2659
|
}, [rpc]);
|
|
2382
|
-
(0,
|
|
2660
|
+
(0, import_react12.useEffect)(() => {
|
|
2383
2661
|
load();
|
|
2384
2662
|
}, [load]);
|
|
2385
|
-
(0,
|
|
2663
|
+
(0, import_react12.useEffect)(() => {
|
|
2386
2664
|
let stopped = false;
|
|
2387
2665
|
const busyFlag = { v: false };
|
|
2388
2666
|
busyPollRef.current = busyFlag;
|
|
@@ -2398,11 +2676,11 @@ var __defProp = Object.defineProperty;
|
|
|
2398
2676
|
busyPollRef.current = null;
|
|
2399
2677
|
};
|
|
2400
2678
|
}, [load]);
|
|
2401
|
-
(0,
|
|
2679
|
+
(0, import_react12.useEffect)(() => () => {
|
|
2402
2680
|
clearTimeout(baseTimer.current);
|
|
2403
2681
|
clearTimeout(modelTimer.current);
|
|
2404
2682
|
}, []);
|
|
2405
|
-
(0,
|
|
2683
|
+
(0, import_react12.useEffect)(() => {
|
|
2406
2684
|
if (!st || !st.remote) return;
|
|
2407
2685
|
if (!remoteDirty.current.base) setRBase(st.remote.baseURL || "");
|
|
2408
2686
|
if (!remoteDirty.current.model) setRModel(st.remote.model || "");
|
|
@@ -2463,15 +2741,15 @@ var __defProp = Object.defineProperty;
|
|
|
2463
2741
|
});
|
|
2464
2742
|
};
|
|
2465
2743
|
if (err === "__unsupported__") {
|
|
2466
|
-
return /* @__PURE__ */ (0,
|
|
2467
|
-
/* @__PURE__ */ (0,
|
|
2468
|
-
/* @__PURE__ */ (0,
|
|
2744
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-mem-rb-card", children: [
|
|
2745
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { fontWeight: 600, marginBottom: 4 }, children: "语义检索(嵌入)" }),
|
|
2746
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-mem-rb-muted", children: "存储处于降级状态,嵌入管理不可用。" })
|
|
2469
2747
|
] });
|
|
2470
2748
|
}
|
|
2471
2749
|
if (!st) {
|
|
2472
|
-
return /* @__PURE__ */ (0,
|
|
2473
|
-
/* @__PURE__ */ (0,
|
|
2474
|
-
err ? /* @__PURE__ */ (0,
|
|
2750
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-mem-rb-card", children: [
|
|
2751
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-mem-rb-muted", children: err ? "嵌入状态读取失败:" + err : "嵌入状态读取中…" }),
|
|
2752
|
+
err ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(NButton, { style: { marginTop: 8 }, onClick: load, children: "重试" }) : null
|
|
2475
2753
|
] });
|
|
2476
2754
|
}
|
|
2477
2755
|
const switchConfirm = "切换嵌入源后将按新模型重建向量索引(期间语义检索暂退化为关键词匹配,不影响对话)。确定切换?";
|
|
@@ -2497,40 +2775,40 @@ var __defProp = Object.defineProperty;
|
|
|
2497
2775
|
const remote = st.remote;
|
|
2498
2776
|
let runtimeRow = null;
|
|
2499
2777
|
if (rt.phase === "installing") {
|
|
2500
|
-
runtimeRow = /* @__PURE__ */ (0,
|
|
2501
|
-
/* @__PURE__ */ (0,
|
|
2502
|
-
/* @__PURE__ */ (0,
|
|
2503
|
-
/* @__PURE__ */ (0,
|
|
2504
|
-
/* @__PURE__ */ (0,
|
|
2778
|
+
runtimeRow = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { marginTop: 8, fontSize: 12 }, children: [
|
|
2779
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: S.flexRow, children: [
|
|
2780
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "安装推理运行时中… 已耗时 " + Math.round(rt.elapsedMs / 1e3) + "s(约 100~200MB,视网络)" }),
|
|
2781
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: S.grow }),
|
|
2782
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(NButton, { onClick: () => call("dsh-memory/embedding-runtime-cancel", {}), children: "取消" })
|
|
2505
2783
|
] }),
|
|
2506
|
-
/* @__PURE__ */ (0,
|
|
2784
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("pre", { style: { ...S.pre, maxHeight: 68, marginTop: 6, fontSize: 11, opacity: 0.85 }, children: (rt.lastLines || []).join("\n") || "等待 npm 输出…" })
|
|
2507
2785
|
] });
|
|
2508
2786
|
} else if (rt.phase === "error") {
|
|
2509
|
-
runtimeRow = /* @__PURE__ */ (0,
|
|
2787
|
+
runtimeRow = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { marginTop: 8, fontSize: 12, color: "var(--dsh-mem-danger)" }, children: "运行时安装失败:" + (rt.error || "未知") + "(重新切换嵌入源可重试)" });
|
|
2510
2788
|
} else if (rt.phase === "ready") {
|
|
2511
|
-
runtimeRow = /* @__PURE__ */ (0,
|
|
2789
|
+
runtimeRow = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-mem-rb-muted", style: { marginTop: 8 }, children: "推理运行时就绪(transformers.js v" + rt.installedVersion + ")" });
|
|
2512
2790
|
} else if (st.source === "local") {
|
|
2513
|
-
runtimeRow = /* @__PURE__ */ (0,
|
|
2791
|
+
runtimeRow = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-mem-rb-muted", style: { marginTop: 8 }, children: "首次启用本地嵌入时会自动安装推理运行时(约 100~200MB)。" });
|
|
2514
2792
|
}
|
|
2515
2793
|
let applyRow = null;
|
|
2516
2794
|
if (ap.phase === "warming") {
|
|
2517
|
-
applyRow = /* @__PURE__ */ (0,
|
|
2795
|
+
applyRow = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-mem-rb-muted", style: { marginTop: 8 }, children: "加载嵌入模型中…(首次需数秒)" });
|
|
2518
2796
|
} else if (ap.phase === "switching") {
|
|
2519
|
-
applyRow = /* @__PURE__ */ (0,
|
|
2797
|
+
applyRow = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-mem-rb-muted", style: { marginTop: 8 }, children: "切换嵌入源中…" });
|
|
2520
2798
|
} else if (ap.phase === "error") {
|
|
2521
|
-
applyRow = /* @__PURE__ */ (0,
|
|
2799
|
+
applyRow = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { marginTop: 8, fontSize: 12, color: "var(--dsh-mem-danger)" }, children: "切换失败:" + ap.message + "(已保存的嵌入源不变,重启后仍按原源运行)" });
|
|
2522
2800
|
} else if (st.reindex && st.reindex.running) {
|
|
2523
2801
|
const rj = st.reindex;
|
|
2524
2802
|
const rDone = rj.l1Done + rj.l0Done;
|
|
2525
2803
|
const rTotal = rj.l1Total + rj.l0Total;
|
|
2526
2804
|
const rPct = rTotal > 0 ? Math.round(rDone / rTotal * 100) : 0;
|
|
2527
|
-
applyRow = /* @__PURE__ */ (0,
|
|
2528
|
-
/* @__PURE__ */ (0,
|
|
2529
|
-
/* @__PURE__ */ (0,
|
|
2530
|
-
/* @__PURE__ */ (0,
|
|
2531
|
-
/* @__PURE__ */ (0,
|
|
2805
|
+
applyRow = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { marginTop: 8 }, children: [
|
|
2806
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: S.flexRow, children: [
|
|
2807
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dsh-mem-rb-muted", children: "重嵌入中 L1 " + rj.l1Done + "/" + rj.l1Total + " · L0 " + rj.l0Done + "/" + rj.l0Total + "(" + rPct + "%)" }),
|
|
2808
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: S.grow }),
|
|
2809
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(NButton, { onClick: () => call("dsh-memory/embedding-reindex-cancel", {}), children: "取消" })
|
|
2532
2810
|
] }),
|
|
2533
|
-
/* @__PURE__ */ (0,
|
|
2811
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { ...S.flexRow, marginTop: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-mem-rb-bar", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-mem-rb-fill", style: { width: rPct + "%" } }) }) })
|
|
2534
2812
|
] });
|
|
2535
2813
|
}
|
|
2536
2814
|
const modelCards = st.models.map((m) => {
|
|
@@ -2539,24 +2817,24 @@ var __defProp = Object.defineProperty;
|
|
|
2539
2817
|
const pct = mDl && dl.overallTotal > 0 ? Math.round(dl.overallReceived / dl.overallTotal * 100) : 0;
|
|
2540
2818
|
let action;
|
|
2541
2819
|
if (mDl) {
|
|
2542
|
-
action = /* @__PURE__ */ (0,
|
|
2543
|
-
/* @__PURE__ */ (0,
|
|
2544
|
-
/* @__PURE__ */ (0,
|
|
2545
|
-
/* @__PURE__ */ (0,
|
|
2546
|
-
/* @__PURE__ */ (0,
|
|
2820
|
+
action = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { flex: 1, minWidth: 200 }, children: [
|
|
2821
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: S.flexRow, children: [
|
|
2822
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dsh-mem-rb-muted", style: { whiteSpace: "nowrap" }, children: (dl.phase === "verifying" ? "校验中 " : "") + fmtMB(dl.overallReceived) + " / " + fmtMB(dl.overallTotal) + "(文件 " + dl.fileIndex + "/" + dl.fileCount + "," + pct + "%" + (dl.speedBps > 0 && dl.phase === "downloading" ? "," + fmtMB(dl.speedBps) + "/s" : "") + ")" }),
|
|
2823
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: S.grow }),
|
|
2824
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(NButton, { onClick: () => call("dsh-memory/embedding-download-cancel", {}), children: "取消" })
|
|
2547
2825
|
] }),
|
|
2548
|
-
/* @__PURE__ */ (0,
|
|
2826
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { ...S.flexRow, marginTop: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-mem-rb-bar", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-mem-rb-fill", style: { width: pct + "%" } }) }) })
|
|
2549
2827
|
] });
|
|
2550
2828
|
} else if (isActive) {
|
|
2551
|
-
action = /* @__PURE__ */ (0,
|
|
2552
|
-
/* @__PURE__ */ (0,
|
|
2553
|
-
localInfo && localInfo.state === "loading" ? /* @__PURE__ */ (0,
|
|
2554
|
-
localInfo && localInfo.state === "failed" ? /* @__PURE__ */ (0,
|
|
2555
|
-
localInfo && localInfo.state === "ready" ? /* @__PURE__ */ (0,
|
|
2829
|
+
action = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: S.flexRow, children: [
|
|
2830
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dsh-mem-tag dsh-mem-tag-work-task", children: "使用中" }),
|
|
2831
|
+
localInfo && localInfo.state === "loading" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dsh-mem-rb-muted", children: "模型加载中…" }) : null,
|
|
2832
|
+
localInfo && localInfo.state === "failed" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { fontSize: 12, color: "var(--dsh-mem-danger)" }, children: "加载失败:" + (localInfo.error || "") }) : null,
|
|
2833
|
+
localInfo && localInfo.state === "ready" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dsh-mem-rb-muted", children: "已就绪" }) : null
|
|
2556
2834
|
] });
|
|
2557
2835
|
} else if (m.state === "downloaded") {
|
|
2558
|
-
action = /* @__PURE__ */ (0,
|
|
2559
|
-
/* @__PURE__ */ (0,
|
|
2836
|
+
action = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: S.flexRow, children: [
|
|
2837
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2560
2838
|
NButton,
|
|
2561
2839
|
{
|
|
2562
2840
|
disabled: ap.busy,
|
|
@@ -2564,7 +2842,7 @@ var __defProp = Object.defineProperty;
|
|
|
2564
2842
|
children: "启用"
|
|
2565
2843
|
}
|
|
2566
2844
|
),
|
|
2567
|
-
/* @__PURE__ */ (0,
|
|
2845
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2568
2846
|
NButton,
|
|
2569
2847
|
{
|
|
2570
2848
|
disabled: dlActive,
|
|
@@ -2574,7 +2852,7 @@ var __defProp = Object.defineProperty;
|
|
|
2574
2852
|
)
|
|
2575
2853
|
] });
|
|
2576
2854
|
} else {
|
|
2577
|
-
action = /* @__PURE__ */ (0,
|
|
2855
|
+
action = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2578
2856
|
NButton,
|
|
2579
2857
|
{
|
|
2580
2858
|
disabled: dlActive || !st.ceilings.local,
|
|
@@ -2584,16 +2862,16 @@ var __defProp = Object.defineProperty;
|
|
|
2584
2862
|
}
|
|
2585
2863
|
);
|
|
2586
2864
|
}
|
|
2587
|
-
return /* @__PURE__ */ (0,
|
|
2865
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2588
2866
|
"div",
|
|
2589
2867
|
{
|
|
2590
2868
|
style: { ...S.flexRow, padding: "8px 0", borderBottom: "1px solid var(--dsh-mem-border)", flexWrap: "wrap" },
|
|
2591
2869
|
children: [
|
|
2592
|
-
/* @__PURE__ */ (0,
|
|
2593
|
-
/* @__PURE__ */ (0,
|
|
2594
|
-
/* @__PURE__ */ (0,
|
|
2870
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { minWidth: 150 }, children: [
|
|
2871
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { fontWeight: 600 }, children: m.name }),
|
|
2872
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-mem-rb-muted", children: m.tags.join(" · ") + " · " + m.dims + " 维 · 上下文 " + m.contextTokens })
|
|
2595
2873
|
] }),
|
|
2596
|
-
/* @__PURE__ */ (0,
|
|
2874
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { flex: 1, minWidth: 180, fontSize: 12, color: "var(--dsh-mem-text-2)" }, children: m.description }),
|
|
2597
2875
|
action
|
|
2598
2876
|
]
|
|
2599
2877
|
},
|
|
@@ -2606,11 +2884,11 @@ var __defProp = Object.defineProperty;
|
|
|
2606
2884
|
const reindexRunning = !!(st.reindex && st.reindex.running);
|
|
2607
2885
|
const canRebuild = vecOk && st.source !== "off" && !reindexRunning && !st.apply.busy;
|
|
2608
2886
|
const rebuildHint = !vecOk ? "向量能力不可用" : st.source === "off" ? "嵌入源已关闭,请先启用" : reindexRunning ? "重建已在进行中" : st.apply.busy ? "嵌入源切换进行中" : "只补缺失向量;已有向量不动。零向量内容会被跳过(重试无意义)";
|
|
2609
|
-
return /* @__PURE__ */ (0,
|
|
2610
|
-
/* @__PURE__ */ (0,
|
|
2611
|
-
/* @__PURE__ */ (0,
|
|
2612
|
-
/* @__PURE__ */ (0,
|
|
2613
|
-
/* @__PURE__ */ (0,
|
|
2887
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "dsh-mem-rb-card", children: [
|
|
2888
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: S.flexRow, children: [
|
|
2889
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { fontWeight: 600, whiteSpace: "nowrap" }, children: "语义检索(嵌入源)" }),
|
|
2890
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: S.grow }),
|
|
2891
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2614
2892
|
Segmented,
|
|
2615
2893
|
{
|
|
2616
2894
|
value: st.source,
|
|
@@ -2623,18 +2901,18 @@ var __defProp = Object.defineProperty;
|
|
|
2623
2901
|
}
|
|
2624
2902
|
)
|
|
2625
2903
|
] }),
|
|
2626
|
-
/* @__PURE__ */ (0,
|
|
2627
|
-
st.activeNote ? /* @__PURE__ */ (0,
|
|
2628
|
-
err && err !== "__unsupported__" ? /* @__PURE__ */ (0,
|
|
2629
|
-
dl && dl.phase === "error" ? /* @__PURE__ */ (0,
|
|
2904
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-mem-rb-muted", style: { marginTop: 4 }, children: st.source === "off" ? "当前:关键词(BM25)检索,不做向量嵌入" : st.source === "remote" ? "当前:远程嵌入(" + (remote.model || "未配置模型") + (remote.baseURL ? " · " + remote.baseURL : "") + ")" : "当前:本地嵌入" + (st.activeModel ? "(" + st.activeModel + ")" : "") }),
|
|
2905
|
+
st.activeNote ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { marginTop: 4, fontSize: 12, color: "var(--dsh-mem-danger)" }, children: st.activeNote }) : null,
|
|
2906
|
+
err && err !== "__unsupported__" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { marginTop: 6, fontSize: 12, color: "var(--dsh-mem-danger)" }, children: err }) : null,
|
|
2907
|
+
dl && dl.phase === "error" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { marginTop: 6, fontSize: 12, color: "var(--dsh-mem-danger)" }, children: "下载失败:" + (dl.error || "") }) : null,
|
|
2630
2908
|
runtimeRow,
|
|
2631
2909
|
applyRow,
|
|
2632
|
-
/* @__PURE__ */ (0,
|
|
2633
|
-
/* @__PURE__ */ (0,
|
|
2634
|
-
/* @__PURE__ */ (0,
|
|
2635
|
-
/* @__PURE__ */ (0,
|
|
2636
|
-
/* @__PURE__ */ (0,
|
|
2637
|
-
/* @__PURE__ */ (0,
|
|
2910
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: RSTY.block, children: [
|
|
2911
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: RSTY.title, children: "远程连接(生效值;运行时覆盖优先于部署 YAML)" }),
|
|
2912
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: RSTY.note, children: "生效端点 " + (remote.baseURL || "(未配置)") + " · 模型 " + (remote.model || "(未配置)") + " · " + (remote.dimensions > 0 ? remote.dimensions + " 维" : "维度跟随部署") + (remote.apiKeySet ? " · 密钥已设置" : " · 密钥未设置") }),
|
|
2913
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: RSTY.row, children: [
|
|
2914
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: RSTY.label, children: "端点 URL" }),
|
|
2915
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2638
2916
|
NInput,
|
|
2639
2917
|
{
|
|
2640
2918
|
style: RSTY.input,
|
|
@@ -2651,9 +2929,9 @@ var __defProp = Object.defineProperty;
|
|
|
2651
2929
|
}
|
|
2652
2930
|
)
|
|
2653
2931
|
] }),
|
|
2654
|
-
/* @__PURE__ */ (0,
|
|
2655
|
-
/* @__PURE__ */ (0,
|
|
2656
|
-
/* @__PURE__ */ (0,
|
|
2932
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: RSTY.row, children: [
|
|
2933
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: RSTY.label, children: "模型名" }),
|
|
2934
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2657
2935
|
NInput,
|
|
2658
2936
|
{
|
|
2659
2937
|
style: RSTY.input,
|
|
@@ -2669,8 +2947,8 @@ var __defProp = Object.defineProperty;
|
|
|
2669
2947
|
}
|
|
2670
2948
|
}
|
|
2671
2949
|
),
|
|
2672
|
-
/* @__PURE__ */ (0,
|
|
2673
|
-
/* @__PURE__ */ (0,
|
|
2950
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: RSTY.label, children: "维度" }),
|
|
2951
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2674
2952
|
NInput,
|
|
2675
2953
|
{
|
|
2676
2954
|
style: { width: 90, minWidth: 0, flex: "0 1 90px" },
|
|
@@ -2690,9 +2968,9 @@ var __defProp = Object.defineProperty;
|
|
|
2690
2968
|
}
|
|
2691
2969
|
)
|
|
2692
2970
|
] }),
|
|
2693
|
-
/* @__PURE__ */ (0,
|
|
2694
|
-
/* @__PURE__ */ (0,
|
|
2695
|
-
/* @__PURE__ */ (0,
|
|
2971
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: RSTY.row, children: [
|
|
2972
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: RSTY.label, children: "API Key" }),
|
|
2973
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2696
2974
|
NInput,
|
|
2697
2975
|
{
|
|
2698
2976
|
style: RSTY.input,
|
|
@@ -2707,8 +2985,8 @@ var __defProp = Object.defineProperty;
|
|
|
2707
2985
|
onBlur: commitRemoteKey
|
|
2708
2986
|
}
|
|
2709
2987
|
),
|
|
2710
|
-
remote.apiKeySet ? /* @__PURE__ */ (0,
|
|
2711
|
-
/* @__PURE__ */ (0,
|
|
2988
|
+
remote.apiKeySet ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: RSTY.chipAccent, children: "已设置" }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: RSTY.chipMuted, children: "未设置" }),
|
|
2989
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2712
2990
|
NButton,
|
|
2713
2991
|
{
|
|
2714
2992
|
title: "写入空串清除运行时密钥(部署 YAML 的密钥不受影响)",
|
|
@@ -2718,12 +2996,12 @@ var __defProp = Object.defineProperty;
|
|
|
2718
2996
|
)
|
|
2719
2997
|
] })
|
|
2720
2998
|
] }),
|
|
2721
|
-
/* @__PURE__ */ (0,
|
|
2999
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: S.panelLabel, children: "本地模型目录(下载后离线可用,不随插件分发)" }),
|
|
2722
3000
|
modelCards,
|
|
2723
|
-
/* @__PURE__ */ (0,
|
|
2724
|
-
/* @__PURE__ */ (0,
|
|
2725
|
-
/* @__PURE__ */ (0,
|
|
2726
|
-
/* @__PURE__ */ (0,
|
|
3001
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: RSTY.block, children: [
|
|
3002
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: RSTY.title, children: "向量索引" }),
|
|
3003
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: RSTY.note, children: vecNote }),
|
|
3004
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: RSTY.row, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2727
3005
|
NButton,
|
|
2728
3006
|
{
|
|
2729
3007
|
disabled: !canRebuild,
|
|
@@ -2737,8 +3015,8 @@ var __defProp = Object.defineProperty;
|
|
|
2737
3015
|
}
|
|
2738
3016
|
|
|
2739
3017
|
// client/src/tabs/RebuildPanel.tsx
|
|
2740
|
-
var
|
|
2741
|
-
var
|
|
3018
|
+
var import_react13 = require("react");
|
|
3019
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2742
3020
|
var RB_PHASE_LABEL = {
|
|
2743
3021
|
preparing: "准备中(归档旧数据 · 清空检索库)",
|
|
2744
3022
|
distilling: "分块蒸馏中",
|
|
@@ -2746,21 +3024,21 @@ var __defProp = Object.defineProperty;
|
|
|
2746
3024
|
};
|
|
2747
3025
|
function RebuildPanel(props) {
|
|
2748
3026
|
const rpc = props.rpc;
|
|
2749
|
-
const [rbRaw, setRb] = (0,
|
|
2750
|
-
const [confirmOpen, setConfirmOpen] = (0,
|
|
2751
|
-
const [busy, setBusy] = (0,
|
|
2752
|
-
const [rbError, setRbError] = (0,
|
|
2753
|
-
const refresh = (0,
|
|
3027
|
+
const [rbRaw, setRb] = (0, import_react13.useState)(null);
|
|
3028
|
+
const [confirmOpen, setConfirmOpen] = (0, import_react13.useState)(false);
|
|
3029
|
+
const [busy, setBusy] = (0, import_react13.useState)(false);
|
|
3030
|
+
const [rbError, setRbError] = (0, import_react13.useState)(null);
|
|
3031
|
+
const refresh = (0, import_react13.useCallback)(() => {
|
|
2754
3032
|
rpc("dsh-memory/rebuild-status", {}).then((r) => {
|
|
2755
3033
|
if (r && r.ok) setRb(r.value);
|
|
2756
3034
|
}).catch(() => {
|
|
2757
3035
|
});
|
|
2758
3036
|
}, [rpc]);
|
|
2759
|
-
(0,
|
|
3037
|
+
(0, import_react13.useEffect)(() => {
|
|
2760
3038
|
refresh();
|
|
2761
3039
|
}, [refresh]);
|
|
2762
3040
|
const running = !!(rbRaw && rbRaw.running);
|
|
2763
|
-
(0,
|
|
3041
|
+
(0, import_react13.useEffect)(() => {
|
|
2764
3042
|
if (!running) return;
|
|
2765
3043
|
const timer = setInterval(refresh, 1500);
|
|
2766
3044
|
return () => {
|
|
@@ -2805,11 +3083,11 @@ var __defProp = Object.defineProperty;
|
|
|
2805
3083
|
} else if (!running && rb.phase === "failed") {
|
|
2806
3084
|
lastNote = "上次重建:失败:" + (rb.error || "未知错误");
|
|
2807
3085
|
}
|
|
2808
|
-
return /* @__PURE__ */ (0,
|
|
2809
|
-
/* @__PURE__ */ (0,
|
|
2810
|
-
/* @__PURE__ */ (0,
|
|
2811
|
-
/* @__PURE__ */ (0,
|
|
2812
|
-
running ? /* @__PURE__ */ (0,
|
|
3086
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "dsh-mem-rb-card", children: [
|
|
3087
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }, children: [
|
|
3088
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { fontWeight: 600, whiteSpace: "nowrap" }, children: "重建记忆" }),
|
|
3089
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-mem-rb-muted", style: { flex: 1, minWidth: 180 }, children: running ? (RB_PHASE_LABEL[rb.phase] || rb.phase) + " · " + rb.done + "/" + rb.total + " 会话(" + pct + "%)" : "从 L0 原始对话重新蒸馏 L1/L2/L3;旧数据先归档(不删除)" }),
|
|
3090
|
+
running ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(NButton, { disabled: busy || rb.cancelRequested, onClick: cancel, children: rb.cancelRequested ? "取消中…" : "取消重建" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2813
3091
|
NButton,
|
|
2814
3092
|
{
|
|
2815
3093
|
disabled: busy || empty,
|
|
@@ -2822,13 +3100,13 @@ var __defProp = Object.defineProperty;
|
|
|
2822
3100
|
}
|
|
2823
3101
|
)
|
|
2824
3102
|
] }),
|
|
2825
|
-
running ? /* @__PURE__ */ (0,
|
|
2826
|
-
/* @__PURE__ */ (0,
|
|
2827
|
-
/* @__PURE__ */ (0,
|
|
3103
|
+
running ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, marginTop: 10 }, children: [
|
|
3104
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-mem-rb-bar", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-mem-rb-fill", style: { width: pct + "%" } }) }),
|
|
3105
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "dsh-mem-rb-muted", style: { whiteSpace: "nowrap" }, children: "产出 " + rb.recordsBuilt + " 条" })
|
|
2828
3106
|
] }) : null,
|
|
2829
|
-
lastNote ? /* @__PURE__ */ (0,
|
|
2830
|
-
rbError ? /* @__PURE__ */ (0,
|
|
2831
|
-
confirmOpen ? /* @__PURE__ */ (0,
|
|
3107
|
+
lastNote ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "dsh-mem-rb-muted", style: { marginTop: 8 }, children: lastNote }) : null,
|
|
3108
|
+
rbError ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { marginTop: 8, fontSize: 12, color: "var(--dsh-mem-danger)" }, children: rbError }) : null,
|
|
3109
|
+
confirmOpen ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
2832
3110
|
NModal,
|
|
2833
3111
|
{
|
|
2834
3112
|
open: true,
|
|
@@ -2837,7 +3115,7 @@ var __defProp = Object.defineProperty;
|
|
|
2837
3115
|
},
|
|
2838
3116
|
title: "确认重建全部记忆?",
|
|
2839
3117
|
footer: [
|
|
2840
|
-
/* @__PURE__ */ (0,
|
|
3118
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2841
3119
|
NButton,
|
|
2842
3120
|
{
|
|
2843
3121
|
onClick: () => {
|
|
@@ -2847,15 +3125,15 @@ var __defProp = Object.defineProperty;
|
|
|
2847
3125
|
},
|
|
2848
3126
|
"cancel"
|
|
2849
3127
|
),
|
|
2850
|
-
/* @__PURE__ */ (0,
|
|
3128
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(NButton, { variant: "primary", disabled: busy, onClick: start, children: busy ? "启动中…" : "开始重建" }, "confirm")
|
|
2851
3129
|
],
|
|
2852
3130
|
children: [
|
|
2853
|
-
/* @__PURE__ */ (0,
|
|
3131
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
|
|
2854
3132
|
"将以 L0 原始对话为事实源重新蒸馏:",
|
|
2855
|
-
/* @__PURE__ */ (0,
|
|
3133
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("b", { children: rb.sessionCount + " 个会话 · " + rb.messageCount + " 条消息" }),
|
|
2856
3134
|
",预计 ≥" + rb.estCalls + " 次蒸馏调用。"
|
|
2857
3135
|
] }),
|
|
2858
|
-
/* @__PURE__ */ (0,
|
|
3136
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { marginTop: 8 }, children: "现有 L1 记忆 / L2 场景 / L3 画像会整体归档(*.bak.时间戳,可手工找回),随后清空重建;重建期间可正常对话,新对话的蒸馏优先进行;中途可取消,已重建部分保留。" })
|
|
2859
3137
|
]
|
|
2860
3138
|
}
|
|
2861
3139
|
) : null
|
|
@@ -2863,8 +3141,8 @@ var __defProp = Object.defineProperty;
|
|
|
2863
3141
|
}
|
|
2864
3142
|
|
|
2865
3143
|
// client/src/tabs/RuminatePanel.tsx
|
|
2866
|
-
var
|
|
2867
|
-
var
|
|
3144
|
+
var import_react14 = require("react");
|
|
3145
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
2868
3146
|
var RM_PHASE_LABEL = {
|
|
2869
3147
|
refreshing: "轻量刷新中",
|
|
2870
3148
|
distilling: "L1 蒸馏中",
|
|
@@ -2885,11 +3163,11 @@ var __defProp = Object.defineProperty;
|
|
|
2885
3163
|
var RM_IDLE_INTERVAL = 3e4;
|
|
2886
3164
|
function RuminatePanel(props) {
|
|
2887
3165
|
const rpc = props.rpc;
|
|
2888
|
-
const [rmRaw, setRm] = (0,
|
|
2889
|
-
const [confirmOpen, setConfirmOpen] = (0,
|
|
2890
|
-
const [busy, setBusy] = (0,
|
|
2891
|
-
const [rmError, setRmError] = (0,
|
|
2892
|
-
const refresh = (0,
|
|
3166
|
+
const [rmRaw, setRm] = (0, import_react14.useState)(null);
|
|
3167
|
+
const [confirmOpen, setConfirmOpen] = (0, import_react14.useState)(false);
|
|
3168
|
+
const [busy, setBusy] = (0, import_react14.useState)(false);
|
|
3169
|
+
const [rmError, setRmError] = (0, import_react14.useState)(null);
|
|
3170
|
+
const refresh = (0, import_react14.useCallback)(() => {
|
|
2893
3171
|
return rpc("dsh-memory/ruminate-status", {}).then((r) => {
|
|
2894
3172
|
if (r && r.ok) {
|
|
2895
3173
|
const st = r.value;
|
|
@@ -2904,14 +3182,14 @@ var __defProp = Object.defineProperty;
|
|
|
2904
3182
|
}).catch(() => {
|
|
2905
3183
|
});
|
|
2906
3184
|
}, [rpc]);
|
|
2907
|
-
const pollRef = (0,
|
|
2908
|
-
const backoffRef = (0,
|
|
2909
|
-
const lastDetailRef = (0,
|
|
2910
|
-
(0,
|
|
3185
|
+
const pollRef = (0, import_react14.useRef)(1500);
|
|
3186
|
+
const backoffRef = (0, import_react14.useRef)(1);
|
|
3187
|
+
const lastDetailRef = (0, import_react14.useRef)(null);
|
|
3188
|
+
(0, import_react14.useEffect)(() => {
|
|
2911
3189
|
refresh();
|
|
2912
3190
|
}, [refresh]);
|
|
2913
3191
|
const running = !!(rmRaw && (rmRaw.running || RM_RUNNING_PHASES.indexOf(rmRaw.phase) >= 0));
|
|
2914
|
-
(0,
|
|
3192
|
+
(0, import_react14.useEffect)(() => {
|
|
2915
3193
|
if (!running) return;
|
|
2916
3194
|
let alive = true;
|
|
2917
3195
|
let timer;
|
|
@@ -2930,13 +3208,13 @@ var __defProp = Object.defineProperty;
|
|
|
2930
3208
|
lastDetailRef.current = null;
|
|
2931
3209
|
};
|
|
2932
3210
|
}, [running, refresh]);
|
|
2933
|
-
(0,
|
|
3211
|
+
(0, import_react14.useEffect)(() => {
|
|
2934
3212
|
if (running) return;
|
|
2935
3213
|
const timer = setInterval(refresh, RM_IDLE_INTERVAL);
|
|
2936
3214
|
return () => clearInterval(timer);
|
|
2937
3215
|
}, [running, refresh]);
|
|
2938
|
-
const [, setTick] = (0,
|
|
2939
|
-
(0,
|
|
3216
|
+
const [, setTick] = (0, import_react14.useState)(0);
|
|
3217
|
+
(0, import_react14.useEffect)(() => {
|
|
2940
3218
|
if (!running) return;
|
|
2941
3219
|
const timer = setInterval(() => setTick((n) => n + 1), 1e3);
|
|
2942
3220
|
return () => clearInterval(timer);
|
|
@@ -2987,11 +3265,11 @@ var __defProp = Object.defineProperty;
|
|
|
2987
3265
|
}
|
|
2988
3266
|
const unit = rm.phase === "refreshing" || rm.phase === "relabeling" ? "步" : "会话";
|
|
2989
3267
|
const progressText = sub ? sub.label + " " + sub.done + "/" + sub.total + "(" + Math.round(sub.done / sub.total * 100) + "%)" : rm.total > 0 ? rm.done + "/" + rm.total + " " + unit + "(" + pct + "%)" : "进行中…";
|
|
2990
|
-
return /* @__PURE__ */ (0,
|
|
2991
|
-
/* @__PURE__ */ (0,
|
|
2992
|
-
/* @__PURE__ */ (0,
|
|
2993
|
-
/* @__PURE__ */ (0,
|
|
2994
|
-
running ? /* @__PURE__ */ (0,
|
|
3268
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "dsh-mem-rb-card", children: [
|
|
3269
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }, children: [
|
|
3270
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { fontWeight: 600, whiteSpace: "nowrap" }, children: "反刍整理" }),
|
|
3271
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-mem-rb-muted", style: { flex: 1, minWidth: 180 }, children: running ? (RM_PHASE_LABEL[rm.phase] || rm.phase) + " · " + progressText + (elapsedText ? " · 已用 " + elapsedText : "") : "冲刷未蒸馏缓冲,跑一轮 L1→L2→L3 消化;不清库不改 L0" }),
|
|
3272
|
+
running ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(NButton, { disabled: busy || rm.cancelRequested, onClick: cancel, children: rm.cancelRequested ? "取消中…" : "取消整理" }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2995
3273
|
NButton,
|
|
2996
3274
|
{
|
|
2997
3275
|
disabled: busy,
|
|
@@ -3004,27 +3282,27 @@ var __defProp = Object.defineProperty;
|
|
|
3004
3282
|
}
|
|
3005
3283
|
)
|
|
3006
3284
|
] }),
|
|
3007
|
-
running ? /* @__PURE__ */ (0,
|
|
3008
|
-
/* @__PURE__ */ (0,
|
|
3285
|
+
running ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10, marginTop: 10 }, children: [
|
|
3286
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-mem-rb-bar", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3009
3287
|
"div",
|
|
3010
3288
|
{
|
|
3011
3289
|
className: "dsh-mem-rb-fill" + (indet ? " dsh-mem-rb-fill-indet" : ""),
|
|
3012
3290
|
style: { width: indet ? "100%" : barPct + "%" }
|
|
3013
3291
|
}
|
|
3014
3292
|
) }),
|
|
3015
|
-
/* @__PURE__ */ (0,
|
|
3293
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "dsh-mem-rb-muted", style: { whiteSpace: "nowrap" }, children: sub ? sub.label + " " + sub.done + "/" + sub.total : "产出 " + rm.recordsBuilt + " 条" })
|
|
3016
3294
|
] }) : null,
|
|
3017
|
-
running && rm.detail ? /* @__PURE__ */ (0,
|
|
3018
|
-
lastNote ? /* @__PURE__ */ (0,
|
|
3019
|
-
rmError ? /* @__PURE__ */ (0,
|
|
3020
|
-
confirmOpen ? /* @__PURE__ */ (0,
|
|
3295
|
+
running && rm.detail ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-mem-rb-muted", style: { marginTop: 6, whiteSpace: "normal" }, children: "当前:" + rm.detail }) : null,
|
|
3296
|
+
lastNote ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "dsh-mem-rb-muted", style: { marginTop: 8 }, children: lastNote }) : null,
|
|
3297
|
+
rmError ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { marginTop: 8, fontSize: 12, color: "var(--dsh-mem-danger)" }, children: rmError }) : null,
|
|
3298
|
+
confirmOpen ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
3021
3299
|
NModal,
|
|
3022
3300
|
{
|
|
3023
3301
|
open: true,
|
|
3024
3302
|
onClose: () => setConfirmOpen(false),
|
|
3025
3303
|
title: "确认反刍整理?",
|
|
3026
3304
|
footer: [
|
|
3027
|
-
/* @__PURE__ */ (0,
|
|
3305
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3028
3306
|
NButton,
|
|
3029
3307
|
{
|
|
3030
3308
|
onClick: () => setConfirmOpen(false),
|
|
@@ -3032,11 +3310,11 @@ var __defProp = Object.defineProperty;
|
|
|
3032
3310
|
},
|
|
3033
3311
|
"cancel"
|
|
3034
3312
|
),
|
|
3035
|
-
/* @__PURE__ */ (0,
|
|
3313
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(NButton, { variant: "primary", disabled: busy, onClick: start, children: busy ? "启动中…" : "反刍整理" }, "confirm")
|
|
3036
3314
|
],
|
|
3037
3315
|
children: [
|
|
3038
|
-
/* @__PURE__ */ (0,
|
|
3039
|
-
/* @__PURE__ */ (0,
|
|
3316
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { children: "将扫描未蒸馏缓冲,按会话逐个跑蒸馏管线,完成后强制 L2 场景整合与 L3 画像更新。" }),
|
|
3317
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { marginTop: 8 }, children: "与重建不同:不清空 L1 检索库、不归档旧产物、不改 L0;仅消化攒而未蒸馏的切片,无缓冲时做轻量 L2/L3 刷新。" })
|
|
3040
3318
|
]
|
|
3041
3319
|
}
|
|
3042
3320
|
) : null
|
|
@@ -3044,13 +3322,13 @@ var __defProp = Object.defineProperty;
|
|
|
3044
3322
|
}
|
|
3045
3323
|
|
|
3046
3324
|
// client/src/tabs/OverviewTab.tsx
|
|
3047
|
-
var
|
|
3325
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
3048
3326
|
function OverviewTab(props) {
|
|
3049
3327
|
const rpc = props.rpc;
|
|
3050
|
-
const [stats, setStats] = (0,
|
|
3051
|
-
const [settingsData, setSettingsData] = (0,
|
|
3052
|
-
const [error, setError] = (0,
|
|
3053
|
-
const load = (0,
|
|
3328
|
+
const [stats, setStats] = (0, import_react15.useState)(null);
|
|
3329
|
+
const [settingsData, setSettingsData] = (0, import_react15.useState)(null);
|
|
3330
|
+
const [error, setError] = (0, import_react15.useState)(null);
|
|
3331
|
+
const load = (0, import_react15.useCallback)(() => {
|
|
3054
3332
|
rpc("dsh-memory/stats", {}).then((r) => {
|
|
3055
3333
|
if (r && r.ok) setStats(r.value);
|
|
3056
3334
|
else setError(r && r.error ? r.error.message : "RPC error");
|
|
@@ -3062,7 +3340,7 @@ var __defProp = Object.defineProperty;
|
|
|
3062
3340
|
}).catch(() => {
|
|
3063
3341
|
});
|
|
3064
3342
|
}, [rpc]);
|
|
3065
|
-
(0,
|
|
3343
|
+
(0, import_react15.useEffect)(() => {
|
|
3066
3344
|
load();
|
|
3067
3345
|
const timer = setInterval(load, 5e3);
|
|
3068
3346
|
return () => {
|
|
@@ -3123,10 +3401,11 @@ var __defProp = Object.defineProperty;
|
|
|
3123
3401
|
const toolRuminate = settingsData && settingsData.settings ? settingsData.settings.toolRuminate !== false : true;
|
|
3124
3402
|
const toolConflict = settingsData && settingsData.settings ? settingsData.settings.toolConflict !== false : true;
|
|
3125
3403
|
const toolMutate = settingsData && settingsData.settings ? settingsData.settings.toolMutate !== false : true;
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
/* @__PURE__ */ (0,
|
|
3404
|
+
const skillsEnabled = settingsData && settingsData.settings ? settingsData.settings.skillsEnabled === true : false;
|
|
3405
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
|
|
3406
|
+
settingsData && settingsData.supported === false ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: S.hint, children: "settings 服务不可用,记忆模式开关未启用(记忆保持全开)。" }) : settingsData ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: S.switchPanel, children: [
|
|
3407
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: S.panelLabel, children: "记忆模式" }),
|
|
3408
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3130
3409
|
SwitchRow,
|
|
3131
3410
|
{
|
|
3132
3411
|
label: "记忆模式",
|
|
@@ -3137,7 +3416,7 @@ var __defProp = Object.defineProperty;
|
|
|
3137
3416
|
}
|
|
3138
3417
|
}
|
|
3139
3418
|
),
|
|
3140
|
-
/* @__PURE__ */ (0,
|
|
3419
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3141
3420
|
SwitchRow,
|
|
3142
3421
|
{
|
|
3143
3422
|
label: "捕获",
|
|
@@ -3149,7 +3428,7 @@ var __defProp = Object.defineProperty;
|
|
|
3149
3428
|
}
|
|
3150
3429
|
}
|
|
3151
3430
|
),
|
|
3152
|
-
/* @__PURE__ */ (0,
|
|
3431
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3153
3432
|
SwitchRow,
|
|
3154
3433
|
{
|
|
3155
3434
|
label: "蒸馏",
|
|
@@ -3161,7 +3440,7 @@ var __defProp = Object.defineProperty;
|
|
|
3161
3440
|
}
|
|
3162
3441
|
}
|
|
3163
3442
|
),
|
|
3164
|
-
/* @__PURE__ */ (0,
|
|
3443
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3165
3444
|
SwitchRow,
|
|
3166
3445
|
{
|
|
3167
3446
|
label: "召回",
|
|
@@ -3173,8 +3452,8 @@ var __defProp = Object.defineProperty;
|
|
|
3173
3452
|
}
|
|
3174
3453
|
}
|
|
3175
3454
|
),
|
|
3176
|
-
/* @__PURE__ */ (0,
|
|
3177
|
-
/* @__PURE__ */ (0,
|
|
3455
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: S.panelLabel, children: "高权限模式" }),
|
|
3456
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3178
3457
|
SwitchRow,
|
|
3179
3458
|
{
|
|
3180
3459
|
label: "高权限模式",
|
|
@@ -3185,8 +3464,20 @@ var __defProp = Object.defineProperty;
|
|
|
3185
3464
|
}
|
|
3186
3465
|
}
|
|
3187
3466
|
),
|
|
3188
|
-
/* @__PURE__ */ (0,
|
|
3189
|
-
/* @__PURE__ */ (0,
|
|
3467
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: S.panelLabel, children: "技能结晶" }),
|
|
3468
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3469
|
+
SwitchRow,
|
|
3470
|
+
{
|
|
3471
|
+
label: "技能(程序性记忆)",
|
|
3472
|
+
desc: skillsEnabled ? "已开启:重复工作方法会结晶为技能候选,注入活跃技能,可在「技能」页审阅晋升" : "默认关闭;开启后注册 memory_skill_* 工具与注入(新装工具需重启后完全生效)",
|
|
3473
|
+
checked: skillsEnabled,
|
|
3474
|
+
onChange: (v) => {
|
|
3475
|
+
toggle("skillsEnabled", v);
|
|
3476
|
+
}
|
|
3477
|
+
}
|
|
3478
|
+
),
|
|
3479
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: S.panelLabel, children: "工具封印" }),
|
|
3480
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3190
3481
|
SwitchRow,
|
|
3191
3482
|
{
|
|
3192
3483
|
label: "Room 管理工具",
|
|
@@ -3197,7 +3488,7 @@ var __defProp = Object.defineProperty;
|
|
|
3197
3488
|
}
|
|
3198
3489
|
}
|
|
3199
3490
|
),
|
|
3200
|
-
/* @__PURE__ */ (0,
|
|
3491
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3201
3492
|
SwitchRow,
|
|
3202
3493
|
{
|
|
3203
3494
|
label: "图谱工具",
|
|
@@ -3208,7 +3499,7 @@ var __defProp = Object.defineProperty;
|
|
|
3208
3499
|
}
|
|
3209
3500
|
}
|
|
3210
3501
|
),
|
|
3211
|
-
/* @__PURE__ */ (0,
|
|
3502
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3212
3503
|
SwitchRow,
|
|
3213
3504
|
{
|
|
3214
3505
|
label: "反刍工具",
|
|
@@ -3219,7 +3510,7 @@ var __defProp = Object.defineProperty;
|
|
|
3219
3510
|
}
|
|
3220
3511
|
}
|
|
3221
3512
|
),
|
|
3222
|
-
/* @__PURE__ */ (0,
|
|
3513
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3223
3514
|
SwitchRow,
|
|
3224
3515
|
{
|
|
3225
3516
|
label: "冲突工具",
|
|
@@ -3230,7 +3521,7 @@ var __defProp = Object.defineProperty;
|
|
|
3230
3521
|
}
|
|
3231
3522
|
}
|
|
3232
3523
|
),
|
|
3233
|
-
/* @__PURE__ */ (0,
|
|
3524
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3234
3525
|
SwitchRow,
|
|
3235
3526
|
{
|
|
3236
3527
|
label: "写删工具",
|
|
@@ -3241,8 +3532,8 @@ var __defProp = Object.defineProperty;
|
|
|
3241
3532
|
}
|
|
3242
3533
|
}
|
|
3243
3534
|
),
|
|
3244
|
-
/* @__PURE__ */ (0,
|
|
3245
|
-
/* @__PURE__ */ (0,
|
|
3535
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: S.panelLabel, children: "人工冲突裁决" }),
|
|
3536
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3246
3537
|
SwitchRow,
|
|
3247
3538
|
{
|
|
3248
3539
|
label: "人工冲突裁决",
|
|
@@ -3253,42 +3544,42 @@ var __defProp = Object.defineProperty;
|
|
|
3253
3544
|
}
|
|
3254
3545
|
}
|
|
3255
3546
|
),
|
|
3256
|
-
/* @__PURE__ */ (0,
|
|
3257
|
-
/* @__PURE__ */ (0,
|
|
3258
|
-
ceilingNote ? /* @__PURE__ */ (0,
|
|
3547
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: S.panelLabel, children: "蒸馏参数" }),
|
|
3548
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DistillSettings, { rpc, disabled: !master, data: settingsData, setData: setSettingsData, onError: setError }),
|
|
3549
|
+
ceilingNote ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: S.hint, children: ceilingNote }) : null
|
|
3259
3550
|
] }) : null,
|
|
3260
|
-
/* @__PURE__ */ (0,
|
|
3261
|
-
/* @__PURE__ */ (0,
|
|
3262
|
-
/* @__PURE__ */ (0,
|
|
3263
|
-
degraded ? /* @__PURE__ */ (0,
|
|
3264
|
-
error ? /* @__PURE__ */ (0,
|
|
3265
|
-
/* @__PURE__ */ (0,
|
|
3266
|
-
/* @__PURE__ */ (0,
|
|
3267
|
-
return /* @__PURE__ */ (0,
|
|
3268
|
-
/* @__PURE__ */ (0,
|
|
3269
|
-
/* @__PURE__ */ (0,
|
|
3551
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(EmbeddingSection, { rpc }),
|
|
3552
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(RebuildPanel, { rpc }),
|
|
3553
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(RuminatePanel, { rpc }),
|
|
3554
|
+
degraded ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { ...S.error, marginBottom: 10 }, children: "⚠ " + stats.message + "。上方数据为最后一次成功读取的值,记忆功能当前未工作。" }) : null,
|
|
3555
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: S.error, children: "获取状态失败:" + error }) : !stats ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: S.intro, children: "正在读取记忆状态…" }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { children: [
|
|
3556
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: S.panelLabel, children: "记忆概况" }),
|
|
3557
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: S.statGrid, children: tiles.map((t) => {
|
|
3558
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "dsh-mem-card", style: S.statTile, children: [
|
|
3559
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: S.statNum, children: t.num }),
|
|
3560
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: S.statLabel, children: t.label })
|
|
3270
3561
|
] }, t.label);
|
|
3271
3562
|
}) }),
|
|
3272
|
-
/* @__PURE__ */ (0,
|
|
3563
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: S.panelLabel, children: "运行状态" }),
|
|
3273
3564
|
infos.map((row2) => {
|
|
3274
|
-
return /* @__PURE__ */ (0,
|
|
3275
|
-
/* @__PURE__ */ (0,
|
|
3276
|
-
/* @__PURE__ */ (0,
|
|
3565
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: S.infoRow, children: [
|
|
3566
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: S.infoKey, children: row2[0] }),
|
|
3567
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: S.infoVal, children: row2[1] })
|
|
3277
3568
|
] }, row2[0]);
|
|
3278
3569
|
})
|
|
3279
3570
|
] }),
|
|
3280
|
-
/* @__PURE__ */ (0,
|
|
3571
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: S.hint, children: "浏览各层记忆内容请切换上方 Tab;原始对话(L0)不入浏览器,可由模型侧 conversation_search 工具查询。" })
|
|
3281
3572
|
] });
|
|
3282
3573
|
}
|
|
3283
3574
|
|
|
3284
3575
|
// client/src/tabs/PersonaTab.tsx
|
|
3285
|
-
var
|
|
3286
|
-
var
|
|
3576
|
+
var import_react16 = require("react");
|
|
3577
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
3287
3578
|
function PersonaTab(props) {
|
|
3288
3579
|
const rpc = props.rpc;
|
|
3289
|
-
const [content, setContent] = (0,
|
|
3290
|
-
const [error, setError] = (0,
|
|
3291
|
-
const load = (0,
|
|
3580
|
+
const [content, setContent] = (0, import_react16.useState)(null);
|
|
3581
|
+
const [error, setError] = (0, import_react16.useState)(null);
|
|
3582
|
+
const load = (0, import_react16.useCallback)(() => {
|
|
3292
3583
|
setError(null);
|
|
3293
3584
|
rpc("dsh-memory/persona", {}).then((r) => {
|
|
3294
3585
|
if (r && r.ok) setContent(r.value.content);
|
|
@@ -3297,23 +3588,23 @@ var __defProp = Object.defineProperty;
|
|
|
3297
3588
|
setError(String(e && e.message || e));
|
|
3298
3589
|
});
|
|
3299
3590
|
}, [rpc]);
|
|
3300
|
-
(0,
|
|
3591
|
+
(0, import_react16.useEffect)(() => {
|
|
3301
3592
|
load();
|
|
3302
3593
|
}, [load]);
|
|
3303
|
-
return /* @__PURE__ */ (0,
|
|
3304
|
-
/* @__PURE__ */ (0,
|
|
3305
|
-
/* @__PURE__ */ (0,
|
|
3306
|
-
/* @__PURE__ */ (0,
|
|
3307
|
-
/* @__PURE__ */ (0,
|
|
3594
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
|
|
3595
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { ...S.flexRow, marginBottom: 10 }, children: [
|
|
3596
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: S.muted, children: error ? "加载失败" : content === null ? "加载中…" : content ? content.length + " 字符" : "未生成画像" }),
|
|
3597
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: S.grow }),
|
|
3598
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(NButton, { onClick: load, children: "刷新" })
|
|
3308
3599
|
] }),
|
|
3309
|
-
error ? /* @__PURE__ */ (0,
|
|
3310
|
-
content ? /* @__PURE__ */ (0,
|
|
3600
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { ...S.error, marginBottom: 10 }, children: "画像读取失败:" + error + "(点右上“刷新”重试)" }) : null,
|
|
3601
|
+
content ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("pre", { style: S.pre, children: content }) : content === null ? null : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { style: S.intro, children: "画像尚未生成;蒸馏若干记忆后 L3 会自动产出。" })
|
|
3311
3602
|
] });
|
|
3312
3603
|
}
|
|
3313
3604
|
|
|
3314
3605
|
// client/src/tabs/RecordsTab.tsx
|
|
3315
|
-
var
|
|
3316
|
-
var
|
|
3606
|
+
var import_react17 = require("react");
|
|
3607
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
3317
3608
|
function retiredSelOf(r) {
|
|
3318
3609
|
if (r === "active") return false;
|
|
3319
3610
|
if (r === "retired") return true;
|
|
@@ -3332,29 +3623,29 @@ var __defProp = Object.defineProperty;
|
|
|
3332
3623
|
function RecordsTab(props) {
|
|
3333
3624
|
const rpc = props.rpc;
|
|
3334
3625
|
const limit = 50;
|
|
3335
|
-
const [items, setItems] = (0,
|
|
3336
|
-
const [hasMore, setHasMore] = (0,
|
|
3337
|
-
const [total, setTotal] = (0,
|
|
3338
|
-
const [sceneOptions, setSceneOptions] = (0,
|
|
3339
|
-
const [loading, setLoading] = (0,
|
|
3340
|
-
const [truncated, setTruncated] = (0,
|
|
3341
|
-
const [error, setError] = (0,
|
|
3342
|
-
const [expandedId, setExpandedId] = (0,
|
|
3343
|
-
const [sel, setSel] = (0,
|
|
3344
|
-
const [hiPriv, setHiPriv] = (0,
|
|
3345
|
-
const [hiPrivBusy, setHiPrivBusy] = (0,
|
|
3346
|
-
const [query, setQuery] = (0,
|
|
3347
|
-
const [typeFilter, setTypeFilter] = (0,
|
|
3348
|
-
const [sceneFilter, setSceneFilter] = (0,
|
|
3349
|
-
const [hallFilter, setHallFilter] = (0,
|
|
3350
|
-
const [tagFilter, setTagFilter] = (0,
|
|
3351
|
-
const [untaggedOnly, setUntaggedOnly] = (0,
|
|
3352
|
-
const [orphanCount, setOrphanCount] = (0,
|
|
3353
|
-
const [retiredFilter, setRetiredFilter] = (0,
|
|
3354
|
-
const [wingCatalog, setHallCatalog] = (0,
|
|
3355
|
-
const [last, setLast] = (0,
|
|
3356
|
-
const seqRef = (0,
|
|
3357
|
-
const fetchPage = (0,
|
|
3626
|
+
const [items, setItems] = (0, import_react17.useState)([]);
|
|
3627
|
+
const [hasMore, setHasMore] = (0, import_react17.useState)(false);
|
|
3628
|
+
const [total, setTotal] = (0, import_react17.useState)(null);
|
|
3629
|
+
const [sceneOptions, setSceneOptions] = (0, import_react17.useState)([]);
|
|
3630
|
+
const [loading, setLoading] = (0, import_react17.useState)(false);
|
|
3631
|
+
const [truncated, setTruncated] = (0, import_react17.useState)(false);
|
|
3632
|
+
const [error, setError] = (0, import_react17.useState)(null);
|
|
3633
|
+
const [expandedId, setExpandedId] = (0, import_react17.useState)(null);
|
|
3634
|
+
const [sel, setSel] = (0, import_react17.useState)(/* @__PURE__ */ new Set());
|
|
3635
|
+
const [hiPriv, setHiPriv] = (0, import_react17.useState)(false);
|
|
3636
|
+
const [hiPrivBusy, setHiPrivBusy] = (0, import_react17.useState)(false);
|
|
3637
|
+
const [query, setQuery] = (0, import_react17.useState)("");
|
|
3638
|
+
const [typeFilter, setTypeFilter] = (0, import_react17.useState)("");
|
|
3639
|
+
const [sceneFilter, setSceneFilter] = (0, import_react17.useState)("");
|
|
3640
|
+
const [hallFilter, setHallFilter] = (0, import_react17.useState)([]);
|
|
3641
|
+
const [tagFilter, setTagFilter] = (0, import_react17.useState)("");
|
|
3642
|
+
const [untaggedOnly, setUntaggedOnly] = (0, import_react17.useState)(false);
|
|
3643
|
+
const [orphanCount, setOrphanCount] = (0, import_react17.useState)(0);
|
|
3644
|
+
const [retiredFilter, setRetiredFilter] = (0, import_react17.useState)("");
|
|
3645
|
+
const [wingCatalog, setHallCatalog] = (0, import_react17.useState)(null);
|
|
3646
|
+
const [last, setLast] = (0, import_react17.useState)({ query: "", type: "", scene: "", halls: [], tag: "", untagged: false, retired: "" });
|
|
3647
|
+
const seqRef = (0, import_react17.useRef)(0);
|
|
3648
|
+
const fetchPage = (0, import_react17.useCallback)(
|
|
3358
3649
|
(conds, offset, append) => {
|
|
3359
3650
|
setLoading(true);
|
|
3360
3651
|
setError(null);
|
|
@@ -3403,23 +3694,23 @@ var __defProp = Object.defineProperty;
|
|
|
3403
3694
|
setLast(conds);
|
|
3404
3695
|
fetchPage(conds, 0, false);
|
|
3405
3696
|
};
|
|
3406
|
-
const loadRooms = (0,
|
|
3697
|
+
const loadRooms = (0, import_react17.useCallback)(() => {
|
|
3407
3698
|
rpc("dsh-memory/rooms-get", {}).then((r) => {
|
|
3408
3699
|
if (r && r.ok) setOrphanCount(r.value.orphanCount ?? 0);
|
|
3409
3700
|
}).catch(() => {
|
|
3410
3701
|
});
|
|
3411
3702
|
}, [rpc]);
|
|
3412
|
-
(0,
|
|
3703
|
+
(0, import_react17.useEffect)(() => {
|
|
3413
3704
|
fetchPage({ query: "", type: "", scene: "", halls: [], tag: "", untagged: false, retired: "" }, 0, false);
|
|
3414
3705
|
loadRooms();
|
|
3415
3706
|
}, [fetchPage, loadRooms]);
|
|
3416
|
-
const loadHiPriv = (0,
|
|
3707
|
+
const loadHiPriv = (0, import_react17.useCallback)(() => {
|
|
3417
3708
|
rpc("dsh-memory/settings-get", {}).then((r) => {
|
|
3418
3709
|
if (r && r.ok && r.value) setHiPriv(!!r.value.settings.memoryMutate);
|
|
3419
3710
|
}).catch(() => {
|
|
3420
3711
|
});
|
|
3421
3712
|
}, [rpc]);
|
|
3422
|
-
(0,
|
|
3713
|
+
(0, import_react17.useEffect)(() => {
|
|
3423
3714
|
loadHiPriv();
|
|
3424
3715
|
}, [loadHiPriv]);
|
|
3425
3716
|
const toggleHiPriv = () => {
|
|
@@ -3480,11 +3771,11 @@ var __defProp = Object.defineProperty;
|
|
|
3480
3771
|
} else if (r) setError(r.error ? r.error.message : "退场失败");
|
|
3481
3772
|
}).catch((e) => setError(String(e && e.message || e)));
|
|
3482
3773
|
};
|
|
3483
|
-
const [retired, setRetired] = (0,
|
|
3484
|
-
const [retiredTotal, setRetiredTotal] = (0,
|
|
3485
|
-
const [showRetired, setShowRetired] = (0,
|
|
3486
|
-
const [retiredBusy, setRetiredBusy] = (0,
|
|
3487
|
-
const loadRetired = (0,
|
|
3774
|
+
const [retired, setRetired] = (0, import_react17.useState)([]);
|
|
3775
|
+
const [retiredTotal, setRetiredTotal] = (0, import_react17.useState)(0);
|
|
3776
|
+
const [showRetired, setShowRetired] = (0, import_react17.useState)(false);
|
|
3777
|
+
const [retiredBusy, setRetiredBusy] = (0, import_react17.useState)(false);
|
|
3778
|
+
const loadRetired = (0, import_react17.useCallback)(() => {
|
|
3488
3779
|
setRetiredBusy(true);
|
|
3489
3780
|
rpc("dsh-memory/records-retired", { limit: 100, offset: 0 }).then((r) => {
|
|
3490
3781
|
if (r && r.ok) {
|
|
@@ -3493,7 +3784,7 @@ var __defProp = Object.defineProperty;
|
|
|
3493
3784
|
} else if (r) setError(r.error ? r.error.message : "已退场列表加载失败");
|
|
3494
3785
|
}).catch((e) => setError(String(e && e.message || e))).finally(() => setRetiredBusy(false));
|
|
3495
3786
|
}, [rpc]);
|
|
3496
|
-
(0,
|
|
3787
|
+
(0, import_react17.useEffect)(() => {
|
|
3497
3788
|
if (showRetired) loadRetired();
|
|
3498
3789
|
}, [showRetired, loadRetired]);
|
|
3499
3790
|
const restoreRecords = (ids) => {
|
|
@@ -3513,11 +3804,11 @@ var __defProp = Object.defineProperty;
|
|
|
3513
3804
|
unknown: "已退场"
|
|
3514
3805
|
};
|
|
3515
3806
|
const countText = total !== null ? "共 " + total + " 条" : items.length + " 条" + (hasMore ? "+" : "");
|
|
3516
|
-
const [usageSummary, setUsageSummary] = (0,
|
|
3807
|
+
const [usageSummary, setUsageSummary] = (0, import_react17.useState)(null);
|
|
3517
3808
|
const selCount = sel.size;
|
|
3518
|
-
return /* @__PURE__ */ (0,
|
|
3519
|
-
/* @__PURE__ */ (0,
|
|
3520
|
-
/* @__PURE__ */ (0,
|
|
3809
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { children: [
|
|
3810
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: S.toolbar, children: [
|
|
3811
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3521
3812
|
NInput,
|
|
3522
3813
|
{
|
|
3523
3814
|
style: { flex: 1, minWidth: 160 },
|
|
@@ -3531,7 +3822,7 @@ var __defProp = Object.defineProperty;
|
|
|
3531
3822
|
}
|
|
3532
3823
|
}
|
|
3533
3824
|
),
|
|
3534
|
-
/* @__PURE__ */ (0,
|
|
3825
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3535
3826
|
NSel,
|
|
3536
3827
|
{
|
|
3537
3828
|
style: { maxWidth: 200 },
|
|
@@ -3544,7 +3835,7 @@ var __defProp = Object.defineProperty;
|
|
|
3544
3835
|
onChange: setTypeFilter
|
|
3545
3836
|
}
|
|
3546
3837
|
),
|
|
3547
|
-
/* @__PURE__ */ (0,
|
|
3838
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3548
3839
|
NSel,
|
|
3549
3840
|
{
|
|
3550
3841
|
style: { maxWidth: 220 },
|
|
@@ -3557,7 +3848,7 @@ var __defProp = Object.defineProperty;
|
|
|
3557
3848
|
onChange: setSceneFilter
|
|
3558
3849
|
}
|
|
3559
3850
|
),
|
|
3560
|
-
/* @__PURE__ */ (0,
|
|
3851
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3561
3852
|
WingMultiSelect,
|
|
3562
3853
|
{
|
|
3563
3854
|
options: wingCatalog ?? Array.from(new Set(items.map((m) => m.hall).filter((h) => !!h))).map((id) => ({ id, label: id })),
|
|
@@ -3565,8 +3856,8 @@ var __defProp = Object.defineProperty;
|
|
|
3565
3856
|
onChange: setHallFilter
|
|
3566
3857
|
}
|
|
3567
3858
|
),
|
|
3568
|
-
/* @__PURE__ */ (0,
|
|
3569
|
-
/* @__PURE__ */ (0,
|
|
3859
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(NButton, { onClick: search, children: "搜索" }),
|
|
3860
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3570
3861
|
NButton,
|
|
3571
3862
|
{
|
|
3572
3863
|
style: {
|
|
@@ -3580,8 +3871,8 @@ var __defProp = Object.defineProperty;
|
|
|
3580
3871
|
}
|
|
3581
3872
|
)
|
|
3582
3873
|
] }),
|
|
3583
|
-
/* @__PURE__ */ (0,
|
|
3584
|
-
/* @__PURE__ */ (0,
|
|
3874
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: { marginBottom: 10, display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }, children: [
|
|
3875
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3585
3876
|
"button",
|
|
3586
3877
|
{
|
|
3587
3878
|
type: "button",
|
|
@@ -3606,10 +3897,10 @@ var __defProp = Object.defineProperty;
|
|
|
3606
3897
|
children: "无绑定 · " + orphanCount
|
|
3607
3898
|
}
|
|
3608
3899
|
),
|
|
3609
|
-
(tagFilter || untaggedOnly) && /* @__PURE__ */ (0,
|
|
3900
|
+
(tagFilter || untaggedOnly) && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { style: S.muted, children: [
|
|
3610
3901
|
"筛选中:",
|
|
3611
3902
|
untaggedOnly ? "无绑定" : tagFilter,
|
|
3612
|
-
/* @__PURE__ */ (0,
|
|
3903
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3613
3904
|
"button",
|
|
3614
3905
|
{
|
|
3615
3906
|
type: "button",
|
|
@@ -3626,7 +3917,7 @@ var __defProp = Object.defineProperty;
|
|
|
3626
3917
|
}
|
|
3627
3918
|
)
|
|
3628
3919
|
] }),
|
|
3629
|
-
/* @__PURE__ */ (0,
|
|
3920
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3630
3921
|
"button",
|
|
3631
3922
|
{
|
|
3632
3923
|
type: "button",
|
|
@@ -3655,15 +3946,15 @@ var __defProp = Object.defineProperty;
|
|
|
3655
3946
|
children: "导出孤儿"
|
|
3656
3947
|
}
|
|
3657
3948
|
),
|
|
3658
|
-
/* @__PURE__ */ (0,
|
|
3949
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: S.muted, children: "Room 标签/分类管理:见「Hall」「Room」标签页。" })
|
|
3659
3950
|
] }),
|
|
3660
|
-
/* @__PURE__ */ (0,
|
|
3661
|
-
/* @__PURE__ */ (0,
|
|
3662
|
-
usageSummary ? /* @__PURE__ */ (0,
|
|
3663
|
-
/* @__PURE__ */ (0,
|
|
3951
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: { ...S.flexRow, marginBottom: 10 }, children: [
|
|
3952
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: S.muted, children: loading ? "加载中…" : countText }),
|
|
3953
|
+
usageSummary ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: S.muted, title: "老化权重效果口径:参与召回尝试的记忆中,进 topN(被注入上下文)的比例", children: "召回使用 " + usageSummary.used + "/" + usageSummary.attempted + "(" + usageSummary.rate + "%)" }) : null,
|
|
3954
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: S.muted, children: "退场筛查" }),
|
|
3664
3955
|
[["", "全部"], ["active", "仅活跃"], ["retired", "仅退场"]].map(([val, label]) => {
|
|
3665
3956
|
const on = retiredFilter === val;
|
|
3666
|
-
return /* @__PURE__ */ (0,
|
|
3957
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3667
3958
|
"button",
|
|
3668
3959
|
{
|
|
3669
3960
|
type: "button",
|
|
@@ -3683,7 +3974,7 @@ var __defProp = Object.defineProperty;
|
|
|
3683
3974
|
val
|
|
3684
3975
|
);
|
|
3685
3976
|
}),
|
|
3686
|
-
/* @__PURE__ */ (0,
|
|
3977
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3687
3978
|
NButton,
|
|
3688
3979
|
{
|
|
3689
3980
|
style: selCount > 0 ? { color: "var(--dsh-mem-danger)" } : void 0,
|
|
@@ -3693,7 +3984,7 @@ var __defProp = Object.defineProperty;
|
|
|
3693
3984
|
children: "删除选中" + (selCount > 0 ? "(" + selCount + ")" : "")
|
|
3694
3985
|
}
|
|
3695
3986
|
),
|
|
3696
|
-
selCount > 0 ? /* @__PURE__ */ (0,
|
|
3987
|
+
selCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3697
3988
|
NButton,
|
|
3698
3989
|
{
|
|
3699
3990
|
onClick: () => {
|
|
@@ -3702,8 +3993,8 @@ var __defProp = Object.defineProperty;
|
|
|
3702
3993
|
children: "清空选择"
|
|
3703
3994
|
}
|
|
3704
3995
|
) : null,
|
|
3705
|
-
/* @__PURE__ */ (0,
|
|
3706
|
-
/* @__PURE__ */ (0,
|
|
3996
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: S.grow }),
|
|
3997
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3707
3998
|
NButton,
|
|
3708
3999
|
{
|
|
3709
4000
|
onClick: () => {
|
|
@@ -3714,13 +4005,13 @@ var __defProp = Object.defineProperty;
|
|
|
3714
4005
|
}
|
|
3715
4006
|
)
|
|
3716
4007
|
] }),
|
|
3717
|
-
!hiPriv ? /* @__PURE__ */ (0,
|
|
3718
|
-
error ? /* @__PURE__ */ (0,
|
|
3719
|
-
truncated ? /* @__PURE__ */ (0,
|
|
3720
|
-
items.length === 0 && !loading && !error ? /* @__PURE__ */ (0,
|
|
4008
|
+
!hiPriv ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: S.hint, children: "提示:删除记忆需先开启高权限模式(右上开关或概览页「高权限模式」),关闭时删除按钮不可用。" }) : null,
|
|
4009
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: S.error, children: error }) : null,
|
|
4010
|
+
truncated ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: S.hint, children: "搜索分页已达检索上限(200 条),更早的结果未显示。请用更精确的关键词或类型/情境过滤。" }) : null,
|
|
4011
|
+
items.length === 0 && !loading && !error ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { style: S.intro, children: "暂无记忆。对话几轮后,蒸馏管线会自动抽取记忆。" }) : items.map((m) => {
|
|
3721
4012
|
const open = expandedId === m.id;
|
|
3722
4013
|
const checked = sel.has(m.id);
|
|
3723
|
-
return /* @__PURE__ */ (0,
|
|
4014
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
3724
4015
|
"div",
|
|
3725
4016
|
{
|
|
3726
4017
|
className: "dsh-mem-card dsh-mem-card-hover",
|
|
@@ -3729,8 +4020,8 @@ var __defProp = Object.defineProperty;
|
|
|
3729
4020
|
setExpandedId(open ? null : m.id);
|
|
3730
4021
|
},
|
|
3731
4022
|
children: [
|
|
3732
|
-
/* @__PURE__ */ (0,
|
|
3733
|
-
/* @__PURE__ */ (0,
|
|
4023
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: S.cardHead, children: [
|
|
4024
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3734
4025
|
"input",
|
|
3735
4026
|
{
|
|
3736
4027
|
type: "checkbox",
|
|
@@ -3745,9 +4036,9 @@ var __defProp = Object.defineProperty;
|
|
|
3745
4036
|
}
|
|
3746
4037
|
}
|
|
3747
4038
|
),
|
|
3748
|
-
/* @__PURE__ */ (0,
|
|
3749
|
-
m.hall ? /* @__PURE__ */ (0,
|
|
3750
|
-
m.retired ? /* @__PURE__ */ (0,
|
|
4039
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "dsh-mem-tag dsh-mem-tag-" + m.type, children: TYPE_LABELS[m.type] || m.type }),
|
|
4040
|
+
m.hall ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "dsh-mem-tag dsh-mem-tag-work-fact", children: "Wing · " + (wingCatalog?.find((h) => h.id === m.hall)?.label || m.hall) }) : null,
|
|
4041
|
+
m.retired ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3751
4042
|
"span",
|
|
3752
4043
|
{
|
|
3753
4044
|
title: "该记忆已退场(软删):移出检索面但仍可恢复,并未真正删除",
|
|
@@ -3762,8 +4053,23 @@ var __defProp = Object.defineProperty;
|
|
|
3762
4053
|
children: "已退场" + (m.retiredReason ? " · " + (RETIRE_REASON_LABEL[m.retiredReason] || m.retiredReason) : "")
|
|
3763
4054
|
}
|
|
3764
4055
|
) : null,
|
|
3765
|
-
/* @__PURE__ */ (0,
|
|
3766
|
-
m.
|
|
4056
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: S.muted, children: "优先级 " + m.priority }),
|
|
4057
|
+
m.maturity ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
4058
|
+
"span",
|
|
4059
|
+
{
|
|
4060
|
+
title: "成熟度(优先级 + 被用次数 + 新鲜度合成):" + m.maturity,
|
|
4061
|
+
style: {
|
|
4062
|
+
fontSize: 11,
|
|
4063
|
+
padding: "1px 6px",
|
|
4064
|
+
borderRadius: 999,
|
|
4065
|
+
whiteSpace: "nowrap",
|
|
4066
|
+
border: "1px solid var(--dsh-mem-border)",
|
|
4067
|
+
color: "var(--dsh-mem-text-2)"
|
|
4068
|
+
},
|
|
4069
|
+
children: m.maturity === "high" ? "成熟·高" : m.maturity === "mid" ? "成熟·中" : "成熟·低"
|
|
4070
|
+
}
|
|
4071
|
+
) : null,
|
|
4072
|
+
m.agingWeight != null ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3767
4073
|
"span",
|
|
3768
4074
|
{
|
|
3769
4075
|
style: {
|
|
@@ -3778,7 +4084,7 @@ var __defProp = Object.defineProperty;
|
|
|
3778
4084
|
children: "老化 " + Math.round(m.agingWeight * 100) + "%"
|
|
3779
4085
|
}
|
|
3780
4086
|
) : null,
|
|
3781
|
-
m.usage ? /* @__PURE__ */ (0,
|
|
4087
|
+
m.usage ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3782
4088
|
"span",
|
|
3783
4089
|
{
|
|
3784
4090
|
style: S.muted,
|
|
@@ -3786,10 +4092,10 @@ var __defProp = Object.defineProperty;
|
|
|
3786
4092
|
children: "用 " + m.usage.used + "/" + m.usage.attempts
|
|
3787
4093
|
}
|
|
3788
4094
|
) : null,
|
|
3789
|
-
m.score !== null && m.score !== void 0 ? /* @__PURE__ */ (0,
|
|
3790
|
-
/* @__PURE__ */ (0,
|
|
3791
|
-
/* @__PURE__ */ (0,
|
|
3792
|
-
m.retired ? /* @__PURE__ */ (0,
|
|
4095
|
+
m.score !== null && m.score !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: S.muted, children: "相关度 " + Number(m.score).toFixed(2) }) : null,
|
|
4096
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: S.grow }),
|
|
4097
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: S.muted, children: fmtTime(m.updatedAt) }),
|
|
4098
|
+
m.retired ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3793
4099
|
NButton,
|
|
3794
4100
|
{
|
|
3795
4101
|
style: { padding: "0 7px", minWidth: 26, height: 26, fontSize: 12, color: "var(--dsh-mem-accent)" },
|
|
@@ -3800,7 +4106,7 @@ var __defProp = Object.defineProperty;
|
|
|
3800
4106
|
},
|
|
3801
4107
|
children: "恢复"
|
|
3802
4108
|
}
|
|
3803
|
-
) : hiPriv ? /* @__PURE__ */ (0,
|
|
4109
|
+
) : hiPriv ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3804
4110
|
NButton,
|
|
3805
4111
|
{
|
|
3806
4112
|
style: { padding: "0 7px", minWidth: 26, height: 26, fontSize: 12, color: "var(--dsh-mem-danger)" },
|
|
@@ -3813,34 +4119,34 @@ var __defProp = Object.defineProperty;
|
|
|
3813
4119
|
}
|
|
3814
4120
|
) : null
|
|
3815
4121
|
] }),
|
|
3816
|
-
/* @__PURE__ */ (0,
|
|
3817
|
-
open ? /* @__PURE__ */ (0,
|
|
4122
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: S.content, children: m.content }),
|
|
4123
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: S.detail, children: "id: " + m.id + "\n情境: " + (m.scene || "-") + "\n版本: v" + m.version + "(去重合并次数 " + m.version + ")\n创建: " + fmtTime(m.createdAt) + "\n活跃时间: " + (m.timestamps && m.timestamps.length > 0 ? m.timestamps.map(fmtTime).join(" → ") : "-") + "\n" + (m.sourceAnchors && m.sourceAnchors.length > 0 ? "来源锚点: " + m.sourceAnchors.join(", ") : "来源锚点: -") }) : null
|
|
3818
4124
|
]
|
|
3819
4125
|
},
|
|
3820
4126
|
m.id
|
|
3821
4127
|
);
|
|
3822
4128
|
}),
|
|
3823
|
-
/* @__PURE__ */ (0,
|
|
3824
|
-
/* @__PURE__ */ (0,
|
|
3825
|
-
showRetired && retiredBusy ? /* @__PURE__ */ (0,
|
|
3826
|
-
showRetired && !retiredBusy && retiredTotal > 0 ? /* @__PURE__ */ (0,
|
|
4129
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: { ...S.flexRow, marginTop: 12 }, children: [
|
|
4130
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(NButton, { onClick: () => setShowRetired((v) => !v), children: (showRetired ? "收起" : "展开") + "「已退场」(可恢复)" }),
|
|
4131
|
+
showRetired && retiredBusy ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: S.muted, children: "加载中…" }) : null,
|
|
4132
|
+
showRetired && !retiredBusy && retiredTotal > 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: S.muted, children: "共 " + retiredTotal + " 条可恢复" }) : null
|
|
3827
4133
|
] }),
|
|
3828
|
-
showRetired ? /* @__PURE__ */ (0,
|
|
3829
|
-
retired.map((m) => /* @__PURE__ */ (0,
|
|
3830
|
-
/* @__PURE__ */ (0,
|
|
3831
|
-
/* @__PURE__ */ (0,
|
|
3832
|
-
m.verdict ? /* @__PURE__ */ (0,
|
|
3833
|
-
/* @__PURE__ */ (0,
|
|
3834
|
-
/* @__PURE__ */ (0,
|
|
3835
|
-
/* @__PURE__ */ (0,
|
|
4134
|
+
showRetired ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: { marginTop: 8 }, children: retired.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { style: S.hint, children: retiredBusy ? " " : "没有已退场的记忆。" }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { children: [
|
|
4135
|
+
retired.map((m) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "dsh-mem-card", style: S.card, children: [
|
|
4136
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: S.cardHead, children: [
|
|
4137
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: S.muted, children: RETIRE_REASON_LABEL[m.retiredReason] || m.retiredReason }),
|
|
4138
|
+
m.verdict ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: S.muted, children: "结论 " + m.verdict }) : null,
|
|
4139
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: S.grow }),
|
|
4140
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: S.muted, children: fmtTime(m.retiredAt) }),
|
|
4141
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(NButton, { disabled: retiredBusy, title: "恢复到检索面", onClick: () => restoreRecords([m.id]), children: "恢复" })
|
|
3836
4142
|
] }),
|
|
3837
|
-
/* @__PURE__ */ (0,
|
|
4143
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: S.content, children: m.content })
|
|
3838
4144
|
] }, m.id)),
|
|
3839
|
-
retiredTotal > retired.length ? /* @__PURE__ */ (0,
|
|
4145
|
+
retiredTotal > retired.length ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { style: S.hint, children: "共 " + retiredTotal + " 条,此处显示 " + retired.length + " 条" }) : null
|
|
3840
4146
|
] }) }) : null,
|
|
3841
|
-
hasMore ? /* @__PURE__ */ (0,
|
|
3842
|
-
/* @__PURE__ */ (0,
|
|
3843
|
-
/* @__PURE__ */ (0,
|
|
4147
|
+
hasMore ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: S.flexRow, children: [
|
|
4148
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: S.grow }),
|
|
4149
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3844
4150
|
NButton,
|
|
3845
4151
|
{
|
|
3846
4152
|
disabled: loading,
|
|
@@ -3854,9 +4160,9 @@ var __defProp = Object.defineProperty;
|
|
|
3854
4160
|
] });
|
|
3855
4161
|
}
|
|
3856
4162
|
function WingMultiSelect(props) {
|
|
3857
|
-
const [open, setOpen] = (0,
|
|
3858
|
-
const wrapRef = (0,
|
|
3859
|
-
(0,
|
|
4163
|
+
const [open, setOpen] = (0, import_react17.useState)(false);
|
|
4164
|
+
const wrapRef = (0, import_react17.useRef)(null);
|
|
4165
|
+
(0, import_react17.useEffect)(() => {
|
|
3860
4166
|
if (!open) return;
|
|
3861
4167
|
const onDown = (e) => {
|
|
3862
4168
|
if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
|
|
@@ -3876,8 +4182,8 @@ var __defProp = Object.defineProperty;
|
|
|
3876
4182
|
const toggle = (id) => {
|
|
3877
4183
|
props.onChange(props.selected.includes(id) ? props.selected.filter((x) => x !== id) : [...props.selected, id]);
|
|
3878
4184
|
};
|
|
3879
|
-
return /* @__PURE__ */ (0,
|
|
3880
|
-
/* @__PURE__ */ (0,
|
|
4185
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { ref: wrapRef, style: { position: "relative", maxWidth: 150 }, children: [
|
|
4186
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
3881
4187
|
"button",
|
|
3882
4188
|
{
|
|
3883
4189
|
type: "button",
|
|
@@ -3886,31 +4192,31 @@ var __defProp = Object.defineProperty;
|
|
|
3886
4192
|
"aria-expanded": open,
|
|
3887
4193
|
onClick: () => setOpen(!open),
|
|
3888
4194
|
children: [
|
|
3889
|
-
/* @__PURE__ */ (0,
|
|
3890
|
-
/* @__PURE__ */ (0,
|
|
4195
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "dsh-mem-select-label", title: summary, children: summary }),
|
|
4196
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "dsh-mem-sel-chev" + (open ? " dsh-mem-sel-chev-open" : "") })
|
|
3891
4197
|
]
|
|
3892
4198
|
}
|
|
3893
4199
|
),
|
|
3894
|
-
open ? /* @__PURE__ */ (0,
|
|
3895
|
-
props.options.length === 0 ? /* @__PURE__ */ (0,
|
|
4200
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "dsh-mem-pop", role: "listbox", style: { left: 0, right: "auto", minWidth: 150 }, children: [
|
|
4201
|
+
props.options.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "dsh-mem-pop-empty", children: "暂无可筛 Hall" }) : null,
|
|
3896
4202
|
props.options.map((o) => {
|
|
3897
4203
|
const active = props.selected.includes(o.id);
|
|
3898
|
-
return /* @__PURE__ */ (0,
|
|
3899
|
-
/* @__PURE__ */ (0,
|
|
3900
|
-
/* @__PURE__ */ (0,
|
|
4204
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("button", { type: "button", className: "dsh-mem-pop-opt", onClick: () => toggle(o.id), "aria-selected": active, children: [
|
|
4205
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "dsh-mem-pop-check", children: active ? "✓" : "" }),
|
|
4206
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "dsh-mem-pop-label", children: o.label })
|
|
3901
4207
|
] }, o.id);
|
|
3902
4208
|
}),
|
|
3903
|
-
props.selected.length > 0 ? /* @__PURE__ */ (0,
|
|
3904
|
-
/* @__PURE__ */ (0,
|
|
3905
|
-
/* @__PURE__ */ (0,
|
|
4209
|
+
props.selected.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("button", { type: "button", className: "dsh-mem-pop-opt", onClick: () => props.onChange([]), children: [
|
|
4210
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "dsh-mem-pop-check" }),
|
|
4211
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "dsh-mem-pop-label", children: "清除筛选" })
|
|
3906
4212
|
] }) : null
|
|
3907
4213
|
] }) : null
|
|
3908
4214
|
] });
|
|
3909
4215
|
}
|
|
3910
4216
|
|
|
3911
4217
|
// client/src/tabs/RoomsTab.tsx
|
|
3912
|
-
var
|
|
3913
|
-
var
|
|
4218
|
+
var import_react18 = require("react");
|
|
4219
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
3914
4220
|
function majorOf(slug) {
|
|
3915
4221
|
const i = slug.indexOf("/");
|
|
3916
4222
|
return i === -1 ? slug : slug.slice(0, i);
|
|
@@ -3939,26 +4245,26 @@ var __defProp = Object.defineProperty;
|
|
|
3939
4245
|
};
|
|
3940
4246
|
function RoomsTab(props) {
|
|
3941
4247
|
const rpc = props.rpc;
|
|
3942
|
-
const [registry, setRegistry] = (0,
|
|
3943
|
-
const [rooms, setRooms] = (0,
|
|
3944
|
-
const [orphanCount, setOrphanCount] = (0,
|
|
3945
|
-
const [busy, setBusy] = (0,
|
|
3946
|
-
const [msg, setMsg] = (0,
|
|
3947
|
-
const [error, setError] = (0,
|
|
3948
|
-
const [hiPriv, setHiPriv] = (0,
|
|
3949
|
-
const [hiPrivBusy, setHiPrivBusy] = (0,
|
|
3950
|
-
const [regSlug, setRegSlug] = (0,
|
|
3951
|
-
const [regLabel, setRegLabel] = (0,
|
|
3952
|
-
const [regDesc, setRegDesc] = (0,
|
|
3953
|
-
const [form, setForm] = (0,
|
|
3954
|
-
const [preview, setPreview] = (0,
|
|
3955
|
-
const [grownOpen, setGrownOpen] = (0,
|
|
3956
|
-
const [dragOverHall, setDragOverHall] = (0,
|
|
3957
|
-
const [picking, setPicking] = (0,
|
|
3958
|
-
const [editing, setEditing] = (0,
|
|
3959
|
-
const [expandedRooms, setExpandedRooms] = (0,
|
|
3960
|
-
const [roomRecords, setRoomRecords] = (0,
|
|
3961
|
-
const [expandedHalls, setExpandedHalls] = (0,
|
|
4248
|
+
const [registry, setRegistry] = (0, import_react18.useState)([]);
|
|
4249
|
+
const [rooms, setRooms] = (0, import_react18.useState)([]);
|
|
4250
|
+
const [orphanCount, setOrphanCount] = (0, import_react18.useState)(0);
|
|
4251
|
+
const [busy, setBusy] = (0, import_react18.useState)(false);
|
|
4252
|
+
const [msg, setMsg] = (0, import_react18.useState)(null);
|
|
4253
|
+
const [error, setError] = (0, import_react18.useState)(null);
|
|
4254
|
+
const [hiPriv, setHiPriv] = (0, import_react18.useState)(false);
|
|
4255
|
+
const [hiPrivBusy, setHiPrivBusy] = (0, import_react18.useState)(false);
|
|
4256
|
+
const [regSlug, setRegSlug] = (0, import_react18.useState)("");
|
|
4257
|
+
const [regLabel, setRegLabel] = (0, import_react18.useState)("");
|
|
4258
|
+
const [regDesc, setRegDesc] = (0, import_react18.useState)("");
|
|
4259
|
+
const [form, setForm] = (0, import_react18.useState)(null);
|
|
4260
|
+
const [preview, setPreview] = (0, import_react18.useState)(null);
|
|
4261
|
+
const [grownOpen, setGrownOpen] = (0, import_react18.useState)(false);
|
|
4262
|
+
const [dragOverHall, setDragOverHall] = (0, import_react18.useState)(null);
|
|
4263
|
+
const [picking, setPicking] = (0, import_react18.useState)(null);
|
|
4264
|
+
const [editing, setEditing] = (0, import_react18.useState)(null);
|
|
4265
|
+
const [expandedRooms, setExpandedRooms] = (0, import_react18.useState)(/* @__PURE__ */ new Set());
|
|
4266
|
+
const [roomRecords, setRoomRecords] = (0, import_react18.useState)({});
|
|
4267
|
+
const [expandedHalls, setExpandedHalls] = (0, import_react18.useState)(() => {
|
|
3962
4268
|
try {
|
|
3963
4269
|
const v = window.localStorage.getItem("dsh.memory.halls.open");
|
|
3964
4270
|
return v ? new Set(JSON.parse(v)) : /* @__PURE__ */ new Set();
|
|
@@ -3966,9 +4272,9 @@ var __defProp = Object.defineProperty;
|
|
|
3966
4272
|
return /* @__PURE__ */ new Set();
|
|
3967
4273
|
}
|
|
3968
4274
|
});
|
|
3969
|
-
const [filter, setFilter] = (0,
|
|
3970
|
-
const dragRef = (0,
|
|
3971
|
-
const [ghost, setGhost] = (0,
|
|
4275
|
+
const [filter, setFilter] = (0, import_react18.useState)("");
|
|
4276
|
+
const dragRef = (0, import_react18.useRef)(null);
|
|
4277
|
+
const [ghost, setGhost] = (0, import_react18.useState)(null);
|
|
3972
4278
|
const onDragLabelDown = (ev, slug) => {
|
|
3973
4279
|
if (!hiPriv || busy || ev.button !== 0) return;
|
|
3974
4280
|
ev.currentTarget.setPointerCapture(ev.pointerId);
|
|
@@ -3993,7 +4299,7 @@ var __defProp = Object.defineProperty;
|
|
|
3993
4299
|
setDragOverHall(null);
|
|
3994
4300
|
if (hall) beginReclass(d.from, hall);
|
|
3995
4301
|
};
|
|
3996
|
-
const loadAll = (0,
|
|
4302
|
+
const loadAll = (0, import_react18.useCallback)(() => {
|
|
3997
4303
|
rpc("dsh-memory/rooms-get", {}).then((r) => {
|
|
3998
4304
|
if (r && r.ok) {
|
|
3999
4305
|
setRooms(r.value.rooms ?? []);
|
|
@@ -4002,13 +4308,13 @@ var __defProp = Object.defineProperty;
|
|
|
4002
4308
|
}
|
|
4003
4309
|
}).catch(() => void 0);
|
|
4004
4310
|
}, [rpc]);
|
|
4005
|
-
const loadHiPriv = (0,
|
|
4311
|
+
const loadHiPriv = (0, import_react18.useCallback)(() => {
|
|
4006
4312
|
rpc("dsh-memory/settings-get", {}).then((r) => {
|
|
4007
4313
|
if (r && r.ok && r.value) setHiPriv(!!r.value.settings.memoryMutate);
|
|
4008
4314
|
}).catch(() => {
|
|
4009
4315
|
});
|
|
4010
4316
|
}, [rpc]);
|
|
4011
|
-
(0,
|
|
4317
|
+
(0, import_react18.useEffect)(() => {
|
|
4012
4318
|
loadAll();
|
|
4013
4319
|
loadHiPriv();
|
|
4014
4320
|
}, [loadAll, loadHiPriv]);
|
|
@@ -4159,7 +4465,7 @@ var __defProp = Object.defineProperty;
|
|
|
4159
4465
|
if (r.value.csv) downloadCsv(r.value.csv, `dsh-memory-room-${slug.replace(/\//g, "-")}-records.csv`);
|
|
4160
4466
|
else setError("导出为空");
|
|
4161
4467
|
});
|
|
4162
|
-
const groups = (0,
|
|
4468
|
+
const groups = (0, import_react18.useMemo)(() => {
|
|
4163
4469
|
const countOf = new Map(rooms.map((r) => [r.room, r.count]));
|
|
4164
4470
|
const byHall = /* @__PURE__ */ new Map();
|
|
4165
4471
|
for (const e of registry) {
|
|
@@ -4176,7 +4482,7 @@ var __defProp = Object.defineProperty;
|
|
|
4176
4482
|
total: entries.reduce((s2, e) => s2 + (countOf.get(e.slug) ?? 0), 0)
|
|
4177
4483
|
})).sort((a, b) => a.hall.localeCompare(b.hall));
|
|
4178
4484
|
}, [registry, rooms]);
|
|
4179
|
-
const grownOnly = (0,
|
|
4485
|
+
const grownOnly = (0, import_react18.useMemo)(() => rooms.filter((r) => !registry.some((e) => e.slug === r.room)), [rooms, registry]);
|
|
4180
4486
|
const persistHalls = (next) => {
|
|
4181
4487
|
try {
|
|
4182
4488
|
window.localStorage.setItem("dsh.memory.halls.open", JSON.stringify([...next]));
|
|
@@ -4196,7 +4502,7 @@ var __defProp = Object.defineProperty;
|
|
|
4196
4502
|
persistHalls(next);
|
|
4197
4503
|
};
|
|
4198
4504
|
const normFilter = filter.trim().toLowerCase();
|
|
4199
|
-
const visibleGroups = (0,
|
|
4505
|
+
const visibleGroups = (0, import_react18.useMemo)(() => {
|
|
4200
4506
|
if (!normFilter) return groups;
|
|
4201
4507
|
return groups.map((g) => {
|
|
4202
4508
|
const hallHit = g.hall.toLowerCase().includes(normFilter) || (g.label ?? "").toLowerCase().includes(normFilter);
|
|
@@ -4206,15 +4512,15 @@ var __defProp = Object.defineProperty;
|
|
|
4206
4512
|
return { ...g, entries };
|
|
4207
4513
|
}).filter((g) => g.entries.length > 0);
|
|
4208
4514
|
}, [groups, normFilter]);
|
|
4209
|
-
const visibleGrown = (0,
|
|
4515
|
+
const visibleGrown = (0, import_react18.useMemo)(
|
|
4210
4516
|
() => normFilter ? grownOnly.filter((r) => r.room.toLowerCase().includes(normFilter)) : grownOnly,
|
|
4211
4517
|
[grownOnly, normFilter]
|
|
4212
4518
|
);
|
|
4213
|
-
return /* @__PURE__ */ (0,
|
|
4214
|
-
/* @__PURE__ */ (0,
|
|
4215
|
-
/* @__PURE__ */ (0,
|
|
4216
|
-
/* @__PURE__ */ (0,
|
|
4217
|
-
/* @__PURE__ */ (0,
|
|
4519
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { children: [
|
|
4520
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { ...S.flexRow, marginBottom: 8 }, children: [
|
|
4521
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: S.muted, children: "Hall = Room 大类 · 大类上限 200,小类「大类/小类」细分不占额度 · 与 Wing(域)筛选无关" }),
|
|
4522
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: S.grow }),
|
|
4523
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4218
4524
|
"button",
|
|
4219
4525
|
{
|
|
4220
4526
|
type: "button",
|
|
@@ -4231,7 +4537,7 @@ var __defProp = Object.defineProperty;
|
|
|
4231
4537
|
children: "导出词表"
|
|
4232
4538
|
}
|
|
4233
4539
|
),
|
|
4234
|
-
/* @__PURE__ */ (0,
|
|
4540
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
4235
4541
|
"button",
|
|
4236
4542
|
{
|
|
4237
4543
|
type: "button",
|
|
@@ -4251,7 +4557,7 @@ var __defProp = Object.defineProperty;
|
|
|
4251
4557
|
]
|
|
4252
4558
|
}
|
|
4253
4559
|
),
|
|
4254
|
-
/* @__PURE__ */ (0,
|
|
4560
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4255
4561
|
"button",
|
|
4256
4562
|
{
|
|
4257
4563
|
type: "button",
|
|
@@ -4266,10 +4572,10 @@ var __defProp = Object.defineProperty;
|
|
|
4266
4572
|
children: hiPriv ? "高权限:开" : "高权限:关"
|
|
4267
4573
|
}
|
|
4268
4574
|
),
|
|
4269
|
-
/* @__PURE__ */ (0,
|
|
4575
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", style: btn, onClick: loadAll, title: "重拉注册表与计数", children: "刷新" })
|
|
4270
4576
|
] }),
|
|
4271
|
-
/* @__PURE__ */ (0,
|
|
4272
|
-
/* @__PURE__ */ (0,
|
|
4577
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", gap: 6, alignItems: "center", marginBottom: 8, flexWrap: "wrap" }, children: [
|
|
4578
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4273
4579
|
"input",
|
|
4274
4580
|
{
|
|
4275
4581
|
value: filter,
|
|
@@ -4278,14 +4584,14 @@ var __defProp = Object.defineProperty;
|
|
|
4278
4584
|
style: { ...S.input, width: 250, fontSize: 12 }
|
|
4279
4585
|
}
|
|
4280
4586
|
),
|
|
4281
|
-
filter ? /* @__PURE__ */ (0,
|
|
4282
|
-
/* @__PURE__ */ (0,
|
|
4283
|
-
/* @__PURE__ */ (0,
|
|
4284
|
-
/* @__PURE__ */ (0,
|
|
4285
|
-
/* @__PURE__ */ (0,
|
|
4587
|
+
filter ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", style: btn, onClick: () => setFilter(""), children: "清除" }) : null,
|
|
4588
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: S.muted, children: `匹配 ${visibleGroups.reduce((s2, g) => s2 + g.entries.length, 0)} room / ${visibleGroups.length} hall` }),
|
|
4589
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: S.grow }),
|
|
4590
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", style: btn, title: "展开全部 hall 的子 room", onClick: () => setAllHalls(true), children: "展开全部" }),
|
|
4591
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", style: btn, title: "收起全部 hall(只留 hall 头)", onClick: () => setAllHalls(false), children: "收起全部" })
|
|
4286
4592
|
] }),
|
|
4287
|
-
/* @__PURE__ */ (0,
|
|
4288
|
-
/* @__PURE__ */ (0,
|
|
4593
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", gap: 6, alignItems: "center", marginBottom: 10 }, children: [
|
|
4594
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4289
4595
|
"input",
|
|
4290
4596
|
{
|
|
4291
4597
|
value: regSlug,
|
|
@@ -4295,7 +4601,7 @@ var __defProp = Object.defineProperty;
|
|
|
4295
4601
|
style: { ...S.input, width: 210, fontSize: 12 }
|
|
4296
4602
|
}
|
|
4297
4603
|
),
|
|
4298
|
-
/* @__PURE__ */ (0,
|
|
4604
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4299
4605
|
"input",
|
|
4300
4606
|
{
|
|
4301
4607
|
value: regLabel,
|
|
@@ -4305,7 +4611,7 @@ var __defProp = Object.defineProperty;
|
|
|
4305
4611
|
style: { ...S.input, width: 110, fontSize: 12 }
|
|
4306
4612
|
}
|
|
4307
4613
|
),
|
|
4308
|
-
/* @__PURE__ */ (0,
|
|
4614
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4309
4615
|
"input",
|
|
4310
4616
|
{
|
|
4311
4617
|
value: regDesc,
|
|
@@ -4315,7 +4621,7 @@ var __defProp = Object.defineProperty;
|
|
|
4315
4621
|
style: { ...S.input, width: 170, fontSize: 12 }
|
|
4316
4622
|
}
|
|
4317
4623
|
),
|
|
4318
|
-
/* @__PURE__ */ (0,
|
|
4624
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4319
4625
|
"button",
|
|
4320
4626
|
{
|
|
4321
4627
|
type: "button",
|
|
@@ -4325,26 +4631,26 @@ var __defProp = Object.defineProperty;
|
|
|
4325
4631
|
children: "注册"
|
|
4326
4632
|
}
|
|
4327
4633
|
),
|
|
4328
|
-
!hiPriv && /* @__PURE__ */ (0,
|
|
4634
|
+
!hiPriv && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: S.muted, children: "管理操作需先开启高权限模式" })
|
|
4329
4635
|
] }),
|
|
4330
|
-
editing ? /* @__PURE__ */ (0,
|
|
4331
|
-
/* @__PURE__ */ (0,
|
|
4636
|
+
editing ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { position: "sticky", top: 0, zIndex: 5, background: "var(--dsh-mem-bg-inset)", display: "flex", alignItems: "center", gap: 6, marginBottom: 8, flexWrap: "wrap", padding: "6px 8px", border: "1px solid var(--dsh-mem-accent)", borderRadius: 8 }, children: [
|
|
4637
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { style: S.muted, children: [
|
|
4332
4638
|
"编辑 ",
|
|
4333
4639
|
editing.slug
|
|
4334
4640
|
] }),
|
|
4335
|
-
/* @__PURE__ */ (0,
|
|
4336
|
-
/* @__PURE__ */ (0,
|
|
4337
|
-
/* @__PURE__ */ (0,
|
|
4338
|
-
/* @__PURE__ */ (0,
|
|
4641
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("input", { value: editing.label, onChange: (ev) => setEditing({ ...editing, label: ev.target.value }), placeholder: "显示名(可中文)", disabled: busy, style: { ...S.input, width: 140, fontSize: 12 } }),
|
|
4642
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("input", { value: editing.description, onChange: (ev) => setEditing({ ...editing, description: ev.target.value }), placeholder: "归类说明(喂标注器)", disabled: busy, style: { ...S.input, width: 200, fontSize: 12 } }),
|
|
4643
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: busy, onClick: saveEditing, style: { ...btn, color: "var(--dsh-mem-accent)", borderColor: "var(--dsh-mem-accent)" }, children: "保存" }),
|
|
4644
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: busy, onClick: () => setEditing(null), style: btn, children: "取消" })
|
|
4339
4645
|
] }) : null,
|
|
4340
|
-
form ? /* @__PURE__ */ (0,
|
|
4341
|
-
/* @__PURE__ */ (0,
|
|
4646
|
+
form ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { position: "sticky", top: 0, zIndex: 5, background: "var(--dsh-mem-bg-inset)", display: "flex", alignItems: "center", gap: 6, marginBottom: 8, flexWrap: "wrap", padding: "6px 8px", border: "1px solid var(--dsh-mem-accent)", borderRadius: 8 }, children: [
|
|
4647
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { style: S.muted, children: [
|
|
4342
4648
|
form.action === "merge" ? "合并" : "归类/改名",
|
|
4343
4649
|
" ",
|
|
4344
4650
|
form.from,
|
|
4345
4651
|
" →"
|
|
4346
4652
|
] }),
|
|
4347
|
-
/* @__PURE__ */ (0,
|
|
4653
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4348
4654
|
"input",
|
|
4349
4655
|
{
|
|
4350
4656
|
value: form.to,
|
|
@@ -4354,7 +4660,7 @@ var __defProp = Object.defineProperty;
|
|
|
4354
4660
|
style: { ...S.input, width: 190, fontSize: 12 }
|
|
4355
4661
|
}
|
|
4356
4662
|
),
|
|
4357
|
-
form.action === "rename" ? /* @__PURE__ */ (0,
|
|
4663
|
+
form.action === "rename" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: { display: "inline-flex", gap: 4, flexWrap: "wrap" }, children: groups.filter((gg) => gg.hall !== majorOf(form.from)).map((gg) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4358
4664
|
"button",
|
|
4359
4665
|
{
|
|
4360
4666
|
type: "button",
|
|
@@ -4365,32 +4671,32 @@ var __defProp = Object.defineProperty;
|
|
|
4365
4671
|
},
|
|
4366
4672
|
gg.hall
|
|
4367
4673
|
)) }) : null,
|
|
4368
|
-
/* @__PURE__ */ (0,
|
|
4369
|
-
/* @__PURE__ */ (0,
|
|
4674
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: busy, onClick: () => previewMerge(), style: { ...btn, color: "var(--dsh-mem-accent)", borderColor: "var(--dsh-mem-accent)" }, children: "预览" }),
|
|
4675
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: busy, onClick: () => {
|
|
4370
4676
|
setForm(null);
|
|
4371
4677
|
setPreview(null);
|
|
4372
4678
|
setPicking(null);
|
|
4373
4679
|
}, style: btn, children: "取消" }),
|
|
4374
|
-
picking ? /* @__PURE__ */ (0,
|
|
4375
|
-
/* @__PURE__ */ (0,
|
|
4680
|
+
picking ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: S.muted, children: "挑选中:点击目标 hall 头完成归类" }) : null,
|
|
4681
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: S.muted, children: "与反刍并发会互相覆盖,请在反刍空闲时执行。" })
|
|
4376
4682
|
] }) : null,
|
|
4377
|
-
preview ? /* @__PURE__ */ (0,
|
|
4378
|
-
/* @__PURE__ */ (0,
|
|
4379
|
-
/* @__PURE__ */ (0,
|
|
4380
|
-
/* @__PURE__ */ (0,
|
|
4683
|
+
preview ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { position: "sticky", top: 0, zIndex: 5, background: "var(--dsh-mem-bg-inset)", marginBottom: 8, padding: "6px 8px", border: "1px solid var(--dsh-mem-danger)", borderRadius: 8, fontSize: 12 }, children: [
|
|
4684
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { children: preview.notice }),
|
|
4685
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", gap: 6, marginTop: 4 }, children: [
|
|
4686
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("button", { type: "button", disabled: busy, onClick: execMerge, style: { ...btn, color: "var(--dsh-mem-danger)", borderColor: "var(--dsh-mem-danger)" }, children: [
|
|
4381
4687
|
"确认执行",
|
|
4382
4688
|
preview.action === "merge" ? "合并" : "归类/改名"
|
|
4383
4689
|
] }),
|
|
4384
|
-
/* @__PURE__ */ (0,
|
|
4690
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: busy, onClick: () => setPreview(null), style: btn, children: "再改改" })
|
|
4385
4691
|
] })
|
|
4386
4692
|
] }) : null,
|
|
4387
|
-
msg ? /* @__PURE__ */ (0,
|
|
4388
|
-
error ? /* @__PURE__ */ (0,
|
|
4389
|
-
ghost ? /* @__PURE__ */ (0,
|
|
4390
|
-
visibleGroups.length === 0 ? /* @__PURE__ */ (0,
|
|
4693
|
+
msg ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: S.hint, children: msg }) : null,
|
|
4694
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: S.error, children: error }) : null,
|
|
4695
|
+
ghost ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { position: "fixed", left: ghost.x + 12, top: ghost.y + 12, zIndex: 9999, pointerEvents: "none", fontSize: 12, padding: "2px 10px", borderRadius: 999, border: "1px solid var(--dsh-mem-accent)", background: "var(--dsh-mem-bg-inset)", color: "var(--dsh-mem-accent)" }, children: ghost.text }) : null,
|
|
4696
|
+
visibleGroups.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { style: S.intro, children: normFilter ? "无匹配的 hall/room。" : "注册表为空。在上方注册 Hall/Room(如 dsh-plugin),或把自生长 slug「收编」进词表 —— 之后候选标注器会优先把相关记忆挂到这些 slug 上。" }) : visibleGroups.map((g) => {
|
|
4391
4697
|
const hallOpen = !!normFilter || expandedHalls.has(g.hall);
|
|
4392
|
-
return /* @__PURE__ */ (0,
|
|
4393
|
-
/* @__PURE__ */ (0,
|
|
4698
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { marginBottom: 10, border: "1px solid var(--dsh-mem-border)", borderRadius: 8, overflow: "hidden" }, children: [
|
|
4699
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
4394
4700
|
"div",
|
|
4395
4701
|
{
|
|
4396
4702
|
"data-hall": g.hall,
|
|
@@ -4431,7 +4737,7 @@ var __defProp = Object.defineProperty;
|
|
|
4431
4737
|
},
|
|
4432
4738
|
title: picking ? "点击此 hall:把「" + picking + "」归入 " + g.hall + " 下(major/minor,预览后确认)" : hiPriv ? "拖入 room 归类到该 hall 下(major/minor;记录随迁,旧名进别名,预览后确认)" : void 0,
|
|
4433
4739
|
children: [
|
|
4434
|
-
/* @__PURE__ */ (0,
|
|
4740
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4435
4741
|
"button",
|
|
4436
4742
|
{
|
|
4437
4743
|
type: "button",
|
|
@@ -4444,13 +4750,13 @@ var __defProp = Object.defineProperty;
|
|
|
4444
4750
|
children: hallOpen ? "▾" : "▸"
|
|
4445
4751
|
}
|
|
4446
4752
|
),
|
|
4447
|
-
/* @__PURE__ */ (0,
|
|
4753
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { style: { fontSize: 12, fontWeight: 600 }, children: [
|
|
4448
4754
|
g.hall,
|
|
4449
|
-
g.label ? /* @__PURE__ */ (0,
|
|
4755
|
+
g.label ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: S.muted, children: " (" + g.label + ")" }) : null
|
|
4450
4756
|
] }),
|
|
4451
|
-
/* @__PURE__ */ (0,
|
|
4452
|
-
/* @__PURE__ */ (0,
|
|
4453
|
-
/* @__PURE__ */ (0,
|
|
4757
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: S.muted, children: `合计 ${g.total} 条 · ${g.entries.length} 个 room` }),
|
|
4758
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: S.grow }),
|
|
4759
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4454
4760
|
"button",
|
|
4455
4761
|
{
|
|
4456
4762
|
type: "button",
|
|
@@ -4471,10 +4777,10 @@ var __defProp = Object.defineProperty;
|
|
|
4471
4777
|
const standalone = e.slug === g.hall;
|
|
4472
4778
|
const count = rooms.find((r) => r.room === e.slug)?.count ?? 0;
|
|
4473
4779
|
const retired = e.status === "retired";
|
|
4474
|
-
return /* @__PURE__ */ (0,
|
|
4475
|
-
/* @__PURE__ */ (0,
|
|
4476
|
-
/* @__PURE__ */ (0,
|
|
4477
|
-
/* @__PURE__ */ (0,
|
|
4780
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { padding: "4px 10px", borderTop: "1px solid var(--dsh-mem-border)", opacity: retired ? 0.55 : 1 }, children: [
|
|
4781
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
4782
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { flex: 1, minWidth: 0, display: "flex", flexWrap: "wrap", gap: "2px 8px", alignItems: "baseline" }, children: [
|
|
4783
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4478
4784
|
"button",
|
|
4479
4785
|
{
|
|
4480
4786
|
type: "button",
|
|
@@ -4484,7 +4790,7 @@ var __defProp = Object.defineProperty;
|
|
|
4484
4790
|
children: expandedRooms.has(e.slug) ? "▾" : "▸"
|
|
4485
4791
|
}
|
|
4486
4792
|
),
|
|
4487
|
-
/* @__PURE__ */ (0,
|
|
4793
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
4488
4794
|
"span",
|
|
4489
4795
|
{
|
|
4490
4796
|
style: { fontSize: 12, cursor: hiPriv && !busy ? "grab" : "default", touchAction: "none" },
|
|
@@ -4498,20 +4804,20 @@ var __defProp = Object.defineProperty;
|
|
|
4498
4804
|
]
|
|
4499
4805
|
}
|
|
4500
4806
|
),
|
|
4501
|
-
e.label ? /* @__PURE__ */ (0,
|
|
4502
|
-
/* @__PURE__ */ (0,
|
|
4503
|
-
retired ? /* @__PURE__ */ (0,
|
|
4504
|
-
(e.aliases ?? []).length > 0 ? /* @__PURE__ */ (0,
|
|
4807
|
+
e.label ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: S.muted, children: e.label }) : null,
|
|
4808
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: S.muted, children: count + " 条" }),
|
|
4809
|
+
retired ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: { ...S.muted, color: "var(--dsh-mem-danger)" }, children: "已退役" }) : null,
|
|
4810
|
+
(e.aliases ?? []).length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: { ...S.muted, wordBreak: "break-all" }, children: "别名: " + (e.aliases ?? []).join(", ") }) : null
|
|
4505
4811
|
] }),
|
|
4506
|
-
/* @__PURE__ */ (0,
|
|
4507
|
-
!hiPriv ? null : /* @__PURE__ */ (0,
|
|
4508
|
-
/* @__PURE__ */ (0,
|
|
4812
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { display: "flex", gap: 6, flexShrink: 0, alignItems: "center" }, children: [
|
|
4813
|
+
!hiPriv ? null : /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
4814
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: busy, title: "编辑显示名/归类说明", onClick: () => {
|
|
4509
4815
|
setEditing({ slug: e.slug, label: e.label ?? "", description: e.description ?? "" });
|
|
4510
4816
|
setForm(null);
|
|
4511
4817
|
setPreview(null);
|
|
4512
4818
|
setPicking(null);
|
|
4513
4819
|
}, style: btn, children: "编辑" }),
|
|
4514
|
-
/* @__PURE__ */ (0,
|
|
4820
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4515
4821
|
"button",
|
|
4516
4822
|
{
|
|
4517
4823
|
type: "button",
|
|
@@ -4532,43 +4838,43 @@ var __defProp = Object.defineProperty;
|
|
|
4532
4838
|
children: picking === e.slug ? "选 hall…" : "归类"
|
|
4533
4839
|
}
|
|
4534
4840
|
),
|
|
4535
|
-
/* @__PURE__ */ (0,
|
|
4841
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: busy, title: `改名(= merge 1:1 + 注册表改名)`, onClick: () => {
|
|
4536
4842
|
setForm({ action: "rename", from: e.slug, to: "" });
|
|
4537
4843
|
setPreview(null);
|
|
4538
4844
|
}, style: btn, children: "改名" }),
|
|
4539
|
-
/* @__PURE__ */ (0,
|
|
4845
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: busy, title: "合并到另一个 Room(dryRun 预览→确认实跑)", onClick: () => {
|
|
4540
4846
|
setForm({ action: "merge", from: e.slug, to: "" });
|
|
4541
4847
|
setPreview(null);
|
|
4542
4848
|
}, style: btn, children: "合并" }),
|
|
4543
|
-
/* @__PURE__ */ (0,
|
|
4544
|
-
!retired ? /* @__PURE__ */ (0,
|
|
4849
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: busy, title: retired ? "恢复该 Room 到词表" : "退役该 Room(存量 tags 不动)", onClick: () => retire(e.slug, retired), style: { ...btn, ...retired ? { color: "var(--dsh-mem-accent)", borderColor: "var(--dsh-mem-accent)" } : { color: "var(--dsh-mem-danger)", borderColor: "var(--dsh-mem-danger)" } }, children: retired ? "恢复" : "退役" }),
|
|
4850
|
+
!retired ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: busy, title: "退役并退场该 Room 下全部记忆(软删,可在「已退场」区恢复)", onClick: () => retire(e.slug, false, true), style: { ...btn, color: "var(--dsh-mem-danger)", borderColor: "var(--dsh-mem-danger)" }, children: "退场" }) : null
|
|
4545
4851
|
] }),
|
|
4546
|
-
/* @__PURE__ */ (0,
|
|
4852
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: busy, title: "导出该 Room 的记录清单 CSV", onClick: () => exportRecords(e.slug), style: btn, children: "导出" })
|
|
4547
4853
|
] })
|
|
4548
4854
|
] }),
|
|
4549
|
-
expandedRooms.has(e.slug) ? /* @__PURE__ */ (0,
|
|
4550
|
-
(roomRecords[e.slug]?.items ?? []).map((it) => /* @__PURE__ */ (0,
|
|
4551
|
-
/* @__PURE__ */ (0,
|
|
4855
|
+
expandedRooms.has(e.slug) ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { margin: "4px 0 2px", padding: "4px 8px", border: "1px dashed var(--dsh-mem-border)", borderRadius: 6 }, children: [
|
|
4856
|
+
(roomRecords[e.slug]?.items ?? []).map((it) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { fontSize: 11, padding: "3px 0", borderBottom: "1px solid var(--dsh-mem-border)" }, children: [
|
|
4857
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "dsh-mem-tag dsh-mem-tag-" + it.type, children: TYPE_LABELS[it.type] || it.type }),
|
|
4552
4858
|
" ",
|
|
4553
|
-
/* @__PURE__ */ (0,
|
|
4554
|
-
/* @__PURE__ */ (0,
|
|
4859
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: S.muted, children: it.updatedAt ? fmtTime(it.updatedAt) : "" }),
|
|
4860
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { marginTop: 2, wordBreak: "break-all", color: "var(--dsh-mem-text-2)" }, children: it.content.length > 120 ? it.content.slice(0, 120) + "…" : it.content })
|
|
4555
4861
|
] }, it.id)),
|
|
4556
|
-
(roomRecords[e.slug]?.items.length ?? 0) === 0 ? /* @__PURE__ */ (0,
|
|
4557
|
-
(roomRecords[e.slug]?.total ?? 0) > (roomRecords[e.slug]?.items.length ?? 0) ? /* @__PURE__ */ (0,
|
|
4862
|
+
(roomRecords[e.slug]?.items.length ?? 0) === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: S.muted, children: "该 Room 暂无记录。" }) : null,
|
|
4863
|
+
(roomRecords[e.slug]?.total ?? 0) > (roomRecords[e.slug]?.items.length ?? 0) ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { ...S.muted, fontSize: 11 }, children: "共 " + roomRecords[e.slug].total + " 条,仅显示前 " + roomRecords[e.slug].items.length + " 条" }) : null
|
|
4558
4864
|
] }) : null
|
|
4559
4865
|
] }, e.slug);
|
|
4560
4866
|
}) : null
|
|
4561
4867
|
] }, g.hall);
|
|
4562
4868
|
}),
|
|
4563
|
-
visibleGrown.length > 0 ? /* @__PURE__ */ (0,
|
|
4564
|
-
/* @__PURE__ */ (0,
|
|
4869
|
+
visibleGrown.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { marginTop: 4 }, children: [
|
|
4870
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("button", { type: "button", onClick: () => setGrownOpen(!grownOpen), style: btn, title: grownOpen ? "收起未注册自生长 Room" : "展开未注册自生长 Room", children: [
|
|
4565
4871
|
grownOpen ? "▾" : "▸",
|
|
4566
4872
|
" 自生长未注册 · 共 ",
|
|
4567
4873
|
visibleGrown.length
|
|
4568
4874
|
] }),
|
|
4569
|
-
/* @__PURE__ */ (0,
|
|
4570
|
-
grownOpen ? /* @__PURE__ */ (0,
|
|
4571
|
-
/* @__PURE__ */ (0,
|
|
4875
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: S.muted, children: "(只在 tags 里涌现,不在词表 —— 收编后标注器才会优先挂靠)" }),
|
|
4876
|
+
grownOpen ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 6, alignItems: "center", marginTop: 6 }, children: visibleGrown.map((r) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { style: { display: "inline-flex", alignItems: "center", gap: 4 }, children: [
|
|
4877
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4572
4878
|
"span",
|
|
4573
4879
|
{
|
|
4574
4880
|
style: { ...btn, cursor: hiPriv && !busy ? "grab" : "default", borderRadius: 999, padding: "2px 8px", touchAction: "none" },
|
|
@@ -4579,8 +4885,8 @@ var __defProp = Object.defineProperty;
|
|
|
4579
4885
|
children: r.room + " · " + r.count
|
|
4580
4886
|
}
|
|
4581
4887
|
),
|
|
4582
|
-
/* @__PURE__ */ (0,
|
|
4583
|
-
/* @__PURE__ */ (0,
|
|
4888
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: !hiPriv || busy, title: "收编进注册表(source=grown,原地)", onClick: () => adopt(r.room), style: { ...btn, color: "var(--dsh-mem-accent)", borderColor: "var(--dsh-mem-accent)", opacity: !hiPriv || busy ? 0.5 : 1 }, children: "收编" }),
|
|
4889
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4584
4890
|
"button",
|
|
4585
4891
|
{
|
|
4586
4892
|
type: "button",
|
|
@@ -4607,8 +4913,8 @@ var __defProp = Object.defineProperty;
|
|
|
4607
4913
|
}
|
|
4608
4914
|
|
|
4609
4915
|
// client/src/tabs/RoomTab.tsx
|
|
4610
|
-
var
|
|
4611
|
-
var
|
|
4916
|
+
var import_react19 = require("react");
|
|
4917
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
4612
4918
|
var btn2 = {
|
|
4613
4919
|
cursor: "pointer",
|
|
4614
4920
|
fontSize: 12,
|
|
@@ -4629,22 +4935,22 @@ var __defProp = Object.defineProperty;
|
|
|
4629
4935
|
}
|
|
4630
4936
|
function RoomTab(props) {
|
|
4631
4937
|
const rpc = props.rpc;
|
|
4632
|
-
const [registry, setRegistry] = (0,
|
|
4633
|
-
const [counts, setCounts] = (0,
|
|
4634
|
-
const [orphanCount, setOrphanCount] = (0,
|
|
4635
|
-
const [busy, setBusy] = (0,
|
|
4636
|
-
const [msg, setMsg] = (0,
|
|
4637
|
-
const [error, setError] = (0,
|
|
4638
|
-
const [hiPriv, setHiPriv] = (0,
|
|
4639
|
-
const [hiPrivBusy, setHiPrivBusy] = (0,
|
|
4640
|
-
const [reg, setReg] = (0,
|
|
4641
|
-
const [editing, setEditing] = (0,
|
|
4642
|
-
const [renaming, setRenaming] = (0,
|
|
4643
|
-
const [expanded, setExpanded] = (0,
|
|
4644
|
-
const [retiredFilter, setRetiredFilter] = (0,
|
|
4645
|
-
const [filter, setFilter] = (0,
|
|
4646
|
-
const [records, setRecords] = (0,
|
|
4647
|
-
const loadAll = (0,
|
|
4938
|
+
const [registry, setRegistry] = (0, import_react19.useState)([]);
|
|
4939
|
+
const [counts, setCounts] = (0, import_react19.useState)([]);
|
|
4940
|
+
const [orphanCount, setOrphanCount] = (0, import_react19.useState)(0);
|
|
4941
|
+
const [busy, setBusy] = (0, import_react19.useState)(false);
|
|
4942
|
+
const [msg, setMsg] = (0, import_react19.useState)(null);
|
|
4943
|
+
const [error, setError] = (0, import_react19.useState)(null);
|
|
4944
|
+
const [hiPriv, setHiPriv] = (0, import_react19.useState)(false);
|
|
4945
|
+
const [hiPrivBusy, setHiPrivBusy] = (0, import_react19.useState)(false);
|
|
4946
|
+
const [reg, setReg] = (0, import_react19.useState)({ slug: "", label: "", description: "" });
|
|
4947
|
+
const [editing, setEditing] = (0, import_react19.useState)(null);
|
|
4948
|
+
const [renaming, setRenaming] = (0, import_react19.useState)(null);
|
|
4949
|
+
const [expanded, setExpanded] = (0, import_react19.useState)(/* @__PURE__ */ new Set());
|
|
4950
|
+
const [retiredFilter, setRetiredFilter] = (0, import_react19.useState)("");
|
|
4951
|
+
const [filter, setFilter] = (0, import_react19.useState)("");
|
|
4952
|
+
const [records, setRecords] = (0, import_react19.useState)({});
|
|
4953
|
+
const loadAll = (0, import_react19.useCallback)(() => {
|
|
4648
4954
|
rpc("dsh-memory/rooms-get", {}).then((r) => {
|
|
4649
4955
|
if (r && r.ok) {
|
|
4650
4956
|
setCounts(r.value.rooms ?? []);
|
|
@@ -4653,13 +4959,13 @@ var __defProp = Object.defineProperty;
|
|
|
4653
4959
|
}
|
|
4654
4960
|
}).catch(() => void 0);
|
|
4655
4961
|
}, [rpc]);
|
|
4656
|
-
const loadHiPriv = (0,
|
|
4962
|
+
const loadHiPriv = (0, import_react19.useCallback)(() => {
|
|
4657
4963
|
rpc("dsh-memory/settings-get", {}).then((r) => {
|
|
4658
4964
|
if (r && r.ok && r.value) setHiPriv(!!r.value.settings.memoryMutate);
|
|
4659
4965
|
}).catch(() => {
|
|
4660
4966
|
});
|
|
4661
4967
|
}, [rpc]);
|
|
4662
|
-
(0,
|
|
4968
|
+
(0, import_react19.useEffect)(() => {
|
|
4663
4969
|
loadAll();
|
|
4664
4970
|
loadHiPriv();
|
|
4665
4971
|
}, [loadAll, loadHiPriv]);
|
|
@@ -4797,11 +5103,11 @@ var __defProp = Object.defineProperty;
|
|
|
4797
5103
|
const visibleRows = normFilter ? rows.filter(
|
|
4798
5104
|
(row2) => row2.slug.toLowerCase().includes(normFilter) || (row2.entry?.label ?? "").toLowerCase().includes(normFilter) || (row2.entry?.aliases ?? []).some((a) => a.toLowerCase().includes(normFilter))
|
|
4799
5105
|
) : rows;
|
|
4800
|
-
return /* @__PURE__ */ (0,
|
|
4801
|
-
/* @__PURE__ */ (0,
|
|
4802
|
-
/* @__PURE__ */ (0,
|
|
4803
|
-
/* @__PURE__ */ (0,
|
|
4804
|
-
/* @__PURE__ */ (0,
|
|
5106
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
|
|
5107
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { ...S.flexRow, marginBottom: 8, flexWrap: "wrap" }, children: [
|
|
5108
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: S.muted, children: "Room 级管理:存在(注册/收编/退役)· 名称(显示名/说明/改名)· 条目(展开浏览) · 归类到 hall 请到「Hall」页" }),
|
|
5109
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: S.grow }),
|
|
5110
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("button", { type: "button", style: btn2, title: "导出无 Room 绑定的孤儿清单(含候选)", onClick: () => run(async () => {
|
|
4805
5111
|
const r = await rpc("dsh-memory/rooms-export", { kind: "orphans" });
|
|
4806
5112
|
if (!r.ok) {
|
|
4807
5113
|
setError(r.error.message);
|
|
@@ -4812,7 +5118,7 @@ var __defProp = Object.defineProperty;
|
|
|
4812
5118
|
"导出孤儿 · ",
|
|
4813
5119
|
orphanCount
|
|
4814
5120
|
] }),
|
|
4815
|
-
/* @__PURE__ */ (0,
|
|
5121
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4816
5122
|
"button",
|
|
4817
5123
|
{
|
|
4818
5124
|
type: "button",
|
|
@@ -4823,35 +5129,35 @@ var __defProp = Object.defineProperty;
|
|
|
4823
5129
|
children: hiPriv ? "高权限:开" : "高权限:关"
|
|
4824
5130
|
}
|
|
4825
5131
|
),
|
|
4826
|
-
/* @__PURE__ */ (0,
|
|
5132
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", style: btn2, onClick: loadAll, children: "刷新" })
|
|
4827
5133
|
] }),
|
|
4828
|
-
editing ? /* @__PURE__ */ (0,
|
|
4829
|
-
/* @__PURE__ */ (0,
|
|
5134
|
+
editing ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { position: "sticky", top: 0, zIndex: 5, background: "var(--dsh-mem-bg-inset)", display: "flex", alignItems: "center", gap: 6, marginBottom: 8, flexWrap: "wrap", padding: "6px 8px", border: "1px solid var(--dsh-mem-accent)", borderRadius: 8 }, children: [
|
|
5135
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { style: S.muted, children: [
|
|
4830
5136
|
"编辑 ",
|
|
4831
5137
|
editing.slug
|
|
4832
5138
|
] }),
|
|
4833
|
-
/* @__PURE__ */ (0,
|
|
4834
|
-
/* @__PURE__ */ (0,
|
|
4835
|
-
/* @__PURE__ */ (0,
|
|
4836
|
-
/* @__PURE__ */ (0,
|
|
5139
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("input", { value: editing.label, onChange: (e) => setEditing({ ...editing, label: e.target.value }), placeholder: "显示名(可中文)", disabled: busy, style: { ...S.input, width: 140, fontSize: 12 } }),
|
|
5140
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("input", { value: editing.description, onChange: (e) => setEditing({ ...editing, description: e.target.value }), placeholder: "归类说明(喂标注器)", disabled: busy, style: { ...S.input, width: 200, fontSize: 12 } }),
|
|
5141
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", disabled: busy, onClick: saveEditing, style: { ...btn2, color: "var(--dsh-mem-accent)", borderColor: "var(--dsh-mem-accent)" }, children: "保存" }),
|
|
5142
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", disabled: busy, onClick: () => setEditing(null), style: btn2, children: "取消" })
|
|
4837
5143
|
] }) : null,
|
|
4838
|
-
renaming ? /* @__PURE__ */ (0,
|
|
4839
|
-
/* @__PURE__ */ (0,
|
|
5144
|
+
renaming ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { position: "sticky", top: 0, zIndex: 5, background: "var(--dsh-mem-bg-inset)", display: "flex", alignItems: "center", gap: 6, marginBottom: 8, flexWrap: "wrap", padding: "6px 8px", border: "1px solid var(--dsh-mem-accent)", borderRadius: 8 }, children: [
|
|
5145
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { style: S.muted, children: [
|
|
4840
5146
|
"改名 ",
|
|
4841
5147
|
renaming.slug,
|
|
4842
5148
|
" →"
|
|
4843
5149
|
] }),
|
|
4844
|
-
/* @__PURE__ */ (0,
|
|
4845
|
-
/* @__PURE__ */ (0,
|
|
4846
|
-
/* @__PURE__ */ (0,
|
|
4847
|
-
/* @__PURE__ */ (0,
|
|
4848
|
-
/* @__PURE__ */ (0,
|
|
5150
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("input", { value: renaming.to, onChange: (e) => setRenaming({ ...renaming, to: e.target.value }), placeholder: "新 slug(可两级:hall/子类)", disabled: busy, style: { ...S.input, width: 200, fontSize: 12 } }),
|
|
5151
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", disabled: busy, onClick: previewRename, style: { ...btn2, color: "var(--dsh-mem-accent)", borderColor: "var(--dsh-mem-accent)" }, children: "预览" }),
|
|
5152
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", disabled: busy, onClick: execRename, style: { ...btn2, color: "var(--dsh-mem-danger)", borderColor: "var(--dsh-mem-danger)" }, children: "确认执行" }),
|
|
5153
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", disabled: busy, onClick: () => setRenaming(null), style: btn2, children: "取消" }),
|
|
5154
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: S.muted, children: "记录随迁;与反刍并发会互相覆盖,请在反刍空闲时执行。" })
|
|
4849
5155
|
] }) : null,
|
|
4850
|
-
/* @__PURE__ */ (0,
|
|
4851
|
-
/* @__PURE__ */ (0,
|
|
5156
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 8, flexWrap: "wrap" }, children: [
|
|
5157
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: S.muted, children: "退场筛选" }),
|
|
4852
5158
|
[["", "全部"], ["active", "活跃"], ["retired", "已退役"]].map(([val, label]) => {
|
|
4853
5159
|
const on = retiredFilter === val;
|
|
4854
|
-
return /* @__PURE__ */ (0,
|
|
5160
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4855
5161
|
"button",
|
|
4856
5162
|
{
|
|
4857
5163
|
type: "button",
|
|
@@ -4871,8 +5177,8 @@ var __defProp = Object.defineProperty;
|
|
|
4871
5177
|
val
|
|
4872
5178
|
);
|
|
4873
5179
|
}),
|
|
4874
|
-
/* @__PURE__ */ (0,
|
|
4875
|
-
/* @__PURE__ */ (0,
|
|
5180
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: S.grow }),
|
|
5181
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4876
5182
|
"input",
|
|
4877
5183
|
{
|
|
4878
5184
|
value: filter,
|
|
@@ -4881,24 +5187,24 @@ var __defProp = Object.defineProperty;
|
|
|
4881
5187
|
style: { ...S.input, width: 230, fontSize: 12 }
|
|
4882
5188
|
}
|
|
4883
5189
|
),
|
|
4884
|
-
filter ? /* @__PURE__ */ (0,
|
|
5190
|
+
filter ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", style: btn2, onClick: () => setFilter(""), children: "清除" }) : null
|
|
4885
5191
|
] }),
|
|
4886
|
-
/* @__PURE__ */ (0,
|
|
4887
|
-
/* @__PURE__ */ (0,
|
|
4888
|
-
/* @__PURE__ */ (0,
|
|
4889
|
-
/* @__PURE__ */ (0,
|
|
4890
|
-
/* @__PURE__ */ (0,
|
|
4891
|
-
!hiPriv && /* @__PURE__ */ (0,
|
|
5192
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", gap: 6, alignItems: "center", marginBottom: 10 }, children: [
|
|
5193
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("input", { value: reg.slug, onChange: (e) => setReg({ ...reg, slug: e.target.value }), placeholder: "slug(如 dsh-plugin 或 dsh-plugin/merge)", disabled: !hiPriv || busy, style: { ...S.input, width: 210, fontSize: 12 } }),
|
|
5194
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("input", { value: reg.label, onChange: (e) => setReg({ ...reg, label: e.target.value }), placeholder: "名称(可中文)", disabled: !hiPriv || busy, style: { ...S.input, width: 110, fontSize: 12 } }),
|
|
5195
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("input", { value: reg.description, onChange: (e) => setReg({ ...reg, description: e.target.value }), placeholder: "归类说明(喂标注器)", disabled: !hiPriv || busy, style: { ...S.input, width: 170, fontSize: 12 } }),
|
|
5196
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", disabled: !hiPriv || busy || !reg.slug.trim(), onClick: register, style: { ...btn2, color: "var(--dsh-mem-accent)", borderColor: "var(--dsh-mem-accent)", opacity: !hiPriv || busy || !reg.slug.trim() ? 0.5 : 1 }, children: "注册" }),
|
|
5197
|
+
!hiPriv && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: S.muted, children: "管理操作需先开启高权限模式" })
|
|
4892
5198
|
] }),
|
|
4893
|
-
msg ? /* @__PURE__ */ (0,
|
|
4894
|
-
error ? /* @__PURE__ */ (0,
|
|
4895
|
-
visibleRows.length === 0 ? normFilter ? /* @__PURE__ */ (0,
|
|
5199
|
+
msg ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: S.hint, children: msg }) : null,
|
|
5200
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: S.error, children: error }) : null,
|
|
5201
|
+
visibleRows.length === 0 ? normFilter ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { style: S.intro, children: "无匹配的 Room。" }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { style: S.intro, children: "暂无 Room:对话/反刍会从标签涌现,或在上方注册。" }) : visibleRows.map((row2) => {
|
|
4896
5202
|
const e = row2.entry;
|
|
4897
5203
|
const retired = e?.status === "retired";
|
|
4898
5204
|
const grownOnly = !e;
|
|
4899
|
-
return /* @__PURE__ */ (0,
|
|
4900
|
-
/* @__PURE__ */ (0,
|
|
4901
|
-
/* @__PURE__ */ (0,
|
|
5205
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { marginBottom: 6, border: "1px solid var(--dsh-mem-border)", borderRadius: 8 }, children: [
|
|
5206
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, padding: "4px 10px" }, children: [
|
|
5207
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4902
5208
|
"button",
|
|
4903
5209
|
{
|
|
4904
5210
|
type: "button",
|
|
@@ -4908,28 +5214,28 @@ var __defProp = Object.defineProperty;
|
|
|
4908
5214
|
children: expanded.has(row2.slug) ? "▾" : "▸"
|
|
4909
5215
|
}
|
|
4910
5216
|
),
|
|
4911
|
-
/* @__PURE__ */ (0,
|
|
4912
|
-
/* @__PURE__ */ (0,
|
|
5217
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { flex: 1, minWidth: 0, display: "flex", flexWrap: "wrap", gap: "2px 8px", alignItems: "baseline" }, children: [
|
|
5218
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { style: { fontSize: 12, opacity: retired ? 0.6 : 1 }, children: [
|
|
4913
5219
|
row2.slug,
|
|
4914
5220
|
e?.source === "pre-registered" ? " ⭐" : ""
|
|
4915
5221
|
] }),
|
|
4916
|
-
e?.label ? /* @__PURE__ */ (0,
|
|
4917
|
-
/* @__PURE__ */ (0,
|
|
4918
|
-
grownOnly ? /* @__PURE__ */ (0,
|
|
4919
|
-
retired ? /* @__PURE__ */ (0,
|
|
4920
|
-
(e?.aliases ?? []).length > 0 ? /* @__PURE__ */ (0,
|
|
5222
|
+
e?.label ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: S.muted, children: e.label }) : null,
|
|
5223
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: S.muted, children: row2.count + " 条" }),
|
|
5224
|
+
grownOnly ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: S.muted, children: "(自生长未注册)" }) : null,
|
|
5225
|
+
retired ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: { ...S.muted, color: "var(--dsh-mem-danger)" }, children: "已退役" }) : null,
|
|
5226
|
+
(e?.aliases ?? []).length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: { ...S.muted, wordBreak: "break-all" }, children: "别名: " + (e?.aliases ?? []).join(", ") }) : null
|
|
4921
5227
|
] }),
|
|
4922
|
-
/* @__PURE__ */ (0,
|
|
4923
|
-
!hiPriv || grownOnly ? null : /* @__PURE__ */ (0,
|
|
4924
|
-
/* @__PURE__ */ (0,
|
|
5228
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { display: "flex", gap: 6, flexShrink: 0, alignItems: "center" }, children: [
|
|
5229
|
+
!hiPriv || grownOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
5230
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", disabled: busy, title: "编辑显示名/归类说明", onClick: () => {
|
|
4925
5231
|
setEditing({ slug: row2.slug, label: e?.label ?? "", description: e?.description ?? "" });
|
|
4926
5232
|
setRenaming(null);
|
|
4927
5233
|
}, style: btn2, children: "编辑" }),
|
|
4928
|
-
/* @__PURE__ */ (0,
|
|
5234
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", disabled: busy, title: "改名(可两级 slug;记录随迁,旧名进别名)", onClick: () => {
|
|
4929
5235
|
setRenaming({ slug: row2.slug, to: "" });
|
|
4930
5236
|
setEditing(null);
|
|
4931
5237
|
}, style: btn2, children: "改名" }),
|
|
4932
|
-
/* @__PURE__ */ (0,
|
|
5238
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4933
5239
|
"button",
|
|
4934
5240
|
{
|
|
4935
5241
|
type: "button",
|
|
@@ -4940,29 +5246,29 @@ var __defProp = Object.defineProperty;
|
|
|
4940
5246
|
children: retired ? "恢复" : "退役"
|
|
4941
5247
|
}
|
|
4942
5248
|
),
|
|
4943
|
-
!retired ? /* @__PURE__ */ (0,
|
|
5249
|
+
!retired ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", disabled: busy, title: "退役并退场该 Room 下全部记忆(软删,可在「已退场」区恢复)", onClick: () => retire(row2.slug, false, true), style: { ...btn2, color: "var(--dsh-mem-danger)", borderColor: "var(--dsh-mem-danger)" }, children: "退场" }) : null
|
|
4944
5250
|
] }),
|
|
4945
|
-
grownOnly ? /* @__PURE__ */ (0,
|
|
4946
|
-
/* @__PURE__ */ (0,
|
|
4947
|
-
/* @__PURE__ */ (0,
|
|
5251
|
+
grownOnly ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
5252
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", disabled: !hiPriv || busy, title: "收编进注册表(source=grown)", onClick: () => adopt(row2.slug), style: { ...btn2, color: "var(--dsh-mem-accent)", borderColor: "var(--dsh-mem-accent)", opacity: !hiPriv || busy ? 0.5 : 1 }, children: "收编" }),
|
|
5253
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", disabled: !hiPriv || busy, title: "退场该 Room 下全部记忆(软删,可在「已退场」区恢复)", onClick: () => {
|
|
4948
5254
|
setRenaming(null);
|
|
4949
5255
|
retire(row2.slug, false, true);
|
|
4950
5256
|
}, style: { ...btn2, color: "var(--dsh-mem-danger)", borderColor: "var(--dsh-mem-danger)", opacity: !hiPriv || busy ? 0.5 : 1 }, children: "退场" })
|
|
4951
5257
|
] }) : null,
|
|
4952
|
-
/* @__PURE__ */ (0,
|
|
5258
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", disabled: busy, title: "导出该 Room 的记录清单 CSV", onClick: () => exportRecords(row2.slug), style: btn2, children: "导出" })
|
|
4953
5259
|
] })
|
|
4954
5260
|
] }),
|
|
4955
|
-
expanded.has(row2.slug) ? /* @__PURE__ */ (0,
|
|
4956
|
-
(records[row2.slug]?.items ?? []).map((it) => /* @__PURE__ */ (0,
|
|
4957
|
-
/* @__PURE__ */ (0,
|
|
5261
|
+
expanded.has(row2.slug) ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { margin: "0 10px 6px", padding: "4px 8px", border: "1px dashed var(--dsh-mem-border)", borderRadius: 6 }, children: [
|
|
5262
|
+
(records[row2.slug]?.items ?? []).map((it) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { style: { fontSize: 11, padding: "3px 0", borderBottom: "1px solid var(--dsh-mem-border)" }, children: [
|
|
5263
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "dsh-mem-tag dsh-mem-tag-" + it.type, children: TYPE_LABELS[it.type] || it.type }),
|
|
4958
5264
|
" ",
|
|
4959
|
-
it.retired ? /* @__PURE__ */ (0,
|
|
5265
|
+
it.retired ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: { ...S.muted, color: "var(--dsh-mem-danger)" }, children: "[已退场]" }) : null,
|
|
4960
5266
|
" ",
|
|
4961
|
-
/* @__PURE__ */ (0,
|
|
4962
|
-
/* @__PURE__ */ (0,
|
|
5267
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: S.muted, children: it.updatedAt ? fmtTime(it.updatedAt) : "" }),
|
|
5268
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { marginTop: 2, wordBreak: "break-all", color: "var(--dsh-mem-text-2)", opacity: it.retired ? 0.55 : 1 }, children: it.content.length > 140 ? it.content.slice(0, 140) + "…" : it.content })
|
|
4963
5269
|
] }, it.id)),
|
|
4964
|
-
(records[row2.slug]?.items.length ?? 0) === 0 ? /* @__PURE__ */ (0,
|
|
4965
|
-
(records[row2.slug]?.total ?? 0) > (records[row2.slug]?.items.length ?? 0) ? /* @__PURE__ */ (0,
|
|
5270
|
+
(records[row2.slug]?.items.length ?? 0) === 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: S.muted, children: "该 Room 暂无记忆条目。" }) : null,
|
|
5271
|
+
(records[row2.slug]?.total ?? 0) > (records[row2.slug]?.items.length ?? 0) ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { ...S.muted, fontSize: 11 }, children: "共 " + records[row2.slug].total + " 条,仅显示前 " + records[row2.slug].items.length + " 条" }) : null
|
|
4966
5272
|
] }) : null
|
|
4967
5273
|
] }, row2.slug);
|
|
4968
5274
|
})
|
|
@@ -4970,13 +5276,13 @@ var __defProp = Object.defineProperty;
|
|
|
4970
5276
|
}
|
|
4971
5277
|
|
|
4972
5278
|
// client/src/tabs/ScenesTab.tsx
|
|
4973
|
-
var
|
|
4974
|
-
var
|
|
5279
|
+
var import_react20 = require("react");
|
|
5280
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
4975
5281
|
function SceneCard(props) {
|
|
4976
5282
|
const s = props.s;
|
|
4977
|
-
const [open, setOpen] = (0,
|
|
4978
|
-
return /* @__PURE__ */ (0,
|
|
4979
|
-
/* @__PURE__ */ (0,
|
|
5283
|
+
const [open, setOpen] = (0, import_react20.useState)(false);
|
|
5284
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "dsh-mem-card dsh-mem-card-hover", style: S.card, children: [
|
|
5285
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
4980
5286
|
"div",
|
|
4981
5287
|
{
|
|
4982
5288
|
style: { ...S.sceneHead, cursor: "pointer", userSelect: "none" },
|
|
@@ -4984,23 +5290,23 @@ var __defProp = Object.defineProperty;
|
|
|
4984
5290
|
setOpen(!open);
|
|
4985
5291
|
},
|
|
4986
5292
|
children: [
|
|
4987
|
-
/* @__PURE__ */ (0,
|
|
4988
|
-
/* @__PURE__ */ (0,
|
|
4989
|
-
s.heat ? /* @__PURE__ */ (0,
|
|
4990
|
-
/* @__PURE__ */ (0,
|
|
4991
|
-
/* @__PURE__ */ (0,
|
|
5293
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "dsh-mem-scene-chev", style: { transform: open ? "rotate(90deg)" : "none" }, children: "▸" }),
|
|
5294
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: S.sceneTitle, children: s.path }),
|
|
5295
|
+
s.heat ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: S.muted, children: "热度 " + s.heat }) : null,
|
|
5296
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: S.grow }),
|
|
5297
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: S.muted, children: "更新 " + fmtTime(s.updated) })
|
|
4992
5298
|
]
|
|
4993
5299
|
}
|
|
4994
5300
|
),
|
|
4995
|
-
s.summary ? /* @__PURE__ */ (0,
|
|
4996
|
-
open ? /* @__PURE__ */ (0,
|
|
5301
|
+
s.summary ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { ...S.muted, marginBottom: 6 }, children: s.summary }) : null,
|
|
5302
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("pre", { style: S.pre, children: s.content || "(空)" }) : null
|
|
4997
5303
|
] });
|
|
4998
5304
|
}
|
|
4999
5305
|
function ScenesTab(props) {
|
|
5000
5306
|
const rpc = props.rpc;
|
|
5001
|
-
const [items, setItems] = (0,
|
|
5002
|
-
const [error, setError] = (0,
|
|
5003
|
-
const load = (0,
|
|
5307
|
+
const [items, setItems] = (0, import_react20.useState)(null);
|
|
5308
|
+
const [error, setError] = (0, import_react20.useState)(null);
|
|
5309
|
+
const load = (0, import_react20.useCallback)(() => {
|
|
5004
5310
|
rpc("dsh-memory/scenes", {}).then((r) => {
|
|
5005
5311
|
if (r && r.ok) {
|
|
5006
5312
|
setItems(r.value.items);
|
|
@@ -5010,25 +5316,25 @@ var __defProp = Object.defineProperty;
|
|
|
5010
5316
|
setError(String(e && e.message || e));
|
|
5011
5317
|
});
|
|
5012
5318
|
}, [rpc]);
|
|
5013
|
-
(0,
|
|
5319
|
+
(0, import_react20.useEffect)(() => {
|
|
5014
5320
|
load();
|
|
5015
5321
|
}, [load]);
|
|
5016
|
-
return /* @__PURE__ */ (0,
|
|
5017
|
-
/* @__PURE__ */ (0,
|
|
5018
|
-
/* @__PURE__ */ (0,
|
|
5019
|
-
/* @__PURE__ */ (0,
|
|
5020
|
-
/* @__PURE__ */ (0,
|
|
5322
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { children: [
|
|
5323
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { ...S.flexRow, marginBottom: 10 }, children: [
|
|
5324
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: S.muted, children: items ? items.length + " 个场景块" : "加载中…" }),
|
|
5325
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: S.grow }),
|
|
5326
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(NButton, { onClick: load, children: "刷新" })
|
|
5021
5327
|
] }),
|
|
5022
|
-
error ? /* @__PURE__ */ (0,
|
|
5023
|
-
items && items.length === 0 ? /* @__PURE__ */ (0,
|
|
5328
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: S.error, children: error }) : null,
|
|
5329
|
+
items && items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { style: S.intro, children: "暂无场景块。累计 5 条新记忆后 L2 会自动整合出第一个场景。" }) : null,
|
|
5024
5330
|
(items || []).map((s) => {
|
|
5025
|
-
return /* @__PURE__ */ (0,
|
|
5331
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SceneCard, { s }, s.path);
|
|
5026
5332
|
})
|
|
5027
5333
|
] });
|
|
5028
5334
|
}
|
|
5029
5335
|
|
|
5030
5336
|
// client/src/panel.tsx
|
|
5031
|
-
var
|
|
5337
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
5032
5338
|
var TABS = [
|
|
5033
5339
|
["overview", "概览"],
|
|
5034
5340
|
["records", "记忆"],
|
|
@@ -5038,30 +5344,71 @@ var __defProp = Object.defineProperty;
|
|
|
5038
5344
|
["room", "Room"],
|
|
5039
5345
|
["persona", "画像"],
|
|
5040
5346
|
["cost", "成本"],
|
|
5041
|
-
["log", "日志"]
|
|
5347
|
+
["log", "日志"],
|
|
5348
|
+
["connect", "来源"],
|
|
5349
|
+
["skills", "技能"]
|
|
5350
|
+
];
|
|
5351
|
+
var SKIN_OPTS = [
|
|
5352
|
+
["light", "浅色"],
|
|
5353
|
+
["dark", "深色"],
|
|
5354
|
+
["auto", "跟随"]
|
|
5042
5355
|
];
|
|
5043
5356
|
function MemoryPanel(props) {
|
|
5044
5357
|
const rpc = props.rpc;
|
|
5045
|
-
const [tab, setTab] = (0,
|
|
5046
|
-
|
|
5047
|
-
(
|
|
5358
|
+
const [tab, setTab] = (0, import_react21.useState)("overview");
|
|
5359
|
+
const [skin, setSkinState] = (0, import_react21.useState)(() => getSkin());
|
|
5360
|
+
ensureThemeStyle(skin);
|
|
5361
|
+
(0, import_react21.useEffect)(() => {
|
|
5362
|
+
applySkin(skin);
|
|
5048
5363
|
watchSidebarIcon();
|
|
5049
|
-
}, []);
|
|
5364
|
+
}, [skin]);
|
|
5365
|
+
const switchSkin = (next) => {
|
|
5366
|
+
setSkin(next);
|
|
5367
|
+
setSkinState(next);
|
|
5368
|
+
};
|
|
5050
5369
|
let body;
|
|
5051
|
-
if (tab === "overview") body = /* @__PURE__ */ (0,
|
|
5052
|
-
else if (tab === "records") body = /* @__PURE__ */ (0,
|
|
5053
|
-
else if (tab === "conflicts") body = /* @__PURE__ */ (0,
|
|
5054
|
-
else if (tab === "scenes") body = /* @__PURE__ */ (0,
|
|
5055
|
-
else if (tab === "rooms") body = /* @__PURE__ */ (0,
|
|
5056
|
-
else if (tab === "room") body = /* @__PURE__ */ (0,
|
|
5057
|
-
else if (tab === "persona") body = /* @__PURE__ */ (0,
|
|
5058
|
-
else if (tab === "cost") body = /* @__PURE__ */ (0,
|
|
5059
|
-
else body = /* @__PURE__ */ (0,
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
/* @__PURE__ */ (0,
|
|
5064
|
-
|
|
5370
|
+
if (tab === "overview") body = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(OverviewTab, { rpc });
|
|
5371
|
+
else if (tab === "records") body = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(RecordsTab, { rpc });
|
|
5372
|
+
else if (tab === "conflicts") body = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ConflictsTab, { rpc });
|
|
5373
|
+
else if (tab === "scenes") body = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ScenesTab, { rpc });
|
|
5374
|
+
else if (tab === "rooms") body = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(RoomsTab, { rpc });
|
|
5375
|
+
else if (tab === "room") body = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(RoomTab, { rpc });
|
|
5376
|
+
else if (tab === "persona") body = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PersonaTab, { rpc });
|
|
5377
|
+
else if (tab === "cost") body = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CostTab, { rpc });
|
|
5378
|
+
else if (tab === "connect") body = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ConnectTab, { rpc });
|
|
5379
|
+
else if (tab === "skills") body = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SkillsTab, { rpc });
|
|
5380
|
+
else body = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LogTab, { rpc });
|
|
5381
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "dsh-mem-root", style: S.section, children: [
|
|
5382
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h2", { style: S.heading, children: "记忆 (Memory)" }),
|
|
5383
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { style: S.intro, children: "L0~L3 分层蒸馏记忆:浏览被记住的内容,控制记忆模式开关。" }),
|
|
5384
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
5385
|
+
"div",
|
|
5386
|
+
{
|
|
5387
|
+
style: {
|
|
5388
|
+
display: "flex",
|
|
5389
|
+
justifyContent: "flex-end",
|
|
5390
|
+
alignItems: "center",
|
|
5391
|
+
gap: 2,
|
|
5392
|
+
marginTop: -6,
|
|
5393
|
+
marginBottom: 10
|
|
5394
|
+
},
|
|
5395
|
+
children: [
|
|
5396
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { style: { fontSize: 12, color: "var(--dsh-mem-text-3)", marginRight: 4 }, children: "皮肤" }),
|
|
5397
|
+
SKIN_OPTS.map((s) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5398
|
+
"button",
|
|
5399
|
+
{
|
|
5400
|
+
className: skin === s[0] ? "dsh-mem-tab dsh-mem-tab-on" : "dsh-mem-tab",
|
|
5401
|
+
onClick: () => switchSkin(s[0]),
|
|
5402
|
+
title: `皮肤:${s[1]}`,
|
|
5403
|
+
children: s[1]
|
|
5404
|
+
},
|
|
5405
|
+
s[0]
|
|
5406
|
+
))
|
|
5407
|
+
]
|
|
5408
|
+
}
|
|
5409
|
+
),
|
|
5410
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: S.tabbar, children: TABS.map((t) => {
|
|
5411
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5065
5412
|
"button",
|
|
5066
5413
|
{
|
|
5067
5414
|
className: tab === t[0] ? "dsh-mem-tab dsh-mem-tab-on" : "dsh-mem-tab",
|
|
@@ -5078,7 +5425,7 @@ var __defProp = Object.defineProperty;
|
|
|
5078
5425
|
}
|
|
5079
5426
|
|
|
5080
5427
|
// client/src/pill/MemoryModePill.tsx
|
|
5081
|
-
var
|
|
5428
|
+
var import_react25 = require("react");
|
|
5082
5429
|
|
|
5083
5430
|
// src/util/context-occupancy.ts
|
|
5084
5431
|
var CONTEXT_METER_CIRCUMFERENCE = 34.55751918948772;
|
|
@@ -5394,23 +5741,23 @@ var __defProp = Object.defineProperty;
|
|
|
5394
5741
|
}
|
|
5395
5742
|
|
|
5396
5743
|
// client/src/pill/WingWheel.tsx
|
|
5397
|
-
var
|
|
5744
|
+
var import_react24 = require("react");
|
|
5398
5745
|
|
|
5399
5746
|
// client/src/pill/SessionInfoArea.tsx
|
|
5400
|
-
var
|
|
5401
|
-
var
|
|
5747
|
+
var import_react22 = require("react");
|
|
5748
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
5402
5749
|
function sinfoCell(val, label, title) {
|
|
5403
|
-
return /* @__PURE__ */ (0,
|
|
5404
|
-
/* @__PURE__ */ (0,
|
|
5405
|
-
/* @__PURE__ */ (0,
|
|
5750
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { title: title || void 0, children: [
|
|
5751
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "dsh-mem-sinfo-val", children: val }),
|
|
5752
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "dsh-mem-sinfo-label", children: label })
|
|
5406
5753
|
] });
|
|
5407
5754
|
}
|
|
5408
5755
|
function SessionInfoArea(props) {
|
|
5409
5756
|
const rpc = props.rpc;
|
|
5410
5757
|
const sessionId = props.sessionId;
|
|
5411
|
-
const [stats, setStats] = (0,
|
|
5412
|
-
const busyRef = (0,
|
|
5413
|
-
(0,
|
|
5758
|
+
const [stats, setStats] = (0, import_react22.useState)(void 0);
|
|
5759
|
+
const busyRef = (0, import_react22.useRef)(false);
|
|
5760
|
+
(0, import_react22.useEffect)(() => {
|
|
5414
5761
|
if (!rpc || !sessionId) return void 0;
|
|
5415
5762
|
let alive = true;
|
|
5416
5763
|
let timer = null;
|
|
@@ -5443,7 +5790,7 @@ var __defProp = Object.defineProperty;
|
|
|
5443
5790
|
}, [rpc, sessionId]);
|
|
5444
5791
|
if (stats === null) return null;
|
|
5445
5792
|
if (stats === void 0) {
|
|
5446
|
-
return /* @__PURE__ */ (0,
|
|
5793
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "dsh-mem-sinfo", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "dsh-mem-sinfo-grid", children: [
|
|
5447
5794
|
sinfoCell("…", "召回命中"),
|
|
5448
5795
|
sinfoCell("…", "攒批进度"),
|
|
5449
5796
|
sinfoCell("…", "本会话记忆"),
|
|
@@ -5492,21 +5839,104 @@ var __defProp = Object.defineProperty;
|
|
|
5492
5839
|
else if (stats.retrieval === "none") note = "检索不可用(FTS 与向量均失效)";
|
|
5493
5840
|
}
|
|
5494
5841
|
const ago = fmtAgo(gl.lastExtractAt);
|
|
5495
|
-
return /* @__PURE__ */ (0,
|
|
5496
|
-
warn ? /* @__PURE__ */ (0,
|
|
5497
|
-
/* @__PURE__ */ (0,
|
|
5842
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "dsh-mem-sinfo", children: [
|
|
5843
|
+
warn ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "dsh-mem-sinfo-warn", children: warn }) : null,
|
|
5844
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "dsh-mem-sinfo-grid", children: [
|
|
5498
5845
|
sinfoCell(rcVal, rcLabel, rcTitle),
|
|
5499
5846
|
sinfoCell(dVal, dLabel, dTitle),
|
|
5500
5847
|
sinfoCell(String(di.producedRecords || 0), "本会话记忆", pTitle),
|
|
5501
5848
|
sinfoCell(stats.l0Count != null ? String(stats.l0Count) : "…", "会话消息")
|
|
5502
5849
|
] }),
|
|
5503
|
-
note ? /* @__PURE__ */ (0,
|
|
5504
|
-
/* @__PURE__ */ (0,
|
|
5850
|
+
note ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "dsh-mem-sinfo-note", children: note }) : null,
|
|
5851
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "dsh-mem-sinfo-sum", children: "待蒸馏 " + (gl.pendingTotal || 0) + " · 上次蒸馏 " + (ago || "尚未蒸馏") })
|
|
5852
|
+
] });
|
|
5853
|
+
}
|
|
5854
|
+
|
|
5855
|
+
// client/src/pill/SessionRecalledArea.tsx
|
|
5856
|
+
var import_react23 = require("react");
|
|
5857
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
5858
|
+
var SHOW_CAP = 6;
|
|
5859
|
+
var POLL_MS2 = 4e3;
|
|
5860
|
+
var MATURITY_LABEL = { high: "成熟·高", mid: "成熟·中", low: "成熟·低" };
|
|
5861
|
+
function SessionRecalledArea(props) {
|
|
5862
|
+
const rpc = props.rpc;
|
|
5863
|
+
const sessionId = props.sessionId;
|
|
5864
|
+
const [records, setRecords] = (0, import_react23.useState)(void 0);
|
|
5865
|
+
(0, import_react23.useEffect)(() => {
|
|
5866
|
+
if (!rpc || !sessionId) return void 0;
|
|
5867
|
+
let alive = true;
|
|
5868
|
+
let timer = null;
|
|
5869
|
+
let seq = 0;
|
|
5870
|
+
const tick = () => {
|
|
5871
|
+
const token = ++seq;
|
|
5872
|
+
rpc("dsh-memory/session-recalled", { sessionId }).then((r) => {
|
|
5873
|
+
if (!alive || token !== seq) return;
|
|
5874
|
+
if (r && r.ok && r.value) setRecords(r.value.records);
|
|
5875
|
+
}).catch(() => {
|
|
5876
|
+
}).then(() => {
|
|
5877
|
+
if (alive) timer = setTimeout(tick, POLL_MS2);
|
|
5878
|
+
});
|
|
5879
|
+
};
|
|
5880
|
+
tick();
|
|
5881
|
+
return () => {
|
|
5882
|
+
alive = false;
|
|
5883
|
+
if (timer) clearTimeout(timer);
|
|
5884
|
+
};
|
|
5885
|
+
}, [rpc, sessionId]);
|
|
5886
|
+
if (records === void 0) return null;
|
|
5887
|
+
const recentFirst = [...records].reverse();
|
|
5888
|
+
const shown = recentFirst.slice(0, SHOW_CAP);
|
|
5889
|
+
const hidden = recentFirst.length - shown.length;
|
|
5890
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "dsh-mem-sinfo", children: [
|
|
5891
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
5892
|
+
"div",
|
|
5893
|
+
{
|
|
5894
|
+
style: { fontSize: 11, color: "var(--dsh-mem-text-3)", marginBottom: 6 },
|
|
5895
|
+
title: "本会话召回注入、且目前仍在上下文里的记忆(压缩/清空后自动消失,不是常驻)",
|
|
5896
|
+
children: "本会话召回 " + records.length + " 条"
|
|
5897
|
+
}
|
|
5898
|
+
),
|
|
5899
|
+
records.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { fontSize: 11, color: "var(--dsh-mem-text-3)", lineHeight: "16px" }, children: "还没召回到记忆(聊几轮后按相关性自动浮现)" }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
5900
|
+
shown.map((r) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: rowStyle, title: rowTitle(r), children: [
|
|
5901
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
5902
|
+
"span",
|
|
5903
|
+
{
|
|
5904
|
+
className: "dsh-mem-tag dsh-mem-tag-" + r.type,
|
|
5905
|
+
style: { flexShrink: 0, whiteSpace: "nowrap" },
|
|
5906
|
+
children: TYPE_LABELS[r.type] || r.type
|
|
5907
|
+
}
|
|
5908
|
+
),
|
|
5909
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "dsh-mem-sinfo-val", style: textStyle, children: r.content }),
|
|
5910
|
+
r.maturity ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { style: { fontSize: 10, color: "var(--dsh-mem-text-3)", whiteSpace: "nowrap", flexShrink: 0 }, children: MATURITY_LABEL[r.maturity] }) : null
|
|
5911
|
+
] }, r.id)),
|
|
5912
|
+
hidden > 0 ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { fontSize: 11, color: "var(--dsh-mem-text-3)" }, children: "+ " + hidden + " 条更早召回(详见面板「记忆」页)" }) : null
|
|
5913
|
+
] })
|
|
5505
5914
|
] });
|
|
5506
5915
|
}
|
|
5916
|
+
var rowStyle = {
|
|
5917
|
+
display: "flex",
|
|
5918
|
+
alignItems: "flex-start",
|
|
5919
|
+
gap: 6,
|
|
5920
|
+
lineHeight: "16px"
|
|
5921
|
+
};
|
|
5922
|
+
var textStyle = {
|
|
5923
|
+
fontSize: 12,
|
|
5924
|
+
lineHeight: "16px",
|
|
5925
|
+
fontWeight: 400,
|
|
5926
|
+
minWidth: 0,
|
|
5927
|
+
display: "-webkit-box",
|
|
5928
|
+
WebkitLineClamp: 2,
|
|
5929
|
+
WebkitBoxOrient: "vertical",
|
|
5930
|
+
overflow: "hidden"
|
|
5931
|
+
};
|
|
5932
|
+
function rowTitle(r) {
|
|
5933
|
+
const head = "[" + (TYPE_LABELS[r.type] || r.type) + "] " + r.content;
|
|
5934
|
+
const sc = r.usageScenario && r.usageScenario.length > 0 ? "\n使用场景:" + r.usageScenario.join(";") : "";
|
|
5935
|
+
return head + sc;
|
|
5936
|
+
}
|
|
5507
5937
|
|
|
5508
5938
|
// client/src/pill/WingWheel.tsx
|
|
5509
|
-
var
|
|
5939
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
5510
5940
|
var SIZE = 196;
|
|
5511
5941
|
var CENTER = SIZE / 2;
|
|
5512
5942
|
var R = 64;
|
|
@@ -5549,17 +5979,17 @@ var __defProp = Object.defineProperty;
|
|
|
5549
5979
|
function WingWheel(props) {
|
|
5550
5980
|
ensureThemeStyle();
|
|
5551
5981
|
const isOff = props.mode === "off";
|
|
5552
|
-
const [overview, setOverview] = (0,
|
|
5553
|
-
const [backfillBusy, setBackfillBusy] = (0,
|
|
5554
|
-
const [localError, setLocalError] = (0,
|
|
5555
|
-
const timersRef = (0,
|
|
5556
|
-
(0,
|
|
5982
|
+
const [overview, setOverview] = (0, import_react24.useState)(null);
|
|
5983
|
+
const [backfillBusy, setBackfillBusy] = (0, import_react24.useState)(false);
|
|
5984
|
+
const [localError, setLocalError] = (0, import_react24.useState)(null);
|
|
5985
|
+
const timersRef = (0, import_react24.useRef)([]);
|
|
5986
|
+
(0, import_react24.useEffect)(
|
|
5557
5987
|
() => () => {
|
|
5558
5988
|
for (const t of timersRef.current) window.clearTimeout(t);
|
|
5559
5989
|
},
|
|
5560
5990
|
[]
|
|
5561
5991
|
);
|
|
5562
|
-
(0,
|
|
5992
|
+
(0, import_react24.useEffect)(() => {
|
|
5563
5993
|
let alive = true;
|
|
5564
5994
|
props.rpc("dsh-memory/wing-overview", {}).then((r) => {
|
|
5565
5995
|
if (!alive) return;
|
|
@@ -5605,28 +6035,28 @@ var __defProp = Object.defineProperty;
|
|
|
5605
6035
|
finish();
|
|
5606
6036
|
});
|
|
5607
6037
|
};
|
|
5608
|
-
const boxRef = (0,
|
|
5609
|
-
const startRef = (0,
|
|
5610
|
-
const movedRef = (0,
|
|
5611
|
-
const downIndexRef = (0,
|
|
5612
|
-
const dragTargetRef = (0,
|
|
5613
|
-
const [drag, setDrag] = (0,
|
|
6038
|
+
const boxRef = (0, import_react24.useRef)(null);
|
|
6039
|
+
const startRef = (0, import_react24.useRef)(null);
|
|
6040
|
+
const movedRef = (0, import_react24.useRef)(false);
|
|
6041
|
+
const downIndexRef = (0, import_react24.useRef)(null);
|
|
6042
|
+
const dragTargetRef = (0, import_react24.useRef)(null);
|
|
6043
|
+
const [drag, setDrag] = (0, import_react24.useState)(null);
|
|
5614
6044
|
const lockedIndex = (() => {
|
|
5615
6045
|
if (props.halls.length !== 1 || !overview) return null;
|
|
5616
6046
|
const i = overview.corners.findIndex((c) => c.id === props.halls[0]);
|
|
5617
6047
|
return i >= 0 ? i : null;
|
|
5618
6048
|
})();
|
|
5619
6049
|
const activeCorner = drag ? drag.index : lockedIndex;
|
|
5620
|
-
const blockPosRef = (0,
|
|
6050
|
+
const blockPosRef = (0, import_react24.useRef)(
|
|
5621
6051
|
activeCorner != null ? cornerXY(activeCorner) : { x: CENTER, y: CENTER }
|
|
5622
6052
|
);
|
|
5623
|
-
const blockTargetRef = (0,
|
|
5624
|
-
const [blockPos, setBlockPos] = (0,
|
|
5625
|
-
(0,
|
|
6053
|
+
const blockTargetRef = (0, import_react24.useRef)(blockPosRef.current);
|
|
6054
|
+
const [blockPos, setBlockPos] = (0, import_react24.useState)(blockPosRef.current);
|
|
6055
|
+
(0, import_react24.useEffect)(() => {
|
|
5626
6056
|
blockTargetRef.current = activeCorner != null ? cornerXY(activeCorner) : { x: CENTER, y: CENTER };
|
|
5627
6057
|
}, [activeCorner]);
|
|
5628
|
-
const reducedMotionRef = (0,
|
|
5629
|
-
(0,
|
|
6058
|
+
const reducedMotionRef = (0, import_react24.useRef)(false);
|
|
6059
|
+
(0, import_react24.useEffect)(() => {
|
|
5630
6060
|
const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
5631
6061
|
const apply2 = () => {
|
|
5632
6062
|
reducedMotionRef.current = mq.matches;
|
|
@@ -5635,7 +6065,7 @@ var __defProp = Object.defineProperty;
|
|
|
5635
6065
|
mq.addEventListener("change", apply2);
|
|
5636
6066
|
return () => mq.removeEventListener("change", apply2);
|
|
5637
6067
|
}, []);
|
|
5638
|
-
(0,
|
|
6068
|
+
(0, import_react24.useEffect)(() => {
|
|
5639
6069
|
let raf = 0;
|
|
5640
6070
|
const loop = () => {
|
|
5641
6071
|
const cur = blockPosRef.current;
|
|
@@ -5724,8 +6154,8 @@ var __defProp = Object.defineProperty;
|
|
|
5724
6154
|
}).join(" ");
|
|
5725
6155
|
const grayStyle = isOff ? { opacity: 0.45, pointerEvents: "none" } : {};
|
|
5726
6156
|
const boundariesDisabled = props.halls.length === 0 || isOff;
|
|
5727
|
-
return /* @__PURE__ */ (0,
|
|
5728
|
-
/* @__PURE__ */ (0,
|
|
6157
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { width: SIZE }, children: [
|
|
6158
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
5729
6159
|
"div",
|
|
5730
6160
|
{
|
|
5731
6161
|
ref: boxRef,
|
|
@@ -5735,7 +6165,7 @@ var __defProp = Object.defineProperty;
|
|
|
5735
6165
|
onPointerUp: onBoxUp,
|
|
5736
6166
|
onPointerCancel: onBoxUp,
|
|
5737
6167
|
children: [
|
|
5738
|
-
/* @__PURE__ */ (0,
|
|
6168
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
5739
6169
|
"svg",
|
|
5740
6170
|
{
|
|
5741
6171
|
width: SIZE,
|
|
@@ -5743,7 +6173,7 @@ var __defProp = Object.defineProperty;
|
|
|
5743
6173
|
style: { position: "absolute", inset: 0, pointerEvents: "none" },
|
|
5744
6174
|
"aria-hidden": "true",
|
|
5745
6175
|
children: [
|
|
5746
|
-
/* @__PURE__ */ (0,
|
|
6176
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5747
6177
|
"polygon",
|
|
5748
6178
|
{
|
|
5749
6179
|
points: polyPoints,
|
|
@@ -5754,7 +6184,7 @@ var __defProp = Object.defineProperty;
|
|
|
5754
6184
|
opacity: 0.45
|
|
5755
6185
|
}
|
|
5756
6186
|
),
|
|
5757
|
-
/* @__PURE__ */ (0,
|
|
6187
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5758
6188
|
"polygon",
|
|
5759
6189
|
{
|
|
5760
6190
|
points: polyPoints,
|
|
@@ -5765,7 +6195,7 @@ var __defProp = Object.defineProperty;
|
|
|
5765
6195
|
),
|
|
5766
6196
|
[0, 1, 2, 3, 4, 5, 6, 7].map((i) => {
|
|
5767
6197
|
const p = cornerPos(i);
|
|
5768
|
-
return /* @__PURE__ */ (0,
|
|
6198
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5769
6199
|
"line",
|
|
5770
6200
|
{
|
|
5771
6201
|
x1: CENTER,
|
|
@@ -5781,7 +6211,7 @@ var __defProp = Object.defineProperty;
|
|
|
5781
6211
|
]
|
|
5782
6212
|
}
|
|
5783
6213
|
),
|
|
5784
|
-
/* @__PURE__ */ (0,
|
|
6214
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5785
6215
|
"div",
|
|
5786
6216
|
{
|
|
5787
6217
|
"aria-hidden": "true",
|
|
@@ -5800,7 +6230,7 @@ var __defProp = Object.defineProperty;
|
|
|
5800
6230
|
}
|
|
5801
6231
|
}
|
|
5802
6232
|
),
|
|
5803
|
-
/* @__PURE__ */ (0,
|
|
6233
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5804
6234
|
"button",
|
|
5805
6235
|
{
|
|
5806
6236
|
type: "button",
|
|
@@ -5834,7 +6264,7 @@ var __defProp = Object.defineProperty;
|
|
|
5834
6264
|
const dim = activeCorner != null && !active;
|
|
5835
6265
|
const empty = count === 0;
|
|
5836
6266
|
const p = cornerPos(i);
|
|
5837
|
-
return /* @__PURE__ */ (0,
|
|
6267
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
5838
6268
|
"div",
|
|
5839
6269
|
{
|
|
5840
6270
|
title: id ? `「${label}」${count ?? 0} 条
|
|
@@ -5863,8 +6293,8 @@ var __defProp = Object.defineProperty;
|
|
|
5863
6293
|
zIndex: 2
|
|
5864
6294
|
},
|
|
5865
6295
|
children: [
|
|
5866
|
-
/* @__PURE__ */ (0,
|
|
5867
|
-
/* @__PURE__ */ (0,
|
|
6296
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: label }),
|
|
6297
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontSize: 8, opacity: 0.75, fontVariantNumeric: "tabular-nums" }, children: count === null ? " " : empty ? "空角" : `${count} 条` })
|
|
5868
6298
|
]
|
|
5869
6299
|
},
|
|
5870
6300
|
id ?? i
|
|
@@ -5873,7 +6303,7 @@ var __defProp = Object.defineProperty;
|
|
|
5873
6303
|
]
|
|
5874
6304
|
}
|
|
5875
6305
|
),
|
|
5876
|
-
/* @__PURE__ */ (0,
|
|
6306
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
5877
6307
|
"div",
|
|
5878
6308
|
{
|
|
5879
6309
|
title: props.halls.length === 0 ? "选定某个角(单 Wing)后,这两项才生效" : "锁定 Wing 时两类无角记忆是否参与召回",
|
|
@@ -5887,9 +6317,9 @@ var __defProp = Object.defineProperty;
|
|
|
5887
6317
|
pointerEvents: boundariesDisabled ? "none" : void 0
|
|
5888
6318
|
},
|
|
5889
6319
|
children: [
|
|
5890
|
-
/* @__PURE__ */ (0,
|
|
5891
|
-
/* @__PURE__ */ (0,
|
|
5892
|
-
/* @__PURE__ */ (0,
|
|
6320
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontSize: 11, color: "var(--dsh-mem-text-3)" }, children: overview ? `另有 ${overview.unlabeled} 条未打标` : "未打标" }),
|
|
6321
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
6322
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5893
6323
|
Segmented,
|
|
5894
6324
|
{
|
|
5895
6325
|
value: props.hallIncludeUnlabeled ? "in" : "ex",
|
|
@@ -5900,7 +6330,7 @@ var __defProp = Object.defineProperty;
|
|
|
5900
6330
|
onChange: (key) => props.onCommitWingBoundaries({ includeUnlabeled: key === "in" })
|
|
5901
6331
|
}
|
|
5902
6332
|
),
|
|
5903
|
-
/* @__PURE__ */ (0,
|
|
6333
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5904
6334
|
Segmented,
|
|
5905
6335
|
{
|
|
5906
6336
|
value: props.hallIncludeGeneral ? "in" : "ex",
|
|
@@ -5915,7 +6345,7 @@ var __defProp = Object.defineProperty;
|
|
|
5915
6345
|
]
|
|
5916
6346
|
}
|
|
5917
6347
|
),
|
|
5918
|
-
/* @__PURE__ */ (0,
|
|
6348
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Row, { label: "会话", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5919
6349
|
Segmented,
|
|
5920
6350
|
{
|
|
5921
6351
|
value: isOff ? "off" : "on",
|
|
@@ -5930,7 +6360,7 @@ var __defProp = Object.defineProperty;
|
|
|
5930
6360
|
onChange: (key) => props.onCommit(key === "off" ? "off" : "auto")
|
|
5931
6361
|
}
|
|
5932
6362
|
) }),
|
|
5933
|
-
props.recall !== void 0 && props.onCommitRecall ? /* @__PURE__ */ (0,
|
|
6363
|
+
props.recall !== void 0 && props.onCommitRecall ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Row, { label: "注入", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5934
6364
|
Segmented,
|
|
5935
6365
|
{
|
|
5936
6366
|
value: props.recall === null ? "follow" : props.recall ? "on" : "off",
|
|
@@ -5943,7 +6373,7 @@ var __defProp = Object.defineProperty;
|
|
|
5943
6373
|
onChange: (key) => props.onCommitRecall(key === "on" ? true : key === "off" ? false : null)
|
|
5944
6374
|
}
|
|
5945
6375
|
) }) : null,
|
|
5946
|
-
/* @__PURE__ */ (0,
|
|
6376
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
5947
6377
|
"div",
|
|
5948
6378
|
{
|
|
5949
6379
|
style: {
|
|
@@ -5954,8 +6384,8 @@ var __defProp = Object.defineProperty;
|
|
|
5954
6384
|
marginTop: 10
|
|
5955
6385
|
},
|
|
5956
6386
|
children: [
|
|
5957
|
-
/* @__PURE__ */ (0,
|
|
5958
|
-
/* @__PURE__ */ (0,
|
|
6387
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontSize: 11, color: "var(--dsh-mem-text-3)" }, children: overview ? `未打标 ${overview.unlabeled} 条` : "未打标计数加载中" }),
|
|
6388
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5959
6389
|
ActionButton,
|
|
5960
6390
|
{
|
|
5961
6391
|
label: backfillBusy ? "回填中…" : "回填",
|
|
@@ -5967,12 +6397,13 @@ var __defProp = Object.defineProperty;
|
|
|
5967
6397
|
]
|
|
5968
6398
|
}
|
|
5969
6399
|
),
|
|
5970
|
-
props.error || localError ? /* @__PURE__ */ (0,
|
|
5971
|
-
/* @__PURE__ */ (0,
|
|
6400
|
+
props.error || localError ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { fontSize: 11, color: "var(--dsh-mem-danger)", marginTop: 8 }, children: props.error || localError }) : null,
|
|
6401
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SessionRecalledArea, { rpc: props.rpc, sessionId: props.sessionId }),
|
|
6402
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SessionInfoArea, { rpc: props.rpc, sessionId: props.sessionId })
|
|
5972
6403
|
] });
|
|
5973
6404
|
}
|
|
5974
6405
|
function Row(props) {
|
|
5975
|
-
return /* @__PURE__ */ (0,
|
|
6406
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
5976
6407
|
"div",
|
|
5977
6408
|
{
|
|
5978
6409
|
style: {
|
|
@@ -5982,7 +6413,7 @@ var __defProp = Object.defineProperty;
|
|
|
5982
6413
|
marginTop: 10
|
|
5983
6414
|
},
|
|
5984
6415
|
children: [
|
|
5985
|
-
/* @__PURE__ */ (0,
|
|
6416
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontSize: 12, color: "var(--dsh-mem-text-3)" }, children: props.label }),
|
|
5986
6417
|
props.children
|
|
5987
6418
|
]
|
|
5988
6419
|
}
|
|
@@ -5990,9 +6421,9 @@ var __defProp = Object.defineProperty;
|
|
|
5990
6421
|
}
|
|
5991
6422
|
var LABEL_FALLBACK = ["工作", "人际", "学习", "创作娱乐", "居家", "健康", "财务", "出行"];
|
|
5992
6423
|
function useViewportClamp(popRef) {
|
|
5993
|
-
const shiftRef = (0,
|
|
5994
|
-
const [shiftX, setShiftX] = (0,
|
|
5995
|
-
(0,
|
|
6424
|
+
const shiftRef = (0, import_react24.useRef)(0);
|
|
6425
|
+
const [shiftX, setShiftX] = (0, import_react24.useState)(0);
|
|
6426
|
+
(0, import_react24.useEffect)(() => {
|
|
5996
6427
|
const clamp = () => {
|
|
5997
6428
|
const el = popRef.current;
|
|
5998
6429
|
if (!el) return;
|
|
@@ -6022,24 +6453,24 @@ var __defProp = Object.defineProperty;
|
|
|
6022
6453
|
}
|
|
6023
6454
|
|
|
6024
6455
|
// client/src/pill/MemoryModePill.tsx
|
|
6025
|
-
var
|
|
6456
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
6026
6457
|
function MemoryModePill(props) {
|
|
6027
6458
|
const rpc = props.rpc;
|
|
6028
6459
|
const sessionId = props.sessionId || props.session && props.session.sessionId;
|
|
6029
|
-
const [mode, setMode] = (0,
|
|
6030
|
-
const [recall, setRecall] = (0,
|
|
6031
|
-
const [recallResolved, setRecallResolved] = (0,
|
|
6032
|
-
const [halls, setWings] = (0,
|
|
6033
|
-
const [hallIncludeUnlabeled, setWingIncludeUnlabeled] = (0,
|
|
6034
|
-
const [hallIncludeGeneral, setWingIncludeGeneral] = (0,
|
|
6035
|
-
const [wingLabels, setHallLabels] = (0,
|
|
6036
|
-
const [error, setError] = (0,
|
|
6037
|
-
const [open, setOpen] = (0,
|
|
6038
|
-
const wrapRef = (0,
|
|
6039
|
-
const popRef = (0,
|
|
6460
|
+
const [mode, setMode] = (0, import_react25.useState)(null);
|
|
6461
|
+
const [recall, setRecall] = (0, import_react25.useState)(null);
|
|
6462
|
+
const [recallResolved, setRecallResolved] = (0, import_react25.useState)(true);
|
|
6463
|
+
const [halls, setWings] = (0, import_react25.useState)([]);
|
|
6464
|
+
const [hallIncludeUnlabeled, setWingIncludeUnlabeled] = (0, import_react25.useState)(true);
|
|
6465
|
+
const [hallIncludeGeneral, setWingIncludeGeneral] = (0, import_react25.useState)(false);
|
|
6466
|
+
const [wingLabels, setHallLabels] = (0, import_react25.useState)({});
|
|
6467
|
+
const [error, setError] = (0, import_react25.useState)(null);
|
|
6468
|
+
const [open, setOpen] = (0, import_react25.useState)(false);
|
|
6469
|
+
const wrapRef = (0, import_react25.useRef)(null);
|
|
6470
|
+
const popRef = (0, import_react25.useRef)(null);
|
|
6040
6471
|
const shiftX = useViewportClamp(popRef);
|
|
6041
|
-
const seqRef = (0,
|
|
6042
|
-
const load = (0,
|
|
6472
|
+
const seqRef = (0, import_react25.useRef)(0);
|
|
6473
|
+
const load = (0, import_react25.useCallback)(() => {
|
|
6043
6474
|
if (!sessionId || !rpc) return;
|
|
6044
6475
|
const token = ++seqRef.current;
|
|
6045
6476
|
setError(null);
|
|
@@ -6064,13 +6495,13 @@ var __defProp = Object.defineProperty;
|
|
|
6064
6495
|
}).catch(() => {
|
|
6065
6496
|
});
|
|
6066
6497
|
}, [sessionId, rpc]);
|
|
6067
|
-
(0,
|
|
6498
|
+
(0, import_react25.useEffect)(() => {
|
|
6068
6499
|
load();
|
|
6069
6500
|
}, [load]);
|
|
6070
|
-
(0,
|
|
6501
|
+
(0, import_react25.useEffect)(() => {
|
|
6071
6502
|
watchSidebarIcon();
|
|
6072
6503
|
}, []);
|
|
6073
|
-
(0,
|
|
6504
|
+
(0, import_react25.useEffect)(() => {
|
|
6074
6505
|
initOccupancyIndicator(
|
|
6075
6506
|
(endpoint, payload) => rpc(endpoint, payload)
|
|
6076
6507
|
);
|
|
@@ -6078,7 +6509,7 @@ var __defProp = Object.defineProperty;
|
|
|
6078
6509
|
watchContextMeter();
|
|
6079
6510
|
noteOccupancySession(sessionId ?? null);
|
|
6080
6511
|
}, [sessionId, rpc]);
|
|
6081
|
-
(0,
|
|
6512
|
+
(0, import_react25.useEffect)(() => {
|
|
6082
6513
|
if (!open) return;
|
|
6083
6514
|
const onDown = (e) => {
|
|
6084
6515
|
if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
|
|
@@ -6093,7 +6524,7 @@ var __defProp = Object.defineProperty;
|
|
|
6093
6524
|
document.removeEventListener("keydown", onKey);
|
|
6094
6525
|
};
|
|
6095
6526
|
}, [open]);
|
|
6096
|
-
const
|
|
6527
|
+
const commit2 = (next) => {
|
|
6097
6528
|
if (!rpc || !sessionId || mode === null || next === mode) return;
|
|
6098
6529
|
const prev = mode;
|
|
6099
6530
|
const token = seqRef.current;
|
|
@@ -6218,8 +6649,8 @@ var __defProp = Object.defineProperty;
|
|
|
6218
6649
|
pillStyle.boxShadow = "0 0 12px color-mix(in srgb, " + info.color + " 30%, transparent)";
|
|
6219
6650
|
pillStyle["--dsh-mem-pill-tint"] = info.color;
|
|
6220
6651
|
}
|
|
6221
|
-
return /* @__PURE__ */ (0,
|
|
6222
|
-
/* @__PURE__ */ (0,
|
|
6652
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { ref: wrapRef, style: { position: "relative", display: "inline-flex" }, children: [
|
|
6653
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
6223
6654
|
"button",
|
|
6224
6655
|
{
|
|
6225
6656
|
type: "button",
|
|
@@ -6232,11 +6663,11 @@ var __defProp = Object.defineProperty;
|
|
|
6232
6663
|
style: pillStyle,
|
|
6233
6664
|
children: [
|
|
6234
6665
|
"记忆 · ",
|
|
6235
|
-
/* @__PURE__ */ (0,
|
|
6666
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: faceLabel })
|
|
6236
6667
|
]
|
|
6237
6668
|
}
|
|
6238
6669
|
),
|
|
6239
|
-
open ? /* @__PURE__ */ (0,
|
|
6670
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6240
6671
|
"div",
|
|
6241
6672
|
{
|
|
6242
6673
|
ref: popRef,
|
|
@@ -6247,19 +6678,19 @@ var __defProp = Object.defineProperty;
|
|
|
6247
6678
|
transform: "translateX(calc(-50% + " + shiftX + "px))",
|
|
6248
6679
|
zIndex: 1e3
|
|
6249
6680
|
},
|
|
6250
|
-
children: /* @__PURE__ */ (0,
|
|
6681
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6251
6682
|
"div",
|
|
6252
6683
|
{
|
|
6253
6684
|
className: "dsh-mem-popover",
|
|
6254
6685
|
style: { position: "relative", padding: "10px 12px" },
|
|
6255
|
-
children: /* @__PURE__ */ (0,
|
|
6686
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6256
6687
|
WingWheel,
|
|
6257
6688
|
{
|
|
6258
6689
|
mode: mode || "auto",
|
|
6259
6690
|
halls,
|
|
6260
6691
|
hallIncludeUnlabeled,
|
|
6261
6692
|
hallIncludeGeneral,
|
|
6262
|
-
onCommit:
|
|
6693
|
+
onCommit: commit2,
|
|
6263
6694
|
onCommitWing: commitWing,
|
|
6264
6695
|
onCommitWingBoundaries: commitWingBoundaries,
|
|
6265
6696
|
recall: loaded ? recall : void 0,
|