dsh-prime-memory 0.22.1 → 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 -1153
- 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 +20 -1
- 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/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 +3 -0
- 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 +1 -1
- package/package.json +1 -1
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,275 +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-alias-bg-layer-3, #ffffff);",
|
|
233
|
-
" --dsh-mem-bg-pop-base: var(--dsw-alias-bg-primary, #ffffff);",
|
|
234
|
-
" --dsh-mem-border: var(--dsw-alias-border-l2, rgba(0,0,0,0.10));",
|
|
235
|
-
" --dsh-mem-border-strong: var(--dsw-alias-border-l3, rgba(0,0,0,0.12));",
|
|
236
|
-
" --dsh-mem-border-pop: var(--dsw-alias-border-inverted, rgba(0,0,0,0));",
|
|
237
|
-
" --dsh-mem-text-1: var(--dsw-alias-label-primary, #0f1115);",
|
|
238
|
-
" --dsh-mem-text-2: var(--dsw-alias-label-secondary, #61666b);",
|
|
239
|
-
" --dsh-mem-text-3: var(--dsw-alias-label-tertiary, #6e7781);",
|
|
240
|
-
" --dsh-mem-danger: var(--dsw-alias-state-error-primary, #d0403f);",
|
|
241
|
-
// 成本折线图系列色:8 档固定色;PALETTE 只引用 var(),1 档锚品牌蓝、8 档中性"其他"
|
|
242
|
-
" --dsh-mem-chart-1: #4d6bfe;",
|
|
243
|
-
" --dsh-mem-chart-2: #0e9c8f;",
|
|
244
|
-
" --dsh-mem-chart-3: #1f9d55;",
|
|
245
|
-
" --dsh-mem-chart-4: #a8821c;",
|
|
246
|
-
" --dsh-mem-chart-5: #d97a0d;",
|
|
247
|
-
" --dsh-mem-chart-6: #d64570;",
|
|
248
|
-
" --dsh-mem-chart-7: #7c5cff;",
|
|
249
|
-
" --dsh-mem-chart-8: #61666b;",
|
|
250
|
-
// 档位色 = 灰 → 品牌蓝的渐变阶(chat/work 过渡蓝、auto 品牌蓝);
|
|
251
|
-
// 文字对比度按 pill 实际底色(流光内底 = bg-card 97% + 档位色 3%)复算 AA 达标
|
|
252
|
-
" --dsh-mem-mode-chat: #5a69b0;",
|
|
253
|
-
" --dsh-mem-mode-work: #5263ca;",
|
|
254
|
-
" --dsh-mem-mode-auto: #3d5be0;",
|
|
255
|
-
// 开关旋钮 / 进度条底(滑轨已随 ModeSlider 删除,填充渐变与停点令牌一并移除)
|
|
256
|
-
" --dsh-mem-thumb: #ffffff;",
|
|
257
|
-
" --dsh-mem-track: rgba(128,140,150,0.32);",
|
|
258
|
-
// wing 八边形令牌(WingWheel):连线 / 角默认 / 角选中 / 空角与未打标态;
|
|
259
|
-
// 全部引用既有中性色与品牌蓝体系,双主题各自声明,无裸色溢出
|
|
260
|
-
" --dsh-mem-wing-line: rgba(128,140,150,0.35);",
|
|
261
|
-
" --dsh-mem-wing-corner: var(--dsh-mem-text-2);",
|
|
262
|
-
" --dsh-mem-wing-corner-on: var(--dsh-mem-accent);",
|
|
263
|
-
" --dsh-mem-wing-empty: var(--dsh-mem-text-3);",
|
|
264
|
-
" --dsh-mem-shadow-card: var(--dsw-shadow-lv1, 0 2px 4px 0 rgba(0,0,0,0.05));",
|
|
265
|
-
" --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,
|
|
266
534
|
"}",
|
|
267
|
-
// ── 令牌(暗色:body[data-ds-dark-theme] 是 dsh 前端的暗色开关) ──
|
|
268
535
|
"body[data-ds-dark-theme] {",
|
|
269
|
-
|
|
270
|
-
" --dsh-mem-accent-text: #7b90ff;",
|
|
271
|
-
" --dsh-mem-accent-fill: #465ce8;",
|
|
272
|
-
" --dsh-mem-accent-weak: rgba(110,133,255,0.14);",
|
|
273
|
-
" --dsh-mem-bg-card: var(--dsw-alias-bg-layer-2, #2c2c2e);",
|
|
274
|
-
" --dsh-mem-bg-inset: var(--dsw-alias-bg-layer-1, #232324);",
|
|
275
|
-
" --dsh-mem-bg-hover: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,0.08));",
|
|
276
|
-
" --dsh-mem-bg-pop: var(--dsw-alias-bg-layer-3, #353638);",
|
|
277
|
-
" --dsh-mem-bg-pop-base: var(--dsw-alias-bg-primary, #1b1c1e);",
|
|
278
|
-
" --dsh-mem-border: var(--dsw-alias-border-l2, rgba(255,255,255,0.12));",
|
|
279
|
-
" --dsh-mem-border-strong: var(--dsw-alias-border-l3, rgba(255,255,255,0.16));",
|
|
280
|
-
" --dsh-mem-border-pop: var(--dsw-alias-border-inverted, rgba(255,255,255,0.06));",
|
|
281
|
-
" --dsh-mem-text-1: var(--dsw-alias-label-primary, #f9fafb);",
|
|
282
|
-
" --dsh-mem-text-2: var(--dsw-alias-label-secondary, #cfd3d6);",
|
|
283
|
-
" --dsh-mem-text-3: var(--dsw-alias-label-tertiary, #8892a6);",
|
|
284
|
-
" --dsh-mem-danger: var(--dsw-alias-state-error-primary, #f4707b);",
|
|
285
|
-
" --dsh-mem-chart-1: #6e85ff;",
|
|
286
|
-
" --dsh-mem-chart-2: #35c4b5;",
|
|
287
|
-
" --dsh-mem-chart-3: #52c98d;",
|
|
288
|
-
" --dsh-mem-chart-4: #d9b23e;",
|
|
289
|
-
" --dsh-mem-chart-5: #f59e5b;",
|
|
290
|
-
" --dsh-mem-chart-6: #f47ba2;",
|
|
291
|
-
" --dsh-mem-chart-7: #a78bfa;",
|
|
292
|
-
" --dsh-mem-chart-8: #8892a6;",
|
|
293
|
-
" --dsh-mem-mode-chat: #97a4ff;",
|
|
294
|
-
" --dsh-mem-mode-work: #8295ff;",
|
|
295
|
-
" --dsh-mem-mode-auto: #7b90ff;",
|
|
296
|
-
" --dsh-mem-thumb: #e8ebf5;",
|
|
297
|
-
" --dsh-mem-track: rgba(148,160,180,0.30);",
|
|
298
|
-
" --dsh-mem-wing-line: rgba(148,160,180,0.32);",
|
|
299
|
-
" --dsh-mem-wing-corner: var(--dsh-mem-text-2);",
|
|
300
|
-
" --dsh-mem-wing-corner-on: var(--dsh-mem-accent);",
|
|
301
|
-
" --dsh-mem-wing-empty: var(--dsh-mem-text-3);",
|
|
302
|
-
" --dsh-mem-shadow-card: var(--dsw-shadow-lv1, 0 2px 4px 0 rgba(0,0,0,0.3));",
|
|
303
|
-
" --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,
|
|
304
537
|
"}",
|
|
305
|
-
//
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
" padding: 5px 14px; font-size: 13px; line-height: 20px; border-radius: 8px; cursor: pointer;",
|
|
310
|
-
" border: 1px solid var(--dsh-mem-border); background: var(--dsh-mem-bg-card); color: var(--dsh-mem-text-1);",
|
|
311
|
-
" 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,
|
|
312
542
|
"}",
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
".dsh-mem-btn:focus-visible { outline: 2px solid var(--dsh-mem-accent); outline-offset: 1px; }",
|
|
316
|
-
".dsh-mem-btn:disabled { opacity: 0.45; cursor: not-allowed; }",
|
|
317
|
-
// ── 控件:输入框 / 下拉 ──
|
|
318
|
-
".dsh-mem-input {",
|
|
319
|
-
" padding: 5px 10px; font-size: 13px; border-radius: 8px; color: var(--dsh-mem-text-1);",
|
|
320
|
-
" border: 1px solid var(--dsh-mem-border); background: var(--dsh-mem-bg-card);",
|
|
321
|
-
" transition: border-color .15s ease, box-shadow .15s ease;",
|
|
543
|
+
'html[data-dsh-mem-skin="dark"] {',
|
|
544
|
+
...DARK_TOK,
|
|
322
545
|
"}",
|
|
323
|
-
|
|
324
|
-
" outline: none; border-color: var(--dsh-mem-accent);",
|
|
325
|
-
" box-shadow: 0 0 0 3px var(--dsh-mem-accent-weak);",
|
|
326
|
-
"}",
|
|
327
|
-
// ── 下拉触发钮(NSel):观感与输入框一致(8px 圆角/同令牌边框底色),
|
|
328
|
-
// 文字 ellipsis + CSS 描边 chevron(展开旋转 180°);弹出面板见 .dsh-mem-pop ──
|
|
329
|
-
".dsh-mem-select {",
|
|
330
|
-
" display: inline-flex; align-items: center; justify-content: space-between; gap: 8px;",
|
|
331
|
-
" width: 100%; min-width: 0; padding: 5px 10px; font: inherit; font-size: 13px; line-height: 20px;",
|
|
332
|
-
" text-align: left; border-radius: 8px; cursor: pointer; color: var(--dsh-mem-text-1);",
|
|
333
|
-
" border: 1px solid var(--dsh-mem-border); background: var(--dsh-mem-bg-card);",
|
|
334
|
-
" transition: border-color .15s ease, box-shadow .15s ease;",
|
|
335
|
-
"}",
|
|
336
|
-
".dsh-mem-select:focus-visible {",
|
|
337
|
-
" outline: none; border-color: var(--dsh-mem-accent);",
|
|
338
|
-
" box-shadow: 0 0 0 3px var(--dsh-mem-accent-weak);",
|
|
339
|
-
"}",
|
|
340
|
-
".dsh-mem-select:disabled { opacity: 0.45; cursor: not-allowed; }",
|
|
341
|
-
".dsh-mem-select-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }",
|
|
342
|
-
// 下拉弹出面板:dsh MenuDropdown 同款——浮层 12 圆角 + menu 底 + lv3 投影;
|
|
343
|
-
// 选项行 10 圆角 + hover 底色 + 选中打勾(active 由 data-active 标记)
|
|
344
|
-
".dsh-mem-sel { position: relative; display: inline-flex; min-width: 0; vertical-align: top; }",
|
|
345
|
-
".dsh-mem-sel-chev {",
|
|
346
|
-
" width: 8px; height: 8px; flex: none; margin-right: 2px;",
|
|
347
|
-
" border-right: 1.5px solid var(--dsh-mem-text-3); border-bottom: 1.5px solid var(--dsh-mem-text-3);",
|
|
348
|
-
" transform: rotate(45deg); transition: transform .12s ease;",
|
|
349
|
-
"}",
|
|
350
|
-
".dsh-mem-sel-chev-open { transform: rotate(225deg); }",
|
|
351
|
-
".dsh-mem-pop {",
|
|
352
|
-
" position: absolute; top: calc(100% + 6px); left: 0; z-index: 30;",
|
|
353
|
-
" min-width: 100%; width: max-content; max-width: 340px; max-height: 264px;",
|
|
354
|
-
" overflow-y: auto; overscroll-behavior: contain; padding: 4px;",
|
|
355
|
-
" // 不透明实底:基色垫底+别名色整层叠印(别名即使带 alpha 也被垫死),2026-10-09 用户修复",
|
|
356
|
-
" 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);",
|
|
357
|
-
" border-radius: 12px; box-shadow: var(--dsh-mem-shadow-pop);",
|
|
358
|
-
"}",
|
|
359
|
-
".dsh-mem-pop-opt {",
|
|
360
|
-
" display: flex; align-items: center; gap: 8px; width: 100%; box-sizing: border-box;",
|
|
361
|
-
" min-height: 32px; padding: 5px 10px; font: inherit; font-size: 13px; line-height: 20px;",
|
|
362
|
-
" text-align: left; color: var(--dsh-mem-text-1); cursor: pointer;",
|
|
363
|
-
" background: none; border: none; outline: none; border-radius: 10px;",
|
|
364
|
-
"}",
|
|
365
|
-
'.dsh-mem-pop-opt:hover, .dsh-mem-pop-opt[data-active="1"] { background: var(--dsh-mem-bg-hover); }',
|
|
366
|
-
".dsh-mem-pop-opt-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }",
|
|
367
|
-
".dsh-mem-pop-check { flex: none; font-size: 12px; color: var(--dsh-mem-text-1); }",
|
|
368
|
-
".dsh-mem-pop-empty { padding: 10px; font-size: 13px; color: var(--dsh-mem-text-3); }",
|
|
369
|
-
// ── Tab(下划线式):active 品牌蓝下划线 + 主文字色 ──
|
|
370
|
-
".dsh-mem-tab {",
|
|
371
|
-
" padding: 6px 12px; font-size: 13px; cursor: pointer; background: none; border: none;",
|
|
372
|
-
" color: var(--dsh-mem-text-2); border-bottom: 2px solid transparent; margin-bottom: -1px;",
|
|
373
|
-
"}",
|
|
374
|
-
".dsh-mem-tab:hover { color: var(--dsh-mem-text-1); }",
|
|
375
|
-
".dsh-mem-tab-on { font-weight: 600; color: var(--dsh-mem-text-1); border-bottom-color: var(--dsh-mem-accent); }",
|
|
376
|
-
".dsh-mem-tab:focus-visible { outline: 2px solid var(--dsh-mem-accent); outline-offset: -2px; }",
|
|
377
|
-
// ── 卡片:hover 微抬(边框加深),只给可交互卡片用 ──
|
|
378
|
-
".dsh-mem-card {",
|
|
379
|
-
" border: 1px solid var(--dsh-mem-border); border-radius: 10px; background: var(--dsh-mem-bg-card);",
|
|
380
|
-
" box-shadow: var(--dsh-mem-shadow-card);",
|
|
381
|
-
"}",
|
|
382
|
-
".dsh-mem-card-hover:hover { border-color: var(--dsh-mem-border-strong); }",
|
|
383
|
-
// ── 场景卡折叠箭头:展开态旋转 90°(进 reduced-motion 压制名单) ──
|
|
384
|
-
".dsh-mem-scene-chev { display: inline-block; transition: transform .15s ease; color: var(--dsh-mem-text-3); }",
|
|
385
|
-
// ── 记忆类型标签:tint 风格(彩底淡色 + 彩字),--dsh-mem-tag-c 由类型类给定 ──
|
|
386
|
-
".dsh-mem-tag {",
|
|
387
|
-
" display: inline-block; padding: 1px 8px; border-radius: 999px;",
|
|
388
|
-
" font-size: 11px; font-weight: 600; line-height: 18px; white-space: nowrap;",
|
|
389
|
-
" color: var(--dsh-mem-tag-c, var(--dsh-mem-text-2));",
|
|
390
|
-
" background: color-mix(in srgb, var(--dsh-mem-tag-c, #8a93a1) 12%, transparent);",
|
|
391
|
-
" border: 1px solid color-mix(in srgb, var(--dsh-mem-tag-c, #8a93a1) 28%, transparent);",
|
|
392
|
-
"}",
|
|
393
|
-
".dsh-mem-tag-persona { --dsh-mem-tag-c: #6f42c1; }",
|
|
394
|
-
".dsh-mem-tag-episodic { --dsh-mem-tag-c: #0757b4; }",
|
|
395
|
-
".dsh-mem-tag-instruction, .dsh-mem-tag-work-artifact { --dsh-mem-tag-c: #8a5a00; }",
|
|
396
|
-
".dsh-mem-tag-work-fact { --dsh-mem-tag-c: #0757b4; }",
|
|
397
|
-
".dsh-mem-tag-work-task { --dsh-mem-tag-c: #116629; }",
|
|
398
|
-
".dsh-mem-tag-work-method { --dsh-mem-tag-c: #6f42c1; }",
|
|
399
|
-
"body[data-ds-dark-theme] .dsh-mem-tag-persona { --dsh-mem-tag-c: #c297ff; }",
|
|
400
|
-
"body[data-ds-dark-theme] .dsh-mem-tag-episodic { --dsh-mem-tag-c: #6cb2ff; }",
|
|
401
|
-
"body[data-ds-dark-theme] .dsh-mem-tag-instruction, body[data-ds-dark-theme] .dsh-mem-tag-work-artifact { --dsh-mem-tag-c: #e3b341; }",
|
|
402
|
-
"body[data-ds-dark-theme] .dsh-mem-tag-work-fact { --dsh-mem-tag-c: #6cb2ff; }",
|
|
403
|
-
"body[data-ds-dark-theme] .dsh-mem-tag-work-task { --dsh-mem-tag-c: #6fca74; }",
|
|
404
|
-
"body[data-ds-dark-theme] .dsh-mem-tag-work-method { --dsh-mem-tag-c: #c297ff; }",
|
|
405
|
-
// ── pill 边缘流光(品牌蓝族,chat/work/auto 三档共用;off 无):border 区画旋转
|
|
406
|
-
// conic 光带;内部必须用【不透明】底色盖住光带——半透明内层会让 conic 透进按钮
|
|
407
|
-
// 内部干扰文字(实测事故)。不透明底 = 主题底混 3% 档位色(--dsh-mem-pill-tint
|
|
408
|
-
// 由 pill inline 给定;3% 保证档位色文字 AA,暗色智能档余量 4.63:1)
|
|
409
|
-
".dsh-mem-flow {",
|
|
410
|
-
" border: 1px solid transparent;",
|
|
411
|
-
" background:",
|
|
412
|
-
" linear-gradient(",
|
|
413
|
-
" color-mix(in srgb, var(--dsh-mem-bg-card, #ffffff) 97%, var(--dsh-mem-pill-tint, #4d6bfe)),",
|
|
414
|
-
" color-mix(in srgb, var(--dsh-mem-bg-card, #ffffff) 97%, var(--dsh-mem-pill-tint, #4d6bfe))",
|
|
415
|
-
" ) padding-box,",
|
|
416
|
-
" conic-gradient(from var(--dsh-mem-angle),",
|
|
417
|
-
" rgba(61,91,224,0.9), rgba(77,107,254,0.95), rgba(147,168,255,1),",
|
|
418
|
-
" rgba(110,133,255,0.9), rgba(61,91,224,0.9)) border-box;",
|
|
419
|
-
" animation: dshMemFlow 3s linear infinite;",
|
|
420
|
-
"}",
|
|
421
|
-
// ── off 档 pill:dsh 透明按钮——无底无边框只留文字,hover 才出 interactive 淡底
|
|
422
|
-
//(裸 button 会露 UA 默认灰底+描边,必须显式压掉) ──
|
|
423
|
-
".dsh-mem-pill-off { border: none; background: transparent; }",
|
|
424
|
-
".dsh-mem-pill-off:hover { background: var(--dsh-mem-bg-hover); }",
|
|
425
|
-
".dsh-mem-pill-off:focus-visible { outline: 2px solid var(--dsh-mem-accent); outline-offset: 1px; }",
|
|
426
|
-
// 流光态焦点环(同一物理按钮的两态焦点反馈对称,配方同 .dsh-mem-btn)
|
|
427
|
-
".dsh-mem-flow:focus-visible { outline: 2px solid var(--dsh-mem-accent); outline-offset: 1px; }",
|
|
428
|
-
// ── 触屏隐形热区(手机端适配):触点目标补足 44px 标准(iOS HIG)。
|
|
429
|
-
// 伪元素不参与布局(浮层/输入栏几何零变化),指针事件落在宿主元素上。
|
|
430
|
-
// 全端统一不做 pointer:coarse 分端(桌面点中目标变大是纯收益)。
|
|
431
|
-
// pill:视觉高 24px,::after 上下各外扩 10px;只上下不左右——左右是宿主输入栏
|
|
432
|
-
// 邻位控件(模式选择器),外扩会制造误触重叠带 ──
|
|
433
|
-
".dsh-mem-pill-hit::after {",
|
|
434
|
-
" content: ''; position: absolute; left: 0; right: 0; top: -10px; bottom: -10px;",
|
|
435
|
-
"}",
|
|
436
|
-
// ── 浮层(dsh 原生菜单同配方:不透明实底 + inverted 描边(浅色不可见)+ lv3 阴影) ──
|
|
437
|
-
".dsh-mem-popover {",
|
|
438
|
-
" border-radius: 12px;",
|
|
439
|
-
" border: 1px solid var(--dsh-mem-border-pop);",
|
|
440
|
-
" background: linear-gradient(var(--dsh-mem-bg-pop), var(--dsh-mem-bg-pop)) , var(--dsh-mem-bg-pop-base);",
|
|
441
|
-
" box-shadow: var(--dsh-mem-shadow-pop);",
|
|
442
|
-
" color: var(--dsh-mem-text-1);",
|
|
443
|
-
"}",
|
|
444
|
-
// ── 重建面板 ──(模态本体走 NModal:原生 Modal 优先,回退 rb-overlay/rb-modal)
|
|
445
|
-
".dsh-mem-rb-card {",
|
|
446
|
-
" border: 1px solid var(--dsh-mem-border); border-radius: 10px; background: var(--dsh-mem-bg-card);",
|
|
447
|
-
" box-shadow: var(--dsh-mem-shadow-card); padding: 12px 14px; margin-bottom: 14px; font-size: 13px;",
|
|
448
|
-
// 剪掉行内溢出的固定宽控件(如维度输入框),防其顶破卡片圆角边界
|
|
449
|
-
" overflow: hidden;",
|
|
450
|
-
"}",
|
|
451
|
-
".dsh-mem-rb-bar { height: 8px; border-radius: 4px; overflow: hidden; flex: 1; background: var(--dsh-mem-track); }",
|
|
452
|
-
".dsh-mem-rb-fill { height: 100%; border-radius: 4px; background: var(--dsh-mem-accent-fill); transition: width .4s ease; }",
|
|
453
|
-
// 无位移阶段(单次 LLM 调用可达分钟级)的呼吸进度条:宽度满格,透明度呼吸表达"在跑"
|
|
454
|
-
"@keyframes dshMemRbBreath { 0%,100% { opacity: 1; } 50% { opacity: .35; } }",
|
|
455
|
-
".dsh-mem-rb-fill-indet { animation: dshMemRbBreath 1.6s ease-in-out infinite; transition: none; }",
|
|
456
|
-
".dsh-mem-rb-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.35);",
|
|
457
|
-
" display: flex; align-items: center; justify-content: center; z-index: 2000; }",
|
|
458
|
-
".dsh-mem-rb-modal { width: 440px; max-width: calc(100vw - 48px); border-radius: 12px;",
|
|
459
|
-
" padding: 18px 20px; font-size: 13px; line-height: 1.6;",
|
|
460
|
-
" border: 1px solid var(--dsh-mem-border); background: var(--dsh-mem-bg-card); color: var(--dsh-mem-text-1);",
|
|
461
|
-
" box-shadow: 0 16px 48px rgba(0,0,0,0.24); }",
|
|
462
|
-
"body[data-ds-dark-theme] .dsh-mem-rb-modal { box-shadow: 0 16px 48px rgba(0,0,0,0.6); }",
|
|
463
|
-
".dsh-mem-rb-muted { font-size: 12px; color: var(--dsh-mem-text-3); }",
|
|
464
|
-
// ── 会话信息区(悬浮卡下半部):分隔线 + 2×2 指标 + 状态行;纯静态 DOM,
|
|
465
|
-
// 不挂 rAF 循环,轮询数据到达才触发本组件小树 re-render ──
|
|
466
|
-
".dsh-mem-sinfo { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--dsh-mem-border); }",
|
|
467
|
-
".dsh-mem-sinfo-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 10px; }",
|
|
468
|
-
".dsh-mem-sinfo-val { font-size: 13px; font-weight: 600; color: var(--dsh-mem-text-1); line-height: 18px; font-variant-numeric: tabular-nums; }",
|
|
469
|
-
".dsh-mem-sinfo-label { font-size: 11px; color: var(--dsh-mem-text-3); line-height: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }",
|
|
470
|
-
".dsh-mem-sinfo-warn { font-size: 11px; color: var(--dsh-mem-danger); line-height: 16px; margin-bottom: 6px; }",
|
|
471
|
-
".dsh-mem-sinfo-note { font-size: 11px; color: var(--dsh-mem-text-3); line-height: 16px; margin-top: 8px; }",
|
|
472
|
-
".dsh-mem-sinfo-sum { font-size: 11px; color: var(--dsh-mem-text-3); line-height: 16px; margin-top: 8px; }",
|
|
473
|
-
// reduced-motion 兜底放样式表末尾:同特异性下后置声明才能压过上面的组件类
|
|
474
|
-
"@media (prefers-reduced-motion: reduce) {",
|
|
475
|
-
" .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; }",
|
|
476
|
-
" .dsh-mem-flow { animation: none; }",
|
|
477
|
-
"}"
|
|
546
|
+
...COMPONENT_CSS
|
|
478
547
|
].join("\n");
|
|
479
|
-
|
|
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);
|
|
480
558
|
}
|
|
481
559
|
|
|
482
560
|
// client/src/tabs/ConflictsTab.tsx
|
|
@@ -808,46 +886,243 @@ var __defProp = Object.defineProperty;
|
|
|
808
886
|
}
|
|
809
887
|
function Side(props) {
|
|
810
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;
|
|
811
890
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: 6 }, children: [
|
|
812
891
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...S.muted, fontWeight: props.accent ? 600 : void 0 }, children: props.label }),
|
|
813
892
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: S.content, children: props.content || GONE }),
|
|
814
893
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...S.muted, fontFamily: "ui-monospace, Consolas, monospace" }, children: props.id }),
|
|
815
|
-
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
|
|
816
896
|
] });
|
|
817
897
|
}
|
|
818
898
|
|
|
819
|
-
// client/src/tabs/
|
|
899
|
+
// client/src/tabs/ConnectTab.tsx
|
|
820
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");
|
|
821
1096
|
|
|
822
1097
|
// client/src/ui/controls.tsx
|
|
823
|
-
var
|
|
1098
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
824
1099
|
function Switch(props) {
|
|
825
1100
|
const on = !!props.checked;
|
|
826
1101
|
const disabled = !!props.disabled;
|
|
827
1102
|
const base = { ...S.switch, ...on ? S.switchOn : S.switchOff, ...disabled ? S.switchDisabled : null };
|
|
828
|
-
return /* @__PURE__ */ (0,
|
|
1103
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
829
1104
|
"div",
|
|
830
1105
|
{
|
|
831
1106
|
style: base,
|
|
832
1107
|
onClick: () => {
|
|
833
1108
|
if (!disabled && props.onChange) props.onChange(!on);
|
|
834
1109
|
},
|
|
835
|
-
children: /* @__PURE__ */ (0,
|
|
1110
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { ...S.knob, left: on ? 18 : 2 } })
|
|
836
1111
|
}
|
|
837
1112
|
);
|
|
838
1113
|
}
|
|
839
1114
|
function SwitchRow(props) {
|
|
840
|
-
return /* @__PURE__ */ (0,
|
|
841
|
-
/* @__PURE__ */ (0,
|
|
842
|
-
/* @__PURE__ */ (0,
|
|
843
|
-
/* @__PURE__ */ (0,
|
|
844
|
-
/* @__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 || "" })
|
|
845
1120
|
] })
|
|
846
1121
|
] });
|
|
847
1122
|
}
|
|
848
1123
|
function ActionButton(props) {
|
|
849
1124
|
const disabled = !!props.disabled;
|
|
850
|
-
return /* @__PURE__ */ (0,
|
|
1125
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
851
1126
|
"button",
|
|
852
1127
|
{
|
|
853
1128
|
type: "button",
|
|
@@ -871,10 +1146,10 @@ var __defProp = Object.defineProperty;
|
|
|
871
1146
|
function Segmented(props) {
|
|
872
1147
|
const value = props.value;
|
|
873
1148
|
const disabled = !!props.disabled;
|
|
874
|
-
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) => {
|
|
875
1150
|
const on = opt.key === value;
|
|
876
1151
|
const optDisabled = disabled || !!opt.disabled;
|
|
877
|
-
return /* @__PURE__ */ (0,
|
|
1152
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
878
1153
|
"span",
|
|
879
1154
|
{
|
|
880
1155
|
title: opt.disabledTitle || opt.title || "",
|
|
@@ -895,7 +1170,7 @@ var __defProp = Object.defineProperty;
|
|
|
895
1170
|
}
|
|
896
1171
|
|
|
897
1172
|
// client/src/tabs/CostTab.tsx
|
|
898
|
-
var
|
|
1173
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
899
1174
|
function renderCostChart(buckets, models, maxY, fmtDate, fmtInt, palette) {
|
|
900
1175
|
const W = 600;
|
|
901
1176
|
const H = 200;
|
|
@@ -910,17 +1185,17 @@ var __defProp = Object.defineProperty;
|
|
|
910
1185
|
const y = (v) => T + ih - v / maxY * ih;
|
|
911
1186
|
const yTicks = [0, maxY / 2, maxY];
|
|
912
1187
|
const xIdx = n > 2 ? [0, Math.floor((n - 1) / 2), n - 1] : n === 2 ? [0, 1] : [0];
|
|
913
|
-
return /* @__PURE__ */ (0,
|
|
914
|
-
/* @__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 }),
|
|
915
1190
|
yTicks.map((v) => {
|
|
916
|
-
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);
|
|
917
1192
|
}),
|
|
918
1193
|
xIdx.map((i) => {
|
|
919
|
-
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);
|
|
920
1195
|
}),
|
|
921
1196
|
models.map((m, mi) => {
|
|
922
1197
|
const pts = buckets.map((b, i) => x(i) + "," + y(b.byModel[m] || 0)).join(" ");
|
|
923
|
-
return /* @__PURE__ */ (0,
|
|
1198
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
924
1199
|
"polyline",
|
|
925
1200
|
{
|
|
926
1201
|
points: pts,
|
|
@@ -964,13 +1239,13 @@ var __defProp = Object.defineProperty;
|
|
|
964
1239
|
var tdStyle = { fontSize: 12.5, color: "var(--dsh-mem-text-1)", textAlign: "right", padding: "4px 10px", fontFamily: "ui-monospace, Consolas, monospace" };
|
|
965
1240
|
function CostTab(props) {
|
|
966
1241
|
const rpc = props.rpc;
|
|
967
|
-
const [data, setData] = (0,
|
|
968
|
-
const [error, setError] = (0,
|
|
969
|
-
const [granularity, setGranularity] = (0,
|
|
970
|
-
const [layer, setLayer] = (0,
|
|
971
|
-
const [rangeDays, setRangeDays] = (0,
|
|
972
|
-
const [rangeOpen, setRangeOpen] = (0,
|
|
973
|
-
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)(() => {
|
|
974
1249
|
setError(null);
|
|
975
1250
|
rpc("dsh-memory/token-cost", {
|
|
976
1251
|
granularity,
|
|
@@ -982,7 +1257,7 @@ var __defProp = Object.defineProperty;
|
|
|
982
1257
|
setError(String(e && e.message || e));
|
|
983
1258
|
});
|
|
984
1259
|
}, [rpc, granularity, rangeDays]);
|
|
985
|
-
(0,
|
|
1260
|
+
(0, import_react5.useEffect)(() => {
|
|
986
1261
|
load();
|
|
987
1262
|
const timer = setInterval(load, 5e3);
|
|
988
1263
|
return () => {
|
|
@@ -1055,13 +1330,13 @@ var __defProp = Object.defineProperty;
|
|
|
1055
1330
|
});
|
|
1056
1331
|
const cell = (lc, r, pick) => {
|
|
1057
1332
|
const w = lc.win[r];
|
|
1058
|
-
return /* @__PURE__ */ (0,
|
|
1333
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { style: tdStyle, children: w ? fmtInt(pick(w)) : "0" }, r);
|
|
1059
1334
|
};
|
|
1060
|
-
return /* @__PURE__ */ (0,
|
|
1061
|
-
/* @__PURE__ */ (0,
|
|
1062
|
-
/* @__PURE__ */ (0,
|
|
1063
|
-
/* @__PURE__ */ (0,
|
|
1064
|
-
/* @__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)(
|
|
1065
1340
|
NButton,
|
|
1066
1341
|
{
|
|
1067
1342
|
onClick: () => {
|
|
@@ -1070,12 +1345,12 @@ var __defProp = Object.defineProperty;
|
|
|
1070
1345
|
children: rangeDays > 0 ? "近 " + rangeDays + " 天" : "近N天"
|
|
1071
1346
|
}
|
|
1072
1347
|
),
|
|
1073
|
-
/* @__PURE__ */ (0,
|
|
1074
|
-
/* @__PURE__ */ (0,
|
|
1348
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: S.grow }),
|
|
1349
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(NButton, { onClick: load, children: "刷新" })
|
|
1075
1350
|
] }),
|
|
1076
|
-
rangeOpen ? /* @__PURE__ */ (0,
|
|
1077
|
-
/* @__PURE__ */ (0,
|
|
1078
|
-
/* @__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)(
|
|
1079
1354
|
NInput,
|
|
1080
1355
|
{
|
|
1081
1356
|
value: rangeDays === 0 ? "" : String(rangeDays),
|
|
@@ -1093,94 +1368,94 @@ var __defProp = Object.defineProperty;
|
|
|
1093
1368
|
}
|
|
1094
1369
|
)
|
|
1095
1370
|
] }) : null,
|
|
1096
|
-
error ? /* @__PURE__ */ (0,
|
|
1097
|
-
/* @__PURE__ */ (0,
|
|
1098
|
-
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: [
|
|
1099
1374
|
renderCostChart(buckets, models, maxY, fmtDate, fmtInt, PALETTE),
|
|
1100
|
-
/* @__PURE__ */ (0,
|
|
1101
|
-
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)(
|
|
1102
1377
|
"span",
|
|
1103
1378
|
{
|
|
1104
1379
|
style: { display: "inline-flex", alignItems: "center", gap: 4, fontSize: 12, color: "var(--dsh-mem-text-2)" },
|
|
1105
1380
|
children: [
|
|
1106
|
-
/* @__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" } }),
|
|
1107
1382
|
m
|
|
1108
1383
|
]
|
|
1109
1384
|
},
|
|
1110
1385
|
"lg" + m
|
|
1111
1386
|
);
|
|
1112
1387
|
}) })
|
|
1113
|
-
] }) : /* @__PURE__ */ (0,
|
|
1114
|
-
/* @__PURE__ */ (0,
|
|
1115
|
-
/* @__PURE__ */ (0,
|
|
1116
|
-
/* @__PURE__ */ (0,
|
|
1117
|
-
/* @__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: "层级" }),
|
|
1118
1393
|
RANGES.map((r) => {
|
|
1119
|
-
return /* @__PURE__ */ (0,
|
|
1394
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { style: thStyle, children: RANGE_LABELS[r] }, r);
|
|
1120
1395
|
})
|
|
1121
1396
|
] }) }),
|
|
1122
|
-
/* @__PURE__ */ (0,
|
|
1123
|
-
return /* @__PURE__ */ (0,
|
|
1124
|
-
/* @__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() }),
|
|
1125
1400
|
RANGES.map((r) => cell(lc, r, (w) => w.outputTokens))
|
|
1126
1401
|
] }, lc.layer);
|
|
1127
1402
|
}) })
|
|
1128
1403
|
] }),
|
|
1129
|
-
/* @__PURE__ */ (0,
|
|
1130
|
-
/* @__PURE__ */ (0,
|
|
1131
|
-
/* @__PURE__ */ (0,
|
|
1132
|
-
/* @__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: "层级" }),
|
|
1133
1408
|
RANGES.map((r) => {
|
|
1134
|
-
return /* @__PURE__ */ (0,
|
|
1409
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { style: thStyle, children: RANGE_LABELS[r] + "-avg" }, r);
|
|
1135
1410
|
})
|
|
1136
1411
|
] }) }),
|
|
1137
|
-
/* @__PURE__ */ (0,
|
|
1138
|
-
return /* @__PURE__ */ (0,
|
|
1139
|
-
/* @__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() }),
|
|
1140
1415
|
RANGES.map((r) => cell(lc, r, (w) => w.avgOutputTokens))
|
|
1141
1416
|
] }, lc.layer);
|
|
1142
1417
|
}) })
|
|
1143
1418
|
] }),
|
|
1144
|
-
/* @__PURE__ */ (0,
|
|
1145
|
-
/* @__PURE__ */ (0,
|
|
1146
|
-
/* @__PURE__ */ (0,
|
|
1147
|
-
/* @__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: "层级" }),
|
|
1148
1423
|
RANGES.map((r) => {
|
|
1149
|
-
return /* @__PURE__ */ (0,
|
|
1424
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { style: thStyle, children: RANGE_LABELS[r] + "-median" }, r);
|
|
1150
1425
|
})
|
|
1151
1426
|
] }) }),
|
|
1152
|
-
/* @__PURE__ */ (0,
|
|
1153
|
-
return /* @__PURE__ */ (0,
|
|
1154
|
-
/* @__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() }),
|
|
1155
1430
|
RANGES.map((r) => cell(lc, r, (w) => w.medianOutputTokens))
|
|
1156
1431
|
] }, lc.layer);
|
|
1157
1432
|
}) })
|
|
1158
1433
|
] }),
|
|
1159
|
-
/* @__PURE__ */ (0,
|
|
1160
|
-
/* @__PURE__ */ (0,
|
|
1161
|
-
return /* @__PURE__ */ (0,
|
|
1162
|
-
/* @__PURE__ */ (0,
|
|
1163
|
-
/* @__PURE__ */ (0,
|
|
1164
|
-
/* @__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 + " 次调用" })
|
|
1165
1440
|
] }, w.range);
|
|
1166
1441
|
}) }),
|
|
1167
|
-
byModel.length > 0 ? /* @__PURE__ */ (0,
|
|
1168
|
-
/* @__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: "按模型(累计)" }),
|
|
1169
1444
|
byModel.map((m) => {
|
|
1170
1445
|
const label = fmtModel(m.provider, m.model);
|
|
1171
|
-
return /* @__PURE__ */ (0,
|
|
1172
|
-
/* @__PURE__ */ (0,
|
|
1173
|
-
/* @__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) })
|
|
1174
1449
|
] }, "m-" + label);
|
|
1175
1450
|
})
|
|
1176
1451
|
] }) : null,
|
|
1177
|
-
data ? /* @__PURE__ */ (0,
|
|
1452
|
+
data ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { style: S.hint, children: "输入按字符、输出/思考按 token 计;趋势图 Y 轴为输出 token,上方可切换层级与颗粒度。" }) : null
|
|
1178
1453
|
] });
|
|
1179
1454
|
}
|
|
1180
1455
|
|
|
1181
1456
|
// client/src/tabs/LogTab.tsx
|
|
1182
|
-
var
|
|
1183
|
-
var
|
|
1457
|
+
var import_react6 = require("react");
|
|
1458
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1184
1459
|
var SOURCES = [
|
|
1185
1460
|
{ id: "", label: "系统日志" },
|
|
1186
1461
|
{ id: "recall_turn", label: "召回追踪" },
|
|
@@ -1203,11 +1478,11 @@ var __defProp = Object.defineProperty;
|
|
|
1203
1478
|
}
|
|
1204
1479
|
function LogTab(props) {
|
|
1205
1480
|
const rpc = props.rpc;
|
|
1206
|
-
const [source, setSource] = (0,
|
|
1207
|
-
const [lines, setLines] = (0,
|
|
1208
|
-
const [error, setError] = (0,
|
|
1209
|
-
const preRef = (0,
|
|
1210
|
-
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)(() => {
|
|
1211
1486
|
setError(null);
|
|
1212
1487
|
if (source === "") {
|
|
1213
1488
|
rpc("dsh-memory/log-tail", { lines: 200 }).then((r) => {
|
|
@@ -1221,25 +1496,25 @@ var __defProp = Object.defineProperty;
|
|
|
1221
1496
|
else setError(r && r.error ? r.error.message : "RPC error");
|
|
1222
1497
|
}).catch((e) => setError(String(e && e.message || e)));
|
|
1223
1498
|
}, [rpc, source]);
|
|
1224
|
-
(0,
|
|
1499
|
+
(0, import_react6.useEffect)(() => {
|
|
1225
1500
|
load();
|
|
1226
1501
|
}, [load]);
|
|
1227
|
-
(0,
|
|
1502
|
+
(0, import_react6.useEffect)(() => {
|
|
1228
1503
|
if (lines && preRef.current) preRef.current.scrollTop = preRef.current.scrollHeight;
|
|
1229
1504
|
}, [lines]);
|
|
1230
|
-
return /* @__PURE__ */ (0,
|
|
1231
|
-
/* @__PURE__ */ (0,
|
|
1232
|
-
SOURCES.map((s) => /* @__PURE__ */ (0,
|
|
1233
|
-
/* @__PURE__ */ (0,
|
|
1234
|
-
/* @__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: "刷新" })
|
|
1235
1510
|
] }),
|
|
1236
|
-
/* @__PURE__ */ (0,
|
|
1237
|
-
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") || "(暂无记录)" })
|
|
1238
1513
|
] });
|
|
1239
1514
|
}
|
|
1240
1515
|
|
|
1241
1516
|
// client/src/tabs/OverviewTab.tsx
|
|
1242
|
-
var
|
|
1517
|
+
var import_react15 = require("react");
|
|
1243
1518
|
|
|
1244
1519
|
// client/src/pill/modes.ts
|
|
1245
1520
|
var MODES = [
|
|
@@ -1259,11 +1534,11 @@ var __defProp = Object.defineProperty;
|
|
|
1259
1534
|
}
|
|
1260
1535
|
|
|
1261
1536
|
// client/src/tabs/DistillSettings.tsx
|
|
1262
|
-
var
|
|
1537
|
+
var import_react11 = require("react");
|
|
1263
1538
|
|
|
1264
1539
|
// client/src/tabs/BudgetInputs.tsx
|
|
1265
|
-
var
|
|
1266
|
-
var
|
|
1540
|
+
var import_react7 = require("react");
|
|
1541
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1267
1542
|
var LAYERS = [
|
|
1268
1543
|
["extract", "抽取"],
|
|
1269
1544
|
["dedup", "去重"],
|
|
@@ -1284,7 +1559,7 @@ var __defProp = Object.defineProperty;
|
|
|
1284
1559
|
const onError = props.onError;
|
|
1285
1560
|
const scope = props.scope ?? "all";
|
|
1286
1561
|
const layers = scope === "all" || scope === "input" ? LAYERS : LAYERS.filter((l) => SCOPE_KEYS[scope].includes(l[0]));
|
|
1287
|
-
const [draft, setDraft] = (0,
|
|
1562
|
+
const [draft, setDraft] = (0, import_react7.useState)(null);
|
|
1288
1563
|
if (!data || !data.budgets) return null;
|
|
1289
1564
|
const cur = data.budgets.current || {};
|
|
1290
1565
|
const def = data.budgets.defaults || {};
|
|
@@ -1380,7 +1655,7 @@ var __defProp = Object.defineProperty;
|
|
|
1380
1655
|
return false;
|
|
1381
1656
|
};
|
|
1382
1657
|
const inputBox = (key, _label, title, width, placeholder, onCommit) => {
|
|
1383
|
-
return /* @__PURE__ */ (0,
|
|
1658
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1384
1659
|
NInput,
|
|
1385
1660
|
{
|
|
1386
1661
|
type: "number",
|
|
@@ -1411,10 +1686,10 @@ var __defProp = Object.defineProperty;
|
|
|
1411
1686
|
const showInput = scope === "all" || scope === "input";
|
|
1412
1687
|
const effNote = layers.map((l) => eff[l[0]] || "?").join(" / ");
|
|
1413
1688
|
const rowLabel = (key) => key === "extract" ? "抽取输出" : key === "dedup" ? "去重输出" : key === "l2" ? "L2 输出" : "L3 输出";
|
|
1414
|
-
const
|
|
1415
|
-
return /* @__PURE__ */ (0,
|
|
1416
|
-
showOutputs ? /* @__PURE__ */ (0,
|
|
1417
|
-
/* @__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)(
|
|
1418
1693
|
"div",
|
|
1419
1694
|
{
|
|
1420
1695
|
style: S.switchLabel,
|
|
@@ -1422,8 +1697,8 @@ var __defProp = Object.defineProperty;
|
|
|
1422
1697
|
children: "输出预算"
|
|
1423
1698
|
}
|
|
1424
1699
|
),
|
|
1425
|
-
/* @__PURE__ */ (0,
|
|
1426
|
-
/* @__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]) }),
|
|
1427
1702
|
inputBox(
|
|
1428
1703
|
l[0],
|
|
1429
1704
|
l[1],
|
|
@@ -1432,11 +1707,11 @@ var __defProp = Object.defineProperty;
|
|
|
1432
1707
|
def[l[0]],
|
|
1433
1708
|
commitOutputs
|
|
1434
1709
|
),
|
|
1435
|
-
/* @__PURE__ */ (0,
|
|
1710
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: 11, color: "var(--dsh-mem-text-3)" }, children: "token" })
|
|
1436
1711
|
] }, l[0])) })
|
|
1437
1712
|
] }) : null,
|
|
1438
|
-
showInput ? /* @__PURE__ */ (0,
|
|
1439
|
-
/* @__PURE__ */ (0,
|
|
1713
|
+
showInput ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { marginTop: 12 }, children: [
|
|
1714
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1440
1715
|
"div",
|
|
1441
1716
|
{
|
|
1442
1717
|
style: S.switchLabel,
|
|
@@ -1444,8 +1719,8 @@ var __defProp = Object.defineProperty;
|
|
|
1444
1719
|
children: "输入预算"
|
|
1445
1720
|
}
|
|
1446
1721
|
),
|
|
1447
|
-
/* @__PURE__ */ (0,
|
|
1448
|
-
/* @__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: "单次输入" }),
|
|
1449
1724
|
inputBox(
|
|
1450
1725
|
"input",
|
|
1451
1726
|
"输入",
|
|
@@ -1454,15 +1729,15 @@ var __defProp = Object.defineProperty;
|
|
|
1454
1729
|
ib.fallback,
|
|
1455
1730
|
commitInput
|
|
1456
1731
|
),
|
|
1457
|
-
/* @__PURE__ */ (0,
|
|
1732
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: 11, color: "var(--dsh-mem-text-3)" }, children: "字符" })
|
|
1458
1733
|
] }) })
|
|
1459
1734
|
] }) : null
|
|
1460
1735
|
] });
|
|
1461
1736
|
}
|
|
1462
1737
|
|
|
1463
1738
|
// client/src/tabs/ChannelEditor.tsx
|
|
1464
|
-
var
|
|
1465
|
-
var
|
|
1739
|
+
var import_react8 = require("react");
|
|
1740
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1466
1741
|
var STY = {
|
|
1467
1742
|
block: { marginTop: 10, paddingTop: 10, borderTop: "1px solid var(--dsh-mem-border)" },
|
|
1468
1743
|
head: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", marginBottom: 6 },
|
|
@@ -1493,15 +1768,15 @@ var __defProp = Object.defineProperty;
|
|
|
1493
1768
|
];
|
|
1494
1769
|
function ChannelEditor(props) {
|
|
1495
1770
|
const { channel, rpc, disabled } = props;
|
|
1496
|
-
const [baseText, setBaseText] = (0,
|
|
1497
|
-
const [keyText, setKeyText] = (0,
|
|
1498
|
-
const baseTimer = (0,
|
|
1499
|
-
const dirty = (0,
|
|
1500
|
-
(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)(() => {
|
|
1501
1776
|
if (!dirty.current) setBaseText(channel.runtimeBaseURL);
|
|
1502
1777
|
}, [channel.runtimeBaseURL]);
|
|
1503
|
-
(0,
|
|
1504
|
-
const
|
|
1778
|
+
(0, import_react8.useEffect)(() => () => clearTimeout(baseTimer.current), []);
|
|
1779
|
+
const commit2 = (patch) => {
|
|
1505
1780
|
rpc("dsh-memory/settings-set", patch).catch(() => {
|
|
1506
1781
|
});
|
|
1507
1782
|
};
|
|
@@ -1511,14 +1786,14 @@ var __defProp = Object.defineProperty;
|
|
|
1511
1786
|
clearTimeout(baseTimer.current);
|
|
1512
1787
|
baseTimer.current = setTimeout(() => {
|
|
1513
1788
|
dirty.current = false;
|
|
1514
|
-
|
|
1789
|
+
commit2({ directBaseURL: v.trim() });
|
|
1515
1790
|
}, 600);
|
|
1516
1791
|
};
|
|
1517
1792
|
const commitKey = () => {
|
|
1518
1793
|
const v = keyText.trim();
|
|
1519
1794
|
if (v) {
|
|
1520
1795
|
dirty.current = true;
|
|
1521
|
-
|
|
1796
|
+
commit2({ directApiKey: v });
|
|
1522
1797
|
dirty.current = false;
|
|
1523
1798
|
}
|
|
1524
1799
|
setKeyText("");
|
|
@@ -1529,29 +1804,29 @@ var __defProp = Object.defineProperty;
|
|
|
1529
1804
|
const deployedDirect = channel.deployed === "direct";
|
|
1530
1805
|
const apiKeySet = channel.runtimeApiKeySet || channel.deployedApiKeySet;
|
|
1531
1806
|
const showWarn = isDirect && !channel.directReady;
|
|
1532
|
-
return /* @__PURE__ */ (0,
|
|
1533
|
-
/* @__PURE__ */ (0,
|
|
1534
|
-
/* @__PURE__ */ (0,
|
|
1535
|
-
/* @__PURE__ */ (0,
|
|
1536
|
-
/* @__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: [
|
|
1537
1812
|
"生效:",
|
|
1538
1813
|
runtime ? runtime === "direct" ? "运行时直连" : "运行时宿主" : "跟随部署配置"
|
|
1539
1814
|
] })
|
|
1540
1815
|
] }),
|
|
1541
|
-
/* @__PURE__ */ (0,
|
|
1542
|
-
/* @__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)(
|
|
1543
1818
|
Segmented,
|
|
1544
1819
|
{
|
|
1545
1820
|
value: runtime,
|
|
1546
1821
|
disabled,
|
|
1547
1822
|
options: MODE_OPTIONS.map((m) => ({ key: m.key, label: m.label, title: m.title })),
|
|
1548
|
-
onChange: (k) =>
|
|
1823
|
+
onChange: (k) => commit2({ distillMode: k })
|
|
1549
1824
|
}
|
|
1550
1825
|
),
|
|
1551
|
-
editing ? /* @__PURE__ */ (0,
|
|
1552
|
-
/* @__PURE__ */ (0,
|
|
1553
|
-
/* @__PURE__ */ (0,
|
|
1554
|
-
/* @__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)(
|
|
1555
1830
|
NInput,
|
|
1556
1831
|
{
|
|
1557
1832
|
style: STY.input,
|
|
@@ -1563,19 +1838,19 @@ var __defProp = Object.defineProperty;
|
|
|
1563
1838
|
if (e.key === "Enter") {
|
|
1564
1839
|
clearTimeout(baseTimer.current);
|
|
1565
1840
|
dirty.current = false;
|
|
1566
|
-
|
|
1841
|
+
commit2({ directBaseURL: baseText.trim() });
|
|
1567
1842
|
}
|
|
1568
1843
|
}
|
|
1569
1844
|
}
|
|
1570
1845
|
),
|
|
1571
|
-
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: [
|
|
1572
1847
|
"部署基线:",
|
|
1573
1848
|
channel.deployedBaseURL || "(空)"
|
|
1574
1849
|
] }) : null
|
|
1575
1850
|
] }),
|
|
1576
|
-
/* @__PURE__ */ (0,
|
|
1577
|
-
/* @__PURE__ */ (0,
|
|
1578
|
-
/* @__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)(
|
|
1579
1854
|
NInput,
|
|
1580
1855
|
{
|
|
1581
1856
|
style: STY.input,
|
|
@@ -1591,41 +1866,41 @@ var __defProp = Object.defineProperty;
|
|
|
1591
1866
|
onBlur: commitKey
|
|
1592
1867
|
}
|
|
1593
1868
|
),
|
|
1594
|
-
apiKeySet ? /* @__PURE__ */ (0,
|
|
1595
|
-
/* @__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)(
|
|
1596
1871
|
NButton,
|
|
1597
1872
|
{
|
|
1598
1873
|
disabled,
|
|
1599
1874
|
title: "写入空串清除运行时密钥(部署 .yml 的密钥不受影响)",
|
|
1600
|
-
onClick: () =>
|
|
1875
|
+
onClick: () => commit2({ directApiKey: "" }),
|
|
1601
1876
|
children: "清除"
|
|
1602
1877
|
}
|
|
1603
1878
|
)
|
|
1604
1879
|
] }),
|
|
1605
|
-
showWarn ? /* @__PURE__ */ (0,
|
|
1606
|
-
] }) : /* @__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" ? "运行时锁定" : "跟随部署配置") + ")" })
|
|
1607
1882
|
] });
|
|
1608
1883
|
}
|
|
1609
1884
|
|
|
1610
1885
|
// client/src/tabs/RouteChainEditor.tsx
|
|
1611
|
-
var
|
|
1886
|
+
var import_react10 = require("react");
|
|
1612
1887
|
|
|
1613
1888
|
// client/src/ui/NSel.tsx
|
|
1614
|
-
var
|
|
1615
|
-
var
|
|
1889
|
+
var import_react9 = require("react");
|
|
1890
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1616
1891
|
function NSel(props) {
|
|
1617
1892
|
const options = props.options || [];
|
|
1618
1893
|
const value = props.value || "";
|
|
1619
1894
|
const disabled = !!props.disabled;
|
|
1620
|
-
const [open, setOpen] = (0,
|
|
1621
|
-
const [idx, setIdx] = (0,
|
|
1622
|
-
const wrapRef = (0,
|
|
1623
|
-
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);
|
|
1624
1899
|
let selectedLabel = "";
|
|
1625
1900
|
for (let si = 0; si < options.length; si++) {
|
|
1626
1901
|
if (options[si].id === value) selectedLabel = options[si].label;
|
|
1627
1902
|
}
|
|
1628
|
-
(0,
|
|
1903
|
+
(0, import_react9.useEffect)(() => {
|
|
1629
1904
|
if (!open) return void 0;
|
|
1630
1905
|
const onDown = (e) => {
|
|
1631
1906
|
if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
|
|
@@ -1635,7 +1910,7 @@ var __defProp = Object.defineProperty;
|
|
|
1635
1910
|
document.removeEventListener("mousedown", onDown);
|
|
1636
1911
|
};
|
|
1637
1912
|
}, [open]);
|
|
1638
|
-
(0,
|
|
1913
|
+
(0, import_react9.useEffect)(() => {
|
|
1639
1914
|
if (!open || !listRef.current) return;
|
|
1640
1915
|
const el = listRef.current.querySelector('[data-active="1"]');
|
|
1641
1916
|
if (el && el.scrollIntoView) el.scrollIntoView({ block: "nearest" });
|
|
@@ -1698,8 +1973,8 @@ var __defProp = Object.defineProperty;
|
|
|
1698
1973
|
const to = e.relatedTarget;
|
|
1699
1974
|
if (!to || wrapRef.current && !wrapRef.current.contains(to)) setOpen(false);
|
|
1700
1975
|
};
|
|
1701
|
-
return /* @__PURE__ */ (0,
|
|
1702
|
-
/* @__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)(
|
|
1703
1978
|
"button",
|
|
1704
1979
|
{
|
|
1705
1980
|
type: "button",
|
|
@@ -1715,13 +1990,13 @@ var __defProp = Object.defineProperty;
|
|
|
1715
1990
|
}
|
|
1716
1991
|
},
|
|
1717
1992
|
children: [
|
|
1718
|
-
/* @__PURE__ */ (0,
|
|
1719
|
-
/* @__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 })
|
|
1720
1995
|
]
|
|
1721
1996
|
}
|
|
1722
1997
|
),
|
|
1723
|
-
open && !disabled ? /* @__PURE__ */ (0,
|
|
1724
|
-
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)(
|
|
1725
2000
|
"button",
|
|
1726
2001
|
{
|
|
1727
2002
|
type: "button",
|
|
@@ -1739,8 +2014,8 @@ var __defProp = Object.defineProperty;
|
|
|
1739
2014
|
if (idx !== i) setIdx(i);
|
|
1740
2015
|
},
|
|
1741
2016
|
children: [
|
|
1742
|
-
/* @__PURE__ */ (0,
|
|
1743
|
-
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
|
|
1744
2019
|
]
|
|
1745
2020
|
},
|
|
1746
2021
|
o.id
|
|
@@ -1750,7 +2025,7 @@ var __defProp = Object.defineProperty;
|
|
|
1750
2025
|
}
|
|
1751
2026
|
|
|
1752
2027
|
// client/src/tabs/RouteChainEditor.tsx
|
|
1753
|
-
var
|
|
2028
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1754
2029
|
var modelsCache = {};
|
|
1755
2030
|
var EFFORT_VOCAB = ["", "off", "none", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
1756
2031
|
var STY2 = {
|
|
@@ -1779,26 +2054,26 @@ var __defProp = Object.defineProperty;
|
|
|
1779
2054
|
const disabled = !!props.disabled;
|
|
1780
2055
|
const scope = props.scope ?? "global";
|
|
1781
2056
|
const isLayer = scope !== "global";
|
|
1782
|
-
const [info, setInfo] = (0,
|
|
1783
|
-
const [rows, setRows] = (0,
|
|
1784
|
-
const [rowErrs, setRowErrs] = (0,
|
|
1785
|
-
const [err, setErr] = (0,
|
|
1786
|
-
const [manual, setManual] = (0,
|
|
1787
|
-
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);
|
|
1788
2063
|
function refreshInfo() {
|
|
1789
2064
|
rpc("dsh-memory/llm-providers", {}).then((r) => {
|
|
1790
2065
|
if (r && r.ok && pendingWrites.current === 0) setInfo(r.value);
|
|
1791
2066
|
}).catch(() => {
|
|
1792
2067
|
});
|
|
1793
2068
|
}
|
|
1794
|
-
(0,
|
|
2069
|
+
(0, import_react10.useEffect)(() => {
|
|
1795
2070
|
refreshInfo();
|
|
1796
2071
|
const timer = setInterval(refreshInfo, 5e3);
|
|
1797
2072
|
return () => {
|
|
1798
2073
|
clearInterval(timer);
|
|
1799
2074
|
};
|
|
1800
2075
|
}, [rpc]);
|
|
1801
|
-
(0,
|
|
2076
|
+
(0, import_react10.useEffect)(() => {
|
|
1802
2077
|
if (!info || !info.providers) return;
|
|
1803
2078
|
info.providers.forEach((p) => {
|
|
1804
2079
|
if (!p.id || modelsCache[p.id]) return;
|
|
@@ -1810,7 +2085,7 @@ var __defProp = Object.defineProperty;
|
|
|
1810
2085
|
}, [rpc, info]);
|
|
1811
2086
|
const layerView = isLayer && info && info.layerChains ? info.layerChains[scope] : null;
|
|
1812
2087
|
const savedRows = isLayer ? layerView?.runtime ?? [] : info && info.chain ? info.chain.current : [];
|
|
1813
|
-
(0,
|
|
2088
|
+
(0, import_react10.useEffect)(() => {
|
|
1814
2089
|
if (rows === null && info && savedRows.length) {
|
|
1815
2090
|
setRows(savedRows.map(copyRow));
|
|
1816
2091
|
}
|
|
@@ -1958,17 +2233,17 @@ var __defProp = Object.defineProperty;
|
|
|
1958
2233
|
providersById[p.id] = p;
|
|
1959
2234
|
});
|
|
1960
2235
|
function roRow(e, i) {
|
|
1961
|
-
return /* @__PURE__ */ (0,
|
|
1962
|
-
/* @__PURE__ */ (0,
|
|
1963
|
-
/* @__PURE__ */ (0,
|
|
1964
|
-
/* @__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 : "跟随部署配置" })
|
|
1965
2240
|
] }, "ro" + i);
|
|
1966
2241
|
}
|
|
1967
2242
|
if (info.pinned) {
|
|
1968
2243
|
const effPin = isLayer ? layerView?.effectiveChain ?? [] : info.chain && info.chain.effectiveChain || [];
|
|
1969
|
-
return /* @__PURE__ */ (0,
|
|
2244
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: STY2.wrap, children: [
|
|
1970
2245
|
effPin.map(roRow),
|
|
1971
|
-
/* @__PURE__ */ (0,
|
|
2246
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: STY2.note, children: "部署已锁定路由(pin),调整请修改 cordis.patch.yml 中 llm 的配置。" })
|
|
1972
2247
|
] });
|
|
1973
2248
|
}
|
|
1974
2249
|
if (rows === null) {
|
|
@@ -1976,21 +2251,21 @@ var __defProp = Object.defineProperty;
|
|
|
1976
2251
|
const lv = layerView;
|
|
1977
2252
|
const src = lv?.source ?? "global";
|
|
1978
2253
|
if (src === "static" && lv) {
|
|
1979
|
-
return /* @__PURE__ */ (0,
|
|
2254
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: STY2.wrap, children: [
|
|
1980
2255
|
lv.static.map((e, i) => roRow({ provider: e.provider, model: e.model, effort: e.reasoningEffort || "" }, i)),
|
|
1981
|
-
/* @__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: "自定义本层链" }) })
|
|
1982
2257
|
] });
|
|
1983
2258
|
}
|
|
1984
2259
|
const previewRows = lv?.effectiveChain ?? [];
|
|
1985
|
-
return /* @__PURE__ */ (0,
|
|
1986
|
-
previewRows.length === 0 ? /* @__PURE__ */ (0,
|
|
1987
|
-
/* @__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: "自定义本层链" }) })
|
|
1988
2263
|
] });
|
|
1989
2264
|
}
|
|
1990
2265
|
const effFollow = info.chain && info.chain.effectiveChain || [];
|
|
1991
|
-
return /* @__PURE__ */ (0,
|
|
1992
|
-
effFollow.length === 0 ? /* @__PURE__ */ (0,
|
|
1993
|
-
/* @__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: "编辑为运行时链" }) })
|
|
1994
2269
|
] });
|
|
1995
2270
|
}
|
|
1996
2271
|
const capped = rows.length >= 8;
|
|
@@ -2031,10 +2306,10 @@ var __defProp = Object.defineProperty;
|
|
|
2031
2306
|
const effortOptions = [{ id: "", label: "跟随部署配置" }].concat(
|
|
2032
2307
|
curEfforts.filter((k) => EFFORT_VOCAB.indexOf(k) >= 0).map((k) => ({ id: k, label: k }))
|
|
2033
2308
|
);
|
|
2034
|
-
return /* @__PURE__ */ (0,
|
|
2035
|
-
/* @__PURE__ */ (0,
|
|
2036
|
-
/* @__PURE__ */ (0,
|
|
2037
|
-
/* @__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)(
|
|
2038
2313
|
NSel,
|
|
2039
2314
|
{
|
|
2040
2315
|
style: { flex: 1, minWidth: 150 },
|
|
@@ -2047,7 +2322,7 @@ var __defProp = Object.defineProperty;
|
|
|
2047
2322
|
}
|
|
2048
2323
|
}
|
|
2049
2324
|
),
|
|
2050
|
-
!row2.provider ? null : manualInput ? /* @__PURE__ */ (0,
|
|
2325
|
+
!row2.provider ? null : manualInput ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2051
2326
|
NInput,
|
|
2052
2327
|
{
|
|
2053
2328
|
style: { flex: 1, minWidth: 150 },
|
|
@@ -2066,7 +2341,7 @@ var __defProp = Object.defineProperty;
|
|
|
2066
2341
|
}
|
|
2067
2342
|
}
|
|
2068
2343
|
}
|
|
2069
|
-
) : /* @__PURE__ */ (0,
|
|
2344
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2070
2345
|
NSel,
|
|
2071
2346
|
{
|
|
2072
2347
|
style: { flex: 1, minWidth: 150 },
|
|
@@ -2079,7 +2354,7 @@ var __defProp = Object.defineProperty;
|
|
|
2079
2354
|
}
|
|
2080
2355
|
}
|
|
2081
2356
|
),
|
|
2082
|
-
/* @__PURE__ */ (0,
|
|
2357
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2083
2358
|
NSel,
|
|
2084
2359
|
{
|
|
2085
2360
|
style: { flexShrink: 0, width: 118 },
|
|
@@ -2093,8 +2368,8 @@ var __defProp = Object.defineProperty;
|
|
|
2093
2368
|
}
|
|
2094
2369
|
)
|
|
2095
2370
|
] }),
|
|
2096
|
-
/* @__PURE__ */ (0,
|
|
2097
|
-
/* @__PURE__ */ (0,
|
|
2371
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: STY2.actions, children: [
|
|
2372
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2098
2373
|
NButton,
|
|
2099
2374
|
{
|
|
2100
2375
|
style: STY2.ico,
|
|
@@ -2106,7 +2381,7 @@ var __defProp = Object.defineProperty;
|
|
|
2106
2381
|
children: "↑"
|
|
2107
2382
|
}
|
|
2108
2383
|
),
|
|
2109
|
-
/* @__PURE__ */ (0,
|
|
2384
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2110
2385
|
NButton,
|
|
2111
2386
|
{
|
|
2112
2387
|
style: STY2.ico,
|
|
@@ -2118,7 +2393,7 @@ var __defProp = Object.defineProperty;
|
|
|
2118
2393
|
children: "↓"
|
|
2119
2394
|
}
|
|
2120
2395
|
),
|
|
2121
|
-
/* @__PURE__ */ (0,
|
|
2396
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2122
2397
|
NButton,
|
|
2123
2398
|
{
|
|
2124
2399
|
style: STY2.ico,
|
|
@@ -2131,14 +2406,14 @@ var __defProp = Object.defineProperty;
|
|
|
2131
2406
|
}
|
|
2132
2407
|
)
|
|
2133
2408
|
] }),
|
|
2134
|
-
isPrimary && !row2.provider ? /* @__PURE__ */ (0,
|
|
2135
|
-
!known ? /* @__PURE__ */ (0,
|
|
2136
|
-
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
|
|
2137
2412
|
] }, "row" + i);
|
|
2138
2413
|
});
|
|
2139
2414
|
const effChain = isLayer ? layerView?.effectiveChain ?? [] : info.chain && info.chain.effectiveChain || [];
|
|
2140
|
-
return /* @__PURE__ */ (0,
|
|
2141
|
-
/* @__PURE__ */ (0,
|
|
2415
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: STY2.wrap, children: [
|
|
2416
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2142
2417
|
"div",
|
|
2143
2418
|
{
|
|
2144
2419
|
style: { ...S.switchDesc, marginBottom: 8 },
|
|
@@ -2147,9 +2422,9 @@ var __defProp = Object.defineProperty;
|
|
|
2147
2422
|
}
|
|
2148
2423
|
),
|
|
2149
2424
|
rowEls,
|
|
2150
|
-
/* @__PURE__ */ (0,
|
|
2151
|
-
/* @__PURE__ */ (0,
|
|
2152
|
-
/* @__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)(
|
|
2153
2428
|
NButton,
|
|
2154
2429
|
{
|
|
2155
2430
|
style: isLayer ? { ...STY2.ghost, color: "var(--dsh-mem-danger)", border: "1px solid var(--dsh-mem-danger)" } : STY2.ghost,
|
|
@@ -2158,13 +2433,13 @@ var __defProp = Object.defineProperty;
|
|
|
2158
2433
|
children: isLayer ? "清除自定义 · 跟随全局" : "清空并跟随部署配置"
|
|
2159
2434
|
}
|
|
2160
2435
|
),
|
|
2161
|
-
/* @__PURE__ */ (0,
|
|
2162
|
-
/* @__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: "保存" })
|
|
2163
2438
|
] }),
|
|
2164
|
-
err ? /* @__PURE__ */ (0,
|
|
2165
|
-
/* @__PURE__ */ (0,
|
|
2166
|
-
/* @__PURE__ */ (0,
|
|
2167
|
-
/* @__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)(
|
|
2168
2443
|
"div",
|
|
2169
2444
|
{
|
|
2170
2445
|
style: { fontSize: 12, color: "var(--dsh-mem-text-2)", wordBreak: "break-all", fontFamily: "ui-monospace, SFMono-Regular, Consolas, monospace" },
|
|
@@ -2176,7 +2451,7 @@ var __defProp = Object.defineProperty;
|
|
|
2176
2451
|
}
|
|
2177
2452
|
|
|
2178
2453
|
// client/src/tabs/DistillSettings.tsx
|
|
2179
|
-
var
|
|
2454
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2180
2455
|
var STY3 = {
|
|
2181
2456
|
hint: { fontSize: 11, color: "var(--dsh-mem-text-3)", margin: "0 0 8px" },
|
|
2182
2457
|
panelHead: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", marginBottom: 8 },
|
|
@@ -2205,9 +2480,9 @@ var __defProp = Object.defineProperty;
|
|
|
2205
2480
|
verticalAlign: "middle",
|
|
2206
2481
|
flexShrink: 0
|
|
2207
2482
|
};
|
|
2208
|
-
if (props.kind === "runtime") return /* @__PURE__ */ (0,
|
|
2209
|
-
if (props.kind === "static") return /* @__PURE__ */ (0,
|
|
2210
|
-
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)" } });
|
|
2211
2486
|
}
|
|
2212
2487
|
var LAYER_META = {
|
|
2213
2488
|
l1: { seg: "L1", title: "L1 · 抽取 / 去重" },
|
|
@@ -2217,9 +2492,9 @@ var __defProp = Object.defineProperty;
|
|
|
2217
2492
|
function DistillSettings(props) {
|
|
2218
2493
|
const rpc = props.rpc;
|
|
2219
2494
|
const disabled = !!props.disabled;
|
|
2220
|
-
const [info, setInfo] = (0,
|
|
2221
|
-
const [tab, setTab] = (0,
|
|
2222
|
-
(0,
|
|
2495
|
+
const [info, setInfo] = (0, import_react11.useState)(null);
|
|
2496
|
+
const [tab, setTab] = (0, import_react11.useState)("g");
|
|
2497
|
+
(0, import_react11.useEffect)(() => {
|
|
2223
2498
|
let alive = true;
|
|
2224
2499
|
const refresh = () => {
|
|
2225
2500
|
rpc("dsh-memory/llm-providers", {}).then((r) => {
|
|
@@ -2242,46 +2517,46 @@ var __defProp = Object.defineProperty;
|
|
|
2242
2517
|
...["l1", "l2", "l3"].map((k) => ({
|
|
2243
2518
|
key: k,
|
|
2244
2519
|
title: LAYER_META[k].title + " · " + (dotOf(k) === "runtime" ? "运行时自定义" : dotOf(k) === "static" ? "部署 YAML 层链(只读)" : "跟随全局"),
|
|
2245
|
-
label: /* @__PURE__ */ (0,
|
|
2246
|
-
/* @__PURE__ */ (0,
|
|
2520
|
+
label: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { children: [
|
|
2521
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Dot, { kind: dotOf(k) }),
|
|
2247
2522
|
LAYER_META[k].seg
|
|
2248
2523
|
] })
|
|
2249
2524
|
}))
|
|
2250
2525
|
];
|
|
2251
2526
|
const chipTitle = (k) => dotOf(k) === "runtime" ? "本层走设置页自定义链" : dotOf(k) === "static" ? "本层走部署 YAML 层链(UI 只读,自定义可覆盖)" : "本层未单独配置,走全局默认链";
|
|
2252
|
-
return /* @__PURE__ */ (0,
|
|
2253
|
-
/* @__PURE__ */ (0,
|
|
2254
|
-
/* @__PURE__ */ (0,
|
|
2255
|
-
/* @__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" }),
|
|
2256
2531
|
" 自定义 · ",
|
|
2257
|
-
/* @__PURE__ */ (0,
|
|
2532
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Dot, { kind: "static" }),
|
|
2258
2533
|
" 部署 YAML · ",
|
|
2259
|
-
/* @__PURE__ */ (0,
|
|
2534
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Dot, { kind: "global" }),
|
|
2260
2535
|
" 跟随全局",
|
|
2261
|
-
/* @__PURE__ */ (0,
|
|
2536
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { title: "每层实际链:运行时自定义 → 部署 YAML 层链 → 全局默认链,逐级兜底;部署 pin 时运行时编辑只读", children: "(层链优先于全局)" })
|
|
2262
2537
|
] }),
|
|
2263
|
-
tab === "g" ? /* @__PURE__ */ (0,
|
|
2264
|
-
/* @__PURE__ */ (0,
|
|
2265
|
-
/* @__PURE__ */ (0,
|
|
2266
|
-
/* @__PURE__ */ (0,
|
|
2267
|
-
/* @__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("、") : "当前无层使用" })
|
|
2268
2543
|
] }),
|
|
2269
|
-
/* @__PURE__ */ (0,
|
|
2270
|
-
/* @__PURE__ */ (0,
|
|
2271
|
-
info?.channel ? /* @__PURE__ */ (0,
|
|
2272
|
-
] }) : /* @__PURE__ */ (0,
|
|
2273
|
-
/* @__PURE__ */ (0,
|
|
2274
|
-
/* @__PURE__ */ (0,
|
|
2275
|
-
/* @__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" : "跟随全局" })
|
|
2276
2551
|
] }),
|
|
2277
|
-
/* @__PURE__ */ (0,
|
|
2278
|
-
/* @__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")
|
|
2279
2554
|
] })
|
|
2280
2555
|
] });
|
|
2281
2556
|
}
|
|
2282
2557
|
|
|
2283
2558
|
// client/src/tabs/EmbeddingSection.tsx
|
|
2284
|
-
var
|
|
2559
|
+
var import_react12 = require("react");
|
|
2285
2560
|
|
|
2286
2561
|
// client/src/dimensions.ts
|
|
2287
2562
|
var DIMS_MIN = 1;
|
|
@@ -2329,7 +2604,7 @@ var __defProp = Object.defineProperty;
|
|
|
2329
2604
|
}
|
|
2330
2605
|
|
|
2331
2606
|
// client/src/tabs/EmbeddingSection.tsx
|
|
2332
|
-
var
|
|
2607
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2333
2608
|
var RSTY = {
|
|
2334
2609
|
block: { marginTop: 10, paddingTop: 10, borderTop: "1px solid var(--dsh-mem-border)" },
|
|
2335
2610
|
title: { fontSize: 12, fontWeight: 600, color: "var(--dsh-mem-text-3)", margin: "0 0 2px" },
|
|
@@ -2353,17 +2628,17 @@ var __defProp = Object.defineProperty;
|
|
|
2353
2628
|
function EmbeddingSection(props) {
|
|
2354
2629
|
const rpc = props.rpc;
|
|
2355
2630
|
const loose = asLoose(rpc);
|
|
2356
|
-
const [st, setSt] = (0,
|
|
2357
|
-
const [err, setErr] = (0,
|
|
2358
|
-
const busyPollRef = (0,
|
|
2359
|
-
const [rBase, setRBase] = (0,
|
|
2360
|
-
const [rModel, setRModel] = (0,
|
|
2361
|
-
const [rDims, setRDims] = (0,
|
|
2362
|
-
const [rKey, setRKey] = (0,
|
|
2363
|
-
const remoteDirty = (0,
|
|
2364
|
-
const baseTimer = (0,
|
|
2365
|
-
const modelTimer = (0,
|
|
2366
|
-
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)(() => {
|
|
2367
2642
|
rpc("dsh-memory/embedding-state-get", {}).then((r) => {
|
|
2368
2643
|
if (r && r.ok && r.value && r.value.supported !== false) {
|
|
2369
2644
|
const v = r.value;
|
|
@@ -2382,10 +2657,10 @@ var __defProp = Object.defineProperty;
|
|
|
2382
2657
|
setErr(String(e && e.message || e));
|
|
2383
2658
|
});
|
|
2384
2659
|
}, [rpc]);
|
|
2385
|
-
(0,
|
|
2660
|
+
(0, import_react12.useEffect)(() => {
|
|
2386
2661
|
load();
|
|
2387
2662
|
}, [load]);
|
|
2388
|
-
(0,
|
|
2663
|
+
(0, import_react12.useEffect)(() => {
|
|
2389
2664
|
let stopped = false;
|
|
2390
2665
|
const busyFlag = { v: false };
|
|
2391
2666
|
busyPollRef.current = busyFlag;
|
|
@@ -2401,11 +2676,11 @@ var __defProp = Object.defineProperty;
|
|
|
2401
2676
|
busyPollRef.current = null;
|
|
2402
2677
|
};
|
|
2403
2678
|
}, [load]);
|
|
2404
|
-
(0,
|
|
2679
|
+
(0, import_react12.useEffect)(() => () => {
|
|
2405
2680
|
clearTimeout(baseTimer.current);
|
|
2406
2681
|
clearTimeout(modelTimer.current);
|
|
2407
2682
|
}, []);
|
|
2408
|
-
(0,
|
|
2683
|
+
(0, import_react12.useEffect)(() => {
|
|
2409
2684
|
if (!st || !st.remote) return;
|
|
2410
2685
|
if (!remoteDirty.current.base) setRBase(st.remote.baseURL || "");
|
|
2411
2686
|
if (!remoteDirty.current.model) setRModel(st.remote.model || "");
|
|
@@ -2466,15 +2741,15 @@ var __defProp = Object.defineProperty;
|
|
|
2466
2741
|
});
|
|
2467
2742
|
};
|
|
2468
2743
|
if (err === "__unsupported__") {
|
|
2469
|
-
return /* @__PURE__ */ (0,
|
|
2470
|
-
/* @__PURE__ */ (0,
|
|
2471
|
-
/* @__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: "存储处于降级状态,嵌入管理不可用。" })
|
|
2472
2747
|
] });
|
|
2473
2748
|
}
|
|
2474
2749
|
if (!st) {
|
|
2475
|
-
return /* @__PURE__ */ (0,
|
|
2476
|
-
/* @__PURE__ */ (0,
|
|
2477
|
-
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
|
|
2478
2753
|
] });
|
|
2479
2754
|
}
|
|
2480
2755
|
const switchConfirm = "切换嵌入源后将按新模型重建向量索引(期间语义检索暂退化为关键词匹配,不影响对话)。确定切换?";
|
|
@@ -2500,40 +2775,40 @@ var __defProp = Object.defineProperty;
|
|
|
2500
2775
|
const remote = st.remote;
|
|
2501
2776
|
let runtimeRow = null;
|
|
2502
2777
|
if (rt.phase === "installing") {
|
|
2503
|
-
runtimeRow = /* @__PURE__ */ (0,
|
|
2504
|
-
/* @__PURE__ */ (0,
|
|
2505
|
-
/* @__PURE__ */ (0,
|
|
2506
|
-
/* @__PURE__ */ (0,
|
|
2507
|
-
/* @__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: "取消" })
|
|
2508
2783
|
] }),
|
|
2509
|
-
/* @__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 输出…" })
|
|
2510
2785
|
] });
|
|
2511
2786
|
} else if (rt.phase === "error") {
|
|
2512
|
-
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 || "未知") + "(重新切换嵌入源可重试)" });
|
|
2513
2788
|
} else if (rt.phase === "ready") {
|
|
2514
|
-
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 + ")" });
|
|
2515
2790
|
} else if (st.source === "local") {
|
|
2516
|
-
runtimeRow = /* @__PURE__ */ (0,
|
|
2791
|
+
runtimeRow = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-mem-rb-muted", style: { marginTop: 8 }, children: "首次启用本地嵌入时会自动安装推理运行时(约 100~200MB)。" });
|
|
2517
2792
|
}
|
|
2518
2793
|
let applyRow = null;
|
|
2519
2794
|
if (ap.phase === "warming") {
|
|
2520
|
-
applyRow = /* @__PURE__ */ (0,
|
|
2795
|
+
applyRow = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-mem-rb-muted", style: { marginTop: 8 }, children: "加载嵌入模型中…(首次需数秒)" });
|
|
2521
2796
|
} else if (ap.phase === "switching") {
|
|
2522
|
-
applyRow = /* @__PURE__ */ (0,
|
|
2797
|
+
applyRow = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "dsh-mem-rb-muted", style: { marginTop: 8 }, children: "切换嵌入源中…" });
|
|
2523
2798
|
} else if (ap.phase === "error") {
|
|
2524
|
-
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 + "(已保存的嵌入源不变,重启后仍按原源运行)" });
|
|
2525
2800
|
} else if (st.reindex && st.reindex.running) {
|
|
2526
2801
|
const rj = st.reindex;
|
|
2527
2802
|
const rDone = rj.l1Done + rj.l0Done;
|
|
2528
2803
|
const rTotal = rj.l1Total + rj.l0Total;
|
|
2529
2804
|
const rPct = rTotal > 0 ? Math.round(rDone / rTotal * 100) : 0;
|
|
2530
|
-
applyRow = /* @__PURE__ */ (0,
|
|
2531
|
-
/* @__PURE__ */ (0,
|
|
2532
|
-
/* @__PURE__ */ (0,
|
|
2533
|
-
/* @__PURE__ */ (0,
|
|
2534
|
-
/* @__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: "取消" })
|
|
2535
2810
|
] }),
|
|
2536
|
-
/* @__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 + "%" } }) }) })
|
|
2537
2812
|
] });
|
|
2538
2813
|
}
|
|
2539
2814
|
const modelCards = st.models.map((m) => {
|
|
@@ -2542,24 +2817,24 @@ var __defProp = Object.defineProperty;
|
|
|
2542
2817
|
const pct = mDl && dl.overallTotal > 0 ? Math.round(dl.overallReceived / dl.overallTotal * 100) : 0;
|
|
2543
2818
|
let action;
|
|
2544
2819
|
if (mDl) {
|
|
2545
|
-
action = /* @__PURE__ */ (0,
|
|
2546
|
-
/* @__PURE__ */ (0,
|
|
2547
|
-
/* @__PURE__ */ (0,
|
|
2548
|
-
/* @__PURE__ */ (0,
|
|
2549
|
-
/* @__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: "取消" })
|
|
2550
2825
|
] }),
|
|
2551
|
-
/* @__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 + "%" } }) }) })
|
|
2552
2827
|
] });
|
|
2553
2828
|
} else if (isActive) {
|
|
2554
|
-
action = /* @__PURE__ */ (0,
|
|
2555
|
-
/* @__PURE__ */ (0,
|
|
2556
|
-
localInfo && localInfo.state === "loading" ? /* @__PURE__ */ (0,
|
|
2557
|
-
localInfo && localInfo.state === "failed" ? /* @__PURE__ */ (0,
|
|
2558
|
-
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
|
|
2559
2834
|
] });
|
|
2560
2835
|
} else if (m.state === "downloaded") {
|
|
2561
|
-
action = /* @__PURE__ */ (0,
|
|
2562
|
-
/* @__PURE__ */ (0,
|
|
2836
|
+
action = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: S.flexRow, children: [
|
|
2837
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2563
2838
|
NButton,
|
|
2564
2839
|
{
|
|
2565
2840
|
disabled: ap.busy,
|
|
@@ -2567,7 +2842,7 @@ var __defProp = Object.defineProperty;
|
|
|
2567
2842
|
children: "启用"
|
|
2568
2843
|
}
|
|
2569
2844
|
),
|
|
2570
|
-
/* @__PURE__ */ (0,
|
|
2845
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2571
2846
|
NButton,
|
|
2572
2847
|
{
|
|
2573
2848
|
disabled: dlActive,
|
|
@@ -2577,7 +2852,7 @@ var __defProp = Object.defineProperty;
|
|
|
2577
2852
|
)
|
|
2578
2853
|
] });
|
|
2579
2854
|
} else {
|
|
2580
|
-
action = /* @__PURE__ */ (0,
|
|
2855
|
+
action = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2581
2856
|
NButton,
|
|
2582
2857
|
{
|
|
2583
2858
|
disabled: dlActive || !st.ceilings.local,
|
|
@@ -2587,16 +2862,16 @@ var __defProp = Object.defineProperty;
|
|
|
2587
2862
|
}
|
|
2588
2863
|
);
|
|
2589
2864
|
}
|
|
2590
|
-
return /* @__PURE__ */ (0,
|
|
2865
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2591
2866
|
"div",
|
|
2592
2867
|
{
|
|
2593
2868
|
style: { ...S.flexRow, padding: "8px 0", borderBottom: "1px solid var(--dsh-mem-border)", flexWrap: "wrap" },
|
|
2594
2869
|
children: [
|
|
2595
|
-
/* @__PURE__ */ (0,
|
|
2596
|
-
/* @__PURE__ */ (0,
|
|
2597
|
-
/* @__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 })
|
|
2598
2873
|
] }),
|
|
2599
|
-
/* @__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 }),
|
|
2600
2875
|
action
|
|
2601
2876
|
]
|
|
2602
2877
|
},
|
|
@@ -2609,11 +2884,11 @@ var __defProp = Object.defineProperty;
|
|
|
2609
2884
|
const reindexRunning = !!(st.reindex && st.reindex.running);
|
|
2610
2885
|
const canRebuild = vecOk && st.source !== "off" && !reindexRunning && !st.apply.busy;
|
|
2611
2886
|
const rebuildHint = !vecOk ? "向量能力不可用" : st.source === "off" ? "嵌入源已关闭,请先启用" : reindexRunning ? "重建已在进行中" : st.apply.busy ? "嵌入源切换进行中" : "只补缺失向量;已有向量不动。零向量内容会被跳过(重试无意义)";
|
|
2612
|
-
return /* @__PURE__ */ (0,
|
|
2613
|
-
/* @__PURE__ */ (0,
|
|
2614
|
-
/* @__PURE__ */ (0,
|
|
2615
|
-
/* @__PURE__ */ (0,
|
|
2616
|
-
/* @__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)(
|
|
2617
2892
|
Segmented,
|
|
2618
2893
|
{
|
|
2619
2894
|
value: st.source,
|
|
@@ -2626,18 +2901,18 @@ var __defProp = Object.defineProperty;
|
|
|
2626
2901
|
}
|
|
2627
2902
|
)
|
|
2628
2903
|
] }),
|
|
2629
|
-
/* @__PURE__ */ (0,
|
|
2630
|
-
st.activeNote ? /* @__PURE__ */ (0,
|
|
2631
|
-
err && err !== "__unsupported__" ? /* @__PURE__ */ (0,
|
|
2632
|
-
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,
|
|
2633
2908
|
runtimeRow,
|
|
2634
2909
|
applyRow,
|
|
2635
|
-
/* @__PURE__ */ (0,
|
|
2636
|
-
/* @__PURE__ */ (0,
|
|
2637
|
-
/* @__PURE__ */ (0,
|
|
2638
|
-
/* @__PURE__ */ (0,
|
|
2639
|
-
/* @__PURE__ */ (0,
|
|
2640
|
-
/* @__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)(
|
|
2641
2916
|
NInput,
|
|
2642
2917
|
{
|
|
2643
2918
|
style: RSTY.input,
|
|
@@ -2654,9 +2929,9 @@ var __defProp = Object.defineProperty;
|
|
|
2654
2929
|
}
|
|
2655
2930
|
)
|
|
2656
2931
|
] }),
|
|
2657
|
-
/* @__PURE__ */ (0,
|
|
2658
|
-
/* @__PURE__ */ (0,
|
|
2659
|
-
/* @__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)(
|
|
2660
2935
|
NInput,
|
|
2661
2936
|
{
|
|
2662
2937
|
style: RSTY.input,
|
|
@@ -2672,8 +2947,8 @@ var __defProp = Object.defineProperty;
|
|
|
2672
2947
|
}
|
|
2673
2948
|
}
|
|
2674
2949
|
),
|
|
2675
|
-
/* @__PURE__ */ (0,
|
|
2676
|
-
/* @__PURE__ */ (0,
|
|
2950
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: RSTY.label, children: "维度" }),
|
|
2951
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2677
2952
|
NInput,
|
|
2678
2953
|
{
|
|
2679
2954
|
style: { width: 90, minWidth: 0, flex: "0 1 90px" },
|
|
@@ -2693,9 +2968,9 @@ var __defProp = Object.defineProperty;
|
|
|
2693
2968
|
}
|
|
2694
2969
|
)
|
|
2695
2970
|
] }),
|
|
2696
|
-
/* @__PURE__ */ (0,
|
|
2697
|
-
/* @__PURE__ */ (0,
|
|
2698
|
-
/* @__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)(
|
|
2699
2974
|
NInput,
|
|
2700
2975
|
{
|
|
2701
2976
|
style: RSTY.input,
|
|
@@ -2710,8 +2985,8 @@ var __defProp = Object.defineProperty;
|
|
|
2710
2985
|
onBlur: commitRemoteKey
|
|
2711
2986
|
}
|
|
2712
2987
|
),
|
|
2713
|
-
remote.apiKeySet ? /* @__PURE__ */ (0,
|
|
2714
|
-
/* @__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)(
|
|
2715
2990
|
NButton,
|
|
2716
2991
|
{
|
|
2717
2992
|
title: "写入空串清除运行时密钥(部署 YAML 的密钥不受影响)",
|
|
@@ -2721,12 +2996,12 @@ var __defProp = Object.defineProperty;
|
|
|
2721
2996
|
)
|
|
2722
2997
|
] })
|
|
2723
2998
|
] }),
|
|
2724
|
-
/* @__PURE__ */ (0,
|
|
2999
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: S.panelLabel, children: "本地模型目录(下载后离线可用,不随插件分发)" }),
|
|
2725
3000
|
modelCards,
|
|
2726
|
-
/* @__PURE__ */ (0,
|
|
2727
|
-
/* @__PURE__ */ (0,
|
|
2728
|
-
/* @__PURE__ */ (0,
|
|
2729
|
-
/* @__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)(
|
|
2730
3005
|
NButton,
|
|
2731
3006
|
{
|
|
2732
3007
|
disabled: !canRebuild,
|
|
@@ -2740,8 +3015,8 @@ var __defProp = Object.defineProperty;
|
|
|
2740
3015
|
}
|
|
2741
3016
|
|
|
2742
3017
|
// client/src/tabs/RebuildPanel.tsx
|
|
2743
|
-
var
|
|
2744
|
-
var
|
|
3018
|
+
var import_react13 = require("react");
|
|
3019
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2745
3020
|
var RB_PHASE_LABEL = {
|
|
2746
3021
|
preparing: "准备中(归档旧数据 · 清空检索库)",
|
|
2747
3022
|
distilling: "分块蒸馏中",
|
|
@@ -2749,21 +3024,21 @@ var __defProp = Object.defineProperty;
|
|
|
2749
3024
|
};
|
|
2750
3025
|
function RebuildPanel(props) {
|
|
2751
3026
|
const rpc = props.rpc;
|
|
2752
|
-
const [rbRaw, setRb] = (0,
|
|
2753
|
-
const [confirmOpen, setConfirmOpen] = (0,
|
|
2754
|
-
const [busy, setBusy] = (0,
|
|
2755
|
-
const [rbError, setRbError] = (0,
|
|
2756
|
-
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)(() => {
|
|
2757
3032
|
rpc("dsh-memory/rebuild-status", {}).then((r) => {
|
|
2758
3033
|
if (r && r.ok) setRb(r.value);
|
|
2759
3034
|
}).catch(() => {
|
|
2760
3035
|
});
|
|
2761
3036
|
}, [rpc]);
|
|
2762
|
-
(0,
|
|
3037
|
+
(0, import_react13.useEffect)(() => {
|
|
2763
3038
|
refresh();
|
|
2764
3039
|
}, [refresh]);
|
|
2765
3040
|
const running = !!(rbRaw && rbRaw.running);
|
|
2766
|
-
(0,
|
|
3041
|
+
(0, import_react13.useEffect)(() => {
|
|
2767
3042
|
if (!running) return;
|
|
2768
3043
|
const timer = setInterval(refresh, 1500);
|
|
2769
3044
|
return () => {
|
|
@@ -2808,11 +3083,11 @@ var __defProp = Object.defineProperty;
|
|
|
2808
3083
|
} else if (!running && rb.phase === "failed") {
|
|
2809
3084
|
lastNote = "上次重建:失败:" + (rb.error || "未知错误");
|
|
2810
3085
|
}
|
|
2811
|
-
return /* @__PURE__ */ (0,
|
|
2812
|
-
/* @__PURE__ */ (0,
|
|
2813
|
-
/* @__PURE__ */ (0,
|
|
2814
|
-
/* @__PURE__ */ (0,
|
|
2815
|
-
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)(
|
|
2816
3091
|
NButton,
|
|
2817
3092
|
{
|
|
2818
3093
|
disabled: busy || empty,
|
|
@@ -2825,13 +3100,13 @@ var __defProp = Object.defineProperty;
|
|
|
2825
3100
|
}
|
|
2826
3101
|
)
|
|
2827
3102
|
] }),
|
|
2828
|
-
running ? /* @__PURE__ */ (0,
|
|
2829
|
-
/* @__PURE__ */ (0,
|
|
2830
|
-
/* @__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 + " 条" })
|
|
2831
3106
|
] }) : null,
|
|
2832
|
-
lastNote ? /* @__PURE__ */ (0,
|
|
2833
|
-
rbError ? /* @__PURE__ */ (0,
|
|
2834
|
-
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)(
|
|
2835
3110
|
NModal,
|
|
2836
3111
|
{
|
|
2837
3112
|
open: true,
|
|
@@ -2840,7 +3115,7 @@ var __defProp = Object.defineProperty;
|
|
|
2840
3115
|
},
|
|
2841
3116
|
title: "确认重建全部记忆?",
|
|
2842
3117
|
footer: [
|
|
2843
|
-
/* @__PURE__ */ (0,
|
|
3118
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2844
3119
|
NButton,
|
|
2845
3120
|
{
|
|
2846
3121
|
onClick: () => {
|
|
@@ -2850,15 +3125,15 @@ var __defProp = Object.defineProperty;
|
|
|
2850
3125
|
},
|
|
2851
3126
|
"cancel"
|
|
2852
3127
|
),
|
|
2853
|
-
/* @__PURE__ */ (0,
|
|
3128
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(NButton, { variant: "primary", disabled: busy, onClick: start, children: busy ? "启动中…" : "开始重建" }, "confirm")
|
|
2854
3129
|
],
|
|
2855
3130
|
children: [
|
|
2856
|
-
/* @__PURE__ */ (0,
|
|
3131
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
|
|
2857
3132
|
"将以 L0 原始对话为事实源重新蒸馏:",
|
|
2858
|
-
/* @__PURE__ */ (0,
|
|
3133
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("b", { children: rb.sessionCount + " 个会话 · " + rb.messageCount + " 条消息" }),
|
|
2859
3134
|
",预计 ≥" + rb.estCalls + " 次蒸馏调用。"
|
|
2860
3135
|
] }),
|
|
2861
|
-
/* @__PURE__ */ (0,
|
|
3136
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { marginTop: 8 }, children: "现有 L1 记忆 / L2 场景 / L3 画像会整体归档(*.bak.时间戳,可手工找回),随后清空重建;重建期间可正常对话,新对话的蒸馏优先进行;中途可取消,已重建部分保留。" })
|
|
2862
3137
|
]
|
|
2863
3138
|
}
|
|
2864
3139
|
) : null
|
|
@@ -2866,8 +3141,8 @@ var __defProp = Object.defineProperty;
|
|
|
2866
3141
|
}
|
|
2867
3142
|
|
|
2868
3143
|
// client/src/tabs/RuminatePanel.tsx
|
|
2869
|
-
var
|
|
2870
|
-
var
|
|
3144
|
+
var import_react14 = require("react");
|
|
3145
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
2871
3146
|
var RM_PHASE_LABEL = {
|
|
2872
3147
|
refreshing: "轻量刷新中",
|
|
2873
3148
|
distilling: "L1 蒸馏中",
|
|
@@ -2888,11 +3163,11 @@ var __defProp = Object.defineProperty;
|
|
|
2888
3163
|
var RM_IDLE_INTERVAL = 3e4;
|
|
2889
3164
|
function RuminatePanel(props) {
|
|
2890
3165
|
const rpc = props.rpc;
|
|
2891
|
-
const [rmRaw, setRm] = (0,
|
|
2892
|
-
const [confirmOpen, setConfirmOpen] = (0,
|
|
2893
|
-
const [busy, setBusy] = (0,
|
|
2894
|
-
const [rmError, setRmError] = (0,
|
|
2895
|
-
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)(() => {
|
|
2896
3171
|
return rpc("dsh-memory/ruminate-status", {}).then((r) => {
|
|
2897
3172
|
if (r && r.ok) {
|
|
2898
3173
|
const st = r.value;
|
|
@@ -2907,14 +3182,14 @@ var __defProp = Object.defineProperty;
|
|
|
2907
3182
|
}).catch(() => {
|
|
2908
3183
|
});
|
|
2909
3184
|
}, [rpc]);
|
|
2910
|
-
const pollRef = (0,
|
|
2911
|
-
const backoffRef = (0,
|
|
2912
|
-
const lastDetailRef = (0,
|
|
2913
|
-
(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)(() => {
|
|
2914
3189
|
refresh();
|
|
2915
3190
|
}, [refresh]);
|
|
2916
3191
|
const running = !!(rmRaw && (rmRaw.running || RM_RUNNING_PHASES.indexOf(rmRaw.phase) >= 0));
|
|
2917
|
-
(0,
|
|
3192
|
+
(0, import_react14.useEffect)(() => {
|
|
2918
3193
|
if (!running) return;
|
|
2919
3194
|
let alive = true;
|
|
2920
3195
|
let timer;
|
|
@@ -2933,13 +3208,13 @@ var __defProp = Object.defineProperty;
|
|
|
2933
3208
|
lastDetailRef.current = null;
|
|
2934
3209
|
};
|
|
2935
3210
|
}, [running, refresh]);
|
|
2936
|
-
(0,
|
|
3211
|
+
(0, import_react14.useEffect)(() => {
|
|
2937
3212
|
if (running) return;
|
|
2938
3213
|
const timer = setInterval(refresh, RM_IDLE_INTERVAL);
|
|
2939
3214
|
return () => clearInterval(timer);
|
|
2940
3215
|
}, [running, refresh]);
|
|
2941
|
-
const [, setTick] = (0,
|
|
2942
|
-
(0,
|
|
3216
|
+
const [, setTick] = (0, import_react14.useState)(0);
|
|
3217
|
+
(0, import_react14.useEffect)(() => {
|
|
2943
3218
|
if (!running) return;
|
|
2944
3219
|
const timer = setInterval(() => setTick((n) => n + 1), 1e3);
|
|
2945
3220
|
return () => clearInterval(timer);
|
|
@@ -2990,11 +3265,11 @@ var __defProp = Object.defineProperty;
|
|
|
2990
3265
|
}
|
|
2991
3266
|
const unit = rm.phase === "refreshing" || rm.phase === "relabeling" ? "步" : "会话";
|
|
2992
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 + "%)" : "进行中…";
|
|
2993
|
-
return /* @__PURE__ */ (0,
|
|
2994
|
-
/* @__PURE__ */ (0,
|
|
2995
|
-
/* @__PURE__ */ (0,
|
|
2996
|
-
/* @__PURE__ */ (0,
|
|
2997
|
-
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)(
|
|
2998
3273
|
NButton,
|
|
2999
3274
|
{
|
|
3000
3275
|
disabled: busy,
|
|
@@ -3007,27 +3282,27 @@ var __defProp = Object.defineProperty;
|
|
|
3007
3282
|
}
|
|
3008
3283
|
)
|
|
3009
3284
|
] }),
|
|
3010
|
-
running ? /* @__PURE__ */ (0,
|
|
3011
|
-
/* @__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)(
|
|
3012
3287
|
"div",
|
|
3013
3288
|
{
|
|
3014
3289
|
className: "dsh-mem-rb-fill" + (indet ? " dsh-mem-rb-fill-indet" : ""),
|
|
3015
3290
|
style: { width: indet ? "100%" : barPct + "%" }
|
|
3016
3291
|
}
|
|
3017
3292
|
) }),
|
|
3018
|
-
/* @__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 + " 条" })
|
|
3019
3294
|
] }) : null,
|
|
3020
|
-
running && rm.detail ? /* @__PURE__ */ (0,
|
|
3021
|
-
lastNote ? /* @__PURE__ */ (0,
|
|
3022
|
-
rmError ? /* @__PURE__ */ (0,
|
|
3023
|
-
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)(
|
|
3024
3299
|
NModal,
|
|
3025
3300
|
{
|
|
3026
3301
|
open: true,
|
|
3027
3302
|
onClose: () => setConfirmOpen(false),
|
|
3028
3303
|
title: "确认反刍整理?",
|
|
3029
3304
|
footer: [
|
|
3030
|
-
/* @__PURE__ */ (0,
|
|
3305
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3031
3306
|
NButton,
|
|
3032
3307
|
{
|
|
3033
3308
|
onClick: () => setConfirmOpen(false),
|
|
@@ -3035,11 +3310,11 @@ var __defProp = Object.defineProperty;
|
|
|
3035
3310
|
},
|
|
3036
3311
|
"cancel"
|
|
3037
3312
|
),
|
|
3038
|
-
/* @__PURE__ */ (0,
|
|
3313
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(NButton, { variant: "primary", disabled: busy, onClick: start, children: busy ? "启动中…" : "反刍整理" }, "confirm")
|
|
3039
3314
|
],
|
|
3040
3315
|
children: [
|
|
3041
|
-
/* @__PURE__ */ (0,
|
|
3042
|
-
/* @__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 刷新。" })
|
|
3043
3318
|
]
|
|
3044
3319
|
}
|
|
3045
3320
|
) : null
|
|
@@ -3047,13 +3322,13 @@ var __defProp = Object.defineProperty;
|
|
|
3047
3322
|
}
|
|
3048
3323
|
|
|
3049
3324
|
// client/src/tabs/OverviewTab.tsx
|
|
3050
|
-
var
|
|
3325
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
3051
3326
|
function OverviewTab(props) {
|
|
3052
3327
|
const rpc = props.rpc;
|
|
3053
|
-
const [stats, setStats] = (0,
|
|
3054
|
-
const [settingsData, setSettingsData] = (0,
|
|
3055
|
-
const [error, setError] = (0,
|
|
3056
|
-
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)(() => {
|
|
3057
3332
|
rpc("dsh-memory/stats", {}).then((r) => {
|
|
3058
3333
|
if (r && r.ok) setStats(r.value);
|
|
3059
3334
|
else setError(r && r.error ? r.error.message : "RPC error");
|
|
@@ -3065,7 +3340,7 @@ var __defProp = Object.defineProperty;
|
|
|
3065
3340
|
}).catch(() => {
|
|
3066
3341
|
});
|
|
3067
3342
|
}, [rpc]);
|
|
3068
|
-
(0,
|
|
3343
|
+
(0, import_react15.useEffect)(() => {
|
|
3069
3344
|
load();
|
|
3070
3345
|
const timer = setInterval(load, 5e3);
|
|
3071
3346
|
return () => {
|
|
@@ -3126,10 +3401,11 @@ var __defProp = Object.defineProperty;
|
|
|
3126
3401
|
const toolRuminate = settingsData && settingsData.settings ? settingsData.settings.toolRuminate !== false : true;
|
|
3127
3402
|
const toolConflict = settingsData && settingsData.settings ? settingsData.settings.toolConflict !== false : true;
|
|
3128
3403
|
const toolMutate = settingsData && settingsData.settings ? settingsData.settings.toolMutate !== false : true;
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
/* @__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)(
|
|
3133
3409
|
SwitchRow,
|
|
3134
3410
|
{
|
|
3135
3411
|
label: "记忆模式",
|
|
@@ -3140,7 +3416,7 @@ var __defProp = Object.defineProperty;
|
|
|
3140
3416
|
}
|
|
3141
3417
|
}
|
|
3142
3418
|
),
|
|
3143
|
-
/* @__PURE__ */ (0,
|
|
3419
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3144
3420
|
SwitchRow,
|
|
3145
3421
|
{
|
|
3146
3422
|
label: "捕获",
|
|
@@ -3152,7 +3428,7 @@ var __defProp = Object.defineProperty;
|
|
|
3152
3428
|
}
|
|
3153
3429
|
}
|
|
3154
3430
|
),
|
|
3155
|
-
/* @__PURE__ */ (0,
|
|
3431
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3156
3432
|
SwitchRow,
|
|
3157
3433
|
{
|
|
3158
3434
|
label: "蒸馏",
|
|
@@ -3164,7 +3440,7 @@ var __defProp = Object.defineProperty;
|
|
|
3164
3440
|
}
|
|
3165
3441
|
}
|
|
3166
3442
|
),
|
|
3167
|
-
/* @__PURE__ */ (0,
|
|
3443
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3168
3444
|
SwitchRow,
|
|
3169
3445
|
{
|
|
3170
3446
|
label: "召回",
|
|
@@ -3176,8 +3452,8 @@ var __defProp = Object.defineProperty;
|
|
|
3176
3452
|
}
|
|
3177
3453
|
}
|
|
3178
3454
|
),
|
|
3179
|
-
/* @__PURE__ */ (0,
|
|
3180
|
-
/* @__PURE__ */ (0,
|
|
3455
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: S.panelLabel, children: "高权限模式" }),
|
|
3456
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3181
3457
|
SwitchRow,
|
|
3182
3458
|
{
|
|
3183
3459
|
label: "高权限模式",
|
|
@@ -3188,8 +3464,20 @@ var __defProp = Object.defineProperty;
|
|
|
3188
3464
|
}
|
|
3189
3465
|
}
|
|
3190
3466
|
),
|
|
3191
|
-
/* @__PURE__ */ (0,
|
|
3192
|
-
/* @__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)(
|
|
3193
3481
|
SwitchRow,
|
|
3194
3482
|
{
|
|
3195
3483
|
label: "Room 管理工具",
|
|
@@ -3200,7 +3488,7 @@ var __defProp = Object.defineProperty;
|
|
|
3200
3488
|
}
|
|
3201
3489
|
}
|
|
3202
3490
|
),
|
|
3203
|
-
/* @__PURE__ */ (0,
|
|
3491
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3204
3492
|
SwitchRow,
|
|
3205
3493
|
{
|
|
3206
3494
|
label: "图谱工具",
|
|
@@ -3211,7 +3499,7 @@ var __defProp = Object.defineProperty;
|
|
|
3211
3499
|
}
|
|
3212
3500
|
}
|
|
3213
3501
|
),
|
|
3214
|
-
/* @__PURE__ */ (0,
|
|
3502
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3215
3503
|
SwitchRow,
|
|
3216
3504
|
{
|
|
3217
3505
|
label: "反刍工具",
|
|
@@ -3222,7 +3510,7 @@ var __defProp = Object.defineProperty;
|
|
|
3222
3510
|
}
|
|
3223
3511
|
}
|
|
3224
3512
|
),
|
|
3225
|
-
/* @__PURE__ */ (0,
|
|
3513
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3226
3514
|
SwitchRow,
|
|
3227
3515
|
{
|
|
3228
3516
|
label: "冲突工具",
|
|
@@ -3233,7 +3521,7 @@ var __defProp = Object.defineProperty;
|
|
|
3233
3521
|
}
|
|
3234
3522
|
}
|
|
3235
3523
|
),
|
|
3236
|
-
/* @__PURE__ */ (0,
|
|
3524
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3237
3525
|
SwitchRow,
|
|
3238
3526
|
{
|
|
3239
3527
|
label: "写删工具",
|
|
@@ -3244,8 +3532,8 @@ var __defProp = Object.defineProperty;
|
|
|
3244
3532
|
}
|
|
3245
3533
|
}
|
|
3246
3534
|
),
|
|
3247
|
-
/* @__PURE__ */ (0,
|
|
3248
|
-
/* @__PURE__ */ (0,
|
|
3535
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: S.panelLabel, children: "人工冲突裁决" }),
|
|
3536
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3249
3537
|
SwitchRow,
|
|
3250
3538
|
{
|
|
3251
3539
|
label: "人工冲突裁决",
|
|
@@ -3256,42 +3544,42 @@ var __defProp = Object.defineProperty;
|
|
|
3256
3544
|
}
|
|
3257
3545
|
}
|
|
3258
3546
|
),
|
|
3259
|
-
/* @__PURE__ */ (0,
|
|
3260
|
-
/* @__PURE__ */ (0,
|
|
3261
|
-
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
|
|
3262
3550
|
] }) : null,
|
|
3263
|
-
/* @__PURE__ */ (0,
|
|
3264
|
-
/* @__PURE__ */ (0,
|
|
3265
|
-
/* @__PURE__ */ (0,
|
|
3266
|
-
degraded ? /* @__PURE__ */ (0,
|
|
3267
|
-
error ? /* @__PURE__ */ (0,
|
|
3268
|
-
/* @__PURE__ */ (0,
|
|
3269
|
-
/* @__PURE__ */ (0,
|
|
3270
|
-
return /* @__PURE__ */ (0,
|
|
3271
|
-
/* @__PURE__ */ (0,
|
|
3272
|
-
/* @__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 })
|
|
3273
3561
|
] }, t.label);
|
|
3274
3562
|
}) }),
|
|
3275
|
-
/* @__PURE__ */ (0,
|
|
3563
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: S.panelLabel, children: "运行状态" }),
|
|
3276
3564
|
infos.map((row2) => {
|
|
3277
|
-
return /* @__PURE__ */ (0,
|
|
3278
|
-
/* @__PURE__ */ (0,
|
|
3279
|
-
/* @__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] })
|
|
3280
3568
|
] }, row2[0]);
|
|
3281
3569
|
})
|
|
3282
3570
|
] }),
|
|
3283
|
-
/* @__PURE__ */ (0,
|
|
3571
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: S.hint, children: "浏览各层记忆内容请切换上方 Tab;原始对话(L0)不入浏览器,可由模型侧 conversation_search 工具查询。" })
|
|
3284
3572
|
] });
|
|
3285
3573
|
}
|
|
3286
3574
|
|
|
3287
3575
|
// client/src/tabs/PersonaTab.tsx
|
|
3288
|
-
var
|
|
3289
|
-
var
|
|
3576
|
+
var import_react16 = require("react");
|
|
3577
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
3290
3578
|
function PersonaTab(props) {
|
|
3291
3579
|
const rpc = props.rpc;
|
|
3292
|
-
const [content, setContent] = (0,
|
|
3293
|
-
const [error, setError] = (0,
|
|
3294
|
-
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)(() => {
|
|
3295
3583
|
setError(null);
|
|
3296
3584
|
rpc("dsh-memory/persona", {}).then((r) => {
|
|
3297
3585
|
if (r && r.ok) setContent(r.value.content);
|
|
@@ -3300,23 +3588,23 @@ var __defProp = Object.defineProperty;
|
|
|
3300
3588
|
setError(String(e && e.message || e));
|
|
3301
3589
|
});
|
|
3302
3590
|
}, [rpc]);
|
|
3303
|
-
(0,
|
|
3591
|
+
(0, import_react16.useEffect)(() => {
|
|
3304
3592
|
load();
|
|
3305
3593
|
}, [load]);
|
|
3306
|
-
return /* @__PURE__ */ (0,
|
|
3307
|
-
/* @__PURE__ */ (0,
|
|
3308
|
-
/* @__PURE__ */ (0,
|
|
3309
|
-
/* @__PURE__ */ (0,
|
|
3310
|
-
/* @__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: "刷新" })
|
|
3311
3599
|
] }),
|
|
3312
|
-
error ? /* @__PURE__ */ (0,
|
|
3313
|
-
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 会自动产出。" })
|
|
3314
3602
|
] });
|
|
3315
3603
|
}
|
|
3316
3604
|
|
|
3317
3605
|
// client/src/tabs/RecordsTab.tsx
|
|
3318
|
-
var
|
|
3319
|
-
var
|
|
3606
|
+
var import_react17 = require("react");
|
|
3607
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
3320
3608
|
function retiredSelOf(r) {
|
|
3321
3609
|
if (r === "active") return false;
|
|
3322
3610
|
if (r === "retired") return true;
|
|
@@ -3335,29 +3623,29 @@ var __defProp = Object.defineProperty;
|
|
|
3335
3623
|
function RecordsTab(props) {
|
|
3336
3624
|
const rpc = props.rpc;
|
|
3337
3625
|
const limit = 50;
|
|
3338
|
-
const [items, setItems] = (0,
|
|
3339
|
-
const [hasMore, setHasMore] = (0,
|
|
3340
|
-
const [total, setTotal] = (0,
|
|
3341
|
-
const [sceneOptions, setSceneOptions] = (0,
|
|
3342
|
-
const [loading, setLoading] = (0,
|
|
3343
|
-
const [truncated, setTruncated] = (0,
|
|
3344
|
-
const [error, setError] = (0,
|
|
3345
|
-
const [expandedId, setExpandedId] = (0,
|
|
3346
|
-
const [sel, setSel] = (0,
|
|
3347
|
-
const [hiPriv, setHiPriv] = (0,
|
|
3348
|
-
const [hiPrivBusy, setHiPrivBusy] = (0,
|
|
3349
|
-
const [query, setQuery] = (0,
|
|
3350
|
-
const [typeFilter, setTypeFilter] = (0,
|
|
3351
|
-
const [sceneFilter, setSceneFilter] = (0,
|
|
3352
|
-
const [hallFilter, setHallFilter] = (0,
|
|
3353
|
-
const [tagFilter, setTagFilter] = (0,
|
|
3354
|
-
const [untaggedOnly, setUntaggedOnly] = (0,
|
|
3355
|
-
const [orphanCount, setOrphanCount] = (0,
|
|
3356
|
-
const [retiredFilter, setRetiredFilter] = (0,
|
|
3357
|
-
const [wingCatalog, setHallCatalog] = (0,
|
|
3358
|
-
const [last, setLast] = (0,
|
|
3359
|
-
const seqRef = (0,
|
|
3360
|
-
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)(
|
|
3361
3649
|
(conds, offset, append) => {
|
|
3362
3650
|
setLoading(true);
|
|
3363
3651
|
setError(null);
|
|
@@ -3406,23 +3694,23 @@ var __defProp = Object.defineProperty;
|
|
|
3406
3694
|
setLast(conds);
|
|
3407
3695
|
fetchPage(conds, 0, false);
|
|
3408
3696
|
};
|
|
3409
|
-
const loadRooms = (0,
|
|
3697
|
+
const loadRooms = (0, import_react17.useCallback)(() => {
|
|
3410
3698
|
rpc("dsh-memory/rooms-get", {}).then((r) => {
|
|
3411
3699
|
if (r && r.ok) setOrphanCount(r.value.orphanCount ?? 0);
|
|
3412
3700
|
}).catch(() => {
|
|
3413
3701
|
});
|
|
3414
3702
|
}, [rpc]);
|
|
3415
|
-
(0,
|
|
3703
|
+
(0, import_react17.useEffect)(() => {
|
|
3416
3704
|
fetchPage({ query: "", type: "", scene: "", halls: [], tag: "", untagged: false, retired: "" }, 0, false);
|
|
3417
3705
|
loadRooms();
|
|
3418
3706
|
}, [fetchPage, loadRooms]);
|
|
3419
|
-
const loadHiPriv = (0,
|
|
3707
|
+
const loadHiPriv = (0, import_react17.useCallback)(() => {
|
|
3420
3708
|
rpc("dsh-memory/settings-get", {}).then((r) => {
|
|
3421
3709
|
if (r && r.ok && r.value) setHiPriv(!!r.value.settings.memoryMutate);
|
|
3422
3710
|
}).catch(() => {
|
|
3423
3711
|
});
|
|
3424
3712
|
}, [rpc]);
|
|
3425
|
-
(0,
|
|
3713
|
+
(0, import_react17.useEffect)(() => {
|
|
3426
3714
|
loadHiPriv();
|
|
3427
3715
|
}, [loadHiPriv]);
|
|
3428
3716
|
const toggleHiPriv = () => {
|
|
@@ -3483,11 +3771,11 @@ var __defProp = Object.defineProperty;
|
|
|
3483
3771
|
} else if (r) setError(r.error ? r.error.message : "退场失败");
|
|
3484
3772
|
}).catch((e) => setError(String(e && e.message || e)));
|
|
3485
3773
|
};
|
|
3486
|
-
const [retired, setRetired] = (0,
|
|
3487
|
-
const [retiredTotal, setRetiredTotal] = (0,
|
|
3488
|
-
const [showRetired, setShowRetired] = (0,
|
|
3489
|
-
const [retiredBusy, setRetiredBusy] = (0,
|
|
3490
|
-
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)(() => {
|
|
3491
3779
|
setRetiredBusy(true);
|
|
3492
3780
|
rpc("dsh-memory/records-retired", { limit: 100, offset: 0 }).then((r) => {
|
|
3493
3781
|
if (r && r.ok) {
|
|
@@ -3496,7 +3784,7 @@ var __defProp = Object.defineProperty;
|
|
|
3496
3784
|
} else if (r) setError(r.error ? r.error.message : "已退场列表加载失败");
|
|
3497
3785
|
}).catch((e) => setError(String(e && e.message || e))).finally(() => setRetiredBusy(false));
|
|
3498
3786
|
}, [rpc]);
|
|
3499
|
-
(0,
|
|
3787
|
+
(0, import_react17.useEffect)(() => {
|
|
3500
3788
|
if (showRetired) loadRetired();
|
|
3501
3789
|
}, [showRetired, loadRetired]);
|
|
3502
3790
|
const restoreRecords = (ids) => {
|
|
@@ -3516,11 +3804,11 @@ var __defProp = Object.defineProperty;
|
|
|
3516
3804
|
unknown: "已退场"
|
|
3517
3805
|
};
|
|
3518
3806
|
const countText = total !== null ? "共 " + total + " 条" : items.length + " 条" + (hasMore ? "+" : "");
|
|
3519
|
-
const [usageSummary, setUsageSummary] = (0,
|
|
3807
|
+
const [usageSummary, setUsageSummary] = (0, import_react17.useState)(null);
|
|
3520
3808
|
const selCount = sel.size;
|
|
3521
|
-
return /* @__PURE__ */ (0,
|
|
3522
|
-
/* @__PURE__ */ (0,
|
|
3523
|
-
/* @__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)(
|
|
3524
3812
|
NInput,
|
|
3525
3813
|
{
|
|
3526
3814
|
style: { flex: 1, minWidth: 160 },
|
|
@@ -3534,7 +3822,7 @@ var __defProp = Object.defineProperty;
|
|
|
3534
3822
|
}
|
|
3535
3823
|
}
|
|
3536
3824
|
),
|
|
3537
|
-
/* @__PURE__ */ (0,
|
|
3825
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3538
3826
|
NSel,
|
|
3539
3827
|
{
|
|
3540
3828
|
style: { maxWidth: 200 },
|
|
@@ -3547,7 +3835,7 @@ var __defProp = Object.defineProperty;
|
|
|
3547
3835
|
onChange: setTypeFilter
|
|
3548
3836
|
}
|
|
3549
3837
|
),
|
|
3550
|
-
/* @__PURE__ */ (0,
|
|
3838
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3551
3839
|
NSel,
|
|
3552
3840
|
{
|
|
3553
3841
|
style: { maxWidth: 220 },
|
|
@@ -3560,7 +3848,7 @@ var __defProp = Object.defineProperty;
|
|
|
3560
3848
|
onChange: setSceneFilter
|
|
3561
3849
|
}
|
|
3562
3850
|
),
|
|
3563
|
-
/* @__PURE__ */ (0,
|
|
3851
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3564
3852
|
WingMultiSelect,
|
|
3565
3853
|
{
|
|
3566
3854
|
options: wingCatalog ?? Array.from(new Set(items.map((m) => m.hall).filter((h) => !!h))).map((id) => ({ id, label: id })),
|
|
@@ -3568,8 +3856,8 @@ var __defProp = Object.defineProperty;
|
|
|
3568
3856
|
onChange: setHallFilter
|
|
3569
3857
|
}
|
|
3570
3858
|
),
|
|
3571
|
-
/* @__PURE__ */ (0,
|
|
3572
|
-
/* @__PURE__ */ (0,
|
|
3859
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(NButton, { onClick: search, children: "搜索" }),
|
|
3860
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3573
3861
|
NButton,
|
|
3574
3862
|
{
|
|
3575
3863
|
style: {
|
|
@@ -3583,8 +3871,8 @@ var __defProp = Object.defineProperty;
|
|
|
3583
3871
|
}
|
|
3584
3872
|
)
|
|
3585
3873
|
] }),
|
|
3586
|
-
/* @__PURE__ */ (0,
|
|
3587
|
-
/* @__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)(
|
|
3588
3876
|
"button",
|
|
3589
3877
|
{
|
|
3590
3878
|
type: "button",
|
|
@@ -3609,10 +3897,10 @@ var __defProp = Object.defineProperty;
|
|
|
3609
3897
|
children: "无绑定 · " + orphanCount
|
|
3610
3898
|
}
|
|
3611
3899
|
),
|
|
3612
|
-
(tagFilter || untaggedOnly) && /* @__PURE__ */ (0,
|
|
3900
|
+
(tagFilter || untaggedOnly) && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { style: S.muted, children: [
|
|
3613
3901
|
"筛选中:",
|
|
3614
3902
|
untaggedOnly ? "无绑定" : tagFilter,
|
|
3615
|
-
/* @__PURE__ */ (0,
|
|
3903
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3616
3904
|
"button",
|
|
3617
3905
|
{
|
|
3618
3906
|
type: "button",
|
|
@@ -3629,7 +3917,7 @@ var __defProp = Object.defineProperty;
|
|
|
3629
3917
|
}
|
|
3630
3918
|
)
|
|
3631
3919
|
] }),
|
|
3632
|
-
/* @__PURE__ */ (0,
|
|
3920
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3633
3921
|
"button",
|
|
3634
3922
|
{
|
|
3635
3923
|
type: "button",
|
|
@@ -3658,15 +3946,15 @@ var __defProp = Object.defineProperty;
|
|
|
3658
3946
|
children: "导出孤儿"
|
|
3659
3947
|
}
|
|
3660
3948
|
),
|
|
3661
|
-
/* @__PURE__ */ (0,
|
|
3949
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: S.muted, children: "Room 标签/分类管理:见「Hall」「Room」标签页。" })
|
|
3662
3950
|
] }),
|
|
3663
|
-
/* @__PURE__ */ (0,
|
|
3664
|
-
/* @__PURE__ */ (0,
|
|
3665
|
-
usageSummary ? /* @__PURE__ */ (0,
|
|
3666
|
-
/* @__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: "退场筛查" }),
|
|
3667
3955
|
[["", "全部"], ["active", "仅活跃"], ["retired", "仅退场"]].map(([val, label]) => {
|
|
3668
3956
|
const on = retiredFilter === val;
|
|
3669
|
-
return /* @__PURE__ */ (0,
|
|
3957
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3670
3958
|
"button",
|
|
3671
3959
|
{
|
|
3672
3960
|
type: "button",
|
|
@@ -3686,7 +3974,7 @@ var __defProp = Object.defineProperty;
|
|
|
3686
3974
|
val
|
|
3687
3975
|
);
|
|
3688
3976
|
}),
|
|
3689
|
-
/* @__PURE__ */ (0,
|
|
3977
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3690
3978
|
NButton,
|
|
3691
3979
|
{
|
|
3692
3980
|
style: selCount > 0 ? { color: "var(--dsh-mem-danger)" } : void 0,
|
|
@@ -3696,7 +3984,7 @@ var __defProp = Object.defineProperty;
|
|
|
3696
3984
|
children: "删除选中" + (selCount > 0 ? "(" + selCount + ")" : "")
|
|
3697
3985
|
}
|
|
3698
3986
|
),
|
|
3699
|
-
selCount > 0 ? /* @__PURE__ */ (0,
|
|
3987
|
+
selCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3700
3988
|
NButton,
|
|
3701
3989
|
{
|
|
3702
3990
|
onClick: () => {
|
|
@@ -3705,8 +3993,8 @@ var __defProp = Object.defineProperty;
|
|
|
3705
3993
|
children: "清空选择"
|
|
3706
3994
|
}
|
|
3707
3995
|
) : null,
|
|
3708
|
-
/* @__PURE__ */ (0,
|
|
3709
|
-
/* @__PURE__ */ (0,
|
|
3996
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: S.grow }),
|
|
3997
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3710
3998
|
NButton,
|
|
3711
3999
|
{
|
|
3712
4000
|
onClick: () => {
|
|
@@ -3717,13 +4005,13 @@ var __defProp = Object.defineProperty;
|
|
|
3717
4005
|
}
|
|
3718
4006
|
)
|
|
3719
4007
|
] }),
|
|
3720
|
-
!hiPriv ? /* @__PURE__ */ (0,
|
|
3721
|
-
error ? /* @__PURE__ */ (0,
|
|
3722
|
-
truncated ? /* @__PURE__ */ (0,
|
|
3723
|
-
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) => {
|
|
3724
4012
|
const open = expandedId === m.id;
|
|
3725
4013
|
const checked = sel.has(m.id);
|
|
3726
|
-
return /* @__PURE__ */ (0,
|
|
4014
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
3727
4015
|
"div",
|
|
3728
4016
|
{
|
|
3729
4017
|
className: "dsh-mem-card dsh-mem-card-hover",
|
|
@@ -3732,8 +4020,8 @@ var __defProp = Object.defineProperty;
|
|
|
3732
4020
|
setExpandedId(open ? null : m.id);
|
|
3733
4021
|
},
|
|
3734
4022
|
children: [
|
|
3735
|
-
/* @__PURE__ */ (0,
|
|
3736
|
-
/* @__PURE__ */ (0,
|
|
4023
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: S.cardHead, children: [
|
|
4024
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3737
4025
|
"input",
|
|
3738
4026
|
{
|
|
3739
4027
|
type: "checkbox",
|
|
@@ -3748,9 +4036,9 @@ var __defProp = Object.defineProperty;
|
|
|
3748
4036
|
}
|
|
3749
4037
|
}
|
|
3750
4038
|
),
|
|
3751
|
-
/* @__PURE__ */ (0,
|
|
3752
|
-
m.hall ? /* @__PURE__ */ (0,
|
|
3753
|
-
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)(
|
|
3754
4042
|
"span",
|
|
3755
4043
|
{
|
|
3756
4044
|
title: "该记忆已退场(软删):移出检索面但仍可恢复,并未真正删除",
|
|
@@ -3765,8 +4053,23 @@ var __defProp = Object.defineProperty;
|
|
|
3765
4053
|
children: "已退场" + (m.retiredReason ? " · " + (RETIRE_REASON_LABEL[m.retiredReason] || m.retiredReason) : "")
|
|
3766
4054
|
}
|
|
3767
4055
|
) : null,
|
|
3768
|
-
/* @__PURE__ */ (0,
|
|
3769
|
-
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)(
|
|
3770
4073
|
"span",
|
|
3771
4074
|
{
|
|
3772
4075
|
style: {
|
|
@@ -3781,7 +4084,7 @@ var __defProp = Object.defineProperty;
|
|
|
3781
4084
|
children: "老化 " + Math.round(m.agingWeight * 100) + "%"
|
|
3782
4085
|
}
|
|
3783
4086
|
) : null,
|
|
3784
|
-
m.usage ? /* @__PURE__ */ (0,
|
|
4087
|
+
m.usage ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3785
4088
|
"span",
|
|
3786
4089
|
{
|
|
3787
4090
|
style: S.muted,
|
|
@@ -3789,10 +4092,10 @@ var __defProp = Object.defineProperty;
|
|
|
3789
4092
|
children: "用 " + m.usage.used + "/" + m.usage.attempts
|
|
3790
4093
|
}
|
|
3791
4094
|
) : null,
|
|
3792
|
-
m.score !== null && m.score !== void 0 ? /* @__PURE__ */ (0,
|
|
3793
|
-
/* @__PURE__ */ (0,
|
|
3794
|
-
/* @__PURE__ */ (0,
|
|
3795
|
-
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)(
|
|
3796
4099
|
NButton,
|
|
3797
4100
|
{
|
|
3798
4101
|
style: { padding: "0 7px", minWidth: 26, height: 26, fontSize: 12, color: "var(--dsh-mem-accent)" },
|
|
@@ -3803,7 +4106,7 @@ var __defProp = Object.defineProperty;
|
|
|
3803
4106
|
},
|
|
3804
4107
|
children: "恢复"
|
|
3805
4108
|
}
|
|
3806
|
-
) : hiPriv ? /* @__PURE__ */ (0,
|
|
4109
|
+
) : hiPriv ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
3807
4110
|
NButton,
|
|
3808
4111
|
{
|
|
3809
4112
|
style: { padding: "0 7px", minWidth: 26, height: 26, fontSize: 12, color: "var(--dsh-mem-danger)" },
|
|
@@ -3816,34 +4119,34 @@ var __defProp = Object.defineProperty;
|
|
|
3816
4119
|
}
|
|
3817
4120
|
) : null
|
|
3818
4121
|
] }),
|
|
3819
|
-
/* @__PURE__ */ (0,
|
|
3820
|
-
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
|
|
3821
4124
|
]
|
|
3822
4125
|
},
|
|
3823
4126
|
m.id
|
|
3824
4127
|
);
|
|
3825
4128
|
}),
|
|
3826
|
-
/* @__PURE__ */ (0,
|
|
3827
|
-
/* @__PURE__ */ (0,
|
|
3828
|
-
showRetired && retiredBusy ? /* @__PURE__ */ (0,
|
|
3829
|
-
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
|
|
3830
4133
|
] }),
|
|
3831
|
-
showRetired ? /* @__PURE__ */ (0,
|
|
3832
|
-
retired.map((m) => /* @__PURE__ */ (0,
|
|
3833
|
-
/* @__PURE__ */ (0,
|
|
3834
|
-
/* @__PURE__ */ (0,
|
|
3835
|
-
m.verdict ? /* @__PURE__ */ (0,
|
|
3836
|
-
/* @__PURE__ */ (0,
|
|
3837
|
-
/* @__PURE__ */ (0,
|
|
3838
|
-
/* @__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: "恢复" })
|
|
3839
4142
|
] }),
|
|
3840
|
-
/* @__PURE__ */ (0,
|
|
4143
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: S.content, children: m.content })
|
|
3841
4144
|
] }, m.id)),
|
|
3842
|
-
retiredTotal > retired.length ? /* @__PURE__ */ (0,
|
|
4145
|
+
retiredTotal > retired.length ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { style: S.hint, children: "共 " + retiredTotal + " 条,此处显示 " + retired.length + " 条" }) : null
|
|
3843
4146
|
] }) }) : null,
|
|
3844
|
-
hasMore ? /* @__PURE__ */ (0,
|
|
3845
|
-
/* @__PURE__ */ (0,
|
|
3846
|
-
/* @__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)(
|
|
3847
4150
|
NButton,
|
|
3848
4151
|
{
|
|
3849
4152
|
disabled: loading,
|
|
@@ -3857,9 +4160,9 @@ var __defProp = Object.defineProperty;
|
|
|
3857
4160
|
] });
|
|
3858
4161
|
}
|
|
3859
4162
|
function WingMultiSelect(props) {
|
|
3860
|
-
const [open, setOpen] = (0,
|
|
3861
|
-
const wrapRef = (0,
|
|
3862
|
-
(0,
|
|
4163
|
+
const [open, setOpen] = (0, import_react17.useState)(false);
|
|
4164
|
+
const wrapRef = (0, import_react17.useRef)(null);
|
|
4165
|
+
(0, import_react17.useEffect)(() => {
|
|
3863
4166
|
if (!open) return;
|
|
3864
4167
|
const onDown = (e) => {
|
|
3865
4168
|
if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
|
|
@@ -3879,8 +4182,8 @@ var __defProp = Object.defineProperty;
|
|
|
3879
4182
|
const toggle = (id) => {
|
|
3880
4183
|
props.onChange(props.selected.includes(id) ? props.selected.filter((x) => x !== id) : [...props.selected, id]);
|
|
3881
4184
|
};
|
|
3882
|
-
return /* @__PURE__ */ (0,
|
|
3883
|
-
/* @__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)(
|
|
3884
4187
|
"button",
|
|
3885
4188
|
{
|
|
3886
4189
|
type: "button",
|
|
@@ -3889,31 +4192,31 @@ var __defProp = Object.defineProperty;
|
|
|
3889
4192
|
"aria-expanded": open,
|
|
3890
4193
|
onClick: () => setOpen(!open),
|
|
3891
4194
|
children: [
|
|
3892
|
-
/* @__PURE__ */ (0,
|
|
3893
|
-
/* @__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" : "") })
|
|
3894
4197
|
]
|
|
3895
4198
|
}
|
|
3896
4199
|
),
|
|
3897
|
-
open ? /* @__PURE__ */ (0,
|
|
3898
|
-
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,
|
|
3899
4202
|
props.options.map((o) => {
|
|
3900
4203
|
const active = props.selected.includes(o.id);
|
|
3901
|
-
return /* @__PURE__ */ (0,
|
|
3902
|
-
/* @__PURE__ */ (0,
|
|
3903
|
-
/* @__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 })
|
|
3904
4207
|
] }, o.id);
|
|
3905
4208
|
}),
|
|
3906
|
-
props.selected.length > 0 ? /* @__PURE__ */ (0,
|
|
3907
|
-
/* @__PURE__ */ (0,
|
|
3908
|
-
/* @__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: "清除筛选" })
|
|
3909
4212
|
] }) : null
|
|
3910
4213
|
] }) : null
|
|
3911
4214
|
] });
|
|
3912
4215
|
}
|
|
3913
4216
|
|
|
3914
4217
|
// client/src/tabs/RoomsTab.tsx
|
|
3915
|
-
var
|
|
3916
|
-
var
|
|
4218
|
+
var import_react18 = require("react");
|
|
4219
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
3917
4220
|
function majorOf(slug) {
|
|
3918
4221
|
const i = slug.indexOf("/");
|
|
3919
4222
|
return i === -1 ? slug : slug.slice(0, i);
|
|
@@ -3942,26 +4245,26 @@ var __defProp = Object.defineProperty;
|
|
|
3942
4245
|
};
|
|
3943
4246
|
function RoomsTab(props) {
|
|
3944
4247
|
const rpc = props.rpc;
|
|
3945
|
-
const [registry, setRegistry] = (0,
|
|
3946
|
-
const [rooms, setRooms] = (0,
|
|
3947
|
-
const [orphanCount, setOrphanCount] = (0,
|
|
3948
|
-
const [busy, setBusy] = (0,
|
|
3949
|
-
const [msg, setMsg] = (0,
|
|
3950
|
-
const [error, setError] = (0,
|
|
3951
|
-
const [hiPriv, setHiPriv] = (0,
|
|
3952
|
-
const [hiPrivBusy, setHiPrivBusy] = (0,
|
|
3953
|
-
const [regSlug, setRegSlug] = (0,
|
|
3954
|
-
const [regLabel, setRegLabel] = (0,
|
|
3955
|
-
const [regDesc, setRegDesc] = (0,
|
|
3956
|
-
const [form, setForm] = (0,
|
|
3957
|
-
const [preview, setPreview] = (0,
|
|
3958
|
-
const [grownOpen, setGrownOpen] = (0,
|
|
3959
|
-
const [dragOverHall, setDragOverHall] = (0,
|
|
3960
|
-
const [picking, setPicking] = (0,
|
|
3961
|
-
const [editing, setEditing] = (0,
|
|
3962
|
-
const [expandedRooms, setExpandedRooms] = (0,
|
|
3963
|
-
const [roomRecords, setRoomRecords] = (0,
|
|
3964
|
-
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)(() => {
|
|
3965
4268
|
try {
|
|
3966
4269
|
const v = window.localStorage.getItem("dsh.memory.halls.open");
|
|
3967
4270
|
return v ? new Set(JSON.parse(v)) : /* @__PURE__ */ new Set();
|
|
@@ -3969,9 +4272,9 @@ var __defProp = Object.defineProperty;
|
|
|
3969
4272
|
return /* @__PURE__ */ new Set();
|
|
3970
4273
|
}
|
|
3971
4274
|
});
|
|
3972
|
-
const [filter, setFilter] = (0,
|
|
3973
|
-
const dragRef = (0,
|
|
3974
|
-
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);
|
|
3975
4278
|
const onDragLabelDown = (ev, slug) => {
|
|
3976
4279
|
if (!hiPriv || busy || ev.button !== 0) return;
|
|
3977
4280
|
ev.currentTarget.setPointerCapture(ev.pointerId);
|
|
@@ -3996,7 +4299,7 @@ var __defProp = Object.defineProperty;
|
|
|
3996
4299
|
setDragOverHall(null);
|
|
3997
4300
|
if (hall) beginReclass(d.from, hall);
|
|
3998
4301
|
};
|
|
3999
|
-
const loadAll = (0,
|
|
4302
|
+
const loadAll = (0, import_react18.useCallback)(() => {
|
|
4000
4303
|
rpc("dsh-memory/rooms-get", {}).then((r) => {
|
|
4001
4304
|
if (r && r.ok) {
|
|
4002
4305
|
setRooms(r.value.rooms ?? []);
|
|
@@ -4005,13 +4308,13 @@ var __defProp = Object.defineProperty;
|
|
|
4005
4308
|
}
|
|
4006
4309
|
}).catch(() => void 0);
|
|
4007
4310
|
}, [rpc]);
|
|
4008
|
-
const loadHiPriv = (0,
|
|
4311
|
+
const loadHiPriv = (0, import_react18.useCallback)(() => {
|
|
4009
4312
|
rpc("dsh-memory/settings-get", {}).then((r) => {
|
|
4010
4313
|
if (r && r.ok && r.value) setHiPriv(!!r.value.settings.memoryMutate);
|
|
4011
4314
|
}).catch(() => {
|
|
4012
4315
|
});
|
|
4013
4316
|
}, [rpc]);
|
|
4014
|
-
(0,
|
|
4317
|
+
(0, import_react18.useEffect)(() => {
|
|
4015
4318
|
loadAll();
|
|
4016
4319
|
loadHiPriv();
|
|
4017
4320
|
}, [loadAll, loadHiPriv]);
|
|
@@ -4162,7 +4465,7 @@ var __defProp = Object.defineProperty;
|
|
|
4162
4465
|
if (r.value.csv) downloadCsv(r.value.csv, `dsh-memory-room-${slug.replace(/\//g, "-")}-records.csv`);
|
|
4163
4466
|
else setError("导出为空");
|
|
4164
4467
|
});
|
|
4165
|
-
const groups = (0,
|
|
4468
|
+
const groups = (0, import_react18.useMemo)(() => {
|
|
4166
4469
|
const countOf = new Map(rooms.map((r) => [r.room, r.count]));
|
|
4167
4470
|
const byHall = /* @__PURE__ */ new Map();
|
|
4168
4471
|
for (const e of registry) {
|
|
@@ -4179,7 +4482,7 @@ var __defProp = Object.defineProperty;
|
|
|
4179
4482
|
total: entries.reduce((s2, e) => s2 + (countOf.get(e.slug) ?? 0), 0)
|
|
4180
4483
|
})).sort((a, b) => a.hall.localeCompare(b.hall));
|
|
4181
4484
|
}, [registry, rooms]);
|
|
4182
|
-
const grownOnly = (0,
|
|
4485
|
+
const grownOnly = (0, import_react18.useMemo)(() => rooms.filter((r) => !registry.some((e) => e.slug === r.room)), [rooms, registry]);
|
|
4183
4486
|
const persistHalls = (next) => {
|
|
4184
4487
|
try {
|
|
4185
4488
|
window.localStorage.setItem("dsh.memory.halls.open", JSON.stringify([...next]));
|
|
@@ -4199,7 +4502,7 @@ var __defProp = Object.defineProperty;
|
|
|
4199
4502
|
persistHalls(next);
|
|
4200
4503
|
};
|
|
4201
4504
|
const normFilter = filter.trim().toLowerCase();
|
|
4202
|
-
const visibleGroups = (0,
|
|
4505
|
+
const visibleGroups = (0, import_react18.useMemo)(() => {
|
|
4203
4506
|
if (!normFilter) return groups;
|
|
4204
4507
|
return groups.map((g) => {
|
|
4205
4508
|
const hallHit = g.hall.toLowerCase().includes(normFilter) || (g.label ?? "").toLowerCase().includes(normFilter);
|
|
@@ -4209,15 +4512,15 @@ var __defProp = Object.defineProperty;
|
|
|
4209
4512
|
return { ...g, entries };
|
|
4210
4513
|
}).filter((g) => g.entries.length > 0);
|
|
4211
4514
|
}, [groups, normFilter]);
|
|
4212
|
-
const visibleGrown = (0,
|
|
4515
|
+
const visibleGrown = (0, import_react18.useMemo)(
|
|
4213
4516
|
() => normFilter ? grownOnly.filter((r) => r.room.toLowerCase().includes(normFilter)) : grownOnly,
|
|
4214
4517
|
[grownOnly, normFilter]
|
|
4215
4518
|
);
|
|
4216
|
-
return /* @__PURE__ */ (0,
|
|
4217
|
-
/* @__PURE__ */ (0,
|
|
4218
|
-
/* @__PURE__ */ (0,
|
|
4219
|
-
/* @__PURE__ */ (0,
|
|
4220
|
-
/* @__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)(
|
|
4221
4524
|
"button",
|
|
4222
4525
|
{
|
|
4223
4526
|
type: "button",
|
|
@@ -4234,7 +4537,7 @@ var __defProp = Object.defineProperty;
|
|
|
4234
4537
|
children: "导出词表"
|
|
4235
4538
|
}
|
|
4236
4539
|
),
|
|
4237
|
-
/* @__PURE__ */ (0,
|
|
4540
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
4238
4541
|
"button",
|
|
4239
4542
|
{
|
|
4240
4543
|
type: "button",
|
|
@@ -4254,7 +4557,7 @@ var __defProp = Object.defineProperty;
|
|
|
4254
4557
|
]
|
|
4255
4558
|
}
|
|
4256
4559
|
),
|
|
4257
|
-
/* @__PURE__ */ (0,
|
|
4560
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4258
4561
|
"button",
|
|
4259
4562
|
{
|
|
4260
4563
|
type: "button",
|
|
@@ -4269,10 +4572,10 @@ var __defProp = Object.defineProperty;
|
|
|
4269
4572
|
children: hiPriv ? "高权限:开" : "高权限:关"
|
|
4270
4573
|
}
|
|
4271
4574
|
),
|
|
4272
|
-
/* @__PURE__ */ (0,
|
|
4575
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", style: btn, onClick: loadAll, title: "重拉注册表与计数", children: "刷新" })
|
|
4273
4576
|
] }),
|
|
4274
|
-
/* @__PURE__ */ (0,
|
|
4275
|
-
/* @__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)(
|
|
4276
4579
|
"input",
|
|
4277
4580
|
{
|
|
4278
4581
|
value: filter,
|
|
@@ -4281,14 +4584,14 @@ var __defProp = Object.defineProperty;
|
|
|
4281
4584
|
style: { ...S.input, width: 250, fontSize: 12 }
|
|
4282
4585
|
}
|
|
4283
4586
|
),
|
|
4284
|
-
filter ? /* @__PURE__ */ (0,
|
|
4285
|
-
/* @__PURE__ */ (0,
|
|
4286
|
-
/* @__PURE__ */ (0,
|
|
4287
|
-
/* @__PURE__ */ (0,
|
|
4288
|
-
/* @__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: "收起全部" })
|
|
4289
4592
|
] }),
|
|
4290
|
-
/* @__PURE__ */ (0,
|
|
4291
|
-
/* @__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)(
|
|
4292
4595
|
"input",
|
|
4293
4596
|
{
|
|
4294
4597
|
value: regSlug,
|
|
@@ -4298,7 +4601,7 @@ var __defProp = Object.defineProperty;
|
|
|
4298
4601
|
style: { ...S.input, width: 210, fontSize: 12 }
|
|
4299
4602
|
}
|
|
4300
4603
|
),
|
|
4301
|
-
/* @__PURE__ */ (0,
|
|
4604
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4302
4605
|
"input",
|
|
4303
4606
|
{
|
|
4304
4607
|
value: regLabel,
|
|
@@ -4308,7 +4611,7 @@ var __defProp = Object.defineProperty;
|
|
|
4308
4611
|
style: { ...S.input, width: 110, fontSize: 12 }
|
|
4309
4612
|
}
|
|
4310
4613
|
),
|
|
4311
|
-
/* @__PURE__ */ (0,
|
|
4614
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4312
4615
|
"input",
|
|
4313
4616
|
{
|
|
4314
4617
|
value: regDesc,
|
|
@@ -4318,7 +4621,7 @@ var __defProp = Object.defineProperty;
|
|
|
4318
4621
|
style: { ...S.input, width: 170, fontSize: 12 }
|
|
4319
4622
|
}
|
|
4320
4623
|
),
|
|
4321
|
-
/* @__PURE__ */ (0,
|
|
4624
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4322
4625
|
"button",
|
|
4323
4626
|
{
|
|
4324
4627
|
type: "button",
|
|
@@ -4328,26 +4631,26 @@ var __defProp = Object.defineProperty;
|
|
|
4328
4631
|
children: "注册"
|
|
4329
4632
|
}
|
|
4330
4633
|
),
|
|
4331
|
-
!hiPriv && /* @__PURE__ */ (0,
|
|
4634
|
+
!hiPriv && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: S.muted, children: "管理操作需先开启高权限模式" })
|
|
4332
4635
|
] }),
|
|
4333
|
-
editing ? /* @__PURE__ */ (0,
|
|
4334
|
-
/* @__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: [
|
|
4335
4638
|
"编辑 ",
|
|
4336
4639
|
editing.slug
|
|
4337
4640
|
] }),
|
|
4338
|
-
/* @__PURE__ */ (0,
|
|
4339
|
-
/* @__PURE__ */ (0,
|
|
4340
|
-
/* @__PURE__ */ (0,
|
|
4341
|
-
/* @__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: "取消" })
|
|
4342
4645
|
] }) : null,
|
|
4343
|
-
form ? /* @__PURE__ */ (0,
|
|
4344
|
-
/* @__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: [
|
|
4345
4648
|
form.action === "merge" ? "合并" : "归类/改名",
|
|
4346
4649
|
" ",
|
|
4347
4650
|
form.from,
|
|
4348
4651
|
" →"
|
|
4349
4652
|
] }),
|
|
4350
|
-
/* @__PURE__ */ (0,
|
|
4653
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4351
4654
|
"input",
|
|
4352
4655
|
{
|
|
4353
4656
|
value: form.to,
|
|
@@ -4357,7 +4660,7 @@ var __defProp = Object.defineProperty;
|
|
|
4357
4660
|
style: { ...S.input, width: 190, fontSize: 12 }
|
|
4358
4661
|
}
|
|
4359
4662
|
),
|
|
4360
|
-
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)(
|
|
4361
4664
|
"button",
|
|
4362
4665
|
{
|
|
4363
4666
|
type: "button",
|
|
@@ -4368,32 +4671,32 @@ var __defProp = Object.defineProperty;
|
|
|
4368
4671
|
},
|
|
4369
4672
|
gg.hall
|
|
4370
4673
|
)) }) : null,
|
|
4371
|
-
/* @__PURE__ */ (0,
|
|
4372
|
-
/* @__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: () => {
|
|
4373
4676
|
setForm(null);
|
|
4374
4677
|
setPreview(null);
|
|
4375
4678
|
setPicking(null);
|
|
4376
4679
|
}, style: btn, children: "取消" }),
|
|
4377
|
-
picking ? /* @__PURE__ */ (0,
|
|
4378
|
-
/* @__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: "与反刍并发会互相覆盖,请在反刍空闲时执行。" })
|
|
4379
4682
|
] }) : null,
|
|
4380
|
-
preview ? /* @__PURE__ */ (0,
|
|
4381
|
-
/* @__PURE__ */ (0,
|
|
4382
|
-
/* @__PURE__ */ (0,
|
|
4383
|
-
/* @__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: [
|
|
4384
4687
|
"确认执行",
|
|
4385
4688
|
preview.action === "merge" ? "合并" : "归类/改名"
|
|
4386
4689
|
] }),
|
|
4387
|
-
/* @__PURE__ */ (0,
|
|
4690
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: busy, onClick: () => setPreview(null), style: btn, children: "再改改" })
|
|
4388
4691
|
] })
|
|
4389
4692
|
] }) : null,
|
|
4390
|
-
msg ? /* @__PURE__ */ (0,
|
|
4391
|
-
error ? /* @__PURE__ */ (0,
|
|
4392
|
-
ghost ? /* @__PURE__ */ (0,
|
|
4393
|
-
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) => {
|
|
4394
4697
|
const hallOpen = !!normFilter || expandedHalls.has(g.hall);
|
|
4395
|
-
return /* @__PURE__ */ (0,
|
|
4396
|
-
/* @__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)(
|
|
4397
4700
|
"div",
|
|
4398
4701
|
{
|
|
4399
4702
|
"data-hall": g.hall,
|
|
@@ -4434,7 +4737,7 @@ var __defProp = Object.defineProperty;
|
|
|
4434
4737
|
},
|
|
4435
4738
|
title: picking ? "点击此 hall:把「" + picking + "」归入 " + g.hall + " 下(major/minor,预览后确认)" : hiPriv ? "拖入 room 归类到该 hall 下(major/minor;记录随迁,旧名进别名,预览后确认)" : void 0,
|
|
4436
4739
|
children: [
|
|
4437
|
-
/* @__PURE__ */ (0,
|
|
4740
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4438
4741
|
"button",
|
|
4439
4742
|
{
|
|
4440
4743
|
type: "button",
|
|
@@ -4447,13 +4750,13 @@ var __defProp = Object.defineProperty;
|
|
|
4447
4750
|
children: hallOpen ? "▾" : "▸"
|
|
4448
4751
|
}
|
|
4449
4752
|
),
|
|
4450
|
-
/* @__PURE__ */ (0,
|
|
4753
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { style: { fontSize: 12, fontWeight: 600 }, children: [
|
|
4451
4754
|
g.hall,
|
|
4452
|
-
g.label ? /* @__PURE__ */ (0,
|
|
4755
|
+
g.label ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: S.muted, children: " (" + g.label + ")" }) : null
|
|
4453
4756
|
] }),
|
|
4454
|
-
/* @__PURE__ */ (0,
|
|
4455
|
-
/* @__PURE__ */ (0,
|
|
4456
|
-
/* @__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)(
|
|
4457
4760
|
"button",
|
|
4458
4761
|
{
|
|
4459
4762
|
type: "button",
|
|
@@ -4474,10 +4777,10 @@ var __defProp = Object.defineProperty;
|
|
|
4474
4777
|
const standalone = e.slug === g.hall;
|
|
4475
4778
|
const count = rooms.find((r) => r.room === e.slug)?.count ?? 0;
|
|
4476
4779
|
const retired = e.status === "retired";
|
|
4477
|
-
return /* @__PURE__ */ (0,
|
|
4478
|
-
/* @__PURE__ */ (0,
|
|
4479
|
-
/* @__PURE__ */ (0,
|
|
4480
|
-
/* @__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)(
|
|
4481
4784
|
"button",
|
|
4482
4785
|
{
|
|
4483
4786
|
type: "button",
|
|
@@ -4487,7 +4790,7 @@ var __defProp = Object.defineProperty;
|
|
|
4487
4790
|
children: expandedRooms.has(e.slug) ? "▾" : "▸"
|
|
4488
4791
|
}
|
|
4489
4792
|
),
|
|
4490
|
-
/* @__PURE__ */ (0,
|
|
4793
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
4491
4794
|
"span",
|
|
4492
4795
|
{
|
|
4493
4796
|
style: { fontSize: 12, cursor: hiPriv && !busy ? "grab" : "default", touchAction: "none" },
|
|
@@ -4501,20 +4804,20 @@ var __defProp = Object.defineProperty;
|
|
|
4501
4804
|
]
|
|
4502
4805
|
}
|
|
4503
4806
|
),
|
|
4504
|
-
e.label ? /* @__PURE__ */ (0,
|
|
4505
|
-
/* @__PURE__ */ (0,
|
|
4506
|
-
retired ? /* @__PURE__ */ (0,
|
|
4507
|
-
(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
|
|
4508
4811
|
] }),
|
|
4509
|
-
/* @__PURE__ */ (0,
|
|
4510
|
-
!hiPriv ? null : /* @__PURE__ */ (0,
|
|
4511
|
-
/* @__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: () => {
|
|
4512
4815
|
setEditing({ slug: e.slug, label: e.label ?? "", description: e.description ?? "" });
|
|
4513
4816
|
setForm(null);
|
|
4514
4817
|
setPreview(null);
|
|
4515
4818
|
setPicking(null);
|
|
4516
4819
|
}, style: btn, children: "编辑" }),
|
|
4517
|
-
/* @__PURE__ */ (0,
|
|
4820
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4518
4821
|
"button",
|
|
4519
4822
|
{
|
|
4520
4823
|
type: "button",
|
|
@@ -4535,43 +4838,43 @@ var __defProp = Object.defineProperty;
|
|
|
4535
4838
|
children: picking === e.slug ? "选 hall…" : "归类"
|
|
4536
4839
|
}
|
|
4537
4840
|
),
|
|
4538
|
-
/* @__PURE__ */ (0,
|
|
4841
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: busy, title: `改名(= merge 1:1 + 注册表改名)`, onClick: () => {
|
|
4539
4842
|
setForm({ action: "rename", from: e.slug, to: "" });
|
|
4540
4843
|
setPreview(null);
|
|
4541
4844
|
}, style: btn, children: "改名" }),
|
|
4542
|
-
/* @__PURE__ */ (0,
|
|
4845
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: busy, title: "合并到另一个 Room(dryRun 预览→确认实跑)", onClick: () => {
|
|
4543
4846
|
setForm({ action: "merge", from: e.slug, to: "" });
|
|
4544
4847
|
setPreview(null);
|
|
4545
4848
|
}, style: btn, children: "合并" }),
|
|
4546
|
-
/* @__PURE__ */ (0,
|
|
4547
|
-
!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
|
|
4548
4851
|
] }),
|
|
4549
|
-
/* @__PURE__ */ (0,
|
|
4852
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", disabled: busy, title: "导出该 Room 的记录清单 CSV", onClick: () => exportRecords(e.slug), style: btn, children: "导出" })
|
|
4550
4853
|
] })
|
|
4551
4854
|
] }),
|
|
4552
|
-
expandedRooms.has(e.slug) ? /* @__PURE__ */ (0,
|
|
4553
|
-
(roomRecords[e.slug]?.items ?? []).map((it) => /* @__PURE__ */ (0,
|
|
4554
|
-
/* @__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 }),
|
|
4555
4858
|
" ",
|
|
4556
|
-
/* @__PURE__ */ (0,
|
|
4557
|
-
/* @__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 })
|
|
4558
4861
|
] }, it.id)),
|
|
4559
|
-
(roomRecords[e.slug]?.items.length ?? 0) === 0 ? /* @__PURE__ */ (0,
|
|
4560
|
-
(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
|
|
4561
4864
|
] }) : null
|
|
4562
4865
|
] }, e.slug);
|
|
4563
4866
|
}) : null
|
|
4564
4867
|
] }, g.hall);
|
|
4565
4868
|
}),
|
|
4566
|
-
visibleGrown.length > 0 ? /* @__PURE__ */ (0,
|
|
4567
|
-
/* @__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: [
|
|
4568
4871
|
grownOpen ? "▾" : "▸",
|
|
4569
4872
|
" 自生长未注册 · 共 ",
|
|
4570
4873
|
visibleGrown.length
|
|
4571
4874
|
] }),
|
|
4572
|
-
/* @__PURE__ */ (0,
|
|
4573
|
-
grownOpen ? /* @__PURE__ */ (0,
|
|
4574
|
-
/* @__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)(
|
|
4575
4878
|
"span",
|
|
4576
4879
|
{
|
|
4577
4880
|
style: { ...btn, cursor: hiPriv && !busy ? "grab" : "default", borderRadius: 999, padding: "2px 8px", touchAction: "none" },
|
|
@@ -4582,8 +4885,8 @@ var __defProp = Object.defineProperty;
|
|
|
4582
4885
|
children: r.room + " · " + r.count
|
|
4583
4886
|
}
|
|
4584
4887
|
),
|
|
4585
|
-
/* @__PURE__ */ (0,
|
|
4586
|
-
/* @__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)(
|
|
4587
4890
|
"button",
|
|
4588
4891
|
{
|
|
4589
4892
|
type: "button",
|
|
@@ -4610,8 +4913,8 @@ var __defProp = Object.defineProperty;
|
|
|
4610
4913
|
}
|
|
4611
4914
|
|
|
4612
4915
|
// client/src/tabs/RoomTab.tsx
|
|
4613
|
-
var
|
|
4614
|
-
var
|
|
4916
|
+
var import_react19 = require("react");
|
|
4917
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
4615
4918
|
var btn2 = {
|
|
4616
4919
|
cursor: "pointer",
|
|
4617
4920
|
fontSize: 12,
|
|
@@ -4632,22 +4935,22 @@ var __defProp = Object.defineProperty;
|
|
|
4632
4935
|
}
|
|
4633
4936
|
function RoomTab(props) {
|
|
4634
4937
|
const rpc = props.rpc;
|
|
4635
|
-
const [registry, setRegistry] = (0,
|
|
4636
|
-
const [counts, setCounts] = (0,
|
|
4637
|
-
const [orphanCount, setOrphanCount] = (0,
|
|
4638
|
-
const [busy, setBusy] = (0,
|
|
4639
|
-
const [msg, setMsg] = (0,
|
|
4640
|
-
const [error, setError] = (0,
|
|
4641
|
-
const [hiPriv, setHiPriv] = (0,
|
|
4642
|
-
const [hiPrivBusy, setHiPrivBusy] = (0,
|
|
4643
|
-
const [reg, setReg] = (0,
|
|
4644
|
-
const [editing, setEditing] = (0,
|
|
4645
|
-
const [renaming, setRenaming] = (0,
|
|
4646
|
-
const [expanded, setExpanded] = (0,
|
|
4647
|
-
const [retiredFilter, setRetiredFilter] = (0,
|
|
4648
|
-
const [filter, setFilter] = (0,
|
|
4649
|
-
const [records, setRecords] = (0,
|
|
4650
|
-
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)(() => {
|
|
4651
4954
|
rpc("dsh-memory/rooms-get", {}).then((r) => {
|
|
4652
4955
|
if (r && r.ok) {
|
|
4653
4956
|
setCounts(r.value.rooms ?? []);
|
|
@@ -4656,13 +4959,13 @@ var __defProp = Object.defineProperty;
|
|
|
4656
4959
|
}
|
|
4657
4960
|
}).catch(() => void 0);
|
|
4658
4961
|
}, [rpc]);
|
|
4659
|
-
const loadHiPriv = (0,
|
|
4962
|
+
const loadHiPriv = (0, import_react19.useCallback)(() => {
|
|
4660
4963
|
rpc("dsh-memory/settings-get", {}).then((r) => {
|
|
4661
4964
|
if (r && r.ok && r.value) setHiPriv(!!r.value.settings.memoryMutate);
|
|
4662
4965
|
}).catch(() => {
|
|
4663
4966
|
});
|
|
4664
4967
|
}, [rpc]);
|
|
4665
|
-
(0,
|
|
4968
|
+
(0, import_react19.useEffect)(() => {
|
|
4666
4969
|
loadAll();
|
|
4667
4970
|
loadHiPriv();
|
|
4668
4971
|
}, [loadAll, loadHiPriv]);
|
|
@@ -4800,11 +5103,11 @@ var __defProp = Object.defineProperty;
|
|
|
4800
5103
|
const visibleRows = normFilter ? rows.filter(
|
|
4801
5104
|
(row2) => row2.slug.toLowerCase().includes(normFilter) || (row2.entry?.label ?? "").toLowerCase().includes(normFilter) || (row2.entry?.aliases ?? []).some((a) => a.toLowerCase().includes(normFilter))
|
|
4802
5105
|
) : rows;
|
|
4803
|
-
return /* @__PURE__ */ (0,
|
|
4804
|
-
/* @__PURE__ */ (0,
|
|
4805
|
-
/* @__PURE__ */ (0,
|
|
4806
|
-
/* @__PURE__ */ (0,
|
|
4807
|
-
/* @__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 () => {
|
|
4808
5111
|
const r = await rpc("dsh-memory/rooms-export", { kind: "orphans" });
|
|
4809
5112
|
if (!r.ok) {
|
|
4810
5113
|
setError(r.error.message);
|
|
@@ -4815,7 +5118,7 @@ var __defProp = Object.defineProperty;
|
|
|
4815
5118
|
"导出孤儿 · ",
|
|
4816
5119
|
orphanCount
|
|
4817
5120
|
] }),
|
|
4818
|
-
/* @__PURE__ */ (0,
|
|
5121
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4819
5122
|
"button",
|
|
4820
5123
|
{
|
|
4821
5124
|
type: "button",
|
|
@@ -4826,35 +5129,35 @@ var __defProp = Object.defineProperty;
|
|
|
4826
5129
|
children: hiPriv ? "高权限:开" : "高权限:关"
|
|
4827
5130
|
}
|
|
4828
5131
|
),
|
|
4829
|
-
/* @__PURE__ */ (0,
|
|
5132
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", style: btn2, onClick: loadAll, children: "刷新" })
|
|
4830
5133
|
] }),
|
|
4831
|
-
editing ? /* @__PURE__ */ (0,
|
|
4832
|
-
/* @__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: [
|
|
4833
5136
|
"编辑 ",
|
|
4834
5137
|
editing.slug
|
|
4835
5138
|
] }),
|
|
4836
|
-
/* @__PURE__ */ (0,
|
|
4837
|
-
/* @__PURE__ */ (0,
|
|
4838
|
-
/* @__PURE__ */ (0,
|
|
4839
|
-
/* @__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: "取消" })
|
|
4840
5143
|
] }) : null,
|
|
4841
|
-
renaming ? /* @__PURE__ */ (0,
|
|
4842
|
-
/* @__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: [
|
|
4843
5146
|
"改名 ",
|
|
4844
5147
|
renaming.slug,
|
|
4845
5148
|
" →"
|
|
4846
5149
|
] }),
|
|
4847
|
-
/* @__PURE__ */ (0,
|
|
4848
|
-
/* @__PURE__ */ (0,
|
|
4849
|
-
/* @__PURE__ */ (0,
|
|
4850
|
-
/* @__PURE__ */ (0,
|
|
4851
|
-
/* @__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: "记录随迁;与反刍并发会互相覆盖,请在反刍空闲时执行。" })
|
|
4852
5155
|
] }) : null,
|
|
4853
|
-
/* @__PURE__ */ (0,
|
|
4854
|
-
/* @__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: "退场筛选" }),
|
|
4855
5158
|
[["", "全部"], ["active", "活跃"], ["retired", "已退役"]].map(([val, label]) => {
|
|
4856
5159
|
const on = retiredFilter === val;
|
|
4857
|
-
return /* @__PURE__ */ (0,
|
|
5160
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4858
5161
|
"button",
|
|
4859
5162
|
{
|
|
4860
5163
|
type: "button",
|
|
@@ -4874,8 +5177,8 @@ var __defProp = Object.defineProperty;
|
|
|
4874
5177
|
val
|
|
4875
5178
|
);
|
|
4876
5179
|
}),
|
|
4877
|
-
/* @__PURE__ */ (0,
|
|
4878
|
-
/* @__PURE__ */ (0,
|
|
5180
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: S.grow }),
|
|
5181
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4879
5182
|
"input",
|
|
4880
5183
|
{
|
|
4881
5184
|
value: filter,
|
|
@@ -4884,24 +5187,24 @@ var __defProp = Object.defineProperty;
|
|
|
4884
5187
|
style: { ...S.input, width: 230, fontSize: 12 }
|
|
4885
5188
|
}
|
|
4886
5189
|
),
|
|
4887
|
-
filter ? /* @__PURE__ */ (0,
|
|
5190
|
+
filter ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", style: btn2, onClick: () => setFilter(""), children: "清除" }) : null
|
|
4888
5191
|
] }),
|
|
4889
|
-
/* @__PURE__ */ (0,
|
|
4890
|
-
/* @__PURE__ */ (0,
|
|
4891
|
-
/* @__PURE__ */ (0,
|
|
4892
|
-
/* @__PURE__ */ (0,
|
|
4893
|
-
/* @__PURE__ */ (0,
|
|
4894
|
-
!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: "管理操作需先开启高权限模式" })
|
|
4895
5198
|
] }),
|
|
4896
|
-
msg ? /* @__PURE__ */ (0,
|
|
4897
|
-
error ? /* @__PURE__ */ (0,
|
|
4898
|
-
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) => {
|
|
4899
5202
|
const e = row2.entry;
|
|
4900
5203
|
const retired = e?.status === "retired";
|
|
4901
5204
|
const grownOnly = !e;
|
|
4902
|
-
return /* @__PURE__ */ (0,
|
|
4903
|
-
/* @__PURE__ */ (0,
|
|
4904
|
-
/* @__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)(
|
|
4905
5208
|
"button",
|
|
4906
5209
|
{
|
|
4907
5210
|
type: "button",
|
|
@@ -4911,28 +5214,28 @@ var __defProp = Object.defineProperty;
|
|
|
4911
5214
|
children: expanded.has(row2.slug) ? "▾" : "▸"
|
|
4912
5215
|
}
|
|
4913
5216
|
),
|
|
4914
|
-
/* @__PURE__ */ (0,
|
|
4915
|
-
/* @__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: [
|
|
4916
5219
|
row2.slug,
|
|
4917
5220
|
e?.source === "pre-registered" ? " ⭐" : ""
|
|
4918
5221
|
] }),
|
|
4919
|
-
e?.label ? /* @__PURE__ */ (0,
|
|
4920
|
-
/* @__PURE__ */ (0,
|
|
4921
|
-
grownOnly ? /* @__PURE__ */ (0,
|
|
4922
|
-
retired ? /* @__PURE__ */ (0,
|
|
4923
|
-
(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
|
|
4924
5227
|
] }),
|
|
4925
|
-
/* @__PURE__ */ (0,
|
|
4926
|
-
!hiPriv || grownOnly ? null : /* @__PURE__ */ (0,
|
|
4927
|
-
/* @__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: () => {
|
|
4928
5231
|
setEditing({ slug: row2.slug, label: e?.label ?? "", description: e?.description ?? "" });
|
|
4929
5232
|
setRenaming(null);
|
|
4930
5233
|
}, style: btn2, children: "编辑" }),
|
|
4931
|
-
/* @__PURE__ */ (0,
|
|
5234
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", disabled: busy, title: "改名(可两级 slug;记录随迁,旧名进别名)", onClick: () => {
|
|
4932
5235
|
setRenaming({ slug: row2.slug, to: "" });
|
|
4933
5236
|
setEditing(null);
|
|
4934
5237
|
}, style: btn2, children: "改名" }),
|
|
4935
|
-
/* @__PURE__ */ (0,
|
|
5238
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4936
5239
|
"button",
|
|
4937
5240
|
{
|
|
4938
5241
|
type: "button",
|
|
@@ -4943,29 +5246,29 @@ var __defProp = Object.defineProperty;
|
|
|
4943
5246
|
children: retired ? "恢复" : "退役"
|
|
4944
5247
|
}
|
|
4945
5248
|
),
|
|
4946
|
-
!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
|
|
4947
5250
|
] }),
|
|
4948
|
-
grownOnly ? /* @__PURE__ */ (0,
|
|
4949
|
-
/* @__PURE__ */ (0,
|
|
4950
|
-
/* @__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: () => {
|
|
4951
5254
|
setRenaming(null);
|
|
4952
5255
|
retire(row2.slug, false, true);
|
|
4953
5256
|
}, style: { ...btn2, color: "var(--dsh-mem-danger)", borderColor: "var(--dsh-mem-danger)", opacity: !hiPriv || busy ? 0.5 : 1 }, children: "退场" })
|
|
4954
5257
|
] }) : null,
|
|
4955
|
-
/* @__PURE__ */ (0,
|
|
5258
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", disabled: busy, title: "导出该 Room 的记录清单 CSV", onClick: () => exportRecords(row2.slug), style: btn2, children: "导出" })
|
|
4956
5259
|
] })
|
|
4957
5260
|
] }),
|
|
4958
|
-
expanded.has(row2.slug) ? /* @__PURE__ */ (0,
|
|
4959
|
-
(records[row2.slug]?.items ?? []).map((it) => /* @__PURE__ */ (0,
|
|
4960
|
-
/* @__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 }),
|
|
4961
5264
|
" ",
|
|
4962
|
-
it.retired ? /* @__PURE__ */ (0,
|
|
5265
|
+
it.retired ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { style: { ...S.muted, color: "var(--dsh-mem-danger)" }, children: "[已退场]" }) : null,
|
|
4963
5266
|
" ",
|
|
4964
|
-
/* @__PURE__ */ (0,
|
|
4965
|
-
/* @__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 })
|
|
4966
5269
|
] }, it.id)),
|
|
4967
|
-
(records[row2.slug]?.items.length ?? 0) === 0 ? /* @__PURE__ */ (0,
|
|
4968
|
-
(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
|
|
4969
5272
|
] }) : null
|
|
4970
5273
|
] }, row2.slug);
|
|
4971
5274
|
})
|
|
@@ -4973,13 +5276,13 @@ var __defProp = Object.defineProperty;
|
|
|
4973
5276
|
}
|
|
4974
5277
|
|
|
4975
5278
|
// client/src/tabs/ScenesTab.tsx
|
|
4976
|
-
var
|
|
4977
|
-
var
|
|
5279
|
+
var import_react20 = require("react");
|
|
5280
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
4978
5281
|
function SceneCard(props) {
|
|
4979
5282
|
const s = props.s;
|
|
4980
|
-
const [open, setOpen] = (0,
|
|
4981
|
-
return /* @__PURE__ */ (0,
|
|
4982
|
-
/* @__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)(
|
|
4983
5286
|
"div",
|
|
4984
5287
|
{
|
|
4985
5288
|
style: { ...S.sceneHead, cursor: "pointer", userSelect: "none" },
|
|
@@ -4987,23 +5290,23 @@ var __defProp = Object.defineProperty;
|
|
|
4987
5290
|
setOpen(!open);
|
|
4988
5291
|
},
|
|
4989
5292
|
children: [
|
|
4990
|
-
/* @__PURE__ */ (0,
|
|
4991
|
-
/* @__PURE__ */ (0,
|
|
4992
|
-
s.heat ? /* @__PURE__ */ (0,
|
|
4993
|
-
/* @__PURE__ */ (0,
|
|
4994
|
-
/* @__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) })
|
|
4995
5298
|
]
|
|
4996
5299
|
}
|
|
4997
5300
|
),
|
|
4998
|
-
s.summary ? /* @__PURE__ */ (0,
|
|
4999
|
-
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
|
|
5000
5303
|
] });
|
|
5001
5304
|
}
|
|
5002
5305
|
function ScenesTab(props) {
|
|
5003
5306
|
const rpc = props.rpc;
|
|
5004
|
-
const [items, setItems] = (0,
|
|
5005
|
-
const [error, setError] = (0,
|
|
5006
|
-
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)(() => {
|
|
5007
5310
|
rpc("dsh-memory/scenes", {}).then((r) => {
|
|
5008
5311
|
if (r && r.ok) {
|
|
5009
5312
|
setItems(r.value.items);
|
|
@@ -5013,25 +5316,25 @@ var __defProp = Object.defineProperty;
|
|
|
5013
5316
|
setError(String(e && e.message || e));
|
|
5014
5317
|
});
|
|
5015
5318
|
}, [rpc]);
|
|
5016
|
-
(0,
|
|
5319
|
+
(0, import_react20.useEffect)(() => {
|
|
5017
5320
|
load();
|
|
5018
5321
|
}, [load]);
|
|
5019
|
-
return /* @__PURE__ */ (0,
|
|
5020
|
-
/* @__PURE__ */ (0,
|
|
5021
|
-
/* @__PURE__ */ (0,
|
|
5022
|
-
/* @__PURE__ */ (0,
|
|
5023
|
-
/* @__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: "刷新" })
|
|
5024
5327
|
] }),
|
|
5025
|
-
error ? /* @__PURE__ */ (0,
|
|
5026
|
-
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,
|
|
5027
5330
|
(items || []).map((s) => {
|
|
5028
|
-
return /* @__PURE__ */ (0,
|
|
5331
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SceneCard, { s }, s.path);
|
|
5029
5332
|
})
|
|
5030
5333
|
] });
|
|
5031
5334
|
}
|
|
5032
5335
|
|
|
5033
5336
|
// client/src/panel.tsx
|
|
5034
|
-
var
|
|
5337
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
5035
5338
|
var TABS = [
|
|
5036
5339
|
["overview", "概览"],
|
|
5037
5340
|
["records", "记忆"],
|
|
@@ -5041,30 +5344,71 @@ var __defProp = Object.defineProperty;
|
|
|
5041
5344
|
["room", "Room"],
|
|
5042
5345
|
["persona", "画像"],
|
|
5043
5346
|
["cost", "成本"],
|
|
5044
|
-
["log", "日志"]
|
|
5347
|
+
["log", "日志"],
|
|
5348
|
+
["connect", "来源"],
|
|
5349
|
+
["skills", "技能"]
|
|
5350
|
+
];
|
|
5351
|
+
var SKIN_OPTS = [
|
|
5352
|
+
["light", "浅色"],
|
|
5353
|
+
["dark", "深色"],
|
|
5354
|
+
["auto", "跟随"]
|
|
5045
5355
|
];
|
|
5046
5356
|
function MemoryPanel(props) {
|
|
5047
5357
|
const rpc = props.rpc;
|
|
5048
|
-
const [tab, setTab] = (0,
|
|
5049
|
-
|
|
5050
|
-
(
|
|
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);
|
|
5051
5363
|
watchSidebarIcon();
|
|
5052
|
-
}, []);
|
|
5364
|
+
}, [skin]);
|
|
5365
|
+
const switchSkin = (next) => {
|
|
5366
|
+
setSkin(next);
|
|
5367
|
+
setSkinState(next);
|
|
5368
|
+
};
|
|
5053
5369
|
let body;
|
|
5054
|
-
if (tab === "overview") body = /* @__PURE__ */ (0,
|
|
5055
|
-
else if (tab === "records") body = /* @__PURE__ */ (0,
|
|
5056
|
-
else if (tab === "conflicts") body = /* @__PURE__ */ (0,
|
|
5057
|
-
else if (tab === "scenes") body = /* @__PURE__ */ (0,
|
|
5058
|
-
else if (tab === "rooms") body = /* @__PURE__ */ (0,
|
|
5059
|
-
else if (tab === "room") body = /* @__PURE__ */ (0,
|
|
5060
|
-
else if (tab === "persona") body = /* @__PURE__ */ (0,
|
|
5061
|
-
else if (tab === "cost") body = /* @__PURE__ */ (0,
|
|
5062
|
-
else body = /* @__PURE__ */ (0,
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
/* @__PURE__ */ (0,
|
|
5067
|
-
|
|
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)(
|
|
5068
5412
|
"button",
|
|
5069
5413
|
{
|
|
5070
5414
|
className: tab === t[0] ? "dsh-mem-tab dsh-mem-tab-on" : "dsh-mem-tab",
|
|
@@ -5081,7 +5425,7 @@ var __defProp = Object.defineProperty;
|
|
|
5081
5425
|
}
|
|
5082
5426
|
|
|
5083
5427
|
// client/src/pill/MemoryModePill.tsx
|
|
5084
|
-
var
|
|
5428
|
+
var import_react25 = require("react");
|
|
5085
5429
|
|
|
5086
5430
|
// src/util/context-occupancy.ts
|
|
5087
5431
|
var CONTEXT_METER_CIRCUMFERENCE = 34.55751918948772;
|
|
@@ -5397,23 +5741,23 @@ var __defProp = Object.defineProperty;
|
|
|
5397
5741
|
}
|
|
5398
5742
|
|
|
5399
5743
|
// client/src/pill/WingWheel.tsx
|
|
5400
|
-
var
|
|
5744
|
+
var import_react24 = require("react");
|
|
5401
5745
|
|
|
5402
5746
|
// client/src/pill/SessionInfoArea.tsx
|
|
5403
|
-
var
|
|
5404
|
-
var
|
|
5747
|
+
var import_react22 = require("react");
|
|
5748
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
5405
5749
|
function sinfoCell(val, label, title) {
|
|
5406
|
-
return /* @__PURE__ */ (0,
|
|
5407
|
-
/* @__PURE__ */ (0,
|
|
5408
|
-
/* @__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 })
|
|
5409
5753
|
] });
|
|
5410
5754
|
}
|
|
5411
5755
|
function SessionInfoArea(props) {
|
|
5412
5756
|
const rpc = props.rpc;
|
|
5413
5757
|
const sessionId = props.sessionId;
|
|
5414
|
-
const [stats, setStats] = (0,
|
|
5415
|
-
const busyRef = (0,
|
|
5416
|
-
(0,
|
|
5758
|
+
const [stats, setStats] = (0, import_react22.useState)(void 0);
|
|
5759
|
+
const busyRef = (0, import_react22.useRef)(false);
|
|
5760
|
+
(0, import_react22.useEffect)(() => {
|
|
5417
5761
|
if (!rpc || !sessionId) return void 0;
|
|
5418
5762
|
let alive = true;
|
|
5419
5763
|
let timer = null;
|
|
@@ -5446,7 +5790,7 @@ var __defProp = Object.defineProperty;
|
|
|
5446
5790
|
}, [rpc, sessionId]);
|
|
5447
5791
|
if (stats === null) return null;
|
|
5448
5792
|
if (stats === void 0) {
|
|
5449
|
-
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: [
|
|
5450
5794
|
sinfoCell("…", "召回命中"),
|
|
5451
5795
|
sinfoCell("…", "攒批进度"),
|
|
5452
5796
|
sinfoCell("…", "本会话记忆"),
|
|
@@ -5495,21 +5839,104 @@ var __defProp = Object.defineProperty;
|
|
|
5495
5839
|
else if (stats.retrieval === "none") note = "检索不可用(FTS 与向量均失效)";
|
|
5496
5840
|
}
|
|
5497
5841
|
const ago = fmtAgo(gl.lastExtractAt);
|
|
5498
|
-
return /* @__PURE__ */ (0,
|
|
5499
|
-
warn ? /* @__PURE__ */ (0,
|
|
5500
|
-
/* @__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: [
|
|
5501
5845
|
sinfoCell(rcVal, rcLabel, rcTitle),
|
|
5502
5846
|
sinfoCell(dVal, dLabel, dTitle),
|
|
5503
5847
|
sinfoCell(String(di.producedRecords || 0), "本会话记忆", pTitle),
|
|
5504
5848
|
sinfoCell(stats.l0Count != null ? String(stats.l0Count) : "…", "会话消息")
|
|
5505
5849
|
] }),
|
|
5506
|
-
note ? /* @__PURE__ */ (0,
|
|
5507
|
-
/* @__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
|
+
] })
|
|
5508
5914
|
] });
|
|
5509
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
|
+
}
|
|
5510
5937
|
|
|
5511
5938
|
// client/src/pill/WingWheel.tsx
|
|
5512
|
-
var
|
|
5939
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
5513
5940
|
var SIZE = 196;
|
|
5514
5941
|
var CENTER = SIZE / 2;
|
|
5515
5942
|
var R = 64;
|
|
@@ -5552,17 +5979,17 @@ var __defProp = Object.defineProperty;
|
|
|
5552
5979
|
function WingWheel(props) {
|
|
5553
5980
|
ensureThemeStyle();
|
|
5554
5981
|
const isOff = props.mode === "off";
|
|
5555
|
-
const [overview, setOverview] = (0,
|
|
5556
|
-
const [backfillBusy, setBackfillBusy] = (0,
|
|
5557
|
-
const [localError, setLocalError] = (0,
|
|
5558
|
-
const timersRef = (0,
|
|
5559
|
-
(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)(
|
|
5560
5987
|
() => () => {
|
|
5561
5988
|
for (const t of timersRef.current) window.clearTimeout(t);
|
|
5562
5989
|
},
|
|
5563
5990
|
[]
|
|
5564
5991
|
);
|
|
5565
|
-
(0,
|
|
5992
|
+
(0, import_react24.useEffect)(() => {
|
|
5566
5993
|
let alive = true;
|
|
5567
5994
|
props.rpc("dsh-memory/wing-overview", {}).then((r) => {
|
|
5568
5995
|
if (!alive) return;
|
|
@@ -5608,28 +6035,28 @@ var __defProp = Object.defineProperty;
|
|
|
5608
6035
|
finish();
|
|
5609
6036
|
});
|
|
5610
6037
|
};
|
|
5611
|
-
const boxRef = (0,
|
|
5612
|
-
const startRef = (0,
|
|
5613
|
-
const movedRef = (0,
|
|
5614
|
-
const downIndexRef = (0,
|
|
5615
|
-
const dragTargetRef = (0,
|
|
5616
|
-
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);
|
|
5617
6044
|
const lockedIndex = (() => {
|
|
5618
6045
|
if (props.halls.length !== 1 || !overview) return null;
|
|
5619
6046
|
const i = overview.corners.findIndex((c) => c.id === props.halls[0]);
|
|
5620
6047
|
return i >= 0 ? i : null;
|
|
5621
6048
|
})();
|
|
5622
6049
|
const activeCorner = drag ? drag.index : lockedIndex;
|
|
5623
|
-
const blockPosRef = (0,
|
|
6050
|
+
const blockPosRef = (0, import_react24.useRef)(
|
|
5624
6051
|
activeCorner != null ? cornerXY(activeCorner) : { x: CENTER, y: CENTER }
|
|
5625
6052
|
);
|
|
5626
|
-
const blockTargetRef = (0,
|
|
5627
|
-
const [blockPos, setBlockPos] = (0,
|
|
5628
|
-
(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)(() => {
|
|
5629
6056
|
blockTargetRef.current = activeCorner != null ? cornerXY(activeCorner) : { x: CENTER, y: CENTER };
|
|
5630
6057
|
}, [activeCorner]);
|
|
5631
|
-
const reducedMotionRef = (0,
|
|
5632
|
-
(0,
|
|
6058
|
+
const reducedMotionRef = (0, import_react24.useRef)(false);
|
|
6059
|
+
(0, import_react24.useEffect)(() => {
|
|
5633
6060
|
const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
5634
6061
|
const apply2 = () => {
|
|
5635
6062
|
reducedMotionRef.current = mq.matches;
|
|
@@ -5638,7 +6065,7 @@ var __defProp = Object.defineProperty;
|
|
|
5638
6065
|
mq.addEventListener("change", apply2);
|
|
5639
6066
|
return () => mq.removeEventListener("change", apply2);
|
|
5640
6067
|
}, []);
|
|
5641
|
-
(0,
|
|
6068
|
+
(0, import_react24.useEffect)(() => {
|
|
5642
6069
|
let raf = 0;
|
|
5643
6070
|
const loop = () => {
|
|
5644
6071
|
const cur = blockPosRef.current;
|
|
@@ -5727,8 +6154,8 @@ var __defProp = Object.defineProperty;
|
|
|
5727
6154
|
}).join(" ");
|
|
5728
6155
|
const grayStyle = isOff ? { opacity: 0.45, pointerEvents: "none" } : {};
|
|
5729
6156
|
const boundariesDisabled = props.halls.length === 0 || isOff;
|
|
5730
|
-
return /* @__PURE__ */ (0,
|
|
5731
|
-
/* @__PURE__ */ (0,
|
|
6157
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { width: SIZE }, children: [
|
|
6158
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
5732
6159
|
"div",
|
|
5733
6160
|
{
|
|
5734
6161
|
ref: boxRef,
|
|
@@ -5738,7 +6165,7 @@ var __defProp = Object.defineProperty;
|
|
|
5738
6165
|
onPointerUp: onBoxUp,
|
|
5739
6166
|
onPointerCancel: onBoxUp,
|
|
5740
6167
|
children: [
|
|
5741
|
-
/* @__PURE__ */ (0,
|
|
6168
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
5742
6169
|
"svg",
|
|
5743
6170
|
{
|
|
5744
6171
|
width: SIZE,
|
|
@@ -5746,7 +6173,7 @@ var __defProp = Object.defineProperty;
|
|
|
5746
6173
|
style: { position: "absolute", inset: 0, pointerEvents: "none" },
|
|
5747
6174
|
"aria-hidden": "true",
|
|
5748
6175
|
children: [
|
|
5749
|
-
/* @__PURE__ */ (0,
|
|
6176
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5750
6177
|
"polygon",
|
|
5751
6178
|
{
|
|
5752
6179
|
points: polyPoints,
|
|
@@ -5757,7 +6184,7 @@ var __defProp = Object.defineProperty;
|
|
|
5757
6184
|
opacity: 0.45
|
|
5758
6185
|
}
|
|
5759
6186
|
),
|
|
5760
|
-
/* @__PURE__ */ (0,
|
|
6187
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5761
6188
|
"polygon",
|
|
5762
6189
|
{
|
|
5763
6190
|
points: polyPoints,
|
|
@@ -5768,7 +6195,7 @@ var __defProp = Object.defineProperty;
|
|
|
5768
6195
|
),
|
|
5769
6196
|
[0, 1, 2, 3, 4, 5, 6, 7].map((i) => {
|
|
5770
6197
|
const p = cornerPos(i);
|
|
5771
|
-
return /* @__PURE__ */ (0,
|
|
6198
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5772
6199
|
"line",
|
|
5773
6200
|
{
|
|
5774
6201
|
x1: CENTER,
|
|
@@ -5784,7 +6211,7 @@ var __defProp = Object.defineProperty;
|
|
|
5784
6211
|
]
|
|
5785
6212
|
}
|
|
5786
6213
|
),
|
|
5787
|
-
/* @__PURE__ */ (0,
|
|
6214
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5788
6215
|
"div",
|
|
5789
6216
|
{
|
|
5790
6217
|
"aria-hidden": "true",
|
|
@@ -5803,7 +6230,7 @@ var __defProp = Object.defineProperty;
|
|
|
5803
6230
|
}
|
|
5804
6231
|
}
|
|
5805
6232
|
),
|
|
5806
|
-
/* @__PURE__ */ (0,
|
|
6233
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5807
6234
|
"button",
|
|
5808
6235
|
{
|
|
5809
6236
|
type: "button",
|
|
@@ -5837,7 +6264,7 @@ var __defProp = Object.defineProperty;
|
|
|
5837
6264
|
const dim = activeCorner != null && !active;
|
|
5838
6265
|
const empty = count === 0;
|
|
5839
6266
|
const p = cornerPos(i);
|
|
5840
|
-
return /* @__PURE__ */ (0,
|
|
6267
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
5841
6268
|
"div",
|
|
5842
6269
|
{
|
|
5843
6270
|
title: id ? `「${label}」${count ?? 0} 条
|
|
@@ -5866,8 +6293,8 @@ var __defProp = Object.defineProperty;
|
|
|
5866
6293
|
zIndex: 2
|
|
5867
6294
|
},
|
|
5868
6295
|
children: [
|
|
5869
|
-
/* @__PURE__ */ (0,
|
|
5870
|
-
/* @__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} 条` })
|
|
5871
6298
|
]
|
|
5872
6299
|
},
|
|
5873
6300
|
id ?? i
|
|
@@ -5876,7 +6303,7 @@ var __defProp = Object.defineProperty;
|
|
|
5876
6303
|
]
|
|
5877
6304
|
}
|
|
5878
6305
|
),
|
|
5879
|
-
/* @__PURE__ */ (0,
|
|
6306
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
5880
6307
|
"div",
|
|
5881
6308
|
{
|
|
5882
6309
|
title: props.halls.length === 0 ? "选定某个角(单 Wing)后,这两项才生效" : "锁定 Wing 时两类无角记忆是否参与召回",
|
|
@@ -5890,9 +6317,9 @@ var __defProp = Object.defineProperty;
|
|
|
5890
6317
|
pointerEvents: boundariesDisabled ? "none" : void 0
|
|
5891
6318
|
},
|
|
5892
6319
|
children: [
|
|
5893
|
-
/* @__PURE__ */ (0,
|
|
5894
|
-
/* @__PURE__ */ (0,
|
|
5895
|
-
/* @__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)(
|
|
5896
6323
|
Segmented,
|
|
5897
6324
|
{
|
|
5898
6325
|
value: props.hallIncludeUnlabeled ? "in" : "ex",
|
|
@@ -5903,7 +6330,7 @@ var __defProp = Object.defineProperty;
|
|
|
5903
6330
|
onChange: (key) => props.onCommitWingBoundaries({ includeUnlabeled: key === "in" })
|
|
5904
6331
|
}
|
|
5905
6332
|
),
|
|
5906
|
-
/* @__PURE__ */ (0,
|
|
6333
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5907
6334
|
Segmented,
|
|
5908
6335
|
{
|
|
5909
6336
|
value: props.hallIncludeGeneral ? "in" : "ex",
|
|
@@ -5918,7 +6345,7 @@ var __defProp = Object.defineProperty;
|
|
|
5918
6345
|
]
|
|
5919
6346
|
}
|
|
5920
6347
|
),
|
|
5921
|
-
/* @__PURE__ */ (0,
|
|
6348
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Row, { label: "会话", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
5922
6349
|
Segmented,
|
|
5923
6350
|
{
|
|
5924
6351
|
value: isOff ? "off" : "on",
|
|
@@ -5933,7 +6360,7 @@ var __defProp = Object.defineProperty;
|
|
|
5933
6360
|
onChange: (key) => props.onCommit(key === "off" ? "off" : "auto")
|
|
5934
6361
|
}
|
|
5935
6362
|
) }),
|
|
5936
|
-
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)(
|
|
5937
6364
|
Segmented,
|
|
5938
6365
|
{
|
|
5939
6366
|
value: props.recall === null ? "follow" : props.recall ? "on" : "off",
|
|
@@ -5946,7 +6373,7 @@ var __defProp = Object.defineProperty;
|
|
|
5946
6373
|
onChange: (key) => props.onCommitRecall(key === "on" ? true : key === "off" ? false : null)
|
|
5947
6374
|
}
|
|
5948
6375
|
) }) : null,
|
|
5949
|
-
/* @__PURE__ */ (0,
|
|
6376
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
5950
6377
|
"div",
|
|
5951
6378
|
{
|
|
5952
6379
|
style: {
|
|
@@ -5957,8 +6384,8 @@ var __defProp = Object.defineProperty;
|
|
|
5957
6384
|
marginTop: 10
|
|
5958
6385
|
},
|
|
5959
6386
|
children: [
|
|
5960
|
-
/* @__PURE__ */ (0,
|
|
5961
|
-
/* @__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)(
|
|
5962
6389
|
ActionButton,
|
|
5963
6390
|
{
|
|
5964
6391
|
label: backfillBusy ? "回填中…" : "回填",
|
|
@@ -5970,12 +6397,13 @@ var __defProp = Object.defineProperty;
|
|
|
5970
6397
|
]
|
|
5971
6398
|
}
|
|
5972
6399
|
),
|
|
5973
|
-
props.error || localError ? /* @__PURE__ */ (0,
|
|
5974
|
-
/* @__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 })
|
|
5975
6403
|
] });
|
|
5976
6404
|
}
|
|
5977
6405
|
function Row(props) {
|
|
5978
|
-
return /* @__PURE__ */ (0,
|
|
6406
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
5979
6407
|
"div",
|
|
5980
6408
|
{
|
|
5981
6409
|
style: {
|
|
@@ -5985,7 +6413,7 @@ var __defProp = Object.defineProperty;
|
|
|
5985
6413
|
marginTop: 10
|
|
5986
6414
|
},
|
|
5987
6415
|
children: [
|
|
5988
|
-
/* @__PURE__ */ (0,
|
|
6416
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontSize: 12, color: "var(--dsh-mem-text-3)" }, children: props.label }),
|
|
5989
6417
|
props.children
|
|
5990
6418
|
]
|
|
5991
6419
|
}
|
|
@@ -5993,9 +6421,9 @@ var __defProp = Object.defineProperty;
|
|
|
5993
6421
|
}
|
|
5994
6422
|
var LABEL_FALLBACK = ["工作", "人际", "学习", "创作娱乐", "居家", "健康", "财务", "出行"];
|
|
5995
6423
|
function useViewportClamp(popRef) {
|
|
5996
|
-
const shiftRef = (0,
|
|
5997
|
-
const [shiftX, setShiftX] = (0,
|
|
5998
|
-
(0,
|
|
6424
|
+
const shiftRef = (0, import_react24.useRef)(0);
|
|
6425
|
+
const [shiftX, setShiftX] = (0, import_react24.useState)(0);
|
|
6426
|
+
(0, import_react24.useEffect)(() => {
|
|
5999
6427
|
const clamp = () => {
|
|
6000
6428
|
const el = popRef.current;
|
|
6001
6429
|
if (!el) return;
|
|
@@ -6025,24 +6453,24 @@ var __defProp = Object.defineProperty;
|
|
|
6025
6453
|
}
|
|
6026
6454
|
|
|
6027
6455
|
// client/src/pill/MemoryModePill.tsx
|
|
6028
|
-
var
|
|
6456
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
6029
6457
|
function MemoryModePill(props) {
|
|
6030
6458
|
const rpc = props.rpc;
|
|
6031
6459
|
const sessionId = props.sessionId || props.session && props.session.sessionId;
|
|
6032
|
-
const [mode, setMode] = (0,
|
|
6033
|
-
const [recall, setRecall] = (0,
|
|
6034
|
-
const [recallResolved, setRecallResolved] = (0,
|
|
6035
|
-
const [halls, setWings] = (0,
|
|
6036
|
-
const [hallIncludeUnlabeled, setWingIncludeUnlabeled] = (0,
|
|
6037
|
-
const [hallIncludeGeneral, setWingIncludeGeneral] = (0,
|
|
6038
|
-
const [wingLabels, setHallLabels] = (0,
|
|
6039
|
-
const [error, setError] = (0,
|
|
6040
|
-
const [open, setOpen] = (0,
|
|
6041
|
-
const wrapRef = (0,
|
|
6042
|
-
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);
|
|
6043
6471
|
const shiftX = useViewportClamp(popRef);
|
|
6044
|
-
const seqRef = (0,
|
|
6045
|
-
const load = (0,
|
|
6472
|
+
const seqRef = (0, import_react25.useRef)(0);
|
|
6473
|
+
const load = (0, import_react25.useCallback)(() => {
|
|
6046
6474
|
if (!sessionId || !rpc) return;
|
|
6047
6475
|
const token = ++seqRef.current;
|
|
6048
6476
|
setError(null);
|
|
@@ -6067,13 +6495,13 @@ var __defProp = Object.defineProperty;
|
|
|
6067
6495
|
}).catch(() => {
|
|
6068
6496
|
});
|
|
6069
6497
|
}, [sessionId, rpc]);
|
|
6070
|
-
(0,
|
|
6498
|
+
(0, import_react25.useEffect)(() => {
|
|
6071
6499
|
load();
|
|
6072
6500
|
}, [load]);
|
|
6073
|
-
(0,
|
|
6501
|
+
(0, import_react25.useEffect)(() => {
|
|
6074
6502
|
watchSidebarIcon();
|
|
6075
6503
|
}, []);
|
|
6076
|
-
(0,
|
|
6504
|
+
(0, import_react25.useEffect)(() => {
|
|
6077
6505
|
initOccupancyIndicator(
|
|
6078
6506
|
(endpoint, payload) => rpc(endpoint, payload)
|
|
6079
6507
|
);
|
|
@@ -6081,7 +6509,7 @@ var __defProp = Object.defineProperty;
|
|
|
6081
6509
|
watchContextMeter();
|
|
6082
6510
|
noteOccupancySession(sessionId ?? null);
|
|
6083
6511
|
}, [sessionId, rpc]);
|
|
6084
|
-
(0,
|
|
6512
|
+
(0, import_react25.useEffect)(() => {
|
|
6085
6513
|
if (!open) return;
|
|
6086
6514
|
const onDown = (e) => {
|
|
6087
6515
|
if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
|
|
@@ -6096,7 +6524,7 @@ var __defProp = Object.defineProperty;
|
|
|
6096
6524
|
document.removeEventListener("keydown", onKey);
|
|
6097
6525
|
};
|
|
6098
6526
|
}, [open]);
|
|
6099
|
-
const
|
|
6527
|
+
const commit2 = (next) => {
|
|
6100
6528
|
if (!rpc || !sessionId || mode === null || next === mode) return;
|
|
6101
6529
|
const prev = mode;
|
|
6102
6530
|
const token = seqRef.current;
|
|
@@ -6221,8 +6649,8 @@ var __defProp = Object.defineProperty;
|
|
|
6221
6649
|
pillStyle.boxShadow = "0 0 12px color-mix(in srgb, " + info.color + " 30%, transparent)";
|
|
6222
6650
|
pillStyle["--dsh-mem-pill-tint"] = info.color;
|
|
6223
6651
|
}
|
|
6224
|
-
return /* @__PURE__ */ (0,
|
|
6225
|
-
/* @__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)(
|
|
6226
6654
|
"button",
|
|
6227
6655
|
{
|
|
6228
6656
|
type: "button",
|
|
@@ -6235,11 +6663,11 @@ var __defProp = Object.defineProperty;
|
|
|
6235
6663
|
style: pillStyle,
|
|
6236
6664
|
children: [
|
|
6237
6665
|
"记忆 · ",
|
|
6238
|
-
/* @__PURE__ */ (0,
|
|
6666
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: faceLabel })
|
|
6239
6667
|
]
|
|
6240
6668
|
}
|
|
6241
6669
|
),
|
|
6242
|
-
open ? /* @__PURE__ */ (0,
|
|
6670
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6243
6671
|
"div",
|
|
6244
6672
|
{
|
|
6245
6673
|
ref: popRef,
|
|
@@ -6250,19 +6678,19 @@ var __defProp = Object.defineProperty;
|
|
|
6250
6678
|
transform: "translateX(calc(-50% + " + shiftX + "px))",
|
|
6251
6679
|
zIndex: 1e3
|
|
6252
6680
|
},
|
|
6253
|
-
children: /* @__PURE__ */ (0,
|
|
6681
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6254
6682
|
"div",
|
|
6255
6683
|
{
|
|
6256
6684
|
className: "dsh-mem-popover",
|
|
6257
6685
|
style: { position: "relative", padding: "10px 12px" },
|
|
6258
|
-
children: /* @__PURE__ */ (0,
|
|
6686
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6259
6687
|
WingWheel,
|
|
6260
6688
|
{
|
|
6261
6689
|
mode: mode || "auto",
|
|
6262
6690
|
halls,
|
|
6263
6691
|
hallIncludeUnlabeled,
|
|
6264
6692
|
hallIncludeGeneral,
|
|
6265
|
-
onCommit:
|
|
6693
|
+
onCommit: commit2,
|
|
6266
6694
|
onCommitWing: commitWing,
|
|
6267
6695
|
onCommitWingBoundaries: commitWingBoundaries,
|
|
6268
6696
|
recall: loaded ? recall : void 0,
|