@memtensor/memos-local-openclaw-plugin 1.0.2-beta.3 → 1.0.2-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capture/index.d.ts.map +1 -1
- package/dist/capture/index.js +41 -1
- package/dist/capture/index.js.map +1 -1
- package/dist/embedding/index.d.ts.map +1 -1
- package/dist/embedding/index.js +20 -7
- package/dist/embedding/index.js.map +1 -1
- package/dist/ingest/providers/anthropic.d.ts.map +1 -1
- package/dist/ingest/providers/anthropic.js +39 -25
- package/dist/ingest/providers/anthropic.js.map +1 -1
- package/dist/ingest/providers/bedrock.d.ts.map +1 -1
- package/dist/ingest/providers/bedrock.js +39 -25
- package/dist/ingest/providers/bedrock.js.map +1 -1
- package/dist/ingest/providers/gemini.d.ts.map +1 -1
- package/dist/ingest/providers/gemini.js +39 -25
- package/dist/ingest/providers/gemini.js.map +1 -1
- package/dist/ingest/providers/index.d.ts +19 -0
- package/dist/ingest/providers/index.d.ts.map +1 -1
- package/dist/ingest/providers/index.js +98 -10
- package/dist/ingest/providers/index.js.map +1 -1
- package/dist/ingest/providers/openai.d.ts.map +1 -1
- package/dist/ingest/providers/openai.js +39 -25
- package/dist/ingest/providers/openai.js.map +1 -1
- package/dist/ingest/worker.d.ts.map +1 -1
- package/dist/ingest/worker.js +8 -14
- package/dist/ingest/worker.js.map +1 -1
- package/dist/skill/bundled-memory-guide.d.ts +1 -1
- package/dist/skill/bundled-memory-guide.d.ts.map +1 -1
- package/dist/skill/bundled-memory-guide.js +9 -0
- package/dist/skill/bundled-memory-guide.js.map +1 -1
- package/dist/storage/sqlite.d.ts +14 -0
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +42 -0
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/viewer/html.d.ts +1 -1
- package/dist/viewer/html.d.ts.map +1 -1
- package/dist/viewer/html.js +276 -51
- package/dist/viewer/html.js.map +1 -1
- package/dist/viewer/server.d.ts +4 -0
- package/dist/viewer/server.d.ts.map +1 -1
- package/dist/viewer/server.js +152 -27
- package/dist/viewer/server.js.map +1 -1
- package/index.ts +38 -85
- package/package.json +2 -1
- package/src/capture/index.ts +56 -1
- package/src/embedding/index.ts +13 -7
- package/src/ingest/providers/anthropic.ts +39 -25
- package/src/ingest/providers/bedrock.ts +39 -25
- package/src/ingest/providers/gemini.ts +39 -25
- package/src/ingest/providers/index.ts +112 -9
- package/src/ingest/providers/openai.ts +39 -25
- package/src/ingest/worker.ts +8 -15
- package/src/skill/bundled-memory-guide.ts +9 -0
- package/src/storage/sqlite.ts +49 -0
- package/src/viewer/html.ts +275 -50
- package/src/viewer/server.ts +143 -32
package/src/viewer/html.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export
|
|
1
|
+
export function viewerHTML(pluginVersion?: string): string {
|
|
2
|
+
const vBadge = pluginVersion ? `<span class="version-badge">v${pluginVersion}</span>` : '';
|
|
3
|
+
return `<!DOCTYPE html>
|
|
2
4
|
<html lang="zh-CN">
|
|
3
5
|
<head>
|
|
4
6
|
<meta charset="UTF-8">
|
|
@@ -110,13 +112,15 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
110
112
|
.topbar .brand{display:flex;align-items:center;gap:10px;font-weight:700;font-size:15px;color:var(--text);letter-spacing:-.02em;flex-shrink:0}
|
|
111
113
|
.topbar .brand .icon{width:32px;height:32px;display:flex;align-items:center;justify-content:center;font-size:22px;background:none;border-radius:0}
|
|
112
114
|
.topbar .brand .sub{font-weight:400;color:var(--text-muted);font-size:11px}
|
|
115
|
+
.version-badge{font-size:10px;font-weight:600;color:var(--text-muted);background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.1);padding:1px 7px;border-radius:6px;margin-left:6px;letter-spacing:.02em;user-select:all}
|
|
116
|
+
[data-theme="light"] .version-badge{background:rgba(0,0,0,.05);border-color:rgba(0,0,0,.08);color:var(--text-sec)}
|
|
113
117
|
.topbar-center{flex:1;display:flex;justify-content:center}
|
|
114
118
|
.topbar .actions{display:flex;align-items:center;gap:6px;flex-shrink:0}
|
|
115
119
|
|
|
116
120
|
.main-content{display:flex;flex:1;max-width:1400px;margin:0 auto;width:100%;padding:28px 32px;gap:28px}
|
|
117
121
|
|
|
118
122
|
/* ─── Sidebar ─── */
|
|
119
|
-
.sidebar{width:260px;flex-shrink:0}
|
|
123
|
+
.sidebar{width:260px;min-width:260px;flex-shrink:0}
|
|
120
124
|
.sidebar .stats-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:24px}
|
|
121
125
|
.stat-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:18px;transition:all .2s}
|
|
122
126
|
.stat-card:hover{border-color:var(--border-glow);background:var(--bg-card-hover)}
|
|
@@ -241,6 +245,16 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
241
245
|
.modal-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:28px}
|
|
242
246
|
|
|
243
247
|
/* ─── Toast ─── */
|
|
248
|
+
.emb-banner{display:flex;align-items:center;gap:10px;padding:12px 20px;font-size:13px;font-weight:500;border-radius:10px;margin:0 32px 0;animation:slideIn .3s ease}
|
|
249
|
+
.emb-banner.warning{background:rgba(245,158,11,.1);color:#d97706;border:1px solid rgba(245,158,11,.25)}
|
|
250
|
+
.emb-banner.error{background:rgba(239,68,68,.1);color:#ef4444;border:1px solid rgba(239,68,68,.25)}
|
|
251
|
+
[data-theme="light"] .emb-banner.warning{background:rgba(245,158,11,.08);color:#b45309}
|
|
252
|
+
[data-theme="light"] .emb-banner.error{background:rgba(239,68,68,.08);color:#dc2626}
|
|
253
|
+
.emb-banner span{flex:1}
|
|
254
|
+
.emb-banner-btn{background:none;border:1px solid currentColor;border-radius:6px;padding:4px 12px;font-size:12px;font-weight:600;color:inherit;cursor:pointer;white-space:nowrap;opacity:.85;transition:opacity .15s}
|
|
255
|
+
.emb-banner-btn:hover{opacity:1}
|
|
256
|
+
.emb-banner-close{background:none;border:none;font-size:18px;color:inherit;cursor:pointer;opacity:.5;padding:0 4px;line-height:1}
|
|
257
|
+
.emb-banner-close:hover{opacity:1}
|
|
244
258
|
.toast-container{position:fixed;top:80px;right:24px;z-index:1000;display:flex;flex-direction:column;gap:8px}
|
|
245
259
|
.toast{padding:14px 20px;border-radius:10px;font-size:13px;font-weight:500;box-shadow:var(--shadow-lg);animation:slideIn .3s ease;display:flex;align-items:center;gap:10px;max-width:360px;border:1px solid}
|
|
246
260
|
.toast.success{background:var(--green-bg);color:var(--green);border-color:rgba(16,185,129,.3)}
|
|
@@ -330,8 +344,12 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
330
344
|
.task-chunk-role.user{color:var(--pri)}
|
|
331
345
|
.task-chunk-role.assistant{color:var(--green)}
|
|
332
346
|
.task-chunk-role.tool{color:var(--amber)}
|
|
333
|
-
.task-chunk-bubble{padding:12px 16px;border-radius:16px;white-space:pre-wrap;word-break:break-word;max-height:
|
|
334
|
-
.task-chunk-bubble.
|
|
347
|
+
.task-chunk-bubble{padding:12px 16px;border-radius:16px;white-space:pre-wrap;word-break:break-word;max-height:none;overflow:hidden;position:relative;transition:all .2s}
|
|
348
|
+
.task-chunk-bubble.collapsed{max-height:200px}
|
|
349
|
+
.task-chunk-expand{display:none;align-items:center;justify-content:center;gap:4px;margin-top:4px;padding:4px 12px;font-size:12px;font-weight:600;color:var(--text-sec);cursor:pointer;user-select:none;border-radius:8px;transition:all .15s}
|
|
350
|
+
.task-chunk-expand:hover{color:var(--pri);background:rgba(99,102,241,.08)}
|
|
351
|
+
.task-chunk-expand .expand-arrow{display:inline-block;font-size:10px;transition:transform .2s}
|
|
352
|
+
.task-chunk-expand.is-expanded .expand-arrow{transform:rotate(180deg)}
|
|
335
353
|
.role-user .task-chunk-bubble{background:var(--pri);color:#000;border-bottom-right-radius:4px}
|
|
336
354
|
.role-assistant .task-chunk-bubble{background:var(--bg-card);border:1px solid var(--border);color:var(--text-sec);border-bottom-left-radius:4px}
|
|
337
355
|
.role-tool .task-chunk-bubble{background:rgba(245,158,11,.08);border:1px solid rgba(245,158,11,.2);color:var(--text-sec);border-bottom-left-radius:4px;font-family:'SF Mono',Monaco,Consolas,monospace;font-size:12px}
|
|
@@ -421,6 +439,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
421
439
|
[data-theme="light"] .nav-tabs .tab.active{background:#fff;border-color:rgba(0,0,0,.1);box-shadow:0 1px 3px rgba(0,0,0,.08);color:var(--text)}
|
|
422
440
|
.analytics-view,.settings-view,.logs-view,.migrate-view{display:none;flex:1;min-width:0;flex-direction:column;gap:20px}
|
|
423
441
|
.analytics-view.show,.settings-view.show,.logs-view.show,.migrate-view.show{display:flex}
|
|
442
|
+
.feed-wrap,.tasks-view,.skills-view,.analytics-view,.settings-view,.logs-view,.migrate-view{max-width:960px}
|
|
424
443
|
|
|
425
444
|
/* ─── Logs ─── */
|
|
426
445
|
.logs-toolbar{display:flex;align-items:center;justify-content:space-between;padding:8px 0}
|
|
@@ -526,6 +545,28 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
526
545
|
[data-theme="light"] .settings-actions .btn-primary:hover{background:rgba(79,70,229,.1);border-color:#4f46e5}
|
|
527
546
|
.settings-saved{display:inline-flex;align-items:center;gap:6px;color:var(--green);font-size:12px;font-weight:600;opacity:0;transition:opacity .3s}
|
|
528
547
|
.settings-saved.show{opacity:1}
|
|
548
|
+
.model-health-bar{margin-bottom:20px;border-radius:var(--radius-lg);overflow:hidden}
|
|
549
|
+
.mh-table{width:100%;border-collapse:separate;border-spacing:0;font-size:12px}
|
|
550
|
+
.mh-table th{text-align:left;padding:6px 12px;font-size:10px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.05em;background:var(--bg);border-bottom:1px solid var(--border)}
|
|
551
|
+
.mh-table td{padding:8px 12px;border-bottom:1px solid var(--border);vertical-align:middle}
|
|
552
|
+
.mh-table tr:last-child td{border-bottom:none}
|
|
553
|
+
.mh-table tr:hover td{background:rgba(99,102,241,.025)}
|
|
554
|
+
.mh-table .mh-cell-name{display:flex;align-items:center;gap:8px;font-weight:500;color:var(--text)}
|
|
555
|
+
.mh-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;display:inline-block}
|
|
556
|
+
.mh-dot.ok{background:#22c55e;box-shadow:0 0 0 2px rgba(34,197,94,.15)}
|
|
557
|
+
.mh-dot.degraded{background:#f59e0b;box-shadow:0 0 0 2px rgba(245,158,11,.15)}
|
|
558
|
+
.mh-dot.error{background:#ef4444;box-shadow:0 0 0 2px rgba(239,68,68,.15);animation:healthPulse 2s ease infinite}
|
|
559
|
+
.mh-dot.unknown{background:#94a3b8;box-shadow:0 0 0 2px rgba(148,163,184,.15)}
|
|
560
|
+
.mh-badge{display:inline-block;padding:2px 7px;border-radius:10px;font-size:10px;font-weight:600;letter-spacing:.02em}
|
|
561
|
+
.mh-badge.ok{background:rgba(34,197,94,.1);color:#16a34a}
|
|
562
|
+
.mh-badge.degraded{background:rgba(245,158,11,.1);color:#d97706}
|
|
563
|
+
.mh-badge.error{background:rgba(239,68,68,.1);color:#dc2626}
|
|
564
|
+
.mh-badge.unknown{background:rgba(148,163,184,.1);color:#64748b}
|
|
565
|
+
.mh-model-name{color:var(--text-muted);font-size:11px;font-family:var(--font-mono,'SFMono-Regular',Consolas,monospace)}
|
|
566
|
+
.mh-err-text{font-size:11px;color:var(--rose);max-width:240px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:help}
|
|
567
|
+
.mh-time{font-size:10px;color:var(--text-muted);white-space:nowrap}
|
|
568
|
+
.mh-empty{padding:16px;font-size:12px;color:var(--text-muted);text-align:center}
|
|
569
|
+
@keyframes healthPulse{0%,100%{opacity:1}50%{opacity:.4}}
|
|
529
570
|
.migrate-log-item{display:flex;align-items:flex-start;gap:10px;padding:8px 14px;border-bottom:1px solid var(--border);animation:migrateFadeIn .3s ease}
|
|
530
571
|
.migrate-log-item:last-child{border-bottom:none}
|
|
531
572
|
.migrate-log-item .log-icon{flex-shrink:0;width:18px;height:18px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:10px;margin-top:2px}
|
|
@@ -546,18 +587,19 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
546
587
|
@keyframes migrateFadeIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
|
|
547
588
|
.feed-wrap{flex:1;min-width:0;display:flex;flex-direction:column}
|
|
548
589
|
.feed-wrap.hide{display:none}
|
|
590
|
+
.analytics-view{flex-direction:column;gap:20px}
|
|
549
591
|
.analytics-cards{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
|
|
550
|
-
.analytics-card{position:relative;overflow:hidden;border-radius:var(--radius-lg);padding:
|
|
592
|
+
.analytics-card{position:relative;overflow:hidden;border-radius:var(--radius-lg);padding:18px 16px;transition:all .2s ease;border:1px solid var(--border);background:var(--bg-card)}
|
|
551
593
|
.analytics-card::before{content:'';position:absolute;top:0;left:0;right:0;height:2px;background:var(--pri);opacity:.5}
|
|
552
594
|
.analytics-card::after{display:none}
|
|
553
595
|
.analytics-card:hover{transform:translateY(-2px);box-shadow:var(--shadow);border-color:var(--border-glow)}
|
|
554
596
|
.analytics-card.green::before{background:var(--green)}
|
|
555
597
|
.analytics-card.amber::before{background:var(--amber)}
|
|
556
|
-
.analytics-card .ac-value{font-size:
|
|
598
|
+
.analytics-card .ac-value{font-size:24px;font-weight:700;letter-spacing:-.03em;color:var(--text);line-height:1;-webkit-text-fill-color:unset;background:none}
|
|
557
599
|
.analytics-card.green .ac-value{color:var(--green);background:none}
|
|
558
600
|
.analytics-card.amber .ac-value{color:var(--amber);background:none}
|
|
559
601
|
.analytics-card .ac-label{font-size:11px;color:var(--text-muted);margin-top:6px;font-weight:500;text-transform:uppercase;letter-spacing:.06em}
|
|
560
|
-
.analytics-section{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:
|
|
602
|
+
.analytics-section{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:18px 20px;position:relative;overflow:hidden}
|
|
561
603
|
.analytics-section::before{display:none}
|
|
562
604
|
.analytics-section h3{font-size:11px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.08em;margin-bottom:16px;display:flex;align-items:center;gap:8px}
|
|
563
605
|
.analytics-section h3 .icon{font-size:14px;opacity:.6}
|
|
@@ -717,7 +759,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
717
759
|
<div class="topbar">
|
|
718
760
|
<div class="brand">
|
|
719
761
|
<div class="icon"><svg width="24" height="24" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg" style="filter:drop-shadow(0 0 8px rgba(255,77,77,.3))"><defs><linearGradient id="tLG" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#ff4d4d"/><stop offset="100%" stop-color="#991b1b"/></linearGradient></defs><path d="M60 10C30 10 15 35 15 55C15 75 30 95 45 100L45 110L55 110L55 100C55 100 60 102 65 100L65 110L75 110L75 100C90 95 105 75 105 55C105 35 90 10 60 10Z" fill="url(#tLG)"/><path d="M20 45C5 40 0 50 5 60C10 70 20 65 25 55C28 48 25 45 20 45Z" fill="url(#tLG)"/><path d="M100 45C115 40 120 50 115 60C110 70 100 65 95 55C92 48 95 45 100 45Z" fill="url(#tLG)"/><path d="M45 15Q35 5 30 8" stroke="#ff4d4d" stroke-width="2" stroke-linecap="round"/><path d="M75 15Q85 5 90 8" stroke="#ff4d4d" stroke-width="2" stroke-linecap="round"/><circle cx="45" cy="35" r="6" fill="#050810"/><circle cx="75" cy="35" r="6" fill="#050810"/><circle cx="46" cy="34" r="2" fill="#00e5cc"/><circle cx="76" cy="34" r="2" fill="#00e5cc"/></svg></div>
|
|
720
|
-
<span data-i18n="title">OpenClaw Memory</span
|
|
762
|
+
<span data-i18n="title">OpenClaw Memory</span>${vBadge}
|
|
721
763
|
</div>
|
|
722
764
|
<div class="topbar-center">
|
|
723
765
|
<nav class="nav-tabs">
|
|
@@ -746,10 +788,12 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
746
788
|
<div class="stat-card amber"><div class="stat-value" id="statEmbeddings">-</div><div class="stat-label" data-i18n="stat.embeddings">Embeddings</div></div>
|
|
747
789
|
<div class="stat-card rose"><div class="stat-value" id="statTimeSpan">-</div><div class="stat-label" data-i18n="stat.days">Days</div></div>
|
|
748
790
|
</div>
|
|
749
|
-
<div id="
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
791
|
+
<div id="sidebarSessionSection">
|
|
792
|
+
<div id="embeddingStatus"></div>
|
|
793
|
+
<div class="section-title" data-i18n="sidebar.sessions">Sessions</div>
|
|
794
|
+
<div class="session-list" id="sessionList"></div>
|
|
795
|
+
<button class="btn btn-sm btn-ghost" style="width:100%;margin-top:20px;justify-content:center;color:var(--text-muted);font-size:11px" onclick="clearAll()" data-i18n="sidebar.clear">\u{1F5D1} Clear All Data</button>
|
|
796
|
+
</div>
|
|
753
797
|
</div>
|
|
754
798
|
|
|
755
799
|
<div class="feed-wrap" id="feedWrap">
|
|
@@ -875,7 +919,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
875
919
|
</div>
|
|
876
920
|
</div>
|
|
877
921
|
<div class="analytics-view" id="analyticsView">
|
|
878
|
-
<div class="metrics-toolbar">
|
|
922
|
+
<div class="metrics-toolbar" style="margin-bottom:0">
|
|
879
923
|
<span style="font-size:12px;color:var(--text-sec);font-weight:600" data-i18n="range">Range</span>
|
|
880
924
|
<button class="range-btn" data-days="7" onclick="setMetricsDays(7)">7 <span data-i18n="range.days">days</span></button>
|
|
881
925
|
<button class="range-btn active" data-days="30" onclick="setMetricsDays(30)">30 <span data-i18n="range.days">days</span></button>
|
|
@@ -907,7 +951,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
907
951
|
<div id="toolAggTable" style="margin-top:20px"></div>
|
|
908
952
|
</div>
|
|
909
953
|
|
|
910
|
-
<div class="breakdown-grid" style="display:grid;grid-template-columns:1fr 1fr;gap:
|
|
954
|
+
<div class="breakdown-grid" style="display:grid;grid-template-columns:1fr 1fr;gap:16px">
|
|
911
955
|
<div class="analytics-section">
|
|
912
956
|
<h3><span class="icon">\u{1F464}</span> <span data-i18n="breakdown.role">By Role</span></h3>
|
|
913
957
|
<div id="breakdownRole"></div>
|
|
@@ -940,6 +984,12 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
940
984
|
<div class="settings-view" id="settingsView">
|
|
941
985
|
<div class="settings-group" id="settingsModelConfig">
|
|
942
986
|
<h2 class="settings-group-title"><span data-i18n="settings.modelconfig">Model Configuration</span></h2>
|
|
987
|
+
<div class="settings-section">
|
|
988
|
+
<h3><span class="icon">\u{1F4CA}</span> <span data-i18n="settings.modelhealth">Model Health</span></h3>
|
|
989
|
+
<div class="model-health-bar" id="modelHealthBar">
|
|
990
|
+
<div style="font-size:12px;color:var(--text-muted);width:100%">Loading model status...</div>
|
|
991
|
+
</div>
|
|
992
|
+
</div>
|
|
943
993
|
<div class="settings-section">
|
|
944
994
|
<h3><span class="icon">\u{1F4E1}</span> <span data-i18n="settings.embedding">Embedding Model</span></h3>
|
|
945
995
|
<div class="settings-grid">
|
|
@@ -1308,6 +1358,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
1308
1358
|
|
|
1309
1359
|
<script>
|
|
1310
1360
|
let activeSession=null,activeRole='',editingId=null,searchTimer=null,memoryCache={},currentPage=1,totalPages=1,totalCount=0,PAGE_SIZE=40,metricsDays=30;
|
|
1361
|
+
let _embeddingWarningShown=false;
|
|
1311
1362
|
|
|
1312
1363
|
/* ─── i18n ─── */
|
|
1313
1364
|
const I18N={
|
|
@@ -1367,6 +1418,8 @@ const I18N={
|
|
|
1367
1418
|
'tasks.untitled':'Untitled Task',
|
|
1368
1419
|
'tasks.chunks':'Related Memories',
|
|
1369
1420
|
'tasks.nochunks':'No memories in this task yet.',
|
|
1421
|
+
'tasks.expand':'Show more',
|
|
1422
|
+
'tasks.collapse':'Show less',
|
|
1370
1423
|
'tasks.skipped.default':'This conversation was too brief to generate a summary. It will not appear in search results.',
|
|
1371
1424
|
'refresh':'\\u21BB Refresh',
|
|
1372
1425
|
'logout':'Logout',
|
|
@@ -1459,6 +1512,9 @@ const I18N={
|
|
|
1459
1512
|
'confirm.clearall2':'Are you absolutely sure?',
|
|
1460
1513
|
'embed.on':'Embedding: ',
|
|
1461
1514
|
'embed.off':'No embedding model',
|
|
1515
|
+
'embed.warn.local':'Using built-in mini model (384d). Search quality is limited — configure an embedding model in Settings for best results.',
|
|
1516
|
+
'embed.err.fail':'Embedding model error detected. Check Settings → Model Health.',
|
|
1517
|
+
'embed.banner.goto':'Go to Settings',
|
|
1462
1518
|
'lang.switch':'中',
|
|
1463
1519
|
'tab.logs':'\u{1F4DD} Logs',
|
|
1464
1520
|
'logs.allTools':'All Tools',
|
|
@@ -1471,6 +1527,7 @@ const I18N={
|
|
|
1471
1527
|
'tab.import':'\u{1F4E5} Import',
|
|
1472
1528
|
'tab.settings':'\u2699 Settings',
|
|
1473
1529
|
'settings.modelconfig':'Model Configuration',
|
|
1530
|
+
'settings.modelhealth':'Model Health',
|
|
1474
1531
|
'settings.embedding':'Embedding Model',
|
|
1475
1532
|
'settings.summarizer':'Summarizer Model',
|
|
1476
1533
|
'settings.skill':'Skill Evolution',
|
|
@@ -1676,6 +1733,8 @@ const I18N={
|
|
|
1676
1733
|
'tasks.untitled':'未命名任务',
|
|
1677
1734
|
'tasks.chunks':'关联记忆',
|
|
1678
1735
|
'tasks.nochunks':'此任务暂无关联记忆。',
|
|
1736
|
+
'tasks.expand':'展开全文',
|
|
1737
|
+
'tasks.collapse':'收起',
|
|
1679
1738
|
'tasks.skipped.default':'对话内容过少,未生成摘要。该任务不会出现在检索结果中。',
|
|
1680
1739
|
'refresh':'\\u21BB 刷新',
|
|
1681
1740
|
'logout':'退出',
|
|
@@ -1768,6 +1827,9 @@ const I18N={
|
|
|
1768
1827
|
'confirm.clearall2':'你真的确定吗?',
|
|
1769
1828
|
'embed.on':'嵌入模型:',
|
|
1770
1829
|
'embed.off':'无嵌入模型',
|
|
1830
|
+
'embed.warn.local':'当前使用内置迷你模型(384维),搜索效果有限。强烈建议在「设置」中配置专用 Embedding 模型以获得最佳效果。',
|
|
1831
|
+
'embed.err.fail':'Embedding 模型调用异常,请前往「设置 → 模型健康」检查。',
|
|
1832
|
+
'embed.banner.goto':'前往设置',
|
|
1771
1833
|
'lang.switch':'EN',
|
|
1772
1834
|
'tab.logs':'\u{1F4DD} 日志',
|
|
1773
1835
|
'logs.allTools':'全部工具',
|
|
@@ -1780,6 +1842,7 @@ const I18N={
|
|
|
1780
1842
|
'tab.import':'\u{1F4E5} 导入',
|
|
1781
1843
|
'tab.settings':'\u2699 设置',
|
|
1782
1844
|
'settings.modelconfig':'模型配置',
|
|
1845
|
+
'settings.modelhealth':'模型健康',
|
|
1783
1846
|
'settings.embedding':'嵌入模型',
|
|
1784
1847
|
'settings.summarizer':'摘要模型',
|
|
1785
1848
|
'settings.skill':'技能进化',
|
|
@@ -2043,6 +2106,7 @@ function switchView(view){
|
|
|
2043
2106
|
const logsView=document.getElementById('logsView');
|
|
2044
2107
|
const settingsView=document.getElementById('settingsView');
|
|
2045
2108
|
const migrateView=document.getElementById('migrateView');
|
|
2109
|
+
const sidebar=document.getElementById('sidebar');
|
|
2046
2110
|
feedWrap.classList.add('hide');
|
|
2047
2111
|
analyticsView.classList.remove('show');
|
|
2048
2112
|
tasksView.classList.remove('show');
|
|
@@ -2050,26 +2114,33 @@ function switchView(view){
|
|
|
2050
2114
|
logsView.classList.remove('show');
|
|
2051
2115
|
settingsView.classList.remove('show');
|
|
2052
2116
|
migrateView.classList.remove('show');
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
loadMetrics();
|
|
2056
|
-
} else if(view==='tasks'){
|
|
2057
|
-
tasksView.classList.add('show');
|
|
2058
|
-
loadTasks();
|
|
2059
|
-
} else if(view==='skills'){
|
|
2060
|
-
skillsView.classList.add('show');
|
|
2061
|
-
loadSkills();
|
|
2062
|
-
} else if(view==='logs'){
|
|
2063
|
-
logsView.classList.add('show');
|
|
2064
|
-
loadLogs();
|
|
2065
|
-
} else if(view==='settings'){
|
|
2066
|
-
settingsView.classList.add('show');
|
|
2067
|
-
loadConfig();
|
|
2068
|
-
} else if(view==='import'){
|
|
2069
|
-
migrateView.classList.add('show');
|
|
2070
|
-
if(!window._migrateRunning) migrateScan();
|
|
2071
|
-
} else {
|
|
2117
|
+
const sessionSection=document.getElementById('sidebarSessionSection');
|
|
2118
|
+
if(view==='memories'){
|
|
2072
2119
|
feedWrap.classList.remove('hide');
|
|
2120
|
+
sessionSection.style.visibility='';
|
|
2121
|
+
sessionSection.style.pointerEvents='';
|
|
2122
|
+
} else if(view==='tasks'||view==='skills'){
|
|
2123
|
+
sessionSection.style.visibility='hidden';
|
|
2124
|
+
sessionSection.style.pointerEvents='none';
|
|
2125
|
+
if(view==='tasks'){tasksView.classList.add('show');loadTasks();}
|
|
2126
|
+
else{skillsView.classList.add('show');loadSkills();}
|
|
2127
|
+
} else {
|
|
2128
|
+
sessionSection.style.visibility='hidden';
|
|
2129
|
+
sessionSection.style.pointerEvents='none';
|
|
2130
|
+
if(view==='analytics'){
|
|
2131
|
+
analyticsView.classList.add('show');
|
|
2132
|
+
loadMetrics();
|
|
2133
|
+
} else if(view==='logs'){
|
|
2134
|
+
logsView.classList.add('show');
|
|
2135
|
+
loadLogs();
|
|
2136
|
+
} else if(view==='settings'){
|
|
2137
|
+
settingsView.classList.add('show');
|
|
2138
|
+
loadConfig();
|
|
2139
|
+
loadModelHealth();
|
|
2140
|
+
} else if(view==='import'){
|
|
2141
|
+
migrateView.classList.add('show');
|
|
2142
|
+
if(!window._migrateRunning) migrateScan();
|
|
2143
|
+
}
|
|
2073
2144
|
}
|
|
2074
2145
|
}
|
|
2075
2146
|
|
|
@@ -2422,14 +2493,16 @@ async function openTaskDetail(taskId){
|
|
|
2422
2493
|
if(task.chunks.length===0){
|
|
2423
2494
|
document.getElementById('taskDetailChunks').innerHTML='<div style="color:var(--text-muted);padding:12px;font-size:13px">'+t('tasks.nochunks')+'</div>';
|
|
2424
2495
|
}else{
|
|
2425
|
-
document.getElementById('taskDetailChunks').innerHTML=task.chunks.map(c
|
|
2496
|
+
document.getElementById('taskDetailChunks').innerHTML=task.chunks.map(function(c,i){
|
|
2426
2497
|
var roleLabel=c.role==='user'?t('tasks.role.user'):c.role==='assistant'?t('tasks.role.assistant'):c.role.toUpperCase();
|
|
2427
2498
|
return '<div class="task-chunk-item role-'+c.role+'">'+
|
|
2428
2499
|
'<div class="task-chunk-role '+c.role+'">'+roleLabel+'</div>'+
|
|
2429
|
-
'<div class="task-chunk-bubble"
|
|
2500
|
+
'<div class="task-chunk-bubble collapsed" id="chunk_b_'+i+'">'+esc(c.content)+'</div>'+
|
|
2501
|
+
'<div class="task-chunk-expand" id="chunk_e_'+i+'" onclick="toggleChunkExpand('+i+')"><span class="expand-arrow">▼</span> <span class="expand-label">'+t('tasks.expand')+'</span></div>'+
|
|
2430
2502
|
'<div class="task-chunk-time">'+formatTime(c.createdAt)+'</div>'+
|
|
2431
2503
|
'</div>';
|
|
2432
2504
|
}).join('');
|
|
2505
|
+
setTimeout(function(){initChunkExpanders(task.chunks.length)},50);
|
|
2433
2506
|
}
|
|
2434
2507
|
}catch(e){
|
|
2435
2508
|
document.getElementById('taskDetailTitle').textContent=t('tasks.error');
|
|
@@ -2493,6 +2566,33 @@ function renderTaskSkillSection(task){
|
|
|
2493
2566
|
}
|
|
2494
2567
|
}
|
|
2495
2568
|
|
|
2569
|
+
function initChunkExpanders(count){
|
|
2570
|
+
for(var i=0;i<count;i++){
|
|
2571
|
+
var b=document.getElementById('chunk_b_'+i);
|
|
2572
|
+
var e=document.getElementById('chunk_e_'+i);
|
|
2573
|
+
if(b && b.scrollHeight > b.clientHeight + 4){
|
|
2574
|
+
e.style.display='flex';
|
|
2575
|
+
} else if(b) {
|
|
2576
|
+
b.classList.remove('collapsed');
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
function toggleChunkExpand(i){
|
|
2581
|
+
var b=document.getElementById('chunk_b_'+i);
|
|
2582
|
+
var e=document.getElementById('chunk_e_'+i);
|
|
2583
|
+
if(!b||!e)return;
|
|
2584
|
+
var expanding=b.classList.contains('collapsed');
|
|
2585
|
+
if(expanding){
|
|
2586
|
+
b.classList.remove('collapsed');
|
|
2587
|
+
e.classList.add('is-expanded');
|
|
2588
|
+
e.querySelector('.expand-label').textContent=t('tasks.collapse');
|
|
2589
|
+
}else{
|
|
2590
|
+
b.classList.add('collapsed');
|
|
2591
|
+
e.classList.remove('is-expanded');
|
|
2592
|
+
e.querySelector('.expand-label').textContent=t('tasks.expand');
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
|
|
2496
2596
|
function closeTaskDetail(event){
|
|
2497
2597
|
if(event && event.target!==document.getElementById('taskDetailOverlay')) return;
|
|
2498
2598
|
document.getElementById('taskDetailOverlay').classList.remove('show');
|
|
@@ -2746,6 +2846,93 @@ async function toggleSkillPublic(id,setPublic){
|
|
|
2746
2846
|
}
|
|
2747
2847
|
}
|
|
2748
2848
|
|
|
2849
|
+
/* ─── Model Health Status ─── */
|
|
2850
|
+
|
|
2851
|
+
const HEALTH_ROLE_LABELS={
|
|
2852
|
+
'embedding':'Embedding',
|
|
2853
|
+
'summarize':'Summarizer',
|
|
2854
|
+
'filterRelevant':'Memory Filter',
|
|
2855
|
+
'judgeDedup':'Dedup Judge',
|
|
2856
|
+
'summarizeTask':'Task Summarizer',
|
|
2857
|
+
'judgeNewTopic':'Topic Judge'
|
|
2858
|
+
};
|
|
2859
|
+
|
|
2860
|
+
function classifyError(msg){
|
|
2861
|
+
if(!msg) return '';
|
|
2862
|
+
if(msg.indexOf('\u989D\u5EA6\u5DF2\u7528\u5C3D')>=0||msg.indexOf('quota')>=0||msg.indexOf('RemainQuota')>=0) return 'API quota exhausted';
|
|
2863
|
+
if(msg.indexOf('401')>=0||msg.indexOf('Unauthorized')>=0) return 'Auth failed (401)';
|
|
2864
|
+
if(msg.indexOf('timeout')>=0||msg.indexOf('Timeout')>=0) return 'Request timed out';
|
|
2865
|
+
if(msg.indexOf('429')>=0) return 'Rate limited (429)';
|
|
2866
|
+
if(msg.indexOf('ECONNREFUSED')>=0) return 'Connection refused';
|
|
2867
|
+
if(msg.indexOf('ENOTFOUND')>=0) return 'DNS resolution failed';
|
|
2868
|
+
if(msg.indexOf('403')>=0) return 'Forbidden (403)';
|
|
2869
|
+
return msg.length>50?msg.slice(0,47)+'...':msg;
|
|
2870
|
+
}
|
|
2871
|
+
|
|
2872
|
+
function shortenModel(s){return s?s.replace('openai_compatible/','').replace('openai/',''):'\u2014';}
|
|
2873
|
+
|
|
2874
|
+
async function loadModelHealth(){
|
|
2875
|
+
var bar=document.getElementById('modelHealthBar');
|
|
2876
|
+
if(!bar) return;
|
|
2877
|
+
try{
|
|
2878
|
+
var r=await fetch('/api/model-health');
|
|
2879
|
+
if(!r.ok){bar.innerHTML='<div class="mh-empty">Health data unavailable</div>';return;}
|
|
2880
|
+
var d=await r.json();
|
|
2881
|
+
var models=d.models||[];
|
|
2882
|
+
if(models.length===0){
|
|
2883
|
+
bar.innerHTML='<div class="mh-empty">No model calls recorded yet</div>';
|
|
2884
|
+
return;
|
|
2885
|
+
}
|
|
2886
|
+
var order=['embedding','summarize','filterRelevant','judgeDedup','summarizeTask','judgeNewTopic'];
|
|
2887
|
+
models.sort(function(a,b){var ai=order.indexOf(a.role),bi=order.indexOf(b.role);if(ai<0)ai=99;if(bi<0)bi=99;return ai-bi;});
|
|
2888
|
+
|
|
2889
|
+
var h='<table class="mh-table"><thead><tr>';
|
|
2890
|
+
h+='<th style="width:30px"></th><th>Role</th><th>Status</th><th>Model</th><th>Issue</th><th style="text-align:right">Updated</th>';
|
|
2891
|
+
h+='</tr></thead><tbody>';
|
|
2892
|
+
|
|
2893
|
+
for(var i=0;i<models.length;i++){
|
|
2894
|
+
var m=models[i];
|
|
2895
|
+
var st=m.status||'unknown';
|
|
2896
|
+
var label=HEALTH_ROLE_LABELS[m.role]||m.role;
|
|
2897
|
+
var badgeText=st==='ok'?'OK':st==='degraded'?'Degraded':st==='error'?'Error':'\u2014';
|
|
2898
|
+
var ago='';
|
|
2899
|
+
if(st==='ok'&&m.lastSuccess) ago=timeAgo(m.lastSuccess);
|
|
2900
|
+
else if(m.lastError) ago=timeAgo(m.lastError);
|
|
2901
|
+
|
|
2902
|
+
h+='<tr>';
|
|
2903
|
+
h+='<td><span class="mh-dot '+st+'"></span></td>';
|
|
2904
|
+
h+='<td><span style="font-weight:500">'+escapeHtml(label)+'</span></td>';
|
|
2905
|
+
h+='<td><span class="mh-badge '+st+'">'+badgeText+'</span></td>';
|
|
2906
|
+
h+='<td><span class="mh-model-name">'+escapeHtml(shortenModel(m.model))+'</span></td>';
|
|
2907
|
+
|
|
2908
|
+
var issue='';
|
|
2909
|
+
if((st==='error'||st==='degraded')&&m.lastErrorMessage){
|
|
2910
|
+
var shortErr=classifyError(m.lastErrorMessage);
|
|
2911
|
+
if(m.failedModel&&m.failedModel!==m.model) issue=shortenModel(m.failedModel)+': ';
|
|
2912
|
+
issue+=shortErr;
|
|
2913
|
+
if(m.consecutiveErrors>1) issue+=' ('+m.consecutiveErrors+'x)';
|
|
2914
|
+
}
|
|
2915
|
+
if(issue) h+='<td><span class="mh-err-text" title="'+escapeHtml(m.lastErrorMessage||'')+'">'+escapeHtml(issue)+'</span></td>';
|
|
2916
|
+
else h+='<td><span style="color:var(--text-muted);font-size:11px">\u2014</span></td>';
|
|
2917
|
+
|
|
2918
|
+
h+='<td style="text-align:right"><span class="mh-time">'+(ago||'\u2014')+'</span></td>';
|
|
2919
|
+
h+='</tr>';
|
|
2920
|
+
}
|
|
2921
|
+
h+='</tbody></table>';
|
|
2922
|
+
bar.innerHTML=h;
|
|
2923
|
+
}catch(e){
|
|
2924
|
+
bar.innerHTML='<div class="mh-empty">Failed to load model health</div>';
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
|
|
2928
|
+
function timeAgo(ts){
|
|
2929
|
+
var diff=Date.now()-ts;
|
|
2930
|
+
if(diff<60000) return 'just now';
|
|
2931
|
+
if(diff<3600000) return Math.floor(diff/60000)+'m ago';
|
|
2932
|
+
if(diff<86400000) return Math.floor(diff/3600000)+'h ago';
|
|
2933
|
+
return Math.floor(diff/86400000)+'d ago';
|
|
2934
|
+
}
|
|
2935
|
+
|
|
2749
2936
|
/* ─── Settings / Config ─── */
|
|
2750
2937
|
async function loadConfig(){
|
|
2751
2938
|
try{
|
|
@@ -2947,15 +3134,16 @@ async function testModel(type){
|
|
|
2947
3134
|
var d=await r.json();
|
|
2948
3135
|
if(d.ok){
|
|
2949
3136
|
resultEl.className='test-result ok';
|
|
2950
|
-
resultEl.innerHTML='\\u2705 '+t('settings.test.ok')+'<div style="margin-top:4px;font-size:11px;color:var(--text-muted)">'+esc(d.detail
|
|
3137
|
+
resultEl.innerHTML='\\u2705 '+t('settings.test.ok')+(d.detail?'<div style="margin-top:4px;font-size:11px;color:var(--text-muted)">'+esc(d.detail)+'</div>':'');
|
|
2951
3138
|
}else{
|
|
2952
|
-
var errMsg=d.error||'Unknown error';
|
|
3139
|
+
var errMsg=(d.error||'Unknown error').replace(/:\s*$/,'').trim();
|
|
2953
3140
|
resultEl.className='test-result fail';
|
|
2954
|
-
resultEl.innerHTML='\\u274C '+t('settings.test.fail')+'<div style="margin-top:6px;font-size:11px;padding:8px 10px;background:rgba(239,68,68,.06);border:1px solid rgba(239,68,68,.15);border-radius:6px;white-space:pre-wrap;word-break:break-all;max-height:120px;overflow-y:auto;font-family:SF Mono,Monaco,Consolas,monospace">'+esc(errMsg)+'</div>';
|
|
3141
|
+
resultEl.innerHTML='\\u274C '+t('settings.test.fail')+(errMsg?'<div style="margin-top:6px;font-size:11px;padding:8px 10px;background:rgba(239,68,68,.06);border:1px solid rgba(239,68,68,.15);border-radius:6px;white-space:pre-wrap;word-break:break-all;max-height:120px;overflow-y:auto;font-family:SF Mono,Monaco,Consolas,monospace">'+esc(errMsg)+'</div>':'');
|
|
2955
3142
|
}
|
|
2956
3143
|
}catch(e){
|
|
3144
|
+
var catchMsg=(e.message||'Network error').replace(/:\s*$/,'').trim();
|
|
2957
3145
|
resultEl.className='test-result fail';
|
|
2958
|
-
resultEl.innerHTML='\\u274C '+t('settings.test.fail')+'<div style="margin-top:6px;font-size:11px;padding:8px 10px;background:rgba(239,68,68,.06);border:1px solid rgba(239,68,68,.15);border-radius:6px;white-space:pre-wrap;word-break:break-all">'+esc(
|
|
3146
|
+
resultEl.innerHTML='\\u274C '+t('settings.test.fail')+(catchMsg?'<div style="margin-top:6px;font-size:11px;padding:8px 10px;background:rgba(239,68,68,.06);border:1px solid rgba(239,68,68,.15);border-radius:6px;white-space:pre-wrap;word-break:break-all">'+esc(catchMsg)+'</div>':'');
|
|
2959
3147
|
}finally{btn.disabled=false;}
|
|
2960
3148
|
}
|
|
2961
3149
|
|
|
@@ -3323,6 +3511,20 @@ async function loadStats(){
|
|
|
3323
3511
|
provEl.innerHTML='<div class="provider-badge offline"><span>\\u26A0</span> '+t('embed.off')+'</div>';
|
|
3324
3512
|
}
|
|
3325
3513
|
|
|
3514
|
+
if(!_embeddingWarningShown){
|
|
3515
|
+
_embeddingWarningShown=true;
|
|
3516
|
+
if(!d.embeddingProvider||d.embeddingProvider==='local'||d.embeddingProvider==='none'){
|
|
3517
|
+
showEmbeddingBanner(t('embed.warn.local'),'warning');
|
|
3518
|
+
}
|
|
3519
|
+
fetch('/api/model-health').then(r=>r.json()).then(mh=>{
|
|
3520
|
+
var models=mh.models||[];
|
|
3521
|
+
var embModel=models.find(m=>m.role==='embedding');
|
|
3522
|
+
if(embModel&&embModel.status==='error'){
|
|
3523
|
+
showEmbeddingBanner(t('embed.err.fail'),'error');
|
|
3524
|
+
}
|
|
3525
|
+
}).catch(()=>{});
|
|
3526
|
+
}
|
|
3527
|
+
|
|
3326
3528
|
const sl=document.getElementById('sessionList');
|
|
3327
3529
|
sl.innerHTML='<div class="session-item'+(activeSession===null?' active':'')+'" onclick="filterSession(null)"><span>'+t('sidebar.allsessions')+'</span><span class="count">'+tm+'</span></div>';
|
|
3328
3530
|
(d.sessions||[]).forEach(s=>{
|
|
@@ -3386,17 +3588,24 @@ async function doSearch(q){
|
|
|
3386
3588
|
if(!q.trim()){currentPage=1;loadMemories();return}
|
|
3387
3589
|
const list=document.getElementById('memoryList');
|
|
3388
3590
|
list.innerHTML='<div class="spinner"></div>';
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3591
|
+
try{
|
|
3592
|
+
const p=getFilterParams();
|
|
3593
|
+
p.set('q',q);
|
|
3594
|
+
const r=await fetch('/api/search?'+p.toString());
|
|
3595
|
+
const d=await r.json();
|
|
3596
|
+
const total=d.total||0;
|
|
3597
|
+
const meta=[];
|
|
3598
|
+
if(d.vectorCount>0) meta.push(d.vectorCount+t('search.meta.semantic'));
|
|
3599
|
+
if(d.ftsCount>0) meta.push(d.ftsCount+t('search.meta.text'));
|
|
3600
|
+
meta.push(total+t('search.meta.results'));
|
|
3601
|
+
document.getElementById('searchMeta').textContent=meta.join(' \\u00B7 ');
|
|
3602
|
+
renderMemories(d.results||[]);
|
|
3603
|
+
document.getElementById('pagination').innerHTML='';
|
|
3604
|
+
}catch(e){
|
|
3605
|
+
document.getElementById('searchMeta').textContent='0'+t('search.meta.results');
|
|
3606
|
+
renderMemories([]);
|
|
3607
|
+
document.getElementById('pagination').innerHTML='';
|
|
3608
|
+
}
|
|
3400
3609
|
}
|
|
3401
3610
|
|
|
3402
3611
|
function debounceSearch(){
|
|
@@ -4203,6 +4412,21 @@ function ppDone(wasStopped,wasFailed,skipReload){
|
|
|
4203
4412
|
if(!skipReload) loadAll();
|
|
4204
4413
|
}
|
|
4205
4414
|
|
|
4415
|
+
/* ─── Embedding Banner ─── */
|
|
4416
|
+
function showEmbeddingBanner(msg,type){
|
|
4417
|
+
if(document.getElementById('embBanner')) return;
|
|
4418
|
+
var cls=type==='error'?'emb-banner error':'emb-banner warning';
|
|
4419
|
+
var icon=type==='error'?'\\u274C':'\\u26A0\\uFE0F';
|
|
4420
|
+
var btn='<button class="emb-banner-btn" onclick="switchView(\\'settings\\');this.parentElement.remove()">'+t('embed.banner.goto')+'</button>';
|
|
4421
|
+
var close='<button class="emb-banner-close" onclick="this.parentElement.remove()">×</button>';
|
|
4422
|
+
var el=document.createElement('div');
|
|
4423
|
+
el.id='embBanner';
|
|
4424
|
+
el.className=cls;
|
|
4425
|
+
el.innerHTML=icon+' <span>'+esc(msg)+'</span>'+btn+close;
|
|
4426
|
+
var mc=document.querySelector('.main-content');
|
|
4427
|
+
if(mc) mc.parentElement.insertBefore(el,mc);
|
|
4428
|
+
}
|
|
4429
|
+
|
|
4206
4430
|
/* ─── Toast ─── */
|
|
4207
4431
|
function toast(msg,type='info'){
|
|
4208
4432
|
const c=document.getElementById('toasts');
|
|
@@ -4256,3 +4480,4 @@ checkAuth();
|
|
|
4256
4480
|
|
|
4257
4481
|
</body>
|
|
4258
4482
|
</html>`;
|
|
4483
|
+
}
|