@memtensor/memos-local-openclaw-plugin 1.0.4-beta.9 → 1.0.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/.env.example +7 -0
- package/README.md +94 -27
- package/dist/capture/index.js +3 -1
- package/dist/capture/index.js.map +1 -1
- package/dist/client/connector.d.ts +5 -0
- package/dist/client/connector.d.ts.map +1 -1
- package/dist/client/connector.js +89 -8
- package/dist/client/connector.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -1
- package/dist/config.js.map +1 -1
- package/dist/hub/server.d.ts +2 -0
- package/dist/hub/server.d.ts.map +1 -1
- package/dist/hub/server.js +240 -35
- package/dist/hub/server.js.map +1 -1
- package/dist/hub/user-manager.d.ts +9 -0
- package/dist/hub/user-manager.d.ts.map +1 -1
- package/dist/hub/user-manager.js +26 -2
- package/dist/hub/user-manager.js.map +1 -1
- package/dist/ingest/chunker.d.ts +2 -1
- package/dist/ingest/chunker.d.ts.map +1 -1
- package/dist/ingest/chunker.js +14 -10
- package/dist/ingest/chunker.js.map +1 -1
- package/dist/ingest/providers/index.js +2 -2
- package/dist/ingest/providers/index.js.map +1 -1
- package/dist/recall/engine.d.ts.map +1 -1
- package/dist/recall/engine.js +22 -4
- package/dist/recall/engine.js.map +1 -1
- package/dist/shared/llm-call.d.ts.map +1 -1
- package/dist/shared/llm-call.js +2 -1
- package/dist/shared/llm-call.js.map +1 -1
- package/dist/sharing/types.d.ts +1 -1
- package/dist/sharing/types.d.ts.map +1 -1
- package/dist/skill/evolver.d.ts +2 -0
- package/dist/skill/evolver.d.ts.map +1 -1
- package/dist/skill/evolver.js +56 -5
- package/dist/skill/evolver.js.map +1 -1
- package/dist/skill/generator.d.ts +2 -0
- package/dist/skill/generator.d.ts.map +1 -1
- package/dist/skill/generator.js +45 -3
- package/dist/skill/generator.js.map +1 -1
- package/dist/skill/installer.d.ts +26 -0
- package/dist/skill/installer.d.ts.map +1 -1
- package/dist/skill/installer.js +80 -4
- package/dist/skill/installer.js.map +1 -1
- package/dist/skill/upgrader.d.ts +2 -0
- package/dist/skill/upgrader.d.ts.map +1 -1
- package/dist/skill/upgrader.js +139 -1
- package/dist/skill/upgrader.js.map +1 -1
- package/dist/skill/validator.d.ts +3 -0
- package/dist/skill/validator.d.ts.map +1 -1
- package/dist/skill/validator.js +75 -0
- package/dist/skill/validator.js.map +1 -1
- package/dist/storage/sqlite.d.ts +57 -0
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +290 -35
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/telemetry.d.ts +4 -1
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +39 -12
- package/dist/telemetry.js.map +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -1
- package/dist/viewer/html.d.ts.map +1 -1
- package/dist/viewer/html.js +564 -225
- package/dist/viewer/html.js.map +1 -1
- package/dist/viewer/server.d.ts +9 -0
- package/dist/viewer/server.d.ts.map +1 -1
- package/dist/viewer/server.js +357 -108
- package/dist/viewer/server.js.map +1 -1
- package/index.ts +412 -53
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -1
- package/prebuilds/darwin-arm64/better_sqlite3.node +0 -0
- package/prebuilds/darwin-x64/better_sqlite3.node +0 -0
- package/prebuilds/linux-x64/better_sqlite3.node +0 -0
- package/prebuilds/win32-x64/better_sqlite3.node +0 -0
- package/src/capture/index.ts +4 -1
- package/src/client/connector.ts +92 -8
- package/src/config.ts +2 -1
- package/src/hub/server.ts +235 -35
- package/src/hub/user-manager.ts +42 -6
- package/src/ingest/chunker.ts +19 -13
- package/src/ingest/providers/index.ts +2 -2
- package/src/recall/engine.ts +20 -4
- package/src/shared/llm-call.ts +2 -1
- package/src/sharing/types.ts +1 -1
- package/src/skill/evolver.ts +58 -6
- package/src/skill/generator.ts +44 -5
- package/src/skill/installer.ts +107 -4
- package/src/skill/upgrader.ts +139 -1
- package/src/skill/validator.ts +79 -0
- package/src/storage/sqlite.ts +318 -40
- package/src/telemetry.ts +39 -14
- package/src/types.ts +11 -0
- package/src/viewer/html.ts +564 -225
- package/src/viewer/server.ts +333 -105
- package/telemetry.credentials.json +5 -0
package/dist/viewer/html.js
CHANGED
|
@@ -157,7 +157,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
157
157
|
.search-bar input::placeholder{color:var(--text-muted)}
|
|
158
158
|
.search-bar input:focus{border-color:var(--pri);box-shadow:0 0 0 3px var(--pri-glow)}
|
|
159
159
|
.search-bar .search-icon{position:absolute;left:14px;top:50%;transform:translateY(-50%);color:var(--text-muted);font-size:14px;pointer-events:none}
|
|
160
|
-
.search-meta{font-size:12px;color:var(--text-sec);
|
|
160
|
+
.search-meta{font-size:12px;color:var(--text-sec);padding:0 2px}.search-meta:not(:empty){margin-bottom:14px}
|
|
161
161
|
.scope-select{padding:10px 12px;border:1px solid var(--border);border-radius:10px;background:var(--bg-card);color:var(--text);font-size:13px;min-width:110px;outline:none}
|
|
162
162
|
.sharing-inline-meta{font-size:12px;color:var(--text-muted);margin:-8px 0 14px 2px}
|
|
163
163
|
.sharing-sidebar-card{margin:14px 0 18px;border:1px solid var(--border);background:var(--bg-card);border-radius:12px;padding:12px;box-shadow:var(--shadow-sm)}
|
|
@@ -251,9 +251,11 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
251
251
|
.au-status-dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:5px;vertical-align:middle;flex-shrink:0;transition:all .3s}
|
|
252
252
|
.au-status-dot.online{background:#22c55e;box-shadow:0 0 8px rgba(34,197,94,.6),0 0 16px rgba(34,197,94,.2);animation:dotBreathe 2s ease-in-out infinite}
|
|
253
253
|
.au-status-dot.offline{background:#6b7280;box-shadow:none}
|
|
254
|
-
.au-status-text{font-size:
|
|
255
|
-
.au-status-text.online{color:#22c55e;text-shadow:0 0 8px rgba(34,197,94,.
|
|
256
|
-
.au-status-text.offline{color:#6b7280}
|
|
254
|
+
.au-status-text{font-size:10px;font-weight:600;letter-spacing:.04em;padding:3px 10px;border-radius:6px;white-space:nowrap}
|
|
255
|
+
.au-status-text.online{color:#22c55e;background:rgba(34,197,94,.08);border:1px solid rgba(34,197,94,.18);text-shadow:0 0 8px rgba(34,197,94,.2)}
|
|
256
|
+
.au-status-text.offline{color:#6b7280;background:rgba(107,114,128,.06);border:1px solid rgba(107,114,128,.1)}
|
|
257
|
+
[data-theme="light"] .au-status-text.online{background:rgba(34,197,94,.06);border-color:rgba(34,197,94,.15)}
|
|
258
|
+
[data-theme="light"] .au-status-text.offline{background:rgba(0,0,0,.03);border-color:rgba(0,0,0,.06)}
|
|
257
259
|
.au-group-header{font-size:13px;font-weight:700;color:var(--text-sec);margin:20px 0 10px;display:flex;align-items:center;gap:8px;letter-spacing:.02em}
|
|
258
260
|
.au-group-header:first-child{margin-top:0}
|
|
259
261
|
.au-group-header .au-group-dot{display:inline-block;width:8px;height:8px;border-radius:50%}
|
|
@@ -288,7 +290,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
288
290
|
.admin-card-tag.tag-version{background:rgba(139,92,246,.1);color:#8b5cf6}
|
|
289
291
|
.admin-card-tag.tag-visibility{background:rgba(99,102,241,.08);color:var(--pri)}
|
|
290
292
|
.admin-card-tag.tag-group{background:rgba(139,92,246,.08);color:#8b5cf6}
|
|
291
|
-
.admin-card-preview{font-size:12px;color:var(--text-sec);line-height:1.5;margin:8px 0;padding:10px 12px;background:rgba(99,102,241,.02);border-radius:10px;border:1px solid rgba(99,102,241,.08);max-height:
|
|
293
|
+
.admin-card-preview{font-size:12px;color:var(--text-sec);line-height:1.5;margin:8px 0;padding:10px 12px;background:rgba(99,102,241,.02);border-radius:10px;border:1px solid rgba(99,102,241,.08);max-height:120px;overflow:hidden;white-space:pre-wrap;word-break:break-all;position:relative;-webkit-mask-image:linear-gradient(to bottom,#000 88%,transparent 100%);mask-image:linear-gradient(to bottom,#000 88%,transparent 100%)}
|
|
292
294
|
.admin-card-actions{display:inline-flex;gap:6px;margin-left:auto;align-items:center;flex-shrink:0}
|
|
293
295
|
.admin-card-time{font-size:11px;color:var(--text-muted)}
|
|
294
296
|
.admin-card-detail{display:none;margin-top:0;padding:20px 24px 24px;border-top:1px dashed rgba(99,102,241,.12);background:linear-gradient(180deg,rgba(99,102,241,.02) 0%,transparent 60%);animation:adminDetailIn .25s ease}
|
|
@@ -323,7 +325,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
323
325
|
.adm-msg-side.assistant .adm-msg-role{color:var(--green)}
|
|
324
326
|
.adm-msg-time{font-size:9px;color:var(--text-muted)}
|
|
325
327
|
.adm-msg-body{flex:1;min-width:0;padding:12px 16px;font-size:13px;line-height:1.75;color:var(--text);white-space:pre-wrap;word-break:break-word}
|
|
326
|
-
.adm-msg-body.collapsed{max-height:120px;overflow:hidden;-webkit-mask-image:linear-gradient(180deg,#000
|
|
328
|
+
.adm-msg-body.collapsed{max-height:120px;overflow:hidden;-webkit-mask-image:linear-gradient(180deg,#000 88%,transparent);mask-image:linear-gradient(180deg,#000 88%,transparent)}
|
|
327
329
|
.adm-msg-toggle{display:none;padding:0 16px 8px;font-size:11px;color:var(--pri);cursor:pointer;transition:color .15s}
|
|
328
330
|
.adm-msg-toggle:hover{color:var(--pri-dark)}
|
|
329
331
|
.admin-card-expand-btn{font-size:12px;color:var(--pri);cursor:pointer;background:none;border:none;padding:2px 6px;font-family:inherit}
|
|
@@ -331,17 +333,21 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
331
333
|
.admin-toolbar{display:flex;align-items:center;gap:10px;margin-bottom:14px;flex-wrap:wrap}
|
|
332
334
|
.admin-toolbar h3{font-size:14px;font-weight:600;color:var(--text);white-space:nowrap;margin:0;margin-right:auto;line-height:32px}
|
|
333
335
|
.admin-toolbar select{box-sizing:border-box;height:32px;font-size:12px;border:1px solid var(--border);border-radius:8px;background:var(--bg-card);color:var(--text);vertical-align:middle;margin:0;padding:0 10px}
|
|
334
|
-
.admin-badge{display:inline-flex;align-items:center;gap:4px;font-size:
|
|
335
|
-
.admin-badge.admin{background:linear-gradient(135deg,rgba(34,197,94,.
|
|
336
|
-
.admin-badge.
|
|
337
|
-
.admin-badge.
|
|
338
|
-
.admin-badge.
|
|
339
|
-
.admin-badge.
|
|
336
|
+
.admin-badge{display:inline-flex;align-items:center;gap:4px;font-size:9px;font-weight:700;padding:3px 10px;border-radius:6px;letter-spacing:.06em;text-transform:uppercase;position:relative;backdrop-filter:blur(4px);transition:all .25s}
|
|
337
|
+
.admin-badge.admin{background:linear-gradient(135deg,rgba(34,197,94,.12),rgba(16,185,129,.06));color:#22c55e;border:1px solid rgba(34,197,94,.2);box-shadow:0 0 12px rgba(34,197,94,.08),inset 0 1px 0 rgba(255,255,255,.05)}
|
|
338
|
+
.admin-badge.admin:hover{box-shadow:0 0 20px rgba(34,197,94,.15),inset 0 1px 0 rgba(255,255,255,.08)}
|
|
339
|
+
.admin-badge.member{background:rgba(99,102,241,.06);color:var(--text-muted);border:1px solid rgba(99,102,241,.12)}
|
|
340
|
+
.admin-badge.pending{background:linear-gradient(135deg,rgba(251,191,36,.12),rgba(245,158,11,.06));color:#fbbf24;border:1px solid rgba(251,191,36,.2);box-shadow:0 0 12px rgba(251,191,36,.08)}
|
|
341
|
+
.admin-badge.public{background:rgba(99,102,241,.08);color:var(--pri);border:1px solid rgba(99,102,241,.15)}
|
|
342
|
+
.admin-badge.group{background:rgba(139,92,246,.08);color:#8b5cf6;border:1px solid rgba(139,92,246,.15)}
|
|
343
|
+
.admin-badge.owner{background:linear-gradient(135deg,rgba(251,191,36,.12),rgba(245,158,11,.08));color:#f59e0b;border:1px solid rgba(251,191,36,.25);box-shadow:0 0 12px rgba(251,191,36,.1),inset 0 1px 0 rgba(255,255,255,.06)}
|
|
344
|
+
.au-badges{display:flex;align-items:center;gap:6px;flex-shrink:0;flex-wrap:wrap;justify-content:flex-end}
|
|
340
345
|
.admin-empty{font-size:13px;color:var(--text-muted);padding:48px 24px;text-align:center;border:1px dashed rgba(99,102,241,.15);border-radius:16px;background:rgba(99,102,241,.02)}
|
|
341
346
|
.admin-empty .ae-icon{font-size:32px;display:block;margin-bottom:10px;opacity:.4}
|
|
342
|
-
[data-theme="light"] .admin-badge.admin{background:rgba(5,150,105,.
|
|
343
|
-
[data-theme="light"] .admin-badge.member{background:rgba(0,0,0,.
|
|
344
|
-
[data-theme="light"] .admin-badge.pending{background:rgba(245,158,11,.
|
|
347
|
+
[data-theme="light"] .admin-badge.admin{background:rgba(5,150,105,.08);color:#059669;border-color:rgba(5,150,105,.18)}
|
|
348
|
+
[data-theme="light"] .admin-badge.member{background:rgba(0,0,0,.04);color:#6b7280;border-color:rgba(0,0,0,.08)}
|
|
349
|
+
[data-theme="light"] .admin-badge.pending{background:rgba(245,158,11,.08);color:#d97706;border-color:rgba(245,158,11,.18)}
|
|
350
|
+
[data-theme="light"] .admin-badge.owner{background:rgba(245,158,11,.08);color:#b45309;border-color:rgba(245,158,11,.2)}
|
|
345
351
|
[data-theme="light"] .admin-header{background:linear-gradient(135deg,rgba(99,102,241,.04) 0%,rgba(6,182,212,.03) 50%,rgba(139,92,246,.04) 100%)}
|
|
346
352
|
[data-theme="light"] .admin-stat-box{background:rgba(255,255,255,.8)}
|
|
347
353
|
[data-theme="light"] .admin-pending-section{background:linear-gradient(135deg,rgba(251,191,36,.03),rgba(245,158,11,.015))}
|
|
@@ -742,7 +748,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
742
748
|
[data-theme="light"] .nav-tabs{background:rgba(0,0,0,.05)}
|
|
743
749
|
[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)}
|
|
744
750
|
.analytics-view,.settings-view,.logs-view,.migrate-view,.admin-view{flex:1;min-width:0;flex-direction:column;gap:20px}
|
|
745
|
-
.feed-wrap,.tasks-view,.skills-view,.analytics-view,.
|
|
751
|
+
.feed-wrap,.tasks-view,.skills-view,.analytics-view,.logs-view,.migrate-view,.admin-view,.settings-view{max-width:960px}
|
|
746
752
|
|
|
747
753
|
/* ─── Logs ─── */
|
|
748
754
|
.logs-toolbar{display:flex;align-items:center;justify-content:space-between;padding:8px 0}
|
|
@@ -801,6 +807,10 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
801
807
|
.recall-score.high{background:rgba(34,197,94,.12);color:#22c55e}
|
|
802
808
|
.recall-score.mid{background:rgba(251,191,36,.12);color:#f59e0b}
|
|
803
809
|
.recall-score.low{background:rgba(248,113,113,.1);color:var(--text-muted)}
|
|
810
|
+
.recall-origin{flex-shrink:0;font-size:9px;font-weight:600;padding:1px 5px;border-radius:4px}
|
|
811
|
+
.recall-origin.local-shared{background:rgba(59,130,246,.12);color:#3b82f6}
|
|
812
|
+
.recall-origin.hub-memory{background:rgba(139,92,246,.12);color:#8b5cf6}
|
|
813
|
+
.recall-origin.hub-remote{background:rgba(139,92,246,.12);color:#8b5cf6}
|
|
804
814
|
.recall-summary-short{flex:1;color:var(--text-sec);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
805
815
|
.recall-expand-icon{flex-shrink:0;font-size:10px;color:var(--text-muted);transition:transform .15s}
|
|
806
816
|
.recall-item.expanded .recall-expand-icon{transform:rotate(90deg)}
|
|
@@ -969,8 +979,6 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
969
979
|
.team-guide-steps li::marker{color:var(--pri);font-weight:700;font-size:11px}
|
|
970
980
|
.team-guide-opt .btn-guide{font-size:11px;padding:5px 14px;border-radius:6px;font-weight:600;border:1px solid rgba(99,102,241,.25);background:rgba(99,102,241,.08);color:var(--pri);cursor:pointer;transition:background .15s,border-color .15s}
|
|
971
981
|
.team-guide-opt .btn-guide:hover{background:rgba(99,102,241,.14);border-color:var(--pri)}
|
|
972
|
-
.team-guide-dismiss{position:absolute;top:10px;right:12px;background:none;border:none;color:var(--text-muted);font-size:15px;cursor:pointer;padding:4px;line-height:1;opacity:.5;transition:opacity .15s}
|
|
973
|
-
.team-guide-dismiss:hover{opacity:1}
|
|
974
982
|
[data-theme="light"] .team-guide{background:linear-gradient(135deg,rgba(6,182,212,.03),rgba(79,70,229,.02));border-color:rgba(6,182,212,.15)}
|
|
975
983
|
[data-theme="light"] .team-guide-opt{box-shadow:0 1px 3px rgba(0,0,0,.03)}
|
|
976
984
|
[data-theme="light"] .team-guide-opt:hover{box-shadow:0 4px 16px rgba(0,0,0,.04)}
|
|
@@ -1213,7 +1221,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
1213
1221
|
</div>
|
|
1214
1222
|
<button class="btn btn-ghost btn-sm" onclick="doLogout()" data-i18n="logout">Logout</button>
|
|
1215
1223
|
</div>
|
|
1216
|
-
|
|
1224
|
+
</div>
|
|
1217
1225
|
</div>
|
|
1218
1226
|
|
|
1219
1227
|
<div class="main-content">
|
|
@@ -1222,7 +1230,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
1222
1230
|
<div class="stat-card pri"><div class="stat-value" id="statTotal">-</div><div class="stat-label" data-i18n="stat.memories">Memories</div></div>
|
|
1223
1231
|
<div class="stat-card green"><div class="stat-value" id="statSessions">-</div><div class="stat-label" data-i18n="stat.sessions">Sessions</div></div>
|
|
1224
1232
|
<div class="stat-card amber"><div class="stat-value" id="statEmbeddings">-</div><div class="stat-label" data-i18n="stat.embeddings">Embeddings</div></div>
|
|
1225
|
-
<div class="stat-card rose"><div class="stat-value" id="
|
|
1233
|
+
<div class="stat-card rose"><div class="stat-value" id="statAgents">-</div><div class="stat-label" data-i18n="stat.agents">Agents</div></div>
|
|
1226
1234
|
</div>
|
|
1227
1235
|
<div id="sidebarSharingSection" style="display:none">
|
|
1228
1236
|
<div class="sharing-sidebar-card">
|
|
@@ -1245,7 +1253,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
1245
1253
|
<select id="filterOwner" class="filter-select" onchange="onOwnerFilterChange()">
|
|
1246
1254
|
<option value="" data-i18n="filter.allagents">All agents</option>
|
|
1247
1255
|
</select>
|
|
1248
|
-
<select id="memorySearchScope" class="filter-select" onchange="onMemoryScopeChange()">
|
|
1256
|
+
<select id="memorySearchScope" class="filter-select" onchange="onMemoryScopeChange()" style="display:none">
|
|
1249
1257
|
<option value="local" data-i18n="scope.thisAgent">This Agent</option>
|
|
1250
1258
|
<option value="allLocal" data-i18n="scope.thisDevice">This Device</option>
|
|
1251
1259
|
<option value="hub" data-i18n="scope.hub">Team</option>
|
|
@@ -1257,7 +1265,6 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
1257
1265
|
<button class="filter-chip active" data-role="" onclick="setRoleFilter(this,'')" data-i18n="filter.all">All</button>
|
|
1258
1266
|
<button class="filter-chip" data-role="user" onclick="setRoleFilter(this,'user')">User</button>
|
|
1259
1267
|
<button class="filter-chip" data-role="assistant" onclick="setRoleFilter(this,'assistant')">Assistant</button>
|
|
1260
|
-
<button class="filter-chip" data-role="system" onclick="setRoleFilter(this,'system')">System</button>
|
|
1261
1268
|
<span class="filter-sep"></span>
|
|
1262
1269
|
<select id="filterSort" class="filter-select" onchange="applyFilters()">
|
|
1263
1270
|
<option value="newest" data-i18n="filter.newest">Newest first</option>
|
|
@@ -1290,7 +1297,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
1290
1297
|
<button class="filter-chip" data-task-status="active" onclick="setTaskStatusFilter(this,'active')" data-i18n="tasks.status.active">Active</button>
|
|
1291
1298
|
<button class="filter-chip" data-task-status="completed" onclick="setTaskStatusFilter(this,'completed')" data-i18n="tasks.status.completed">Completed</button>
|
|
1292
1299
|
<button class="filter-chip" data-task-status="skipped" onclick="setTaskStatusFilter(this,'skipped')" data-i18n="tasks.status.skipped">Skipped</button>
|
|
1293
|
-
<select id="taskSearchScope" class="scope-select" onchange="onTaskScopeChange()">
|
|
1300
|
+
<select id="taskSearchScope" class="scope-select" onchange="onTaskScopeChange()" style="display:none">
|
|
1294
1301
|
<option value="local" data-i18n="scope.thisAgent">This Agent</option>
|
|
1295
1302
|
<option value="allLocal" data-i18n="scope.thisDevice">This Device</option>
|
|
1296
1303
|
<option value="hub" data-i18n="scope.hub">Team</option>
|
|
@@ -1332,13 +1339,13 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
1332
1339
|
<div class="search-bar">
|
|
1333
1340
|
<span class="search-icon">🔍</span>
|
|
1334
1341
|
<input type="text" id="skillSearchInput" placeholder="Search skills..." data-i18n-ph="skills.search.placeholder" oninput="debounceSkillSearch()">
|
|
1335
|
-
<select id="skillSearchScope" class="scope-select" onchange="onSkillScopeChange()">
|
|
1342
|
+
<select id="skillSearchScope" class="scope-select" onchange="onSkillScopeChange()" style="display:none">
|
|
1336
1343
|
<option value="local" data-i18n="scope.thisAgent">This Agent</option>
|
|
1337
1344
|
<option value="allLocal" data-i18n="scope.thisDevice">This Device</option>
|
|
1338
1345
|
<option value="hub" data-i18n="scope.hub">Team</option>
|
|
1339
1346
|
</select>
|
|
1340
1347
|
</div>
|
|
1341
|
-
<div class="search-meta" id="skillSearchMeta"></div>
|
|
1348
|
+
<div class="search-meta" id="skillSearchMeta" style="display:none"></div>
|
|
1342
1349
|
<div class="tasks-header">
|
|
1343
1350
|
<div class="tasks-stats">
|
|
1344
1351
|
<div class="tasks-stat"><span class="tasks-stat-value" id="skillsTotalCount">-</span><span class="tasks-stat-label" data-i18n="skills.total">Total Skills</span></div>
|
|
@@ -1352,8 +1359,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
1352
1359
|
<button class="filter-chip" data-skill-status="active" onclick="setSkillStatusFilter(this,'active')" data-i18n="skills.filter.active">Active</button>
|
|
1353
1360
|
<button class="filter-chip" data-skill-status="draft" onclick="setSkillStatusFilter(this,'draft')" data-i18n="skills.filter.draft">Draft</button>
|
|
1354
1361
|
<button class="filter-chip" data-skill-status="archived" onclick="setSkillStatusFilter(this,'archived')" data-i18n="skills.filter.archived">Archived</button>
|
|
1355
|
-
<
|
|
1356
|
-
<select id="skillVisibilityFilter" class="filter-select" onchange="loadSkills()">
|
|
1362
|
+
<select id="skillVisibilityFilter" class="filter-select" onchange="loadSkills()" style="display:none">
|
|
1357
1363
|
<option value="" data-i18n="filter.allvisibility">All visibility</option>
|
|
1358
1364
|
<option value="public" data-i18n="filter.public">Public</option>
|
|
1359
1365
|
<option value="private" data-i18n="filter.private">Private</option>
|
|
@@ -1440,7 +1446,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
1440
1446
|
<select id="logToolFilter" onchange="onLogFilterChange()" style="font-size:12px;padding:4px 8px;border-radius:6px;border:1px solid var(--border);background:var(--card);color:var(--text);min-width:120px">
|
|
1441
1447
|
<option value="" data-i18n="logs.allTools">All Tools</option>
|
|
1442
1448
|
</select>
|
|
1443
|
-
|
|
1449
|
+
|
|
1444
1450
|
</div>
|
|
1445
1451
|
<div class="logs-toolbar-right">
|
|
1446
1452
|
<input type="checkbox" id="logAutoRefresh" style="display:none">
|
|
@@ -1636,9 +1642,8 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
1636
1642
|
</div>
|
|
1637
1643
|
</div>
|
|
1638
1644
|
<div class="settings-card-body">
|
|
1639
|
-
<!-- team setup guide (inside Hub card) -->
|
|
1645
|
+
<!-- team setup guide (inside Hub card) — always visible when sharing is not configured -->
|
|
1640
1646
|
<div class="team-guide" id="teamSetupGuide">
|
|
1641
|
-
<button class="team-guide-dismiss" onclick="dismissTeamGuide()" title="Dismiss">×</button>
|
|
1642
1647
|
<div class="team-guide-title">\u{1F680} <span data-i18n="guide.title">Get Started with Team Collaboration</span></div>
|
|
1643
1648
|
<div class="team-guide-subtitle" data-i18n="guide.subtitle">MemOS supports team memory sharing. Choose one of the following options to enable collaboration, or continue using local-only mode.</div>
|
|
1644
1649
|
<div class="team-guide-options">
|
|
@@ -1652,7 +1657,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
1652
1657
|
<li><span data-i18n="guide.join.s1">Ask your team admin for the Server Address and Team Token</span></li>
|
|
1653
1658
|
<li><span data-i18n="guide.join.s2">Enable sharing above, select "Client" mode</span></li>
|
|
1654
1659
|
<li><span data-i18n="guide.join.s3">Fill in Server Address and Team Token, click "Test Connection"</span></li>
|
|
1655
|
-
<li><span data-i18n="guide.join.s4">Save
|
|
1660
|
+
<li><span data-i18n="guide.join.s4">Click "Save & Apply" — the service restarts automatically (page refreshes)</span></li>
|
|
1656
1661
|
</ol>
|
|
1657
1662
|
<button class="btn-guide" onclick="guideGoToHub('client')" data-i18n="guide.join.btn">\u2192 Configure Client Mode</button>
|
|
1658
1663
|
</div>
|
|
@@ -1664,7 +1669,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
1664
1669
|
<div class="team-guide-opt-desc" data-i18n="guide.hub.desc">Be the team server. Run it on this device so others can connect and share memories with you.</div>
|
|
1665
1670
|
<ol class="team-guide-steps">
|
|
1666
1671
|
<li><span data-i18n="guide.hub.s1">Enable sharing above, select "Server" mode</span></li>
|
|
1667
|
-
<li><span data-i18n="guide.hub.s2">Set a team name,
|
|
1672
|
+
<li><span data-i18n="guide.hub.s2">Set a team name, click "Save & Apply" — the service restarts automatically</span></li>
|
|
1668
1673
|
<li><span data-i18n="guide.hub.s3">Share the Server Address and Team Token with your team members</span></li>
|
|
1669
1674
|
<li><span data-i18n="guide.hub.s4">Approve join requests in the Admin Panel</span></li>
|
|
1670
1675
|
</ol>
|
|
@@ -1725,7 +1730,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
1725
1730
|
<div style="font-weight:700;color:var(--text);margin-bottom:4px" data-i18n="settings.hub.clientSteps.title">Quick Setup (3 steps)</div>
|
|
1726
1731
|
<div><span style="color:var(--accent)">1.</span> <span data-i18n="settings.hub.clientSteps.s1">Ask your team admin for the Server Address and Team Token</span></div>
|
|
1727
1732
|
<div><span style="color:var(--accent)">2.</span> <span data-i18n="settings.hub.clientSteps.s2">Fill them in below, click "Test Connection" to verify</span></div>
|
|
1728
|
-
<div><span style="color:var(--accent)">3.</span> <span data-i18n="settings.hub.clientSteps.s3">Click "Save
|
|
1733
|
+
<div><span style="color:var(--accent)">3.</span> <span data-i18n="settings.hub.clientSteps.s3">Click "Save & Apply" — the service will restart and page refreshes automatically</span></div>
|
|
1729
1734
|
</div>
|
|
1730
1735
|
<div class="settings-grid">
|
|
1731
1736
|
<div class="settings-field full-width">
|
|
@@ -2082,8 +2087,8 @@ const I18N={
|
|
|
2082
2087
|
'skills.load.error':'Failed to load skills',
|
|
2083
2088
|
'skills.hub.title':'\u{1F310} Team Skills',
|
|
2084
2089
|
'scope.local':'Local',
|
|
2085
|
-
'scope.thisAgent':'This Agent',
|
|
2086
|
-
'scope.thisDevice':'
|
|
2090
|
+
'scope.thisAgent':'This Agent Only',
|
|
2091
|
+
'scope.thisDevice':'All Local Agents',
|
|
2087
2092
|
'scope.group':'Group',
|
|
2088
2093
|
'scope.all':'All',
|
|
2089
2094
|
'skills.visibility.public':'Shared Locally',
|
|
@@ -2121,6 +2126,13 @@ const I18N={
|
|
|
2121
2126
|
'notif.userJoin':'New user requests to join the team',
|
|
2122
2127
|
'notif.userOnline':'User came online',
|
|
2123
2128
|
'notif.userOffline':'User went offline',
|
|
2129
|
+
'notif.userLeft':'User has left the team',
|
|
2130
|
+
'notif.membershipApproved':'Your team join request has been approved',
|
|
2131
|
+
'notif.membershipRejected':'Your team join request has been declined',
|
|
2132
|
+
'notif.membershipRemoved':'You have been removed from the team by the admin',
|
|
2133
|
+
'notif.hubShutdown':'The team server has been shut down',
|
|
2134
|
+
'notif.rolePromoted':'You have been promoted to admin',
|
|
2135
|
+
'notif.roleDemoted':'You have been changed to member',
|
|
2124
2136
|
'notif.clearAll':'Clear all',
|
|
2125
2137
|
'notif.timeAgo.just':'just now',
|
|
2126
2138
|
'notif.timeAgo.min':'{n}m ago',
|
|
@@ -2129,7 +2141,7 @@ const I18N={
|
|
|
2129
2141
|
'stat.memories':'Memories',
|
|
2130
2142
|
'stat.sessions':'Sessions',
|
|
2131
2143
|
'stat.embeddings':'Embeddings',
|
|
2132
|
-
'stat.
|
|
2144
|
+
'stat.agents':'Agents',
|
|
2133
2145
|
'stat.active':'active',
|
|
2134
2146
|
'stat.deduped':'deduped',
|
|
2135
2147
|
'sidebar.sessions':'Sessions',
|
|
@@ -2228,6 +2240,9 @@ const I18N={
|
|
|
2228
2240
|
'logs.recall.noHits':'No matching memories',
|
|
2229
2241
|
'logs.recall.noneRelevant':'LLM filter: none relevant',
|
|
2230
2242
|
'logs.recall.more':'{n} more...',
|
|
2243
|
+
'recall.origin.localShared':'Local Shared',
|
|
2244
|
+
'recall.origin.hubMemory':'Team Cache',
|
|
2245
|
+
'recall.origin.hubRemote':'Team',
|
|
2231
2246
|
'tab.import':'\u{1F4E5} Import',
|
|
2232
2247
|
'tab.settings':'\u2699 Settings',
|
|
2233
2248
|
'settings.modelconfig':'Model Configuration',
|
|
@@ -2268,12 +2283,12 @@ const I18N={
|
|
|
2268
2283
|
'settings.test.ok':'Connected',
|
|
2269
2284
|
'settings.test.fail':'Failed',
|
|
2270
2285
|
'settings.session.expired':'Session expired, please refresh the page to log in again',
|
|
2271
|
-
'settings.save':'Save
|
|
2286
|
+
'settings.save':'Save & Apply',
|
|
2272
2287
|
'settings.reset':'Reset',
|
|
2273
2288
|
'settings.saved':'Saved',
|
|
2274
|
-
'settings.restart.hint':'
|
|
2275
|
-
'settings.restart.autoRefresh':'
|
|
2276
|
-
'settings.restart.waiting':'Configuration saved.
|
|
2289
|
+
'settings.restart.hint':'Changes will take effect after the service restarts automatically.',
|
|
2290
|
+
'settings.restart.autoRefresh':'Service restarting, page will refresh automatically...',
|
|
2291
|
+
'settings.restart.waiting':'Configuration saved. Service is restarting...',
|
|
2277
2292
|
'settings.save.fail':'Failed to save settings',
|
|
2278
2293
|
'settings.save.emb.required':'Embedding model is required. Please configure an embedding model before saving.',
|
|
2279
2294
|
'settings.save.emb.fail':'Embedding model test failed, cannot save',
|
|
@@ -2400,16 +2415,16 @@ const I18N={
|
|
|
2400
2415
|
'settings.hub.tokenCopied':'Team Token copied!',
|
|
2401
2416
|
'settings.hub.hubSteps.title':'Quick Setup (3 steps)',
|
|
2402
2417
|
'settings.hub.hubSteps.s1':'Fill in Team Name below (or keep default)',
|
|
2403
|
-
'settings.hub.hubSteps.s2':'Click "Save
|
|
2418
|
+
'settings.hub.hubSteps.s2':'Click "Save & Apply" — the service will restart automatically',
|
|
2404
2419
|
'settings.hub.hubSteps.s3':'Share the Server Address and Team Token below with your team members',
|
|
2405
2420
|
'settings.hub.clientSteps.title':'Quick Setup (3 steps)',
|
|
2406
2421
|
'settings.hub.clientSteps.s1':'Ask your team admin for the Server Address and Team Token',
|
|
2407
2422
|
'settings.hub.clientSteps.s2':'Fill them in below, click "Test Connection" to verify',
|
|
2408
|
-
'settings.hub.clientSteps.s3':'Click "Save
|
|
2423
|
+
'settings.hub.clientSteps.s3':'Click "Save & Apply" — the service will restart and page refreshes automatically',
|
|
2409
2424
|
'settings.hub.shareInfo.title':'Share this info with your team members:',
|
|
2410
2425
|
'settings.hub.shareInfo.yourIP':'your-IP',
|
|
2411
2426
|
'settings.hub.shareInfo.clickCopy':'Click to copy',
|
|
2412
|
-
'settings.hub.restartAlert':'Team sharing config saved!
|
|
2427
|
+
'settings.hub.restartAlert':'Team sharing config saved! The service will restart automatically to apply changes.',
|
|
2413
2428
|
'settings.hub.hubAddress':'Server Address',
|
|
2414
2429
|
'settings.hub.hubAddress.hint':'Team server address, e.g. 192.168.1.100:18800',
|
|
2415
2430
|
'settings.hub.teamTokenClient':'Team Token',
|
|
@@ -2430,6 +2445,10 @@ const I18N={
|
|
|
2430
2445
|
'sidebar.hub':'\u{1F310} Team Sharing',
|
|
2431
2446
|
'sharing.sidebar.connected':'Connected',
|
|
2432
2447
|
'sharing.sidebar.disconnected':'Disconnected',
|
|
2448
|
+
'sharing.sidebar.hubRunning':'Hub Running',
|
|
2449
|
+
'sharing.sidebar.teamName':'Team',
|
|
2450
|
+
'sharing.sidebar.members':'Members',
|
|
2451
|
+
'sharing.sidebar.online':'online',
|
|
2433
2452
|
'sharing.sidebar.pending':'Pending Approval',
|
|
2434
2453
|
'sharing.sidebar.rejected':'Rejected',
|
|
2435
2454
|
'sharing.sidebar.starting':'Starting...',
|
|
@@ -2439,11 +2458,21 @@ const I18N={
|
|
|
2439
2458
|
'sharing.sidebar.targetHub':'Team Server:',
|
|
2440
2459
|
'sharing.pendingApproval.hint':'Your join request has been submitted. Please wait for the team admin to approve.',
|
|
2441
2460
|
'sharing.rejected.hint':'Your join request was rejected by the team admin. Please contact the admin or retry.',
|
|
2461
|
+
'sharing.removed.hint':'You have been removed from the team by the admin. You can re-apply to join.',
|
|
2462
|
+
'sharing.joinTeam':'Join Team',
|
|
2463
|
+
'sharing.joinSent.pending':'Join request sent! Waiting for admin approval.',
|
|
2464
|
+
'sharing.joinSent.active':'Successfully joined the team!',
|
|
2442
2465
|
'sharing.retryJoin':'Retry Join',
|
|
2443
2466
|
'sharing.retryJoin.hint':'Clears local data and re-submits the join request',
|
|
2444
2467
|
'sharing.retryJoin.confirm':'This will clear your current connection and re-submit a join request. Continue?',
|
|
2468
|
+
'sharing.leaveTeam':'Leave Team',
|
|
2469
|
+
'sharing.leaveTeam.confirm':'You are about to leave team "{team}".\\n\\nWhat will happen:\\n\\u2022 You will disconnect from the team server\\n\\u2022 The team admin will be notified that you left\\n\\u2022 You will no longer receive shared memories, tasks, or skills\\n\\u2022 Your local data is preserved and not affected\\n\\u2022 You can rejoin later if the admin approves\\n\\nAre you sure?',
|
|
2470
|
+
'sharing.leaveTeam.success':'You have left the team. Sharing has been disabled.',
|
|
2471
|
+
'sharing.leaveTeam.fail':'Failed to leave team',
|
|
2472
|
+
'sharing.team.default':'the team',
|
|
2445
2473
|
'sharing.retryJoin.success':'Join request re-submitted. Waiting for admin approval.',
|
|
2446
2474
|
'sharing.retryJoin.fail':'Failed to retry join',
|
|
2475
|
+
'sharing.ownerRemoved':'(removed)',
|
|
2447
2476
|
'sharing.cannotJoinSelf':'Cannot join your own server. Please enter a remote server address.',
|
|
2448
2477
|
'scope.hub':'Team',
|
|
2449
2478
|
'memory.detail.title':'Memory Detail',
|
|
@@ -2494,6 +2523,7 @@ const I18N={
|
|
|
2494
2523
|
'admin.editName':'Edit Name',
|
|
2495
2524
|
'admin.lastAdminHint':'Last admin — cannot remove or demote',
|
|
2496
2525
|
'admin.ownerHint':'Hub owner — cannot be demoted or removed',
|
|
2526
|
+
'admin.selfHint':'This is you',
|
|
2497
2527
|
'admin.editNamePrompt':'Enter new username:',
|
|
2498
2528
|
'confirm.promoteAdmin':'Promote this user to admin? They will be able to manage all team members and resources.',
|
|
2499
2529
|
'confirm.demoteMember':'Demote this admin to member?',
|
|
@@ -2555,6 +2585,8 @@ const I18N={
|
|
|
2555
2585
|
'toast.userApproved':'User approved',
|
|
2556
2586
|
'sharing.approved.toast':'Your join request has been approved!',
|
|
2557
2587
|
'sharing.rejected.toast':'Your join request was rejected by the admin.',
|
|
2588
|
+
'sharing.hubOffline.toast':'Team server is offline. Will reconnect automatically when it comes back.',
|
|
2589
|
+
'sharing.hubReconnected.toast':'Team server is back online! Connection restored.',
|
|
2558
2590
|
'toast.userRejected':'User rejected',
|
|
2559
2591
|
'toast.approveFail':'Approve failed',
|
|
2560
2592
|
'toast.rejectFail':'Reject failed',
|
|
@@ -2647,9 +2679,9 @@ const I18N={
|
|
|
2647
2679
|
'share.status.agents':'Local',
|
|
2648
2680
|
'share.status.hub':'Team',
|
|
2649
2681
|
'share.scope.title':'Sharing Scope',
|
|
2650
|
-
'share.scope.private':'
|
|
2651
|
-
'share.scope.local':'
|
|
2652
|
-
'share.scope.team':'Team',
|
|
2682
|
+
'share.scope.private':'Private',
|
|
2683
|
+
'share.scope.local':'Local Shared',
|
|
2684
|
+
'share.scope.team':'Team Shared',
|
|
2653
2685
|
'share.scope.current':'Current',
|
|
2654
2686
|
'share.scope.teamDisabled':'Not connected to team server',
|
|
2655
2687
|
'share.scope.teamIncludes':'Includes visibility to all local agents',
|
|
@@ -2714,9 +2746,10 @@ const I18N={
|
|
|
2714
2746
|
'update.dismiss':'Dismiss',
|
|
2715
2747
|
'sharing.disable.confirm.hub':'You are about to shut down the team server.\\n\\nWhat will happen:\\n\\u2022 All connected team members will be disconnected\\n\\u2022 They will no longer be able to sync memories, tasks, or skills\\n\\u2022 Shared data is preserved and will be available when you re-enable\\n\\nAre you sure?',
|
|
2716
2748
|
'sharing.disable.confirm.client':'You are about to disconnect from the team.\\n\\nWhat will happen:\\n\\u2022 You will no longer receive shared memories, tasks, or skills from the team\\n\\u2022 Your local data is preserved and will not be affected\\n\\u2022 You can reconnect later by re-enabling sharing\\n\\nAre you sure?',
|
|
2717
|
-
'sharing.disable.restartAlert':'Sharing has been disabled.
|
|
2718
|
-
'sharing.switch.hubToClient':'You are about to switch from Server to Client mode.\\n\\nWhat will happen:\\n\\u2022 The Hub server will shut down after
|
|
2719
|
-
'sharing.switch.clientToHub':'You are about to switch from Client to Server mode.\\n\\nWhat will happen:\\n\\u2022 You will disconnect from the current team\\n\\u2022 A new Hub server will start after
|
|
2749
|
+
'sharing.disable.restartAlert':'Sharing has been disabled. The service will restart automatically to apply the change.',
|
|
2750
|
+
'sharing.switch.hubToClient':'You are about to switch from Server to Client mode.\\n\\nWhat will happen:\\n\\u2022 The Hub server will shut down after the service restarts\\n\\u2022 All connected team members will be disconnected\\n\\u2022 Shared data on the Hub is preserved for future use\\n\\u2022 You will join the specified remote team as a client\\n\\nAre you sure?',
|
|
2751
|
+
'sharing.switch.clientToHub':'You are about to switch from Client to Server mode.\\n\\nWhat will happen:\\n\\u2022 You will disconnect from the current team\\n\\u2022 A new Hub server will start after the service restarts\\n\\u2022 Your local data is not affected\\n\\nAre you sure?',
|
|
2752
|
+
'sharing.switch.hubAddress':'You are about to leave the current team and join a different one.\\n\\nWhat will happen:\\n\\u2022 You will disconnect from the current team server\\n\\u2022 The current team admin will be notified that you left\\n\\u2022 You will join the new team server as a new member\\n\\u2022 Your local data is not affected\\n\\nAre you sure?',
|
|
2720
2753
|
'admin.notEnabled.title':'Team sharing is not enabled',
|
|
2721
2754
|
'admin.notEnabled.desc':'The Admin Panel is used to manage team members, shared memories, tasks, and skills. To use this feature, you need to enable team sharing first.',
|
|
2722
2755
|
'admin.notEnabled.setupHub':'Set Up as Team Server',
|
|
@@ -2734,12 +2767,12 @@ const I18N={
|
|
|
2734
2767
|
'guide.join.s1':'Ask your team admin for the Server Address and Team Token',
|
|
2735
2768
|
'guide.join.s2':'Go to Settings \u2192 Team Sharing, enable sharing, select "Client" mode',
|
|
2736
2769
|
'guide.join.s3':'Fill in Server Address and Team Token, click "Test Connection"',
|
|
2737
|
-
'guide.join.s4':'Save
|
|
2770
|
+
'guide.join.s4':'Click "Save & Apply" — the service restarts automatically (page refreshes)',
|
|
2738
2771
|
'guide.join.btn':'\u2192 Configure Client Mode',
|
|
2739
2772
|
'guide.hub.title':'Start Your Own Team Server',
|
|
2740
2773
|
'guide.hub.desc':'Be the team server. Run it on this device so others can connect and share memories with you.',
|
|
2741
2774
|
'guide.hub.s1':'Go to Settings \u2192 Team Sharing, enable sharing, select "Server" mode',
|
|
2742
|
-
'guide.hub.s2':'Set a team name,
|
|
2775
|
+
'guide.hub.s2':'Set a team name, click "Save & Apply" — the service restarts automatically',
|
|
2743
2776
|
'guide.hub.s3':'Share the Server Address and Team Token with your team members',
|
|
2744
2777
|
'guide.hub.s4':'Approve join requests in the Admin Panel',
|
|
2745
2778
|
'guide.hub.btn':'\u2192 Configure Server Mode'
|
|
@@ -2791,8 +2824,8 @@ const I18N={
|
|
|
2791
2824
|
'skills.load.error':'加载技能失败',
|
|
2792
2825
|
'skills.hub.title':'\u{1F310} 团队共享技能',
|
|
2793
2826
|
'scope.local':'本地',
|
|
2794
|
-
'scope.thisAgent':'
|
|
2795
|
-
'scope.thisDevice':'
|
|
2827
|
+
'scope.thisAgent':'仅本智能体',
|
|
2828
|
+
'scope.thisDevice':'本机所有智能体',
|
|
2796
2829
|
'scope.group':'团队',
|
|
2797
2830
|
'scope.all':'全部',
|
|
2798
2831
|
'skills.visibility.public':'本机共享',
|
|
@@ -2830,6 +2863,13 @@ const I18N={
|
|
|
2830
2863
|
'notif.userJoin':'有新用户申请加入团队',
|
|
2831
2864
|
'notif.userOnline':'用户上线了',
|
|
2832
2865
|
'notif.userOffline':'用户下线了',
|
|
2866
|
+
'notif.userLeft':'用户已退出团队',
|
|
2867
|
+
'notif.membershipApproved':'你的团队加入申请已通过',
|
|
2868
|
+
'notif.membershipRejected':'你的团队加入申请已被拒绝',
|
|
2869
|
+
'notif.membershipRemoved':'你已被管理员移出团队',
|
|
2870
|
+
'notif.hubShutdown':'团队服务已关闭',
|
|
2871
|
+
'notif.rolePromoted':'你已被提升为管理员',
|
|
2872
|
+
'notif.roleDemoted':'你已被设为普通成员',
|
|
2833
2873
|
'notif.clearAll':'清除全部',
|
|
2834
2874
|
'notif.timeAgo.just':'刚刚',
|
|
2835
2875
|
'notif.timeAgo.min':'{n}分钟前',
|
|
@@ -2838,7 +2878,7 @@ const I18N={
|
|
|
2838
2878
|
'stat.memories':'记忆',
|
|
2839
2879
|
'stat.sessions':'会话',
|
|
2840
2880
|
'stat.embeddings':'嵌入',
|
|
2841
|
-
'stat.
|
|
2881
|
+
'stat.agents':'智能体',
|
|
2842
2882
|
'stat.active':'活跃',
|
|
2843
2883
|
'stat.deduped':'已去重',
|
|
2844
2884
|
'sidebar.sessions':'会话列表',
|
|
@@ -2937,6 +2977,9 @@ const I18N={
|
|
|
2937
2977
|
'logs.recall.noHits':'未匹配到记忆',
|
|
2938
2978
|
'logs.recall.noneRelevant':'LLM 过滤:无相关记忆',
|
|
2939
2979
|
'logs.recall.more':'还有 {n} 条...',
|
|
2980
|
+
'recall.origin.localShared':'本机共享',
|
|
2981
|
+
'recall.origin.hubMemory':'团队缓存',
|
|
2982
|
+
'recall.origin.hubRemote':'团队',
|
|
2940
2983
|
'tab.import':'\u{1F4E5} 导入',
|
|
2941
2984
|
'tab.settings':'\u2699 设置',
|
|
2942
2985
|
'settings.modelconfig':'模型配置',
|
|
@@ -2977,12 +3020,12 @@ const I18N={
|
|
|
2977
3020
|
'settings.test.ok':'连接成功',
|
|
2978
3021
|
'settings.test.fail':'连接失败',
|
|
2979
3022
|
'settings.session.expired':'登录已过期,请刷新页面重新登录',
|
|
2980
|
-
'settings.save':'
|
|
3023
|
+
'settings.save':'保存并应用',
|
|
2981
3024
|
'settings.reset':'重置',
|
|
2982
3025
|
'settings.saved':'已保存',
|
|
2983
|
-
'settings.restart.hint':'
|
|
2984
|
-
'settings.restart.autoRefresh':'
|
|
2985
|
-
'settings.restart.waiting':'
|
|
3026
|
+
'settings.restart.hint':'修改将在服务自动重启后生效。',
|
|
3027
|
+
'settings.restart.autoRefresh':'服务重启中,页面将自动刷新...',
|
|
3028
|
+
'settings.restart.waiting':'配置已保存,服务正在重启...',
|
|
2986
3029
|
'settings.save.fail':'保存设置失败',
|
|
2987
3030
|
'settings.save.emb.required':'嵌入模型为必填项,请先配置嵌入模型再保存。',
|
|
2988
3031
|
'settings.save.emb.fail':'嵌入模型测试失败,无法保存',
|
|
@@ -3109,16 +3152,16 @@ const I18N={
|
|
|
3109
3152
|
'settings.hub.tokenCopied':'团队令牌已复制!',
|
|
3110
3153
|
'settings.hub.hubSteps.title':'快速配置(3 步)',
|
|
3111
3154
|
'settings.hub.hubSteps.s1':'填写下方团队名称(或保持默认)',
|
|
3112
|
-
'settings.hub.hubSteps.s2':'
|
|
3155
|
+
'settings.hub.hubSteps.s2':'点击「保存并应用」,服务将自动重启',
|
|
3113
3156
|
'settings.hub.hubSteps.s3':'将下方的服务器地址和团队令牌分享给团队成员',
|
|
3114
3157
|
'settings.hub.clientSteps.title':'快速配置(3 步)',
|
|
3115
3158
|
'settings.hub.clientSteps.s1':'向团队管理员获取服务器地址和团队令牌',
|
|
3116
3159
|
'settings.hub.clientSteps.s2':'填入下方,点击"测试连接"验证连通性',
|
|
3117
|
-
'settings.hub.clientSteps.s3':'
|
|
3160
|
+
'settings.hub.clientSteps.s3':'点击「保存并应用」,服务将自动重启(页面会自动刷新)',
|
|
3118
3161
|
'settings.hub.shareInfo.title':'请将以下信息分享给团队成员:',
|
|
3119
3162
|
'settings.hub.shareInfo.yourIP':'你的IP',
|
|
3120
3163
|
'settings.hub.shareInfo.clickCopy':'点击复制',
|
|
3121
|
-
'settings.hub.restartAlert':'
|
|
3164
|
+
'settings.hub.restartAlert':'团队共享配置已保存!服务将自动重启以应用更改。',
|
|
3122
3165
|
'settings.hub.hubAddress':'服务器地址',
|
|
3123
3166
|
'settings.hub.hubAddress.hint':'团队服务器地址,如 192.168.1.100:18800',
|
|
3124
3167
|
'settings.hub.teamTokenClient':'团队令牌',
|
|
@@ -3139,6 +3182,10 @@ const I18N={
|
|
|
3139
3182
|
'sidebar.hub':'\u{1F310} 团队共享',
|
|
3140
3183
|
'sharing.sidebar.connected':'已连接',
|
|
3141
3184
|
'sharing.sidebar.disconnected':'已断开',
|
|
3185
|
+
'sharing.sidebar.hubRunning':'服务运行中',
|
|
3186
|
+
'sharing.sidebar.teamName':'团队',
|
|
3187
|
+
'sharing.sidebar.members':'成员',
|
|
3188
|
+
'sharing.sidebar.online':'在线',
|
|
3142
3189
|
'sharing.sidebar.pending':'等待审核',
|
|
3143
3190
|
'sharing.sidebar.rejected':'已拒绝',
|
|
3144
3191
|
'sharing.sidebar.starting':'启动中...',
|
|
@@ -3148,11 +3195,21 @@ const I18N={
|
|
|
3148
3195
|
'sharing.sidebar.targetHub':'团队服务器:',
|
|
3149
3196
|
'sharing.pendingApproval.hint':'加入申请已提交,请等待团队管理员审核通过。',
|
|
3150
3197
|
'sharing.rejected.hint':'您的加入申请已被团队管理员拒绝,请联系管理员或重新申请。',
|
|
3198
|
+
'sharing.removed.hint':'您已被管理员从团队中移除,可以重新申请加入。',
|
|
3199
|
+
'sharing.joinTeam':'加入团队',
|
|
3200
|
+
'sharing.joinSent.pending':'加入申请已发送,等待管理员审批。',
|
|
3201
|
+
'sharing.joinSent.active':'成功加入团队!',
|
|
3151
3202
|
'sharing.retryJoin':'重新申请',
|
|
3152
3203
|
'sharing.retryJoin.hint':'清除本地连接数据并重新提交加入申请',
|
|
3153
3204
|
'sharing.retryJoin.confirm':'这将清除当前连接数据并重新提交加入申请,是否继续?',
|
|
3205
|
+
'sharing.leaveTeam':'退出团队',
|
|
3206
|
+
'sharing.leaveTeam.confirm':'你即将退出团队「{team}」。\\n\\n退出后将会:\\n\\u2022 断开与团队服务器的连接\\n\\u2022 团队管理员会收到你退出的通知\\n\\u2022 你将无法再接收团队共享的记忆、任务和技能\\n\\u2022 你的本地数据不受影响,会完整保留\\n\\u2022 之后可以重新申请加入(需管理员审批)\\n\\n确定要退出吗?',
|
|
3207
|
+
'sharing.leaveTeam.success':'你已退出团队,团队共享已关闭。',
|
|
3208
|
+
'sharing.leaveTeam.fail':'退出团队失败',
|
|
3209
|
+
'sharing.team.default':'该团队',
|
|
3154
3210
|
'sharing.retryJoin.success':'加入申请已重新提交,请等待管理员审核。',
|
|
3155
3211
|
'sharing.retryJoin.fail':'重新申请失败',
|
|
3212
|
+
'sharing.ownerRemoved':'(已移除)',
|
|
3156
3213
|
'sharing.cannotJoinSelf':'不能加入自己的服务端,请输入远程服务器地址。',
|
|
3157
3214
|
'scope.hub':'团队',
|
|
3158
3215
|
'memory.detail.title':'记忆详情',
|
|
@@ -3203,6 +3260,7 @@ const I18N={
|
|
|
3203
3260
|
'admin.editName':'编辑名称',
|
|
3204
3261
|
'admin.lastAdminHint':'唯一管理员 — 无法删除或降级',
|
|
3205
3262
|
'admin.ownerHint':'Hub 创建者 — 不可降级或移除',
|
|
3263
|
+
'admin.selfHint':'这是你自己',
|
|
3206
3264
|
'admin.editNamePrompt':'请输入新用户名:',
|
|
3207
3265
|
'confirm.promoteAdmin':'确定要将此用户提升为管理员吗?管理员可以管理所有团队成员和资源。',
|
|
3208
3266
|
'confirm.demoteMember':'确定要将此管理员降为普通成员吗?',
|
|
@@ -3264,6 +3322,8 @@ const I18N={
|
|
|
3264
3322
|
'toast.userApproved':'用户已批准',
|
|
3265
3323
|
'sharing.approved.toast':'您的加入申请已通过审核!',
|
|
3266
3324
|
'sharing.rejected.toast':'您的加入申请已被管理员拒绝。',
|
|
3325
|
+
'sharing.hubOffline.toast':'团队服务已离线,恢复后将自动重新连接。',
|
|
3326
|
+
'sharing.hubReconnected.toast':'团队服务已恢复上线,连接已自动恢复!',
|
|
3267
3327
|
'toast.userRejected':'用户已拒绝',
|
|
3268
3328
|
'toast.approveFail':'批准失败',
|
|
3269
3329
|
'toast.rejectFail':'拒绝失败',
|
|
@@ -3356,9 +3416,9 @@ const I18N={
|
|
|
3356
3416
|
'share.status.agents':'本机',
|
|
3357
3417
|
'share.status.hub':'团队',
|
|
3358
3418
|
'share.scope.title':'共享范围',
|
|
3359
|
-
'share.scope.private':'
|
|
3360
|
-
'share.scope.local':'
|
|
3361
|
-
'share.scope.team':'
|
|
3419
|
+
'share.scope.private':'私有',
|
|
3420
|
+
'share.scope.local':'本机共享',
|
|
3421
|
+
'share.scope.team':'团队共享',
|
|
3362
3422
|
'share.scope.current':'当前',
|
|
3363
3423
|
'share.scope.teamDisabled':'未连接团队服务器',
|
|
3364
3424
|
'share.scope.teamIncludes':'包含本机所有智能体的可见性',
|
|
@@ -3423,9 +3483,10 @@ const I18N={
|
|
|
3423
3483
|
'update.dismiss':'关闭',
|
|
3424
3484
|
'sharing.disable.confirm.hub':'你即将关闭团队服务。\\n\\n关闭后将会:\\n\\u2022 所有已连接的团队成员将断开连接\\n\\u2022 他们将无法继续同步记忆、任务和技能\\n\\u2022 已共享的数据会保留,重新开启后仍可使用\\n\\n确定要关闭吗?',
|
|
3425
3485
|
'sharing.disable.confirm.client':'你即将断开与团队的连接。\\n\\n断开后将会:\\n\\u2022 你将无法再接收团队共享的记忆、任务和技能\\n\\u2022 你的本地数据不受影响,会完整保留\\n\\u2022 之后可以随时重新开启共享来恢复连接\\n\\n确定要断开吗?',
|
|
3426
|
-
'sharing.disable.restartAlert':'
|
|
3427
|
-
'sharing.switch.hubToClient':'你即将从服务端模式切换为客户端模式。\\n\\n切换后将会:\\n\\u2022 Hub
|
|
3428
|
-
'sharing.switch.clientToHub':'你即将从客户端模式切换为服务端模式。\\n\\n切换后将会:\\n\\u2022 你将断开与当前团队的连接\\n\\u2022
|
|
3486
|
+
'sharing.disable.restartAlert':'共享已关闭,服务将自动重启以应用更改。',
|
|
3487
|
+
'sharing.switch.hubToClient':'你即将从服务端模式切换为客户端模式。\\n\\n切换后将会:\\n\\u2022 Hub 服务将在服务重启后关闭\\n\\u2022 所有已连接的团队成员将断开连接\\n\\u2022 Hub 上的共享数据会保留,以后可恢复使用\\n\\u2022 你将作为客户端加入指定的远程团队\\n\\n确定要切换吗?',
|
|
3488
|
+
'sharing.switch.clientToHub':'你即将从客户端模式切换为服务端模式。\\n\\n切换后将会:\\n\\u2022 你将断开与当前团队的连接\\n\\u2022 服务重启后将启动新的 Hub 服务\\n\\u2022 你的本地数据不受影响\\n\\n确定要切换吗?',
|
|
3489
|
+
'sharing.switch.hubAddress':'你即将离开当前团队并加入新的团队。\\n\\n操作后将会:\\n\\u2022 你将断开与当前团队服务器的连接\\n\\u2022 当前团队管理员会收到你离开的通知\\n\\u2022 你将作为新成员加入新的团队服务器\\n\\u2022 你的本地数据不受影响\\n\\n确定要切换吗?',
|
|
3429
3490
|
'admin.notEnabled.title':'团队共享尚未开启',
|
|
3430
3491
|
'admin.notEnabled.desc':'管理面板用于管理团队成员、共享的记忆、任务和技能。使用此功能前,需要先开启团队共享。',
|
|
3431
3492
|
'admin.notEnabled.setupHub':'配置为团队服务端',
|
|
@@ -3443,12 +3504,12 @@ const I18N={
|
|
|
3443
3504
|
'guide.join.s1':'向团队管理员索取服务器地址和团队令牌',
|
|
3444
3505
|
'guide.join.s2':'前往「设置 → 团队共享」,开启共享,选择「客户端」模式',
|
|
3445
3506
|
'guide.join.s3':'填写服务器地址和团队令牌,点击「测试连接」',
|
|
3446
|
-
'guide.join.s4':'
|
|
3507
|
+
'guide.join.s4':'点击「保存并应用」,服务将自动重启(页面会自动刷新)',
|
|
3447
3508
|
'guide.join.btn':'\u2192 配置客户端模式',
|
|
3448
3509
|
'guide.hub.title':'自建团队服务',
|
|
3449
3510
|
'guide.hub.desc':'将本机作为团队服务端,让其他成员连接过来共享记忆。',
|
|
3450
3511
|
'guide.hub.s1':'前往「设置 → 团队共享」,开启共享,选择「服务端」模式',
|
|
3451
|
-
'guide.hub.s2':'
|
|
3512
|
+
'guide.hub.s2':'设置团队名称,点击「保存并应用」,服务将自动重启',
|
|
3452
3513
|
'guide.hub.s3':'将服务器地址和团队令牌分享给团队成员',
|
|
3453
3514
|
'guide.hub.s4':'在管理面板中审批加入请求',
|
|
3454
3515
|
'guide.hub.btn':'\u2192 配置服务端模式'
|
|
@@ -3554,12 +3615,28 @@ async function doReset(){
|
|
|
3554
3615
|
}
|
|
3555
3616
|
|
|
3556
3617
|
var _sharingRole='client';
|
|
3618
|
+
var _loadedClientHubAddress='';
|
|
3557
3619
|
function _genToken(len){
|
|
3558
3620
|
var a=new Uint8Array(len||18);crypto.getRandomValues(a);
|
|
3559
3621
|
return btoa(String.fromCharCode.apply(null,a)).replace(/\\+/g,'-').replace(/\\//g,'_').replace(/=+$/,'');
|
|
3560
3622
|
}
|
|
3561
|
-
function onSharingToggle(){
|
|
3562
|
-
var
|
|
3623
|
+
async function onSharingToggle(){
|
|
3624
|
+
var chk=document.getElementById('cfgSharingEnabled');
|
|
3625
|
+
var on=chk.checked;
|
|
3626
|
+
if(!on && sharingStatusCache && sharingStatusCache.enabled){
|
|
3627
|
+
var prevRole=sharingStatusCache.role;
|
|
3628
|
+
var confirmMsg=prevRole==='hub'?t('sharing.disable.confirm.hub'):t('sharing.disable.confirm.client');
|
|
3629
|
+
if(!(await confirmModal(confirmMsg,{danger:true}))){
|
|
3630
|
+
chk.checked=true;
|
|
3631
|
+
return;
|
|
3632
|
+
}
|
|
3633
|
+
var cfg={sharing:{enabled:false,role:prevRole}};
|
|
3634
|
+
chk.disabled=true;
|
|
3635
|
+
var result=await doSaveConfig(cfg, null, 'hubSaved');
|
|
3636
|
+
chk.disabled=false;
|
|
3637
|
+
if(!result){chk.checked=true;return;}
|
|
3638
|
+
return;
|
|
3639
|
+
}
|
|
3563
3640
|
document.getElementById('sharingConfigPanel').style.display=on?'block':'none';
|
|
3564
3641
|
var pw=document.getElementById('sharingPanelsWrap');
|
|
3565
3642
|
if(pw) pw.style.display=on?'':'none';
|
|
@@ -3577,20 +3654,25 @@ function selectSharingRole(role){
|
|
|
3577
3654
|
var tp=document.getElementById('sharingTeamPanel');
|
|
3578
3655
|
var ap=document.getElementById('sharingAdminPanel');
|
|
3579
3656
|
if(role==='client'){
|
|
3580
|
-
if(sp) sp.style.display='none';
|
|
3657
|
+
if(sp) { sp.style.display='none'; sp.innerHTML=''; }
|
|
3581
3658
|
if(tp) tp.style.display='none';
|
|
3582
3659
|
if(ap) ap.style.display='none';
|
|
3583
3660
|
}else{
|
|
3584
|
-
if(sp) sp.style.display='';
|
|
3661
|
+
if(sp) { sp.style.display='none'; sp.innerHTML=''; }
|
|
3585
3662
|
if(tp) tp.style.display='';
|
|
3586
3663
|
if(ap) ap.style.display='';
|
|
3587
3664
|
}
|
|
3665
|
+
_lastSettingsFingerprint='';
|
|
3666
|
+
setTimeout(function(){ loadSharingStatus(true); },200);
|
|
3588
3667
|
if(role==='hub'){
|
|
3589
3668
|
var tk=document.getElementById('cfgHubTeamToken');
|
|
3590
3669
|
if(!tk.value.trim()) tk.value=_genToken(18);
|
|
3591
3670
|
var tn=document.getElementById('cfgHubTeamName');
|
|
3592
3671
|
if(!tn.value.trim()) tn.value='My Team';
|
|
3593
3672
|
}
|
|
3673
|
+
var card=document.getElementById('settingsSharingConfig');
|
|
3674
|
+
var saveBtn=card&&card.querySelector('.settings-actions .btn-primary');
|
|
3675
|
+
if(saveBtn&&typeof _hubSaveBtnLabel==='function') saveBtn.textContent=_hubSaveBtnLabel();
|
|
3594
3676
|
}
|
|
3595
3677
|
var _cachedLocalIP='';
|
|
3596
3678
|
function updateHubShareInfo(){
|
|
@@ -3625,13 +3707,6 @@ async function testHubConnection(){
|
|
|
3625
3707
|
if(!addr){result.innerHTML='<span style="color:var(--rose)">\u274C '+t('settings.hub.test.noAddr')+'</span>';return;}
|
|
3626
3708
|
btn.disabled=true;result.innerHTML=t('settings.hub.test.testing');
|
|
3627
3709
|
try{
|
|
3628
|
-
var ipsData=await fetch('/api/local-ips').then(function(r){return r.json();});
|
|
3629
|
-
var localAddrs=['127.0.0.1','localhost','0.0.0.0'].concat(ipsData.ips||[]);
|
|
3630
|
-
var parsed=new URL(addr.indexOf('://')>-1?addr:'http://'+addr);
|
|
3631
|
-
if(localAddrs.indexOf(parsed.hostname)>=0){
|
|
3632
|
-
result.innerHTML='<span style="color:var(--rose)">\u274C '+t('sharing.cannotJoinSelf')+'</span>';
|
|
3633
|
-
btn.disabled=false;return;
|
|
3634
|
-
}
|
|
3635
3710
|
}catch(e){}
|
|
3636
3711
|
try{
|
|
3637
3712
|
var url=addr.match(/^https?:\\/\\//)?addr:'http://'+addr;
|
|
@@ -3681,13 +3756,20 @@ function switchView(view){
|
|
|
3681
3756
|
else if(view==='skills') loadSkills();
|
|
3682
3757
|
else if(view==='analytics') loadMetrics();
|
|
3683
3758
|
else if(view==='logs') loadLogs();
|
|
3684
|
-
else if(view==='settings'){loadConfig()
|
|
3759
|
+
else if(view==='settings'){loadConfig().then(function(){
|
|
3760
|
+
var sharingOn=document.getElementById('cfgSharingEnabled');
|
|
3761
|
+
var sharingNotEnabled=!sharingOn||!sharingOn.checked;
|
|
3762
|
+
if(sharingNotEnabled){
|
|
3763
|
+
switchSettingsTab('hub',document.querySelector('.settings-tab-btn[data-tab="hub"]'));
|
|
3764
|
+
}
|
|
3765
|
+
});loadModelHealth();}
|
|
3685
3766
|
else if(view==='import'){if(!window._migrateRunning) migrateScan(false);}
|
|
3686
|
-
else if(view==='admin'){loadAdminData();}
|
|
3767
|
+
else if(view==='admin'){_lastAdminFingerprint='';loadAdminData();}
|
|
3687
3768
|
}
|
|
3688
3769
|
|
|
3689
3770
|
function onMemoryScopeChange(){
|
|
3690
3771
|
memorySearchScope=document.getElementById('memorySearchScope')?.value||'local';
|
|
3772
|
+
try{localStorage.setItem('memos_memorySearchScope',memorySearchScope);}catch(e){}
|
|
3691
3773
|
currentPage=1;
|
|
3692
3774
|
activeSession=null;activeRole='';
|
|
3693
3775
|
_lastMemoriesFingerprint='';
|
|
@@ -3696,7 +3778,7 @@ function onMemoryScopeChange(){
|
|
|
3696
3778
|
var ownerSel=document.getElementById('filterOwner');
|
|
3697
3779
|
var filterBar=document.getElementById('filterBar');
|
|
3698
3780
|
var dateFilter=document.querySelector('.date-filter');
|
|
3699
|
-
if(ownerSel)
|
|
3781
|
+
if(ownerSel){ownerSel.style.display=(isHub||isLocal)?'none':'';if(isHub||isLocal)ownerSel.value='';}
|
|
3700
3782
|
if(filterBar) filterBar.style.display=isHub?'none':'';
|
|
3701
3783
|
if(dateFilter) dateFilter.style.display=isHub?'none':'';
|
|
3702
3784
|
if(document.getElementById('searchInput').value.trim()) doSearch(document.getElementById('searchInput').value);
|
|
@@ -3721,6 +3803,13 @@ function onTaskScopeChange(){
|
|
|
3721
3803
|
|
|
3722
3804
|
var _clientPendingPollTimer=null;
|
|
3723
3805
|
var _lastSharingConnStatus='';
|
|
3806
|
+
function _updateScopeSelectorsVisibility(hubAvailable){
|
|
3807
|
+
var ids=['memorySearchScope','taskSearchScope','skillSearchScope'];
|
|
3808
|
+
for(var i=0;i<ids.length;i++){
|
|
3809
|
+
var el=document.getElementById(ids[i]);
|
|
3810
|
+
if(el) el.style.display=hubAvailable?'':'none';
|
|
3811
|
+
}
|
|
3812
|
+
}
|
|
3724
3813
|
async function loadSharingStatus(forcePending){
|
|
3725
3814
|
try{
|
|
3726
3815
|
const r=await fetch('/api/sharing/status');
|
|
@@ -3733,19 +3822,36 @@ async function loadSharingStatus(forcePending){
|
|
|
3733
3822
|
if(!d||!d.enabled){
|
|
3734
3823
|
if(_clientPendingPollTimer){clearInterval(_clientPendingPollTimer);_clientPendingPollTimer=null;}
|
|
3735
3824
|
_lastSharingConnStatus='';
|
|
3825
|
+
_updateScopeSelectorsVisibility(false);
|
|
3736
3826
|
return;
|
|
3737
3827
|
}
|
|
3738
3828
|
var conn=d.connection||{};
|
|
3739
3829
|
var curStatus=conn.rejected?'rejected':conn.pendingApproval?'pending':conn.connected?'connected':'none';
|
|
3740
|
-
|
|
3830
|
+
var hubActive=d.role==='hub'||curStatus==='connected';
|
|
3831
|
+
_updateScopeSelectorsVisibility(hubActive);
|
|
3832
|
+
if(_lastSharingConnStatus==='pending'&&curStatus==='rejected'&&d.role==='client'){
|
|
3741
3833
|
toast(t('sharing.rejected.toast'),'error');
|
|
3742
3834
|
}
|
|
3743
|
-
if(_lastSharingConnStatus==='pending'&&curStatus==='connected'){
|
|
3835
|
+
if(_lastSharingConnStatus==='pending'&&curStatus==='connected'&&d.role==='client'){
|
|
3744
3836
|
toast(t('sharing.approved.toast'),'success');
|
|
3837
|
+
loadMemories();loadTasks();loadSkills();
|
|
3838
|
+
if(_notifSSE){_notifSSE.close();_notifSSE=null;_notifSSEConnected=false;}
|
|
3839
|
+
connectNotifSSE();
|
|
3840
|
+
loadNotifications();
|
|
3841
|
+
}
|
|
3842
|
+
if(_lastSharingConnStatus==='connected'&&curStatus==='none'&&d.role==='client'){
|
|
3843
|
+
toast(t('sharing.hubOffline.toast'),'error');
|
|
3844
|
+
}
|
|
3845
|
+
if(_lastSharingConnStatus==='none'&&curStatus==='connected'&&d.role==='client'){
|
|
3846
|
+
toast(t('sharing.hubReconnected.toast'),'success');
|
|
3847
|
+
loadMemories();loadTasks();loadSkills();
|
|
3848
|
+
if(_notifSSE){_notifSSE.close();_notifSSE=null;_notifSSEConnected=false;}
|
|
3849
|
+
connectNotifSSE();
|
|
3850
|
+
loadNotifications();
|
|
3745
3851
|
}
|
|
3746
3852
|
_lastSharingConnStatus=curStatus;
|
|
3747
3853
|
if(curStatus==='pending'&&!_clientPendingPollTimer){
|
|
3748
|
-
_clientPendingPollTimer=setInterval(function(){loadSharingStatus(false);},
|
|
3854
|
+
_clientPendingPollTimer=setInterval(function(){loadSharingStatus(false);},5000);
|
|
3749
3855
|
}
|
|
3750
3856
|
if(curStatus!=='pending'&&_clientPendingPollTimer){
|
|
3751
3857
|
clearInterval(_clientPendingPollTimer);
|
|
@@ -3755,6 +3861,7 @@ async function loadSharingStatus(forcePending){
|
|
|
3755
3861
|
renderSharingSidebar(null);
|
|
3756
3862
|
renderSharingSettings(null);
|
|
3757
3863
|
updateTeamGuide(null);
|
|
3864
|
+
_updateScopeSelectorsVisibility(false);
|
|
3758
3865
|
}
|
|
3759
3866
|
}
|
|
3760
3867
|
|
|
@@ -3766,7 +3873,8 @@ function renderSharingSidebar(data){
|
|
|
3766
3873
|
var badgeEl=document.getElementById('sharingSidebarConnBadge');
|
|
3767
3874
|
if(!statusEl||!hintEl) return;
|
|
3768
3875
|
var conn=data&&data.connection||{};
|
|
3769
|
-
var
|
|
3876
|
+
var hs=data&&data.hubStats||{};
|
|
3877
|
+
var fp=JSON.stringify({e:!!data&&!!data.enabled,r:data&&data.role,pa:!!conn.pendingApproval,rj:!!conn.rejected,c:!!conn.connected,u:conn.user&&conn.user.username,tn:conn.teamName,cc:!!data&&!!data.clientConfigured,hu:data&&data.hubUrl,tm:hs.totalMembers,om:hs.onlineMembers,pm:hs.pendingMembers});
|
|
3770
3878
|
if(fp===_lastSidebarFingerprint) return;
|
|
3771
3879
|
_lastSidebarFingerprint=fp;
|
|
3772
3880
|
if(!data||!data.enabled){
|
|
@@ -3781,8 +3889,16 @@ function renderSharingSidebar(data){
|
|
|
3781
3889
|
badgeEl.innerHTML='<span style="display:inline-flex;align-items:center;gap:4px;font-size:10px;font-weight:600;padding:2px 8px;border-radius:9999px;background:'+color+'15;color:'+color+'"><span style="display:inline-block;width:6px;height:6px;border-radius:50%;background:'+color+(glow?';box-shadow:0 0 4px '+color:'')+'"></span>'+esc(text)+'</span>';
|
|
3782
3890
|
}
|
|
3783
3891
|
if(data.role==='hub'){
|
|
3784
|
-
setBadge('#34d399',t('sharing.sidebar.
|
|
3785
|
-
|
|
3892
|
+
setBadge('#34d399',t('sharing.sidebar.hubRunning'),true);
|
|
3893
|
+
var hs=data.hubStats||{};
|
|
3894
|
+
var html='<div class="info-grid">';
|
|
3895
|
+
if(conn.teamName) html+='<span class="label">'+t('sharing.sidebar.teamName')+'</span><span class="value" style="font-weight:600">'+esc(conn.teamName)+'</span>';
|
|
3896
|
+
html+='<span class="label">'+t('sharing.sidebar.members')+'</span><span class="value">'+(hs.totalMembers||0)+' <span style="opacity:.5;font-size:10px">/ '+t('sharing.sidebar.online')+' '+(hs.onlineMembers||0)+'</span></span>';
|
|
3897
|
+
if(hs.pendingMembers>0){
|
|
3898
|
+
html+='<span class="label">'+t('sharing.sidebar.pending')+'</span><span class="value" style="color:var(--yellow,#fbbf24);font-weight:600">'+hs.pendingMembers+'</span>';
|
|
3899
|
+
}
|
|
3900
|
+
html+='</div>';
|
|
3901
|
+
statusEl.innerHTML=html;
|
|
3786
3902
|
hintEl.textContent='';
|
|
3787
3903
|
}else if(conn.pendingApproval&&conn.user){
|
|
3788
3904
|
setBadge('#fbbf24',t('sharing.sidebar.pending'),false);
|
|
@@ -3798,8 +3914,18 @@ function renderSharingSidebar(data){
|
|
|
3798
3914
|
html+='<span class="label">'+t('sharing.sidebar.identity')+'</span><span class="value">'+esc(conn.user.username||'-')+'</span>';
|
|
3799
3915
|
if(conn.teamName) html+='<span class="label">'+t('sharing.team')+'</span><span class="value">'+esc(conn.teamName)+'</span>';
|
|
3800
3916
|
html+='</div>';
|
|
3917
|
+
html+='<div style="margin-top:8px"><button class="btn btn-sm btn-primary" onclick="retryHubJoin()" style="font-size:11px">'+t('sharing.retryJoin')+'</button></div>';
|
|
3801
3918
|
statusEl.innerHTML=html;
|
|
3802
3919
|
hintEl.textContent=t('sharing.rejected.hint');
|
|
3920
|
+
}else if(conn.removed&&conn.user){
|
|
3921
|
+
setBadge('#ef4444',t('sharing.sidebar.disconnected'),false);
|
|
3922
|
+
var html='<div class="info-grid">';
|
|
3923
|
+
html+='<span class="label">'+t('sharing.sidebar.identity')+'</span><span class="value">'+esc(conn.user.username||'-')+'</span>';
|
|
3924
|
+
if(conn.teamName) html+='<span class="label">'+t('sharing.team')+'</span><span class="value">'+esc(conn.teamName)+'</span>';
|
|
3925
|
+
html+='</div>';
|
|
3926
|
+
html+='<div style="margin-top:8px"><button class="btn btn-sm btn-primary" onclick="retryHubJoin()" style="font-size:11px">'+t('sharing.retryJoin')+'</button></div>';
|
|
3927
|
+
statusEl.innerHTML=html;
|
|
3928
|
+
hintEl.textContent=t('sharing.removed.hint');
|
|
3803
3929
|
}else if(conn.connected&&conn.user){
|
|
3804
3930
|
var isAdmin=conn.user.role==='admin';
|
|
3805
3931
|
setBadge('#34d399',t('sharing.sidebar.connected'),true);
|
|
@@ -3834,16 +3960,29 @@ function renderSharingSettings(data){
|
|
|
3834
3960
|
if(!data||!data.enabled){
|
|
3835
3961
|
statusEl.innerHTML='';teamEl.innerHTML='';adminEl.innerHTML='';
|
|
3836
3962
|
if(panelsWrap) panelsWrap.style.display='none';
|
|
3963
|
+
var adminNavTab0=document.querySelector('.tab[data-view="admin"]');
|
|
3964
|
+
if(adminNavTab0) adminNavTab0.style.display='none';
|
|
3965
|
+
if(_activeView==='admin') switchView('memories');
|
|
3837
3966
|
return;
|
|
3838
3967
|
}
|
|
3839
3968
|
if(panelsWrap) panelsWrap.style.display='';
|
|
3840
3969
|
var conn=data.connection||{};
|
|
3841
3970
|
var user=conn.user||{};
|
|
3842
3971
|
var actualRole=data.role||_sharingRole||'client';
|
|
3843
|
-
|
|
3972
|
+
var prevIsAdmin=!!window._isHubAdmin;
|
|
3844
3973
|
var isAdmin=(data.admin&&data.admin.canManageUsers)||(conn.connected&&user.role==='admin')||(actualRole==='hub');
|
|
3845
3974
|
window._isHubAdmin=isAdmin;
|
|
3846
3975
|
if(isAdmin) startAdminPoll();
|
|
3976
|
+
var adminNavTab=document.querySelector('.tab[data-view="admin"]');
|
|
3977
|
+
if(adminNavTab){
|
|
3978
|
+
var showTab=(actualRole==='hub')||(conn.connected);
|
|
3979
|
+
adminNavTab.style.display=showTab?'':'none';
|
|
3980
|
+
if(!showTab&&_activeView==='admin') switchView('memories');
|
|
3981
|
+
}
|
|
3982
|
+
if(prevIsAdmin&&!isAdmin&&_activeView==='admin'){
|
|
3983
|
+
_lastAdminFingerprint='';
|
|
3984
|
+
loadAdminData();
|
|
3985
|
+
}
|
|
3847
3986
|
var hubAdminBtn=document.getElementById('hubAdminEntryBtn');
|
|
3848
3987
|
|
|
3849
3988
|
if(actualRole==='hub'){
|
|
@@ -3865,6 +4004,8 @@ function renderSharingSettings(data){
|
|
|
3865
4004
|
connBadge='<span class="hic-badge pending"><span class="hic-dot amber"></span>'+t('sharing.sidebar.pending')+'</span>';
|
|
3866
4005
|
}else if(conn.rejected){
|
|
3867
4006
|
connBadge='<span class="hic-badge disconnected"><span class="hic-dot red"></span>'+t('sharing.sidebar.rejected')+'</span>';
|
|
4007
|
+
}else if(conn.removed){
|
|
4008
|
+
connBadge='<span class="hic-badge disconnected"><span class="hic-dot red"></span>'+t('sharing.sidebar.disconnected')+'</span>';
|
|
3868
4009
|
}else if(conn.connected){
|
|
3869
4010
|
connBadge='<span class="hic-badge connected"><span class="hic-dot green"></span>'+t('sharing.sidebar.connected')+'</span>';
|
|
3870
4011
|
}else{
|
|
@@ -3880,13 +4021,21 @@ function renderSharingSettings(data){
|
|
|
3880
4021
|
sh+='</div><div class="hic-empty" style="color:#ef4444">'+t('sharing.rejected.hint')+'</div>'+
|
|
3881
4022
|
'<div style="margin-top:10px;padding:0 16px 14px"><button class="btn btn-sm btn-primary" onclick="retryHubJoin()">'+t('sharing.retryJoin')+'</button>'+
|
|
3882
4023
|
'<span style="font-size:11px;color:var(--text-muted);margin-left:8px">'+t('sharing.retryJoin.hint')+'</span></div></div>';
|
|
4024
|
+
}else if(conn.removed){
|
|
4025
|
+
if(user.username) sh+='<span class="hic-label">'+t('sharing.user')+'</span><span class="hic-value">'+esc(user.username)+'</span>';
|
|
4026
|
+
sh+='</div><div class="hic-empty" style="color:#ef4444">'+t('sharing.removed.hint')+'</div>'+
|
|
4027
|
+
'<div style="margin-top:10px;padding:0 16px 14px"><button class="btn btn-sm btn-primary" onclick="retryHubJoin()">'+t('sharing.retryJoin')+'</button>'+
|
|
4028
|
+
'<span style="font-size:11px;color:var(--text-muted);margin-left:8px">'+t('sharing.retryJoin.hint')+'</span></div></div>';
|
|
3883
4029
|
}else if(conn.connected&&user.username){
|
|
3884
4030
|
sh+='<span class="hic-label">'+t('sharing.user')+'</span><span class="hic-value" style="display:flex;align-items:center;gap:6px">'+
|
|
3885
4031
|
'<input type="text" id="hubUsernameInput" value="'+esc(user.username)+'" style="border:1px solid var(--border);border-radius:6px;padding:3px 8px;font-size:12px;background:var(--bg);color:var(--text);width:120px;font-family:inherit" />'+
|
|
3886
4032
|
'<button class="btn btn-sm" onclick="updateHubUsername()" style="padding:2px 10px;font-size:11px">'+t('sharing.saveUsername')+'</button>'+
|
|
3887
4033
|
'</span>';
|
|
3888
4034
|
sh+='<span class="hic-label">'+t('sharing.team')+'</span><span class="hic-value">'+esc(conn.teamName||'-')+'</span>';
|
|
3889
|
-
sh+='</div
|
|
4035
|
+
sh+='</div>'+
|
|
4036
|
+
'<div style="border-top:1px solid var(--border);margin-top:10px;padding:10px 16px 6px;display:flex;align-items:center;justify-content:flex-end">'+
|
|
4037
|
+
'<button class="btn btn-sm" onclick="leaveTeam()" style="color:#ef4444;border-color:rgba(239,68,68,.3);font-size:11px;padding:4px 12px">'+t('sharing.leaveTeam')+'</button>'+
|
|
4038
|
+
'</div></div>';
|
|
3890
4039
|
}else{
|
|
3891
4040
|
sh+='</div><div class="hic-empty" style="color:var(--text-muted)">'+t('sharing.disconnected.hint')+'</div>'+
|
|
3892
4041
|
'<div style="margin-top:10px;padding:0 16px 14px"><button class="btn btn-sm btn-primary" id="btnRetryConn" onclick="retryConnection()">'+t('sharing.retryConnection')+'</button>'+
|
|
@@ -3905,6 +4054,7 @@ async function retryConnection(){
|
|
|
3905
4054
|
var result=document.getElementById('retryConnResult');
|
|
3906
4055
|
if(btn){btn.disabled=true;btn.textContent=t('sharing.retryConnection.loading');}
|
|
3907
4056
|
if(result) result.innerHTML='<span style="color:var(--text-muted)">'+t('sharing.retryConnection.loading')+'</span>';
|
|
4057
|
+
toast(t('sharing.retryConnection.loading'),'info');
|
|
3908
4058
|
try{
|
|
3909
4059
|
await loadSharingStatus(false);
|
|
3910
4060
|
var d=sharingStatusCache;
|
|
@@ -3912,9 +4062,11 @@ async function retryConnection(){
|
|
|
3912
4062
|
toast(t('sharing.retryConnection.success'),'success');
|
|
3913
4063
|
if(result) result.innerHTML='<span style="color:#22c55e">\\u2705 '+t('sharing.retryConnection.success')+'</span>';
|
|
3914
4064
|
}else{
|
|
4065
|
+
toast(t('sharing.retryConnection.fail'),'error');
|
|
3915
4066
|
if(result) result.innerHTML='<span style="color:#ef4444">'+t('sharing.retryConnection.fail')+'</span>';
|
|
3916
4067
|
}
|
|
3917
4068
|
}catch(e){
|
|
4069
|
+
toast(t('sharing.retryConnection.fail'),'error');
|
|
3918
4070
|
if(result) result.innerHTML='<span style="color:#ef4444">'+t('sharing.retryConnection.fail')+'</span>';
|
|
3919
4071
|
}
|
|
3920
4072
|
if(btn){btn.disabled=false;btn.textContent=t('sharing.retryConnection');}
|
|
@@ -3927,19 +4079,36 @@ async function retryHubJoin(){
|
|
|
3927
4079
|
var d=await r.json();
|
|
3928
4080
|
if(d.ok){
|
|
3929
4081
|
toast(t('sharing.retryJoin.success'),'success');
|
|
3930
|
-
|
|
4082
|
+
_lastSidebarFingerprint='';_lastSettingsFingerprint='';_lastSharingConnStatus='';
|
|
4083
|
+
setTimeout(function(){loadSharingStatus(true);},800);
|
|
3931
4084
|
}else{
|
|
3932
4085
|
toast(d.error||t('sharing.retryJoin.fail'),'error');
|
|
3933
4086
|
}
|
|
3934
4087
|
}catch(e){toast(t('sharing.retryJoin.fail')+': '+e.message,'error');}
|
|
3935
4088
|
}
|
|
3936
4089
|
|
|
4090
|
+
async function leaveTeam(){
|
|
4091
|
+
var teamName=(sharingStatusCache&&sharingStatusCache.connection&&sharingStatusCache.connection.teamName)||'';
|
|
4092
|
+
var msg=t('sharing.leaveTeam.confirm').replace('{team}',teamName||t('sharing.team.default'));
|
|
4093
|
+
if(!(await confirmModal(msg,{danger:true}))) return;
|
|
4094
|
+
try{
|
|
4095
|
+
var r=await fetch('/api/sharing/leave',{method:'POST',headers:{'Content-Type':'application/json'},body:'{}'});
|
|
4096
|
+
var d=await r.json();
|
|
4097
|
+
if(d.ok){
|
|
4098
|
+
toast(t('sharing.leaveTeam.success'),'success');
|
|
4099
|
+
showRestartOverlay(t('settings.restart.waiting'));
|
|
4100
|
+
}else{
|
|
4101
|
+
toast(d.error||t('sharing.leaveTeam.fail'),'error');
|
|
4102
|
+
}
|
|
4103
|
+
}catch(e){toast(t('sharing.leaveTeam.fail')+': '+e.message,'error');}
|
|
4104
|
+
}
|
|
4105
|
+
|
|
3937
4106
|
async function updateHubUsername(){
|
|
3938
4107
|
var input=document.getElementById('hubUsernameInput');
|
|
3939
4108
|
if(!input) return;
|
|
3940
4109
|
var newName=input.value.trim();
|
|
3941
4110
|
if(!newName||newName.length<2||newName.length>32){
|
|
3942
|
-
|
|
4111
|
+
alertModal(t('sharing.username.invalid'));
|
|
3943
4112
|
return;
|
|
3944
4113
|
}
|
|
3945
4114
|
try{
|
|
@@ -3950,17 +4119,17 @@ async function updateHubUsername(){
|
|
|
3950
4119
|
});
|
|
3951
4120
|
var d=await r.json();
|
|
3952
4121
|
if(d.error==='username_taken'){
|
|
3953
|
-
|
|
4122
|
+
alertModal(t('sharing.username.taken'),{danger:true});
|
|
3954
4123
|
return;
|
|
3955
4124
|
}
|
|
3956
4125
|
if(d.error){
|
|
3957
|
-
|
|
4126
|
+
alertModal(d.error,{danger:true});
|
|
3958
4127
|
return;
|
|
3959
4128
|
}
|
|
3960
4129
|
toast(t('sharing.username.updated'),'success');
|
|
3961
4130
|
loadSharingStatus(false);
|
|
3962
4131
|
}catch(e){
|
|
3963
|
-
|
|
4132
|
+
alertModal(t('sharing.username.error'),{danger:true});
|
|
3964
4133
|
}
|
|
3965
4134
|
}
|
|
3966
4135
|
|
|
@@ -4006,7 +4175,7 @@ async function approveSharingUser(userId,username){
|
|
|
4006
4175
|
try{
|
|
4007
4176
|
const r=await fetch('/api/sharing/approve-user',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({userId:userId,username:username})});
|
|
4008
4177
|
const d=await r.json();
|
|
4009
|
-
if(d.ok){toast(t('toast.userApproved'),'success');loadSharingPendingUsers();loadSharingStatus(true);} else {toast(d.error||t('toast.approveFail'),'error');}
|
|
4178
|
+
if(d.ok){toast(t('toast.userApproved'),'success');loadSharingPendingUsers();loadSharingStatus(true);_lastAdminFingerprint='';loadAdminData();} else {toast(d.error||t('toast.approveFail'),'error');}
|
|
4010
4179
|
}catch(e){toast(t('toast.approveFail')+': '+e.message,'error');}
|
|
4011
4180
|
}
|
|
4012
4181
|
|
|
@@ -4014,23 +4183,15 @@ async function rejectSharingUser(userId,username){
|
|
|
4014
4183
|
try{
|
|
4015
4184
|
const r=await fetch('/api/sharing/reject-user',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({userId:userId,username:username})});
|
|
4016
4185
|
const d=await r.json();
|
|
4017
|
-
if(d.ok){toast(t('toast.userRejected'),'success');loadSharingPendingUsers();} else {toast(d.error||t('toast.rejectFail'),'error');}
|
|
4186
|
+
if(d.ok){toast(t('toast.userRejected'),'success');loadSharingPendingUsers();_lastAdminFingerprint='';loadAdminData();} else {toast(d.error||t('toast.rejectFail'),'error');}
|
|
4018
4187
|
}catch(e){toast(t('toast.rejectFail')+': '+e.message,'error');}
|
|
4019
4188
|
}
|
|
4020
4189
|
|
|
4021
4190
|
/* ─── Team Setup Guide ─── */
|
|
4022
|
-
var TEAM_GUIDE_DISMISSED_KEY='memos-team-guide-dismissed';
|
|
4023
4191
|
function updateTeamGuide(sharingData){
|
|
4024
4192
|
var el=document.getElementById('teamSetupGuide');
|
|
4025
4193
|
if(!el) return;
|
|
4026
|
-
|
|
4027
|
-
var isConfigured=sharingData&&sharingData.enabled;
|
|
4028
|
-
el.style.display=isConfigured?'none':'block';
|
|
4029
|
-
}
|
|
4030
|
-
function dismissTeamGuide(){
|
|
4031
|
-
localStorage.setItem(TEAM_GUIDE_DISMISSED_KEY,'1');
|
|
4032
|
-
var el=document.getElementById('teamSetupGuide');
|
|
4033
|
-
if(el) el.style.display='none';
|
|
4194
|
+
el.style.display='block';
|
|
4034
4195
|
}
|
|
4035
4196
|
function guideGoToHub(role){
|
|
4036
4197
|
switchSettingsTab('hub',document.querySelector('.settings-tab-btn[data-tab="hub"]'));
|
|
@@ -4063,7 +4224,7 @@ function adminPaginateHtml(total,page,refilterFn){
|
|
|
4063
4224
|
if(end<pages) html+=(end<pages-1?'<span class="pg-info">...</span>':'')+'<button class="pg-btn" onclick="'+refilterFn+'Page('+(pages-1)+')">'+pages+'</button>';
|
|
4064
4225
|
html+='<button class="pg-btn'+(page>=pages-1?' disabled':'')+'" onclick="'+refilterFn+'Page('+(page+1)+')">\\u2192</button>';
|
|
4065
4226
|
html+='<span class="pg-info">'+total+' '+t('pagination.total')+'</span>';
|
|
4066
|
-
|
|
4227
|
+
html+='</div>';
|
|
4067
4228
|
return html;
|
|
4068
4229
|
}
|
|
4069
4230
|
|
|
@@ -4125,12 +4286,12 @@ async function loadAdminData(){
|
|
|
4125
4286
|
var fetches;
|
|
4126
4287
|
if(isAdmin){
|
|
4127
4288
|
fetches=await Promise.all([
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4289
|
+
fetch('/api/sharing/users').then(function(r){return r.json();}),
|
|
4290
|
+
fetch('/api/admin/shared-tasks').then(function(r){return r.json();}),
|
|
4291
|
+
fetch('/api/admin/shared-skills').then(function(r){return r.json();}),
|
|
4292
|
+
fetch('/api/sharing/pending-users').then(function(r){return r.json();}),
|
|
4293
|
+
fetch('/api/admin/shared-memories').then(function(r){return r.json();})
|
|
4294
|
+
]);
|
|
4134
4295
|
}else{
|
|
4135
4296
|
fetches=await Promise.all([
|
|
4136
4297
|
Promise.resolve({users:[]}),
|
|
@@ -4147,7 +4308,7 @@ async function loadAdminData(){
|
|
|
4147
4308
|
var _newMemories=Array.isArray(memoriesR.memories)?memoriesR.memories:[];
|
|
4148
4309
|
var pending=isAdmin?(Array.isArray(pendingR.users)?pendingR.users:[]):[];
|
|
4149
4310
|
var _fp=_newUsers.length+':'+_newTasks.length+':'+_newSkills.length+':'+_newMemories.length+':'+pending.length
|
|
4150
|
-
+':'+_newUsers.map(function(u){return u.id+'|'+(u.isOnline?1:0)+'|'+(u.role||'')}).join(',')
|
|
4311
|
+
+':'+_newUsers.map(function(u){return u.id+'|'+(u.isOnline?1:0)+'|'+(u.role||'')+'|'+(u.status||'')+'|'+(u.username||'')+'|'+(u.memoryCount||0)+'|'+(u.taskCount||0)+'|'+(u.skillCount||0)}).join(',')
|
|
4151
4312
|
+':'+_newMemories.map(function(m){return m.id}).join(',')
|
|
4152
4313
|
+':'+_newTasks.map(function(t){return t.id+'|'+(t.status||'')}).join(',')
|
|
4153
4314
|
+':'+_newSkills.map(function(s){return s.id+'|'+(s.status||'')}).join(',')
|
|
@@ -4200,11 +4361,15 @@ function updateAdminTabsVisibility(){
|
|
|
4200
4361
|
if(subEl) subEl.textContent=isAdmin?t('admin.subtitle'):t('admin.subtitle.member');
|
|
4201
4362
|
}
|
|
4202
4363
|
|
|
4364
|
+
var _lastAdminStatsFp='';
|
|
4203
4365
|
function renderAdminStats(pendingCount){
|
|
4204
4366
|
var el=document.getElementById('adminStats');
|
|
4205
4367
|
if(!el) return;
|
|
4206
4368
|
var isAdmin=!!window._isHubAdmin;
|
|
4207
4369
|
var onlineCount=adminDataCache.users.filter(function(u){return !!u.isOnline;}).length;
|
|
4370
|
+
var sfp=onlineCount+':'+adminDataCache.users.length+':'+pendingCount+':'+(adminDataCache.memories||[]).length+':'+adminDataCache.tasks.length+':'+adminDataCache.skills.length+':'+isAdmin;
|
|
4371
|
+
if(sfp===_lastAdminStatsFp) return;
|
|
4372
|
+
_lastAdminStatsFp=sfp;
|
|
4208
4373
|
el.innerHTML=
|
|
4209
4374
|
(isAdmin?'<div class="admin-stat-box"><span class="as-icon">\u{1F465}</span><div class="val">'+onlineCount+' / '+adminDataCache.users.length+'</div><div class="lbl">'+t('admin.stat.activeUsers')+'</div></div>'+
|
|
4210
4375
|
'<div class="admin-stat-box"><span class="as-icon">\u{23F3}</span><div class="val">'+pendingCount+'</div><div class="lbl">'+t('admin.stat.pending')+'</div></div>':'')+
|
|
@@ -4226,9 +4391,10 @@ function auRelativeTime(ts){
|
|
|
4226
4391
|
return t('notif.timeAgo.day').replace('{n}',Math.floor(diff/86400000));
|
|
4227
4392
|
}
|
|
4228
4393
|
|
|
4229
|
-
function renderAdminUserCard(u,adminCount){
|
|
4394
|
+
function renderAdminUserCard(u,adminCount,myUserId){
|
|
4230
4395
|
var uid=escAttr(u.id);
|
|
4231
4396
|
var uname=escAttr(u.username||'');
|
|
4397
|
+
var isSelf=!!(myUserId&&u.id===myUserId);
|
|
4232
4398
|
var online=!!u.isOnline;
|
|
4233
4399
|
var statusCls=online?'online':'offline';
|
|
4234
4400
|
|
|
@@ -4262,7 +4428,9 @@ function renderAdminUserCard(u,adminCount){
|
|
|
4262
4428
|
var infoHtml='<div class="au-info">'+infoRows.join('')+'</div>';
|
|
4263
4429
|
|
|
4264
4430
|
var actions='';
|
|
4265
|
-
if(
|
|
4431
|
+
if(isSelf){
|
|
4432
|
+
actions+='<span style="font-size:11px;color:var(--text-muted);padding:4px 0">'+t('admin.selfHint')+'</span>';
|
|
4433
|
+
}else if(u.isOwner){
|
|
4266
4434
|
actions+='<span style="font-size:11px;color:var(--text-muted);padding:4px 0">'+t('admin.ownerHint')+'</span>';
|
|
4267
4435
|
}else if(u.role!=='admin'){
|
|
4268
4436
|
actions+='<button class="btn btn-sm btn-ghost" onclick="adminToggleRole("'+uid+'","admin")" style="color:var(--accent)">'+t('admin.promoteAdmin')+'</button>';
|
|
@@ -4273,12 +4441,13 @@ function renderAdminUserCard(u,adminCount){
|
|
|
4273
4441
|
}else{
|
|
4274
4442
|
actions+='<span style="font-size:11px;color:var(--text-muted);padding:4px 0">'+t('admin.lastAdminHint')+'</span>';
|
|
4275
4443
|
}
|
|
4276
|
-
var
|
|
4444
|
+
var badgesHtml='<div class="au-badges">'+statusLabel+
|
|
4445
|
+
'<span class="admin-badge '+(u.role==='admin'?'admin':'member')+'">'+esc(u.role||'member').toUpperCase()+'</span>'+
|
|
4446
|
+
(u.isOwner?'<span class="admin-badge owner">OWNER</span>':'')+
|
|
4447
|
+
'</div>';
|
|
4277
4448
|
|
|
4278
|
-
return '<div class="admin-card au-card au-'+statusCls+'"><div class="admin-card-header"><div style="flex:1;min-width:0
|
|
4279
|
-
|
|
4280
|
-
'</div>'+
|
|
4281
|
-
'<div style="display:flex;align-items:center;gap:6px"><span class="admin-badge '+(u.role==='admin'?'admin':'member')+'">'+esc(u.role||'member')+'</span>'+ownerBadge+'</div></div>'+
|
|
4449
|
+
return '<div class="admin-card au-card au-'+statusCls+'"><div class="admin-card-header"><div style="flex:1;min-width:0">'+titleDisplay+editRow+'</div>'+
|
|
4450
|
+
badgesHtml+'</div>'+
|
|
4282
4451
|
contribHtml+infoHtml+
|
|
4283
4452
|
(actions?'<div class="admin-card-actions" style="border-top:1px solid rgba(99,102,241,.08);padding-top:12px;margin-top:6px">'+actions+'</div>':'')+
|
|
4284
4453
|
'</div>';
|
|
@@ -4313,6 +4482,7 @@ function renderAdminUsers(users,pending){
|
|
|
4313
4482
|
offlineUsers.sort(function(a,b){return (b.lastActiveAt||0)-(a.lastActiveAt||0);});
|
|
4314
4483
|
var sorted=onlineUsers.concat(offlineUsers);
|
|
4315
4484
|
var adminCount=users.filter(function(x){return x.role==='admin';}).length;
|
|
4485
|
+
var myUserId=sharingStatusCache&&sharingStatusCache.connection&&sharingStatusCache.connection.user?sharingStatusCache.connection.user.id:null;
|
|
4316
4486
|
|
|
4317
4487
|
if(sorted.length===0){
|
|
4318
4488
|
html+='<div class="admin-empty"><span class="ae-icon">\u{1F465}</span>'+t('admin.noActiveUsers')+'</div>';
|
|
@@ -4321,13 +4491,13 @@ function renderAdminUsers(users,pending){
|
|
|
4321
4491
|
if(onlineUsers.length===0){
|
|
4322
4492
|
html+='<div style="font-size:12px;color:var(--text-muted);padding:8px 0 12px">\u2014</div>';
|
|
4323
4493
|
}else{
|
|
4324
|
-
for(var i=0;i<onlineUsers.length;i++) html+=renderAdminUserCard(onlineUsers[i],adminCount);
|
|
4494
|
+
for(var i=0;i<onlineUsers.length;i++) html+=renderAdminUserCard(onlineUsers[i],adminCount,myUserId);
|
|
4325
4495
|
}
|
|
4326
4496
|
html+='<div class="au-group-header"><span class="au-group-dot offline"></span>'+t('admin.offlineUsers')+' <span class="au-group-count">('+offlineUsers.length+')</span></div>';
|
|
4327
4497
|
if(offlineUsers.length===0){
|
|
4328
4498
|
html+='<div style="font-size:12px;color:var(--text-muted);padding:8px 0 12px">\u2014</div>';
|
|
4329
4499
|
}else{
|
|
4330
|
-
for(var j=0;j<offlineUsers.length;j++) html+=renderAdminUserCard(offlineUsers[j],adminCount);
|
|
4500
|
+
for(var j=0;j<offlineUsers.length;j++) html+=renderAdminUserCard(offlineUsers[j],adminCount,myUserId);
|
|
4331
4501
|
}
|
|
4332
4502
|
}
|
|
4333
4503
|
el.innerHTML=html;
|
|
@@ -4338,7 +4508,7 @@ async function adminApproveUser(userId,username){
|
|
|
4338
4508
|
try{
|
|
4339
4509
|
var r=await fetch('/api/sharing/approve-user',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({userId:userId,username:username})});
|
|
4340
4510
|
var d=await r.json();
|
|
4341
|
-
if(d.ok){toast(t('toast.userApproved'),'success');loadAdminData();}else{toast(d.error||t('toast.approveFail'),'error');}
|
|
4511
|
+
if(d.ok){toast(t('toast.userApproved'),'success');_lastAdminFingerprint='';loadAdminData();}else{toast(d.error||t('toast.approveFail'),'error');}
|
|
4342
4512
|
}catch(e){toast(t('toast.approveFail')+': '+e.message,'error');}
|
|
4343
4513
|
}
|
|
4344
4514
|
async function adminRejectUser(userId){
|
|
@@ -4346,7 +4516,7 @@ async function adminRejectUser(userId){
|
|
|
4346
4516
|
try{
|
|
4347
4517
|
var r=await fetch('/api/sharing/reject-user',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({userId:userId})});
|
|
4348
4518
|
var d=await r.json();
|
|
4349
|
-
if(d.ok){toast(t('toast.userRejected'),'success');loadAdminData();}else{toast(d.error||t('toast.rejectFail'),'error');}
|
|
4519
|
+
if(d.ok){toast(t('toast.userRejected'),'success');_lastAdminFingerprint='';loadAdminData();}else{toast(d.error||t('toast.rejectFail'),'error');}
|
|
4350
4520
|
}catch(e){toast(t('toast.rejectFail')+': '+e.message,'error');}
|
|
4351
4521
|
}
|
|
4352
4522
|
async function adminToggleRole(userId,newRole){
|
|
@@ -4355,7 +4525,14 @@ async function adminToggleRole(userId,newRole){
|
|
|
4355
4525
|
try{
|
|
4356
4526
|
var r=await fetch('/api/sharing/change-role',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({userId:userId,role:newRole})});
|
|
4357
4527
|
var d=await r.json();
|
|
4358
|
-
if(d.ok){
|
|
4528
|
+
if(d.ok){
|
|
4529
|
+
toast(t('toast.roleChanged'),'success');
|
|
4530
|
+
_lastAdminFingerprint='';
|
|
4531
|
+
_lastSettingsFingerprint='';
|
|
4532
|
+
_lastSidebarFingerprint='';
|
|
4533
|
+
await loadSharingStatus(false);
|
|
4534
|
+
loadAdminData();
|
|
4535
|
+
}
|
|
4359
4536
|
else if(d.error==='cannot_demote_owner'){toast(t('admin.ownerHint'),'error');}
|
|
4360
4537
|
else{toast(d.error||t('toast.roleChangeFail'),'error');}
|
|
4361
4538
|
}catch(e){toast(t('toast.roleChangeFail')+': '+e.message,'error');}
|
|
@@ -4381,13 +4558,24 @@ async function adminSaveEditName(userId){
|
|
|
4381
4558
|
var inputEl=document.getElementById('au_input_'+userId);
|
|
4382
4559
|
if(!inputEl) return;
|
|
4383
4560
|
var newName=inputEl.value.trim();
|
|
4384
|
-
if(!newName||newName.length<2||newName.length>32){
|
|
4561
|
+
if(!newName||newName.length<2||newName.length>32){
|
|
4562
|
+
alertModal(t('toast.invalidUsername'),{title:t('admin.editName')});
|
|
4563
|
+
return;
|
|
4564
|
+
}
|
|
4385
4565
|
inputEl.disabled=true;
|
|
4386
4566
|
try{
|
|
4387
4567
|
var r=await fetch('/api/sharing/rename-user',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({userId:userId,username:newName})});
|
|
4388
4568
|
var d=await r.json();
|
|
4389
|
-
if(d.ok){toast(t('toast.usernameChanged'),'success');
|
|
4390
|
-
|
|
4569
|
+
if(d.ok){toast(t('toast.usernameChanged'),'success');adminCancelEditName(userId);loadAdminData();}
|
|
4570
|
+
else{
|
|
4571
|
+
inputEl.disabled=false;
|
|
4572
|
+
if(d.error==='username_taken'){
|
|
4573
|
+
alertModal(t('sharing.username.taken'),{title:t('admin.editName'),danger:true});
|
|
4574
|
+
}else{
|
|
4575
|
+
alertModal(d.error||t('toast.renameFail'),{title:t('admin.editName'),danger:true});
|
|
4576
|
+
}
|
|
4577
|
+
}
|
|
4578
|
+
}catch(e){inputEl.disabled=false;alertModal(t('toast.renameFail'),{title:t('admin.editName'),danger:true});}
|
|
4391
4579
|
}
|
|
4392
4580
|
|
|
4393
4581
|
async function adminRemoveUser(userId,username){
|
|
@@ -4396,7 +4584,7 @@ async function adminRemoveUser(userId,username){
|
|
|
4396
4584
|
try{
|
|
4397
4585
|
var r=await fetch('/api/sharing/remove-user',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({userId:userId,cleanResources:clean})});
|
|
4398
4586
|
var d=await r.json();
|
|
4399
|
-
if(d.ok){toast(t('toast.userRemoved'),'success');loadAdminData();}
|
|
4587
|
+
if(d.ok){toast(t('toast.userRemoved'),'success');_lastAdminFingerprint='';loadAdminData();}
|
|
4400
4588
|
else if(d.error==='cannot_remove_owner'){toast(t('admin.ownerHint'),'error');}
|
|
4401
4589
|
else{toast(d.error||t('toast.removeFail'),'error');}
|
|
4402
4590
|
}catch(e){toast(t('toast.removeFail')+': '+e.message,'error');}
|
|
@@ -4465,7 +4653,7 @@ function renderAdminTasks(tasks){
|
|
|
4465
4653
|
'<div class="admin-card-header"><div class="admin-card-title">'+esc(tk.title||tk.id)+'</div></div>'+
|
|
4466
4654
|
'<div class="admin-card-tags">'+
|
|
4467
4655
|
'<div class="admin-card-tags-left">'+
|
|
4468
|
-
'<span class="admin-card-tag tag-owner">\u{1F464} '+
|
|
4656
|
+
'<span class="admin-card-tag tag-owner">\u{1F464} '+fmtOwner(tk)+'</span>'+
|
|
4469
4657
|
(tk.status?'<span class="admin-card-tag tag-status">'+esc(tk.status)+'</span>':'')+
|
|
4470
4658
|
(tk.chunkCount!=null?'<span class="admin-card-tag tag-kind">\u{1F4DD} '+tk.chunkCount+' '+t('admin.chunks')+'</span>':'')+
|
|
4471
4659
|
'</div>'+
|
|
@@ -4527,7 +4715,7 @@ function renderAdminSkills(skills){
|
|
|
4527
4715
|
'<div class="admin-card-header"><div class="admin-card-title">'+esc(s.name||s.id)+'</div></div>'+
|
|
4528
4716
|
'<div class="admin-card-tags">'+
|
|
4529
4717
|
'<div class="admin-card-tags-left">'+
|
|
4530
|
-
'<span class="admin-card-tag tag-owner">\u{1F464} '+
|
|
4718
|
+
'<span class="admin-card-tag tag-owner">\u{1F464} '+fmtOwner(s)+'</span>'+
|
|
4531
4719
|
(s.status?'<span class="admin-card-tag tag-status">'+esc(s.status)+'</span>':'')+
|
|
4532
4720
|
(s.version!=null?'<span class="admin-card-tag tag-version">v'+s.version+'</span>':'')+
|
|
4533
4721
|
(qs!=null?'<span class="admin-card-tag tag-kind">\u2605 '+Number(qs).toFixed(1)+'</span>':'')+
|
|
@@ -4592,7 +4780,7 @@ function renderAdminMemories(memories){
|
|
|
4592
4780
|
'<div class="admin-card-header"><div class="admin-card-title">'+esc(m.summary||m.content?.slice(0,80)||m.id)+'</div></div>'+
|
|
4593
4781
|
'<div class="admin-card-tags">'+
|
|
4594
4782
|
'<div class="admin-card-tags-left">'+
|
|
4595
|
-
'<span class="admin-card-tag tag-owner">\u{1F464} '+
|
|
4783
|
+
'<span class="admin-card-tag tag-owner">\u{1F464} '+fmtOwner(m)+'</span>'+
|
|
4596
4784
|
(m.role?'<span class="admin-card-tag tag-role">'+esc(m.role)+'</span>':'')+
|
|
4597
4785
|
(m.kind?'<span class="admin-card-tag tag-kind">'+esc(m.kind)+'</span>':'')+
|
|
4598
4786
|
'</div>'+
|
|
@@ -4636,7 +4824,7 @@ function toggleAdminMemoryCard(cardId,idx){
|
|
|
4636
4824
|
(m.kind?'<span class="meta-item">'+t('admin.kind')+esc(m.kind)+'</span>':'')+
|
|
4637
4825
|
(m.role?'<span class="meta-item">'+t('admin.role')+esc(m.role)+'</span>':'')+
|
|
4638
4826
|
(m.visibility?'<span class="meta-item">'+t('admin.visibility')+esc(m.visibility)+'</span>':'')+
|
|
4639
|
-
'<span class="meta-item">'+t('admin.owner')+
|
|
4827
|
+
'<span class="meta-item">'+t('admin.owner')+fmtOwner(m)+'</span>'+
|
|
4640
4828
|
(m.groupName?'<span class="meta-item">'+t('admin.group')+esc(m.groupName)+'</span>':'')+
|
|
4641
4829
|
'<span class="meta-item">'+new Date(m.updatedAt||m.createdAt||0).toLocaleString(dateLoc())+'</span>'+
|
|
4642
4830
|
'</div>';
|
|
@@ -4692,7 +4880,7 @@ async function toggleAdminTaskCard(cardId,idx){
|
|
|
4692
4880
|
var metaHtml='<div class="admin-card-detail-meta admin-task-meta">'+
|
|
4693
4881
|
(tk.status?'<span class="meta-item"><span class="task-status-badge '+tk.status+'">'+esc(tk.status)+'</span></span>':'')+
|
|
4694
4882
|
(tk.visibility?'<span class="meta-item">'+t('admin.visibility')+esc(tk.visibility)+'</span>':'')+
|
|
4695
|
-
'<span class="meta-item">'+t('admin.owner')+
|
|
4883
|
+
'<span class="meta-item">'+t('admin.owner')+fmtOwner(tk)+'</span>'+
|
|
4696
4884
|
(tk.groupName?'<span class="meta-item">'+t('admin.group')+esc(tk.groupName)+'</span>':'')+
|
|
4697
4885
|
(task.chunks&&task.chunks.length?'<span class="meta-item">\u{1F4AC} '+task.chunks.length+' '+t('tasks.chunks.label')+'</span>':'')+
|
|
4698
4886
|
(task.startedAt?'<span class="meta-item">\u{1F4C5} '+formatDateTimeSeconds(task.startedAt)+'</span>':'')+
|
|
@@ -4779,7 +4967,7 @@ async function toggleAdminSkillCard(cardId,idx){
|
|
|
4779
4967
|
(localSkill.status?'<span class="meta-item"><span class="skill-badge status-'+localSkill.status+'">'+esc(localSkill.status)+'</span></span>':'')+
|
|
4780
4968
|
(sk.visibility?'<span class="meta-item">'+t('admin.visibility')+esc(sk.visibility||'hub')+'</span>':'')+
|
|
4781
4969
|
(qs!=null?'<span class="meta-item"><span class="skill-badge quality '+(qs>=7?'high':qs>=5?'mid':'low')+'">\u2605 '+Number(qs).toFixed(1)+'/10</span></span>':'')+
|
|
4782
|
-
'<span class="meta-item">'+t('admin.owner')+
|
|
4970
|
+
'<span class="meta-item">'+t('admin.owner')+fmtOwner(sk)+'</span>'+
|
|
4783
4971
|
(sk.groupName?'<span class="meta-item">'+t('admin.group')+esc(sk.groupName)+'</span>':'')+
|
|
4784
4972
|
'<span class="meta-item">'+t('admin.updated')+new Date(sk.updatedAt||sk.createdAt||0).toLocaleString(dateLoc())+'</span>'+
|
|
4785
4973
|
'</div>';
|
|
@@ -4848,7 +5036,7 @@ function renderSharingMemorySearchResults(data,query){
|
|
|
4848
5036
|
'<div class="summary">'+(idx+1)+'. '+esc(hit.summary||'(no summary)')+'</div>'+
|
|
4849
5037
|
'<div class="excerpt">'+esc(hit.excerpt||'')+'</div>'+
|
|
4850
5038
|
'<div class="hub-hit-meta">'+
|
|
4851
|
-
'<span class="meta-chip">owner: '+
|
|
5039
|
+
'<span class="meta-chip">owner: '+fmtOwner(hit)+'</span>'+
|
|
4852
5040
|
(hit.groupName?'<span class="meta-chip">group: '+esc(hit.groupName)+'</span>':'')+
|
|
4853
5041
|
'<span class="meta-chip">visibility: '+esc(hit.visibility||'hub')+'</span>'+
|
|
4854
5042
|
'</div>'+
|
|
@@ -4933,7 +5121,7 @@ function openHubTaskDetailFromCache(cacheKey,idx){
|
|
|
4933
5121
|
var meta=[
|
|
4934
5122
|
'<span class="meta-item">\\u{1F310} '+t('scope.hub')+'</span>',
|
|
4935
5123
|
task.status?'<span class="meta-item"><span class="task-status-badge '+task.status+'">'+esc(task.status)+'</span></span>':'',
|
|
4936
|
-
'<span class="meta-item">'+t('admin.owner')+
|
|
5124
|
+
'<span class="meta-item">'+t('admin.owner')+fmtOwner(task)+'</span>',
|
|
4937
5125
|
task.groupName?'<span class="meta-item">'+t('admin.group')+esc(task.groupName)+'</span>':'',
|
|
4938
5126
|
task.visibility?'<span class="meta-item">'+t('admin.visibility')+esc(task.visibility)+'</span>':'',
|
|
4939
5127
|
task.chunkCount!=null?'<span class="meta-item">\\u{1F4DD} '+esc(String(task.chunkCount))+' '+t('tasks.chunks.label')+'</span>':'',
|
|
@@ -4964,14 +5152,14 @@ function openHubSkillDetailFromCache(cacheKey,idx){
|
|
|
4964
5152
|
skill.status?'<span class="meta-item"><span class="skill-badge status-'+skill.status+'">'+esc(skill.status)+'</span></span>':'',
|
|
4965
5153
|
'<span class="meta-item">visibility: '+esc(skill.visibility||'hub')+'</span>',
|
|
4966
5154
|
qsBadge,
|
|
4967
|
-
'<span class="meta-item">'+t('admin.owner')+
|
|
5155
|
+
'<span class="meta-item">'+t('admin.owner')+fmtOwner(skill)+'</span>',
|
|
4968
5156
|
skill.groupName?'<span class="meta-item">'+t('admin.group')+esc(skill.groupName)+'</span>':'',
|
|
4969
5157
|
(skill.updatedAt||skill.createdAt)?'<span class="meta-item">'+t('admin.updated')+new Date(skill.updatedAt||skill.createdAt).toLocaleString(dateLoc())+'</span>':'',
|
|
4970
5158
|
].filter(Boolean);
|
|
4971
5159
|
document.getElementById('skillDetailMeta').innerHTML=meta.join('');
|
|
4972
5160
|
document.getElementById('skillDetailDesc').textContent=skill.description||'';
|
|
4973
5161
|
document.getElementById('skillFilesList').innerHTML='';
|
|
4974
|
-
document.getElementById('skillDetailContent').innerHTML=skill.content?
|
|
5162
|
+
document.getElementById('skillDetailContent').innerHTML=skill.content?renderSkillMarkdown(skill.content):'';
|
|
4975
5163
|
document.getElementById('skillVersionsList').innerHTML='';
|
|
4976
5164
|
document.getElementById('skillRelatedTasks').innerHTML='';
|
|
4977
5165
|
var visBtn=document.getElementById('skillVisibilityBtn');
|
|
@@ -5014,6 +5202,7 @@ function openScopeSelectorModal(resourceType, resourceId, currentScope, onConfir
|
|
|
5014
5202
|
var existing=document.getElementById('scopeSelectorOverlay');
|
|
5015
5203
|
if(existing) existing.remove();
|
|
5016
5204
|
var teamEnabled=sharingStatusCache&&sharingStatusCache.enabled;
|
|
5205
|
+
var teamConnected=teamEnabled&&sharingStatusCache.connection&&sharingStatusCache.connection.connected;
|
|
5017
5206
|
var overlay=document.createElement('div');
|
|
5018
5207
|
overlay.id='scopeSelectorOverlay';
|
|
5019
5208
|
overlay.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);backdrop-filter:blur(6px);z-index:10000;display:flex;align-items:center;justify-content:center;animation:fadeIn 0.12s ease';
|
|
@@ -5027,7 +5216,7 @@ function openScopeSelectorModal(resourceType, resourceId, currentScope, onConfir
|
|
|
5027
5216
|
for(var i=0;i<scopes.length;i++){
|
|
5028
5217
|
var sc=scopes[i];
|
|
5029
5218
|
var isCurrent=sc===currentScope;
|
|
5030
|
-
var isDisabled=sc==='team'
|
|
5219
|
+
var isDisabled=sc==='team'&&(!teamEnabled||!teamConnected);
|
|
5031
5220
|
var color=getScopeColor(sc);
|
|
5032
5221
|
var cursor=isDisabled?'not-allowed':'pointer';
|
|
5033
5222
|
var opacity=isDisabled?'0.4':'1';
|
|
@@ -5096,7 +5285,8 @@ async function confirmScopeSelection(){
|
|
|
5096
5285
|
if(st.onConfirm) st.onConfirm(newScope);
|
|
5097
5286
|
else loadAll();
|
|
5098
5287
|
}else{
|
|
5099
|
-
|
|
5288
|
+
var errMsg=d.error==='inactive_memory'?t('share.scope.inactiveDisabled'):(d.message||d.error||t('share.scope.changeFail'));
|
|
5289
|
+
toast(errMsg,'error');
|
|
5100
5290
|
}
|
|
5101
5291
|
}catch(e){toast(t('share.scope.changeFail')+': '+e.message,'error');}
|
|
5102
5292
|
}
|
|
@@ -5347,6 +5537,13 @@ function parseMemoryAddEntries(out){
|
|
|
5347
5537
|
return results;
|
|
5348
5538
|
}
|
|
5349
5539
|
|
|
5540
|
+
function recallOriginBadge(origin){
|
|
5541
|
+
if(origin==='local-shared') return '<span class="recall-origin local-shared">'+t('recall.origin.localShared')+'</span>';
|
|
5542
|
+
if(origin==='hub-memory') return '<span class="recall-origin hub-memory">'+t('recall.origin.hubMemory')+'</span>';
|
|
5543
|
+
if(origin==='hub-remote') return '<span class="recall-origin hub-remote">'+t('recall.origin.hubRemote')+'</span>';
|
|
5544
|
+
return '';
|
|
5545
|
+
}
|
|
5546
|
+
|
|
5350
5547
|
function buildLogSummary(lg){
|
|
5351
5548
|
let inputObj=null;
|
|
5352
5549
|
try{inputObj=JSON.parse(lg.input);}catch(_){}
|
|
@@ -5371,8 +5568,9 @@ function buildLogSummary(lg){
|
|
|
5371
5568
|
var scoreClass=c.score>=0.7?'high':c.score>=0.5?'mid':'low';
|
|
5372
5569
|
var shortText=escapeHtml(c.summary||c.content||c.original_excerpt||'');
|
|
5373
5570
|
var fullText=escapeHtml(c.content||c.original_excerpt||c.summary||'');
|
|
5571
|
+
var oBadge=recallOriginBadge(c.origin);
|
|
5374
5572
|
html+='<div class="recall-item" onclick="event.stopPropagation();this.classList.toggle(\\\'expanded\\\')">';
|
|
5375
|
-
html+='<div class="recall-item-head"><span class="recall-score '+scoreClass+'">'+c.score.toFixed(2)+'</span><span class="log-msg-role '+(c.role||'user')+'">'+(c.role||'user')+'</span
|
|
5573
|
+
html+='<div class="recall-item-head"><span class="recall-score '+scoreClass+'">'+c.score.toFixed(2)+'</span><span class="log-msg-role '+(c.role||'user')+'">'+(c.role||'user')+'</span>'+oBadge+'<span class="recall-summary-short">'+shortText+'</span><span class="recall-expand-icon">\u25B6</span></div>';
|
|
5376
5574
|
html+='<div class="recall-summary-full">'+fullText+'</div>';
|
|
5377
5575
|
html+='</div>';
|
|
5378
5576
|
});
|
|
@@ -5385,8 +5583,9 @@ function buildLogSummary(lg){
|
|
|
5385
5583
|
var scoreClass=f.score>=0.7?'high':f.score>=0.5?'mid':'low';
|
|
5386
5584
|
var shortText=escapeHtml(f.summary||f.content||f.original_excerpt||'');
|
|
5387
5585
|
var fullText=escapeHtml(f.content||f.original_excerpt||f.summary||'');
|
|
5586
|
+
var oBadge=recallOriginBadge(f.origin);
|
|
5388
5587
|
html+='<div class="recall-item" onclick="event.stopPropagation();this.classList.toggle(\\\'expanded\\\')">';
|
|
5389
|
-
html+='<div class="recall-item-head"><span class="recall-score '+scoreClass+'">'+f.score.toFixed(2)+'</span><span class="log-msg-role '+(f.role||'user')+'">'+(f.role||'user')+'</span
|
|
5588
|
+
html+='<div class="recall-item-head"><span class="recall-score '+scoreClass+'">'+f.score.toFixed(2)+'</span><span class="log-msg-role '+(f.role||'user')+'">'+(f.role||'user')+'</span>'+oBadge+'<span class="recall-summary-short">'+shortText+'</span><span class="recall-expand-icon">\u25B6</span></div>';
|
|
5390
5589
|
html+='<div class="recall-summary-full">'+fullText+'</div>';
|
|
5391
5590
|
html+='</div>';
|
|
5392
5591
|
});
|
|
@@ -5450,8 +5649,9 @@ function buildRecallDetailHtml(rd){
|
|
|
5450
5649
|
var scoreClass=c.score>=0.7?'high':c.score>=0.5?'mid':'low';
|
|
5451
5650
|
var shortText=escapeHtml(c.summary||c.content||c.original_excerpt||'');
|
|
5452
5651
|
var fullText=escapeHtml(c.content||c.original_excerpt||c.summary||'');
|
|
5652
|
+
var oBadge=recallOriginBadge(c.origin);
|
|
5453
5653
|
html+='<div class="recall-item" onclick="event.stopPropagation();this.classList.toggle(\\\'expanded\\\')">';
|
|
5454
|
-
html+='<div class="recall-item-head"><span class="recall-idx">'+(i+1)+'</span><span class="recall-score '+scoreClass+'">'+c.score.toFixed(3)+'</span><span class="log-msg-role '+(c.role||'user')+'">'+(c.role||'user')+'</span
|
|
5654
|
+
html+='<div class="recall-item-head"><span class="recall-idx">'+(i+1)+'</span><span class="recall-score '+scoreClass+'">'+c.score.toFixed(3)+'</span><span class="log-msg-role '+(c.role||'user')+'">'+(c.role||'user')+'</span>'+oBadge+'<span class="recall-summary-short">'+shortText+'</span><span class="recall-expand-icon">\u25B6</span></div>';
|
|
5455
5655
|
html+='<div class="recall-summary-full">'+fullText+'</div>';
|
|
5456
5656
|
html+='</div>';
|
|
5457
5657
|
});
|
|
@@ -5465,8 +5665,9 @@ function buildRecallDetailHtml(rd){
|
|
|
5465
5665
|
var scoreClass=f.score>=0.7?'high':f.score>=0.5?'mid':'low';
|
|
5466
5666
|
var shortText=escapeHtml(f.summary||f.content||f.original_excerpt||'');
|
|
5467
5667
|
var fullText=escapeHtml(f.content||f.original_excerpt||f.summary||'');
|
|
5668
|
+
var oBadge=recallOriginBadge(f.origin);
|
|
5468
5669
|
html+='<div class="recall-item" onclick="event.stopPropagation();this.classList.toggle(\\\'expanded\\\')">';
|
|
5469
|
-
html+='<div class="recall-item-head"><span class="recall-idx">'+(i+1)+'</span><span class="recall-score '+scoreClass+'">'+f.score.toFixed(3)+'</span><span class="log-msg-role '+(f.role||'user')+'">'+(f.role||'user')+'</span
|
|
5670
|
+
html+='<div class="recall-item-head"><span class="recall-idx">'+(i+1)+'</span><span class="recall-score '+scoreClass+'">'+f.score.toFixed(3)+'</span><span class="log-msg-role '+(f.role||'user')+'">'+(f.role||'user')+'</span>'+oBadge+'<span class="recall-summary-short">'+shortText+'</span><span class="recall-expand-icon">\u25B6</span></div>';
|
|
5470
5671
|
html+='<div class="recall-summary-full">'+fullText+'</div>';
|
|
5471
5672
|
html+='</div>';
|
|
5472
5673
|
});
|
|
@@ -6042,7 +6243,7 @@ async function loadSkills(silent){
|
|
|
6042
6243
|
'<div class="summary">'+esc(skill.name)+'</div>'+
|
|
6043
6244
|
'<div class="excerpt">'+esc(skill.description||'')+'</div>'+
|
|
6044
6245
|
'<div class="hub-skill-meta">'+
|
|
6045
|
-
'<span class="meta-chip">owner: '+
|
|
6246
|
+
'<span class="meta-chip">owner: '+fmtOwner(skill)+'</span>'+
|
|
6046
6247
|
(skill.groupName?'<span class="meta-chip">group: '+esc(skill.groupName)+'</span>':'')+
|
|
6047
6248
|
'<span class="meta-chip">visibility: '+esc(skill.visibility||'hub')+'</span>'+
|
|
6048
6249
|
(skill.version!=null?'<span class="meta-chip">v'+skill.version+'</span>':'')+
|
|
@@ -6089,12 +6290,12 @@ async function loadHubTasks(){
|
|
|
6089
6290
|
return '<div class="task-card" onclick="openHubTaskDetailFromCache(\\x27hub\\x27,'+idx+')" style="cursor:pointer">'+
|
|
6090
6291
|
'<div class="task-card-top">'+
|
|
6091
6292
|
'<div class="task-card-title">'+esc(task.title||'(no title)')+'</div>'+
|
|
6092
|
-
'<div class="task-card-badges"
|
|
6293
|
+
'<div class="task-card-badges">'+renderScopeBadge('team')+'</div>'+
|
|
6093
6294
|
'</div>'+
|
|
6094
6295
|
(task.summary?'<div class="task-card-summary">'+esc(task.summary)+'</div>':'')+
|
|
6095
6296
|
'<div class="task-card-bottom">'+
|
|
6096
6297
|
(timeStr?'<span class="tag"><span class="icon">\\u{1F4C5}</span> '+timeStr+'</span>':'')+
|
|
6097
|
-
'<span class="tag"><span class="icon">\\u{1F464}</span> '+
|
|
6298
|
+
'<span class="tag"><span class="icon">\\u{1F464}</span> '+fmtOwner(task)+'</span>'+
|
|
6098
6299
|
(task.chunkCount!=null?'<span class="tag"><span class="icon">\\u{1F4DD}</span> '+task.chunkCount+' '+t('tasks.chunks.label')+'</span>':'')+
|
|
6099
6300
|
'</div>'+
|
|
6100
6301
|
'</div>';
|
|
@@ -6127,12 +6328,12 @@ async function loadHubSkills(hubList, localIds){
|
|
|
6127
6328
|
'<div class="summary">'+esc(skill.name)+'</div>'+
|
|
6128
6329
|
'<div class="excerpt">'+esc(skill.description||'')+'</div>'+
|
|
6129
6330
|
'<div class="hub-skill-meta">'+
|
|
6130
|
-
'<span class="meta-chip">owner: '+
|
|
6331
|
+
'<span class="meta-chip">owner: '+fmtOwner(skill)+'</span>'+
|
|
6131
6332
|
(skill.groupName?'<span class="meta-chip">group: '+esc(skill.groupName)+'</span>':'')+
|
|
6132
6333
|
'<span class="meta-chip">visibility: '+esc(skill.visibility||'hub')+'</span>'+
|
|
6133
6334
|
(skill.version!=null?'<span class="meta-chip">v'+skill.version+'</span>':'')+
|
|
6134
6335
|
'</div>'+
|
|
6135
|
-
'<div class="hub-skill-actions"><button class="btn btn-sm" onclick="event.stopPropagation();pullHubSkill(\\''+escAttr(skill.
|
|
6336
|
+
'<div class="hub-skill-actions"><button class="btn btn-sm" onclick="event.stopPropagation();pullHubSkill(\\''+escAttr(skill.id)+'\\')">'+t('skill.pullToLocal')+'</button></div>'+
|
|
6136
6337
|
'</div>';
|
|
6137
6338
|
}).join('');
|
|
6138
6339
|
}catch(e){
|
|
@@ -6466,6 +6667,7 @@ async function loadConfig(){
|
|
|
6466
6667
|
document.getElementById('cfgHubTeamName').value=hub.teamName||'';
|
|
6467
6668
|
document.getElementById('cfgHubTeamToken').value=hub.teamToken||'';
|
|
6468
6669
|
document.getElementById('cfgClientHubAddress').value=client.hubAddress||'';
|
|
6670
|
+
_loadedClientHubAddress=client.hubAddress||'';
|
|
6469
6671
|
document.getElementById('cfgClientTeamToken').value=client.teamToken||'';
|
|
6470
6672
|
document.getElementById('cfgClientNickname').value=client.nickname||'';
|
|
6471
6673
|
document.getElementById('cfgClientUserToken').value=client.userToken||'';
|
|
@@ -6511,20 +6713,24 @@ function flashSaved(id){
|
|
|
6511
6713
|
}
|
|
6512
6714
|
|
|
6513
6715
|
async function doSaveConfig(cfg, btnEl, savedId){
|
|
6514
|
-
btnEl.disabled=true;btnEl.textContent=t('settings.test.loading');
|
|
6515
|
-
function done(){btnEl.disabled=false;btnEl.textContent=t('settings.save');}
|
|
6716
|
+
if(btnEl){btnEl.disabled=true;btnEl.textContent=t('settings.test.loading');}
|
|
6717
|
+
function done(){if(btnEl){btnEl.disabled=false;btnEl.textContent=t('settings.save');}}
|
|
6516
6718
|
try{
|
|
6517
6719
|
const r=await fetch('/api/config',{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(cfg)});
|
|
6518
|
-
if(r.status===401){done();toast(t('settings.session.expired'),'error');return
|
|
6720
|
+
if(r.status===401){done();toast(t('settings.session.expired'),'error');return null;}
|
|
6519
6721
|
if(!r.ok) throw new Error(await r.text());
|
|
6722
|
+
var data=await r.json().catch(function(){return {ok:true};});
|
|
6520
6723
|
flashSaved(savedId);
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
|
|
6724
|
+
if(data&&data.restart){
|
|
6725
|
+
showRestartOverlay(t('settings.restart.waiting'));
|
|
6726
|
+
}else{
|
|
6727
|
+
done();
|
|
6728
|
+
}
|
|
6729
|
+
return data;
|
|
6524
6730
|
}catch(e){
|
|
6525
6731
|
toast(t('settings.save.fail')+': '+e.message,'error');
|
|
6526
6732
|
done();
|
|
6527
|
-
return
|
|
6733
|
+
return null;
|
|
6528
6734
|
}
|
|
6529
6735
|
}
|
|
6530
6736
|
|
|
@@ -6619,11 +6825,19 @@ async function saveModelsConfig(){
|
|
|
6619
6825
|
await doSaveConfig(cfg, saveBtn, 'modelsSaved');
|
|
6620
6826
|
}
|
|
6621
6827
|
|
|
6828
|
+
function _hubSaveBtnLabel(){
|
|
6829
|
+
var on=document.getElementById('cfgSharingEnabled');
|
|
6830
|
+
if(on&&on.checked&&_sharingRole==='client'){
|
|
6831
|
+
var prevClient=sharingStatusCache&&sharingStatusCache.enabled&&sharingStatusCache.role==='client';
|
|
6832
|
+
return prevClient?t('settings.save'):t('sharing.joinTeam');
|
|
6833
|
+
}
|
|
6834
|
+
return t('settings.save');
|
|
6835
|
+
}
|
|
6622
6836
|
async function saveHubConfig(){
|
|
6623
6837
|
var card=document.getElementById('settingsSharingConfig');
|
|
6624
6838
|
var saveBtn=card.querySelector('.settings-actions .btn-primary');
|
|
6625
6839
|
saveBtn.disabled=true;saveBtn.textContent=t('settings.test.loading');
|
|
6626
|
-
function done(){saveBtn.disabled=false;saveBtn.textContent=
|
|
6840
|
+
function done(){saveBtn.disabled=false;saveBtn.textContent=_hubSaveBtnLabel();}
|
|
6627
6841
|
|
|
6628
6842
|
const cfg={};
|
|
6629
6843
|
var sharingEnabled=document.getElementById('cfgSharingEnabled').checked;
|
|
@@ -6637,7 +6851,7 @@ async function saveHubConfig(){
|
|
|
6637
6851
|
var hubTeamName=document.getElementById('cfgHubTeamName').value.trim();
|
|
6638
6852
|
var hubTeamToken=document.getElementById('cfgHubTeamToken').value.trim();
|
|
6639
6853
|
var hubAdminName=document.getElementById('cfgHubAdminName').value.trim();
|
|
6640
|
-
cfg.sharing.hub={port:
|
|
6854
|
+
if(hubPort) cfg.sharing.hub={port:Number(hubPort)}; else cfg.sharing.hub={};
|
|
6641
6855
|
if(hubTeamName) cfg.sharing.hub.teamName=hubTeamName;
|
|
6642
6856
|
if(hubTeamToken) cfg.sharing.hub.teamToken=hubTeamToken;
|
|
6643
6857
|
cfg.sharing.client={hubAddress:'',userToken:'',teamToken:''};
|
|
@@ -6654,15 +6868,9 @@ async function saveHubConfig(){
|
|
|
6654
6868
|
if(clientNickname) cfg.sharing.client.nickname=clientNickname;
|
|
6655
6869
|
if(clientTeamToken) cfg.sharing.client.teamToken=clientTeamToken;
|
|
6656
6870
|
if(clientUserToken) cfg.sharing.client.userToken=clientUserToken;
|
|
6657
|
-
cfg.sharing.hub={
|
|
6871
|
+
cfg.sharing.hub={teamName:'',teamToken:''};
|
|
6658
6872
|
if(clientAddr){
|
|
6659
6873
|
try{
|
|
6660
|
-
var ips=await fetch('/api/local-ips').then(function(r){return r.json();});
|
|
6661
|
-
var localAddrs=['127.0.0.1','localhost','0.0.0.0'].concat(ips.ips||[]);
|
|
6662
|
-
var parsed=new URL(clientAddr.indexOf('://')>-1?clientAddr:'http://'+clientAddr);
|
|
6663
|
-
if(localAddrs.indexOf(parsed.hostname)>=0){
|
|
6664
|
-
done();toast(t('sharing.cannotJoinSelf'),'error');return;
|
|
6665
|
-
}
|
|
6666
6874
|
}catch(e){}
|
|
6667
6875
|
try{
|
|
6668
6876
|
var testUrl=clientAddr.indexOf('://')>-1?clientAddr:'http://'+clientAddr;
|
|
@@ -6672,8 +6880,8 @@ async function saveHubConfig(){
|
|
|
6672
6880
|
if(!td.ok){
|
|
6673
6881
|
var errMsg=td.error==='cannot_join_self'?t('sharing.cannotJoinSelf'):(td.error||t('settings.hub.test.fail'));
|
|
6674
6882
|
done();toast(errMsg,'error');return;
|
|
6675
|
-
|
|
6676
|
-
|
|
6883
|
+
}
|
|
6884
|
+
}catch(e){
|
|
6677
6885
|
done();toast(t('settings.hub.test.fail')+': '+String(e),'error');return;
|
|
6678
6886
|
}
|
|
6679
6887
|
}
|
|
@@ -6689,25 +6897,40 @@ async function saveHubConfig(){
|
|
|
6689
6897
|
var switchMsg=prevRole==='hub'?t('sharing.switch.hubToClient'):t('sharing.switch.clientToHub');
|
|
6690
6898
|
if(!(await confirmModal(switchMsg,{danger:true}))){done();return;}
|
|
6691
6899
|
}
|
|
6900
|
+
if(prevSharingEnabled&&sharingEnabled&&prevRole==='client'&&_sharingRole==='client'){
|
|
6901
|
+
var newAddr=(document.getElementById('cfgClientHubAddress').value||'').trim();
|
|
6902
|
+
if(_loadedClientHubAddress&&newAddr&&newAddr!==_loadedClientHubAddress){
|
|
6903
|
+
if(!(await confirmModal(t('sharing.switch.hubAddress'),{danger:true}))){done();return;}
|
|
6904
|
+
}
|
|
6905
|
+
}
|
|
6692
6906
|
|
|
6693
|
-
var
|
|
6694
|
-
if(
|
|
6907
|
+
var result=await doSaveConfig(cfg, saveBtn, 'hubSaved');
|
|
6908
|
+
if(result){
|
|
6695
6909
|
if(sharingEnabled&&_sharingRole==='hub'){
|
|
6696
6910
|
var adminNameEl=document.getElementById('cfgHubAdminName');
|
|
6697
6911
|
if(adminNameEl&&adminNameEl.value.trim()){
|
|
6698
6912
|
try{await fetch('/api/sharing/update-username',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({username:adminNameEl.value.trim()})});}catch(e){}
|
|
6699
6913
|
}
|
|
6700
6914
|
}
|
|
6915
|
+
if(sharingEnabled&&_sharingRole==='client'&&result.joinStatus){
|
|
6916
|
+
if(result.joinStatus==='pending'){
|
|
6917
|
+
toast(t('sharing.joinSent.pending'),'success');
|
|
6918
|
+
}else if(result.joinStatus==='active'){
|
|
6919
|
+
toast(t('sharing.joinSent.active'),'success');
|
|
6920
|
+
}else{
|
|
6921
|
+
toast(t('settings.saved'),'success');
|
|
6922
|
+
}
|
|
6923
|
+
}else{
|
|
6924
|
+
toast(t('settings.saved'),'success');
|
|
6925
|
+
}
|
|
6701
6926
|
_lastSidebarFingerprint='';
|
|
6702
6927
|
_lastSettingsFingerprint='';
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
var needsRestart=enabledChanged||roleChanged;
|
|
6928
|
+
_lastSharingConnStatus='';
|
|
6929
|
+
_lastAdminFingerprint='';
|
|
6930
|
+
_lastAdminStatsFp='';
|
|
6707
6931
|
if(sharingEnabled) updateHubShareInfo();
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
}
|
|
6932
|
+
loadSharingStatus(true);
|
|
6933
|
+
if(_activeView==='admin') loadAdminData();
|
|
6711
6934
|
}
|
|
6712
6935
|
}
|
|
6713
6936
|
|
|
@@ -6797,6 +7020,8 @@ function renderSkillMarkdown(md){
|
|
|
6797
7020
|
function closeSkillDetail(event){
|
|
6798
7021
|
if(event && event.target!==document.getElementById('skillDetailOverlay')) return;
|
|
6799
7022
|
document.getElementById('skillDetailOverlay').classList.remove('show');
|
|
7023
|
+
currentSkillId='';
|
|
7024
|
+
currentSkillDetail=null;
|
|
6800
7025
|
}
|
|
6801
7026
|
|
|
6802
7027
|
async function deleteSkill(skillId){
|
|
@@ -7131,22 +7356,29 @@ var _livePollBusy=false;
|
|
|
7131
7356
|
async function _livePollTick(){
|
|
7132
7357
|
if(_livePollBusy||document.hidden) return;
|
|
7133
7358
|
_livePollBusy=true;
|
|
7359
|
+
var _savedScrollY=window.scrollY;
|
|
7360
|
+
var _scrollTargets=['memoryList','tasksList','skillsList','adminUsersPanel','adminMemoriesPanel','adminTasksPanel','adminSkillsPanel'];
|
|
7361
|
+
var _savedScrollMap={};
|
|
7362
|
+
_scrollTargets.forEach(function(id){var el=document.getElementById(id);if(el&&el.scrollTop)_savedScrollMap[id]=el.scrollTop;});
|
|
7134
7363
|
try{
|
|
7135
|
-
if(sharingStatusCache&&sharingStatusCache.enabled&&_lastSharingConnStatus!=='rejected') loadSharingStatus(false);
|
|
7136
|
-
if(!_notifSSEConnected) pollNotifCount();
|
|
7137
|
-
pollAdminPending();
|
|
7138
|
-
if(_activeView==='admin') loadAdminData();
|
|
7364
|
+
if(sharingStatusCache&&sharingStatusCache.enabled&&_lastSharingConnStatus!=='rejected') await loadSharingStatus(false);
|
|
7365
|
+
if(!_notifSSEConnected) await pollNotifCount();
|
|
7366
|
+
await pollAdminPending();
|
|
7367
|
+
if(_activeView==='admin') await loadAdminData();
|
|
7139
7368
|
else if(_activeView==='memories'){
|
|
7140
7369
|
var _searchVal=(document.getElementById('searchInput')||{}).value||'';
|
|
7141
7370
|
if(!_searchVal.trim()){
|
|
7142
|
-
if(memorySearchScope==='hub') loadHubMemories(true);
|
|
7143
|
-
else{loadStats();loadMemories(null,true);}
|
|
7371
|
+
if(memorySearchScope==='hub') await loadHubMemories(true);
|
|
7372
|
+
else{var _pollOwner=memorySearchScope==='local'?_currentAgentOwner:undefined;await loadStats(_pollOwner);await loadMemories(null,true);}
|
|
7144
7373
|
}
|
|
7145
7374
|
}
|
|
7146
|
-
else if(_activeView==='tasks') loadTasks(true);
|
|
7147
|
-
else if(_activeView==='skills') loadSkills(true);
|
|
7148
|
-
else if(_activeView==='analytics') loadMetrics();
|
|
7375
|
+
else if(_activeView==='tasks') await loadTasks(true);
|
|
7376
|
+
else if(_activeView==='skills') await loadSkills(true);
|
|
7377
|
+
else if(_activeView==='analytics') await loadMetrics();
|
|
7149
7378
|
}catch(e){}
|
|
7379
|
+
await new Promise(function(r){requestAnimationFrame(r);});
|
|
7380
|
+
window.scrollTo(0,_savedScrollY);
|
|
7381
|
+
for(var _sid in _savedScrollMap){var _sel=document.getElementById(_sid);if(_sel)_sel.scrollTop=_savedScrollMap[_sid];}
|
|
7150
7382
|
_livePollBusy=false;
|
|
7151
7383
|
}
|
|
7152
7384
|
|
|
@@ -7190,6 +7422,9 @@ function connectNotifSSE(){
|
|
|
7190
7422
|
_notifUnread=d.unreadCount||0;
|
|
7191
7423
|
renderNotifBadge();
|
|
7192
7424
|
if(_notifUnread>prev&&_notifPanelOpen) loadNotifications();
|
|
7425
|
+
if(_notifUnread>prev&&_activeView==='memories'&&memorySearchScope!=='hub'){
|
|
7426
|
+
syncTeamShareRemovedFromNotifications().then(function(){ loadMemories(currentPage,true); });
|
|
7427
|
+
}
|
|
7193
7428
|
}
|
|
7194
7429
|
if(d.type==='cleared'){
|
|
7195
7430
|
_notifUnread=0;_notifCache=[];
|
|
@@ -7239,7 +7474,12 @@ function notifTimeAgo(ts){
|
|
|
7239
7474
|
function notifIcon(resource,type){
|
|
7240
7475
|
if(type==='user_online') return '\\u{1F7E2}';
|
|
7241
7476
|
if(type==='user_offline') return '\\u{1F534}';
|
|
7477
|
+
if(type==='user_left') return '\\u{1F6AA}';
|
|
7242
7478
|
if(type==='user_join_request') return '\\u{1F464}';
|
|
7479
|
+
if(type==='membership_removed') return '\\u{26D4}';
|
|
7480
|
+
if(type==='hub_shutdown') return '\\u{1F6D1}';
|
|
7481
|
+
if(type==='role_promoted') return '\\u{2B06}';
|
|
7482
|
+
if(type==='role_demoted') return '\\u{2B07}';
|
|
7243
7483
|
if(resource==='memory') return '\\u{1F4DD}';
|
|
7244
7484
|
if(resource==='task') return '\\u{1F4CB}';
|
|
7245
7485
|
if(resource==='skill') return '\\u{1F9E0}';
|
|
@@ -7265,6 +7505,27 @@ function notifTypeText(n){
|
|
|
7265
7505
|
if(n.type==='user_offline'){
|
|
7266
7506
|
return t('notif.userOffline');
|
|
7267
7507
|
}
|
|
7508
|
+
if(n.type==='user_left'){
|
|
7509
|
+
return t('notif.userLeft');
|
|
7510
|
+
}
|
|
7511
|
+
if(n.type==='membership_approved'){
|
|
7512
|
+
return t('notif.membershipApproved');
|
|
7513
|
+
}
|
|
7514
|
+
if(n.type==='membership_rejected'){
|
|
7515
|
+
return t('notif.membershipRejected');
|
|
7516
|
+
}
|
|
7517
|
+
if(n.type==='membership_removed'){
|
|
7518
|
+
return t('notif.membershipRemoved');
|
|
7519
|
+
}
|
|
7520
|
+
if(n.type==='hub_shutdown'){
|
|
7521
|
+
return t('notif.hubShutdown');
|
|
7522
|
+
}
|
|
7523
|
+
if(n.type==='role_promoted'){
|
|
7524
|
+
return t('notif.rolePromoted');
|
|
7525
|
+
}
|
|
7526
|
+
if(n.type==='role_demoted'){
|
|
7527
|
+
return t('notif.roleDemoted');
|
|
7528
|
+
}
|
|
7268
7529
|
return n.message||n.type;
|
|
7269
7530
|
}
|
|
7270
7531
|
|
|
@@ -7299,6 +7560,21 @@ function renderNotifBadge(){
|
|
|
7299
7560
|
}
|
|
7300
7561
|
}
|
|
7301
7562
|
|
|
7563
|
+
var _notifKnownTypes={membership_approved:1,membership_rejected:1,membership_removed:1,hub_shutdown:1,user_left:1,user_online:1,user_offline:1,user_join_request:1,role_promoted:1,role_demoted:1,resource_removed:1,resource_shared:1,resource_unshared:1};
|
|
7564
|
+
function notifDisplayTitle(n){
|
|
7565
|
+
if(_notifKnownTypes[n.type]) return notifTypeText(n);
|
|
7566
|
+
return n.title||notifTypeText(n);
|
|
7567
|
+
}
|
|
7568
|
+
function notifDisplayDetail(n){
|
|
7569
|
+
if(_notifKnownTypes[n.type]){
|
|
7570
|
+
if(n.type==='resource_removed'||n.type==='resource_shared'||n.type==='resource_unshared') return n.title||'';
|
|
7571
|
+
var m=n.title&&n.title.match(/["\u201C]([^"\u201D]+)["\u201D]/);
|
|
7572
|
+
if(m) return m[1];
|
|
7573
|
+
if(n.type==='user_left'||n.type==='user_online'||n.type==='user_offline'||n.type==='user_join_request') return n.title||'';
|
|
7574
|
+
return '';
|
|
7575
|
+
}
|
|
7576
|
+
return n.title||'';
|
|
7577
|
+
}
|
|
7302
7578
|
function renderNotifPanel(){
|
|
7303
7579
|
var body=document.getElementById('notifPanelBody');
|
|
7304
7580
|
if(!body) return;
|
|
@@ -7308,11 +7584,12 @@ function renderNotifPanel(){
|
|
|
7308
7584
|
}
|
|
7309
7585
|
body.innerHTML=_notifCache.map(function(n){
|
|
7310
7586
|
var cls='notif-item'+(n.read?'':' unread');
|
|
7587
|
+
var detail=notifDisplayDetail(n);
|
|
7311
7588
|
return '<div class="'+cls+'" onclick="markNotifRead("'+esc(n.id)+'")">'+
|
|
7312
7589
|
'<div class="notif-item-icon">'+notifIcon(n.resource,n.type)+'</div>'+
|
|
7313
7590
|
'<div class="notif-item-body">'+
|
|
7314
|
-
'<div class="notif-item-title">'+esc(
|
|
7315
|
-
'<div class="notif-item-name">'+esc(
|
|
7591
|
+
'<div class="notif-item-title">'+esc(notifDisplayTitle(n))+'</div>'+
|
|
7592
|
+
(detail?'<div class="notif-item-name">'+esc(detail)+'</div>':'')+
|
|
7316
7593
|
'<div class="notif-item-time">'+notifTimeAgo(n.createdAt)+'</div>'+
|
|
7317
7594
|
'</div>'+
|
|
7318
7595
|
'<div class="notif-item-dot"></div>'+
|
|
@@ -7366,6 +7643,7 @@ async function loadAll(){
|
|
|
7366
7643
|
startLivePoller();
|
|
7367
7644
|
}
|
|
7368
7645
|
|
|
7646
|
+
var _lastStatsFp='';
|
|
7369
7647
|
async function loadStats(ownerFilter){
|
|
7370
7648
|
let d;
|
|
7371
7649
|
try{
|
|
@@ -7380,24 +7658,17 @@ async function loadStats(ownerFilter){
|
|
|
7380
7658
|
const dedupB=d.dedupBreakdown||{};
|
|
7381
7659
|
const activeCount=dedupB.active||tm;
|
|
7382
7660
|
const inactiveCount=(dedupB.duplicate||0)+(dedupB.merged||0);
|
|
7661
|
+
var agentCount=(d.owners&&d.owners.length)?d.owners.length:1;
|
|
7662
|
+
var sfp=tm+':'+(d.totalSessions||0)+':'+(d.totalEmbeddings||0)+':'+agentCount+':'+(d.embeddingProvider||'none')+':'+(ownerFilter||'');
|
|
7663
|
+
if(sfp===_lastStatsFp) return;
|
|
7664
|
+
_lastStatsFp=sfp;
|
|
7383
7665
|
document.getElementById('statTotal').textContent=tm;
|
|
7384
7666
|
if(inactiveCount>0){
|
|
7385
7667
|
document.getElementById('statTotal').title=activeCount+' '+t('stat.active')+', '+inactiveCount+' '+t('stat.deduped');
|
|
7386
7668
|
}
|
|
7387
7669
|
document.getElementById('statSessions').textContent=d.totalSessions||0;
|
|
7388
7670
|
document.getElementById('statEmbeddings').textContent=d.totalEmbeddings||0;
|
|
7389
|
-
|
|
7390
|
-
if(d.timeRange&&d.timeRange.earliest!=null&&d.timeRange.latest!=null){
|
|
7391
|
-
let e=Number(d.timeRange.earliest), l=Number(d.timeRange.latest);
|
|
7392
|
-
if(Number.isFinite(e)&&Number.isFinite(l)){
|
|
7393
|
-
if(e<1e12) e*=1000;
|
|
7394
|
-
if(l<1e12) l*=1000;
|
|
7395
|
-
days=Math.round((l-e)/86400000);
|
|
7396
|
-
days=Math.max(0,Math.min(36500,days));
|
|
7397
|
-
if(days===0) days=1;
|
|
7398
|
-
}
|
|
7399
|
-
}
|
|
7400
|
-
document.getElementById('statTimeSpan').textContent=days;
|
|
7671
|
+
document.getElementById('statAgents').textContent=agentCount;
|
|
7401
7672
|
|
|
7402
7673
|
const provEl=document.getElementById('embeddingStatus');
|
|
7403
7674
|
if(d.embeddingProvider && d.embeddingProvider!=='none'){
|
|
@@ -7492,18 +7763,38 @@ function getFilterParams(){
|
|
|
7492
7763
|
const scope=memorySearchScope||'local';
|
|
7493
7764
|
if(scope==='local'){
|
|
7494
7765
|
p.set('owner',_currentAgentOwner);
|
|
7495
|
-
}else{
|
|
7496
|
-
|
|
7497
|
-
|
|
7766
|
+
}else if(scope==='allLocal'){
|
|
7767
|
+
const owner=document.getElementById('filterOwner').value;
|
|
7768
|
+
if(owner) p.set('owner',owner);
|
|
7498
7769
|
}
|
|
7499
7770
|
return p;
|
|
7500
7771
|
}
|
|
7501
7772
|
|
|
7773
|
+
/** Hub admin removed a shared memory — badge-only: clear team_shared_chunks (never touches chunks/embeddings/hub_memories recall data). */
|
|
7774
|
+
async function syncTeamShareRemovedFromNotifications(){
|
|
7775
|
+
try{
|
|
7776
|
+
var r=await fetch('/api/sharing/notifications');
|
|
7777
|
+
var d=await r.json();
|
|
7778
|
+
var list=d.notifications||[];
|
|
7779
|
+
for(var i=0;i<list.length;i++){
|
|
7780
|
+
var n=list[i];
|
|
7781
|
+
if(n.type!=='resource_removed'||n.resource!=='memory'||!n.message) continue;
|
|
7782
|
+
try{
|
|
7783
|
+
var meta=JSON.parse(n.message);
|
|
7784
|
+
if(meta.sourceChunkId){
|
|
7785
|
+
await fetch('/api/sharing/sync-hub-removal',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({sourceChunkId:meta.sourceChunkId,memoryId:meta.memoryId||''})});
|
|
7786
|
+
}
|
|
7787
|
+
}catch(e){}
|
|
7788
|
+
}
|
|
7789
|
+
}catch(e){}
|
|
7790
|
+
}
|
|
7791
|
+
|
|
7502
7792
|
async function loadMemories(page,silent){
|
|
7503
7793
|
if(page) currentPage=page;
|
|
7504
7794
|
const list=document.getElementById('memoryList');
|
|
7505
7795
|
if(!silent) list.innerHTML='<div class="spinner"></div>';
|
|
7506
7796
|
try{
|
|
7797
|
+
if(!silent) await syncTeamShareRemovedFromNotifications();
|
|
7507
7798
|
const p=getFilterParams();
|
|
7508
7799
|
p.set('limit',PAGE_SIZE);
|
|
7509
7800
|
p.set('page',currentPage);
|
|
@@ -7524,11 +7815,11 @@ async function loadMemories(page,silent){
|
|
|
7524
7815
|
renderPagination();
|
|
7525
7816
|
}catch(e){
|
|
7526
7817
|
if(!silent){
|
|
7527
|
-
|
|
7528
|
-
|
|
7818
|
+
list.innerHTML='';
|
|
7819
|
+
totalPages=1;totalCount=0;
|
|
7529
7820
|
_lastMemoriesFingerprint='';
|
|
7530
|
-
|
|
7531
|
-
|
|
7821
|
+
renderMemories([]);
|
|
7822
|
+
renderPagination();
|
|
7532
7823
|
}
|
|
7533
7824
|
}
|
|
7534
7825
|
}
|
|
@@ -7555,9 +7846,9 @@ async function loadHubMemories(silent){
|
|
|
7555
7846
|
}catch(e){
|
|
7556
7847
|
if(!silent){
|
|
7557
7848
|
_lastMemoriesFingerprint='';
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7849
|
+
document.getElementById('searchMeta').textContent='0'+t('search.meta.results');
|
|
7850
|
+
renderMemories([]);
|
|
7851
|
+
document.getElementById('pagination').innerHTML='';
|
|
7561
7852
|
}
|
|
7562
7853
|
}
|
|
7563
7854
|
}
|
|
@@ -7678,7 +7969,7 @@ function renderMemories(items){
|
|
|
7678
7969
|
const mergeBadge=mc>0?'<span class="merge-badge">\\u{1F504} '+t('card.evolved')+' '+mc+t('card.times')+'</span>':'';
|
|
7679
7970
|
const updatedAt=(m.updated_at&&m.updated_at>m.created_at)?'<span class="card-updated">'+t('card.updated')+' '+new Date(m.updated_at).toLocaleString(dateLoc())+'</span>':'';
|
|
7680
7971
|
const ds=m.dedup_status||'active';
|
|
7681
|
-
const isInactive=ds==='merged';
|
|
7972
|
+
const isInactive=ds==='merged'||ds==='duplicate';
|
|
7682
7973
|
const dedupBadge=ds==='duplicate'?'<span class="dedup-badge duplicate">'+t('card.dedupDuplicate')+'</span>':ds==='merged'?'<span class="dedup-badge merged">'+t('card.dedupMerged')+'</span>':'';
|
|
7683
7974
|
const isImported=sid.startsWith('openclaw-import-')||sid.startsWith('openclaw-session-');
|
|
7684
7975
|
const importBadge=isImported?'<span class="import-badge">\u{1F990} '+t('card.imported')+'</span>':'';
|
|
@@ -7687,8 +7978,8 @@ function renderMemories(items){
|
|
|
7687
7978
|
const localManaged=!!m.localSharingManaged;
|
|
7688
7979
|
const memShared=m.sharingVisibility||null;
|
|
7689
7980
|
const isHubScope=memorySearchScope==='hub';
|
|
7690
|
-
const memScope=
|
|
7691
|
-
const memScopeBadge=renderScopeBadge(memScope);
|
|
7981
|
+
const memScope=memShared?'team':isPublicMem?'local':'private';
|
|
7982
|
+
const memScopeBadge=isHubScope?renderScopeBadge('team'):renderScopeBadge(memScope);
|
|
7692
7983
|
let dedupInfo='';
|
|
7693
7984
|
if(ds==='duplicate'||ds==='merged'){
|
|
7694
7985
|
const reason=m.dedup_reason?'<span style="font-size:11px;color:var(--text-muted)">'+t('card.dedupReason')+esc(m.dedup_reason)+'</span>':'';
|
|
@@ -7873,6 +8164,11 @@ function esc(s){
|
|
|
7873
8164
|
if(!s)return'';
|
|
7874
8165
|
return s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
|
|
7875
8166
|
}
|
|
8167
|
+
function fmtOwner(item){
|
|
8168
|
+
var name=item.ownerName||item.sourceUserId||'unknown';
|
|
8169
|
+
if(item.ownerStatus==='removed') return esc(name)+' <span style="color:#ef4444;font-size:0.9em">'+t('sharing.ownerRemoved')+'</span>';
|
|
8170
|
+
return esc(name);
|
|
8171
|
+
}
|
|
7876
8172
|
|
|
7877
8173
|
function renderSummaryHtml(raw){
|
|
7878
8174
|
if(!raw)return'';
|
|
@@ -8599,18 +8895,25 @@ function confirmModal(message,opts){
|
|
|
8599
8895
|
_confirmResolve=resolve;
|
|
8600
8896
|
var overlay=document.getElementById('confirmOverlay');
|
|
8601
8897
|
document.getElementById('confirmTitle').textContent=opts.title||t('confirm.title')||'\u786E\u8BA4';
|
|
8602
|
-
document.getElementById('confirmBody').
|
|
8898
|
+
document.getElementById('confirmBody').innerText=message||'';
|
|
8603
8899
|
var okBtn=document.getElementById('confirmOkBtn');
|
|
8604
8900
|
okBtn.textContent=opts.okText||t('confirm.ok')||'\u786E\u5B9A';
|
|
8605
8901
|
okBtn.className='btn-confirm-ok'+(opts.danger?' danger':'');
|
|
8606
|
-
document.getElementById('confirmCancelBtn')
|
|
8902
|
+
var cancelBtn=document.getElementById('confirmCancelBtn');
|
|
8903
|
+
cancelBtn.textContent=opts.cancelText||t('confirm.cancel')||'\u53D6\u6D88';
|
|
8904
|
+
cancelBtn.style.display=opts.hideCancel?'none':'';
|
|
8607
8905
|
overlay.classList.add('show');
|
|
8608
8906
|
});
|
|
8609
8907
|
}
|
|
8610
8908
|
function confirmModalClose(result){
|
|
8611
8909
|
document.getElementById('confirmOverlay').classList.remove('show');
|
|
8910
|
+
document.getElementById('confirmCancelBtn').style.display='';
|
|
8612
8911
|
if(_confirmResolve){var r=_confirmResolve;_confirmResolve=null;r(result);}
|
|
8613
8912
|
}
|
|
8913
|
+
function alertModal(message,opts){
|
|
8914
|
+
opts=opts||{};
|
|
8915
|
+
return confirmModal(message,Object.assign({},opts,{hideCancel:true,okText:opts.okText||t('confirm.ok')||'\u77E5\u9053\u4E86'}));
|
|
8916
|
+
}
|
|
8614
8917
|
|
|
8615
8918
|
/* ─── Theme ─── */
|
|
8616
8919
|
const VIEWER_THEME_KEY='memos-viewer-theme';
|
|
@@ -8633,14 +8936,35 @@ function showRestartOverlay(msg){
|
|
|
8633
8936
|
/* ─── Update check ─── */
|
|
8634
8937
|
function waitForGatewayAndReload(maxAttempts,attempt){
|
|
8635
8938
|
attempt=attempt||0;
|
|
8939
|
+
var phase=arguments.length>2?arguments[2]:'waitDown';
|
|
8940
|
+
var MAX_WAIT_DOWN=8;
|
|
8636
8941
|
function forceReload(){window.location.href=window.location.pathname+'?_t='+Date.now();}
|
|
8637
8942
|
if(attempt>=maxAttempts){forceReload();return;}
|
|
8943
|
+
var delay=phase==='waitDown'?1500:2500;
|
|
8638
8944
|
setTimeout(function(){
|
|
8639
8945
|
fetch('/api/auth/status').then(function(r){
|
|
8640
|
-
if(
|
|
8641
|
-
|
|
8642
|
-
|
|
8643
|
-
|
|
8946
|
+
if(phase==='waitDown'){
|
|
8947
|
+
if(r.ok||r.status===401||r.status===403){
|
|
8948
|
+
if(attempt>=MAX_WAIT_DOWN){
|
|
8949
|
+
forceReload();
|
|
8950
|
+
}else{
|
|
8951
|
+
waitForGatewayAndReload(maxAttempts,attempt+1,'waitDown');
|
|
8952
|
+
}
|
|
8953
|
+
}else{
|
|
8954
|
+
waitForGatewayAndReload(maxAttempts,0,'waitUp');
|
|
8955
|
+
}
|
|
8956
|
+
}else{
|
|
8957
|
+
if(r.ok||r.status===401||r.status===403) forceReload();
|
|
8958
|
+
else waitForGatewayAndReload(maxAttempts,attempt+1,'waitUp');
|
|
8959
|
+
}
|
|
8960
|
+
}).catch(function(){
|
|
8961
|
+
if(phase==='waitDown'){
|
|
8962
|
+
waitForGatewayAndReload(maxAttempts,0,'waitUp');
|
|
8963
|
+
}else{
|
|
8964
|
+
waitForGatewayAndReload(maxAttempts,attempt+1,'waitUp');
|
|
8965
|
+
}
|
|
8966
|
+
});
|
|
8967
|
+
},delay);
|
|
8644
8968
|
}
|
|
8645
8969
|
function doUpdateInstall(packageSpec,btnEl,statusEl){
|
|
8646
8970
|
btnEl.disabled=true;
|
|
@@ -8674,9 +8998,12 @@ async function checkForUpdate(){
|
|
|
8674
8998
|
const d=await r.json();
|
|
8675
8999
|
if(!d.updateAvailable)return;
|
|
8676
9000
|
const pkgSpec=d.installCommand?d.installCommand.replace(/^(?:npx\s+)?openclaw\s+plugins\s+install\s+/,''):(d.packageName+'@'+d.latest);
|
|
9001
|
+
var bannerWrap=document.createElement('div');
|
|
9002
|
+
bannerWrap.id='updateBannerWrap';
|
|
9003
|
+
bannerWrap.style.cssText='background:linear-gradient(135deg,rgba(99,102,241,.08),rgba(139,92,246,.06));border-bottom:1px solid rgba(99,102,241,.18);backdrop-filter:blur(8px);animation:slideIn .3s ease';
|
|
8677
9004
|
var banner=document.createElement('div');
|
|
8678
9005
|
banner.id='updateBanner';
|
|
8679
|
-
banner.style.cssText='display:flex;align-items:center;gap:12px;padding:10px 32px;max-width:1400px;margin:0 auto;
|
|
9006
|
+
banner.style.cssText='display:flex;align-items:center;gap:12px;padding:10px 32px;width:100%;max-width:1400px;margin:0 auto;font-size:13px;font-weight:500;box-sizing:border-box;color:var(--pri)';
|
|
8680
9007
|
var textNode=document.createElement('div');
|
|
8681
9008
|
textNode.style.cssText='display:flex;align-items:center;gap:8px;flex-shrink:0;font-size:13px';
|
|
8682
9009
|
textNode.innerHTML='<span style="font-size:15px">\u2728</span> '+t('update.available')+' <span style="padding:2px 8px;border-radius:6px;background:rgba(99,102,241,.1);font-size:12px;font-weight:600">v'+esc(d.current)+'</span> <span style="opacity:.5">\u2192</span> <span style="padding:2px 8px;border-radius:6px;background:rgba(52,211,153,.12);color:var(--green);font-size:12px;font-weight:600">v'+esc(d.latest)+'</span>';
|
|
@@ -8696,18 +9023,30 @@ async function checkForUpdate(){
|
|
|
8696
9023
|
btnClose.innerHTML='×';
|
|
8697
9024
|
btnClose.onmouseenter=function(){this.style.opacity='1'};
|
|
8698
9025
|
btnClose.onmouseleave=function(){this.style.opacity='.5'};
|
|
8699
|
-
btnClose.onclick=function(){
|
|
9026
|
+
btnClose.onclick=function(){bannerWrap.remove()};
|
|
9027
|
+
var spacerL=document.createElement('div');
|
|
9028
|
+
spacerL.style.cssText='flex:1';
|
|
9029
|
+
banner.appendChild(spacerL);
|
|
8700
9030
|
banner.appendChild(textNode);
|
|
8701
9031
|
banner.appendChild(statusDiv);
|
|
8702
9032
|
banner.appendChild(spacer);
|
|
8703
9033
|
banner.appendChild(btnClose);
|
|
9034
|
+
bannerWrap.appendChild(banner);
|
|
8704
9035
|
var tb=document.querySelector('.topbar');
|
|
8705
|
-
if(tb&&tb.parentNode){tb.parentNode.insertBefore(
|
|
8706
|
-
else{document.body.insertBefore(
|
|
9036
|
+
if(tb&&tb.parentNode){tb.parentNode.insertBefore(bannerWrap,tb);}
|
|
9037
|
+
else{document.body.insertBefore(bannerWrap,document.body.firstChild);}
|
|
8707
9038
|
}catch(e){}
|
|
8708
9039
|
}
|
|
8709
9040
|
|
|
8710
9041
|
/* ─── Init ─── */
|
|
9042
|
+
try{
|
|
9043
|
+
var savedScope=localStorage.getItem('memos_memorySearchScope');
|
|
9044
|
+
if(savedScope&&(savedScope==='local'||savedScope==='allLocal'||savedScope==='hub')){
|
|
9045
|
+
memorySearchScope=savedScope;
|
|
9046
|
+
var scopeEl=document.getElementById('memorySearchScope');
|
|
9047
|
+
if(scopeEl) scopeEl.value=savedScope;
|
|
9048
|
+
}
|
|
9049
|
+
}catch(e){}
|
|
8711
9050
|
document.getElementById('modalOverlay').addEventListener('click',e=>{if(e.target.id==='modalOverlay')closeModal()});
|
|
8712
9051
|
document.getElementById('searchInput').addEventListener('keydown',e=>{if(e.key==='Escape'){e.target.value='';currentPage=1;if(memorySearchScope==='hub')loadHubMemories();else loadMemories();}});
|
|
8713
9052
|
applyI18n();
|