@memtensor/memos-local-openclaw-plugin 1.0.4-beta.11 → 1.0.4-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/connector.d.ts +4 -0
- package/dist/client/connector.d.ts.map +1 -1
- package/dist/client/connector.js +49 -11
- package/dist/client/connector.js.map +1 -1
- package/dist/hub/server.d.ts.map +1 -1
- package/dist/hub/server.js +21 -4
- package/dist/hub/server.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/recall/engine.d.ts.map +1 -1
- package/dist/recall/engine.js +5 -2
- package/dist/recall/engine.js.map +1 -1
- package/dist/storage/sqlite.d.ts +13 -0
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +64 -7
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/viewer/html.d.ts.map +1 -1
- package/dist/viewer/html.js +77 -28
- package/dist/viewer/html.js.map +1 -1
- package/dist/viewer/server.d.ts +1 -0
- package/dist/viewer/server.d.ts.map +1 -1
- package/dist/viewer/server.js +30 -8
- package/dist/viewer/server.js.map +1 -1
- package/index.ts +22 -20
- package/package.json +1 -1
- package/src/client/connector.ts +48 -11
- package/src/hub/server.ts +19 -4
- package/src/ingest/chunker.ts +19 -13
- package/src/recall/engine.ts +5 -2
- package/src/storage/sqlite.ts +69 -7
- package/src/viewer/html.ts +77 -28
- package/src/viewer/server.ts +29 -9
package/src/viewer/html.ts
CHANGED
|
@@ -976,8 +976,6 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
976
976
|
.team-guide-steps li::marker{color:var(--pri);font-weight:700;font-size:11px}
|
|
977
977
|
.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}
|
|
978
978
|
.team-guide-opt .btn-guide:hover{background:rgba(99,102,241,.14);border-color:var(--pri)}
|
|
979
|
-
.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}
|
|
980
|
-
.team-guide-dismiss:hover{opacity:1}
|
|
981
979
|
[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)}
|
|
982
980
|
[data-theme="light"] .team-guide-opt{box-shadow:0 1px 3px rgba(0,0,0,.03)}
|
|
983
981
|
[data-theme="light"] .team-guide-opt:hover{box-shadow:0 4px 16px rgba(0,0,0,.04)}
|
|
@@ -1641,9 +1639,8 @@ input,textarea,select{font-family:inherit;font-size:inherit}
|
|
|
1641
1639
|
</div>
|
|
1642
1640
|
</div>
|
|
1643
1641
|
<div class="settings-card-body">
|
|
1644
|
-
<!-- team setup guide (inside Hub card) -->
|
|
1642
|
+
<!-- team setup guide (inside Hub card) — always visible when sharing is not configured -->
|
|
1645
1643
|
<div class="team-guide" id="teamSetupGuide">
|
|
1646
|
-
<button class="team-guide-dismiss" onclick="dismissTeamGuide()" title="Dismiss">×</button>
|
|
1647
1644
|
<div class="team-guide-title">\u{1F680} <span data-i18n="guide.title">Get Started with Team Collaboration</span></div>
|
|
1648
1645
|
<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>
|
|
1649
1646
|
<div class="team-guide-options">
|
|
@@ -2126,6 +2123,8 @@ const I18N={
|
|
|
2126
2123
|
'notif.userJoin':'New user requests to join the team',
|
|
2127
2124
|
'notif.userOnline':'User came online',
|
|
2128
2125
|
'notif.userOffline':'User went offline',
|
|
2126
|
+
'notif.membershipApproved':'Your team join request has been approved',
|
|
2127
|
+
'notif.membershipRejected':'Your team join request has been declined',
|
|
2129
2128
|
'notif.clearAll':'Clear all',
|
|
2130
2129
|
'notif.timeAgo.just':'just now',
|
|
2131
2130
|
'notif.timeAgo.min':'{n}m ago',
|
|
@@ -2448,6 +2447,9 @@ const I18N={
|
|
|
2448
2447
|
'sharing.pendingApproval.hint':'Your join request has been submitted. Please wait for the team admin to approve.',
|
|
2449
2448
|
'sharing.rejected.hint':'Your join request was rejected by the team admin. Please contact the admin or retry.',
|
|
2450
2449
|
'sharing.removed.hint':'You have been removed from the team by the admin. You can re-apply to join.',
|
|
2450
|
+
'sharing.joinTeam':'Join Team',
|
|
2451
|
+
'sharing.joinSent.pending':'Join request sent! Waiting for admin approval.',
|
|
2452
|
+
'sharing.joinSent.active':'Successfully joined the team!',
|
|
2451
2453
|
'sharing.retryJoin':'Retry Join',
|
|
2452
2454
|
'sharing.retryJoin.hint':'Clears local data and re-submits the join request',
|
|
2453
2455
|
'sharing.retryJoin.confirm':'This will clear your current connection and re-submit a join request. Continue?',
|
|
@@ -2840,6 +2842,8 @@ const I18N={
|
|
|
2840
2842
|
'notif.userJoin':'有新用户申请加入团队',
|
|
2841
2843
|
'notif.userOnline':'用户上线了',
|
|
2842
2844
|
'notif.userOffline':'用户下线了',
|
|
2845
|
+
'notif.membershipApproved':'你的团队加入申请已通过',
|
|
2846
|
+
'notif.membershipRejected':'你的团队加入申请已被拒绝',
|
|
2843
2847
|
'notif.clearAll':'清除全部',
|
|
2844
2848
|
'notif.timeAgo.just':'刚刚',
|
|
2845
2849
|
'notif.timeAgo.min':'{n}分钟前',
|
|
@@ -3162,6 +3166,9 @@ const I18N={
|
|
|
3162
3166
|
'sharing.pendingApproval.hint':'加入申请已提交,请等待团队管理员审核通过。',
|
|
3163
3167
|
'sharing.rejected.hint':'您的加入申请已被团队管理员拒绝,请联系管理员或重新申请。',
|
|
3164
3168
|
'sharing.removed.hint':'您已被管理员从团队中移除,可以重新申请加入。',
|
|
3169
|
+
'sharing.joinTeam':'加入团队',
|
|
3170
|
+
'sharing.joinSent.pending':'加入申请已发送,等待管理员审批。',
|
|
3171
|
+
'sharing.joinSent.active':'成功加入团队!',
|
|
3165
3172
|
'sharing.retryJoin':'重新申请',
|
|
3166
3173
|
'sharing.retryJoin.hint':'清除本地连接数据并重新提交加入申请',
|
|
3167
3174
|
'sharing.retryJoin.confirm':'这将清除当前连接数据并重新提交加入申请,是否继续?',
|
|
@@ -3606,6 +3613,9 @@ function selectSharingRole(role){
|
|
|
3606
3613
|
var tn=document.getElementById('cfgHubTeamName');
|
|
3607
3614
|
if(!tn.value.trim()) tn.value='My Team';
|
|
3608
3615
|
}
|
|
3616
|
+
var card=document.getElementById('settingsSharingConfig');
|
|
3617
|
+
var saveBtn=card&&card.querySelector('.settings-actions .btn-primary');
|
|
3618
|
+
if(saveBtn&&typeof _hubSaveBtnLabel==='function') saveBtn.textContent=_hubSaveBtnLabel();
|
|
3609
3619
|
}
|
|
3610
3620
|
var _cachedLocalIP='';
|
|
3611
3621
|
function updateHubShareInfo(){
|
|
@@ -3696,9 +3706,15 @@ function switchView(view){
|
|
|
3696
3706
|
else if(view==='skills') loadSkills();
|
|
3697
3707
|
else if(view==='analytics') loadMetrics();
|
|
3698
3708
|
else if(view==='logs') loadLogs();
|
|
3699
|
-
else if(view==='settings'){loadConfig()
|
|
3709
|
+
else if(view==='settings'){loadConfig().then(function(){
|
|
3710
|
+
var sharingOn=document.getElementById('cfgSharingEnabled');
|
|
3711
|
+
var sharingNotEnabled=!sharingOn||!sharingOn.checked;
|
|
3712
|
+
if(sharingNotEnabled){
|
|
3713
|
+
switchSettingsTab('hub',document.querySelector('.settings-tab-btn[data-tab="hub"]'));
|
|
3714
|
+
}
|
|
3715
|
+
});loadModelHealth();}
|
|
3700
3716
|
else if(view==='import'){if(!window._migrateRunning) migrateScan(false);}
|
|
3701
|
-
else if(view==='admin'){loadAdminData();}
|
|
3717
|
+
else if(view==='admin'){_lastAdminFingerprint='';loadAdminData();}
|
|
3702
3718
|
}
|
|
3703
3719
|
|
|
3704
3720
|
function onMemoryScopeChange(){
|
|
@@ -3736,6 +3752,13 @@ function onTaskScopeChange(){
|
|
|
3736
3752
|
|
|
3737
3753
|
var _clientPendingPollTimer=null;
|
|
3738
3754
|
var _lastSharingConnStatus='';
|
|
3755
|
+
function _updateScopeSelectorsVisibility(hubAvailable){
|
|
3756
|
+
var ids=['memorySearchScope','taskSearchScope','skillSearchScope'];
|
|
3757
|
+
for(var i=0;i<ids.length;i++){
|
|
3758
|
+
var el=document.getElementById(ids[i]);
|
|
3759
|
+
if(el) el.style.display=hubAvailable?'':'none';
|
|
3760
|
+
}
|
|
3761
|
+
}
|
|
3739
3762
|
async function loadSharingStatus(forcePending){
|
|
3740
3763
|
try{
|
|
3741
3764
|
const r=await fetch('/api/sharing/status');
|
|
@@ -3748,19 +3771,26 @@ async function loadSharingStatus(forcePending){
|
|
|
3748
3771
|
if(!d||!d.enabled){
|
|
3749
3772
|
if(_clientPendingPollTimer){clearInterval(_clientPendingPollTimer);_clientPendingPollTimer=null;}
|
|
3750
3773
|
_lastSharingConnStatus='';
|
|
3774
|
+
_updateScopeSelectorsVisibility(false);
|
|
3751
3775
|
return;
|
|
3752
3776
|
}
|
|
3753
3777
|
var conn=d.connection||{};
|
|
3754
3778
|
var curStatus=conn.rejected?'rejected':conn.pendingApproval?'pending':conn.connected?'connected':'none';
|
|
3779
|
+
var hubActive=d.role==='hub'||curStatus==='connected';
|
|
3780
|
+
_updateScopeSelectorsVisibility(hubActive);
|
|
3755
3781
|
if(_lastSharingConnStatus==='pending'&&curStatus==='rejected'){
|
|
3756
3782
|
toast(t('sharing.rejected.toast'),'error');
|
|
3757
3783
|
}
|
|
3758
3784
|
if(_lastSharingConnStatus==='pending'&&curStatus==='connected'){
|
|
3759
3785
|
toast(t('sharing.approved.toast'),'success');
|
|
3786
|
+
loadMemories();loadTasks();loadSkills();
|
|
3787
|
+
if(_notifSSE){_notifSSE.close();_notifSSE=null;_notifSSEConnected=false;}
|
|
3788
|
+
connectNotifSSE();
|
|
3789
|
+
loadNotifications();
|
|
3760
3790
|
}
|
|
3761
3791
|
_lastSharingConnStatus=curStatus;
|
|
3762
3792
|
if(curStatus==='pending'&&!_clientPendingPollTimer){
|
|
3763
|
-
_clientPendingPollTimer=setInterval(function(){loadSharingStatus(false);},
|
|
3793
|
+
_clientPendingPollTimer=setInterval(function(){loadSharingStatus(false);},5000);
|
|
3764
3794
|
}
|
|
3765
3795
|
if(curStatus!=='pending'&&_clientPendingPollTimer){
|
|
3766
3796
|
clearInterval(_clientPendingPollTimer);
|
|
@@ -3770,6 +3800,7 @@ async function loadSharingStatus(forcePending){
|
|
|
3770
3800
|
renderSharingSidebar(null);
|
|
3771
3801
|
renderSharingSettings(null);
|
|
3772
3802
|
updateTeamGuide(null);
|
|
3803
|
+
_updateScopeSelectorsVisibility(false);
|
|
3773
3804
|
}
|
|
3774
3805
|
}
|
|
3775
3806
|
|
|
@@ -4040,7 +4071,7 @@ async function approveSharingUser(userId,username){
|
|
|
4040
4071
|
try{
|
|
4041
4072
|
const r=await fetch('/api/sharing/approve-user',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({userId:userId,username:username})});
|
|
4042
4073
|
const d=await r.json();
|
|
4043
|
-
if(d.ok){toast(t('toast.userApproved'),'success');loadSharingPendingUsers();loadSharingStatus(true);} else {toast(d.error||t('toast.approveFail'),'error');}
|
|
4074
|
+
if(d.ok){toast(t('toast.userApproved'),'success');loadSharingPendingUsers();loadSharingStatus(true);_lastAdminFingerprint='';loadAdminData();} else {toast(d.error||t('toast.approveFail'),'error');}
|
|
4044
4075
|
}catch(e){toast(t('toast.approveFail')+': '+e.message,'error');}
|
|
4045
4076
|
}
|
|
4046
4077
|
|
|
@@ -4048,24 +4079,17 @@ async function rejectSharingUser(userId,username){
|
|
|
4048
4079
|
try{
|
|
4049
4080
|
const r=await fetch('/api/sharing/reject-user',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({userId:userId,username:username})});
|
|
4050
4081
|
const d=await r.json();
|
|
4051
|
-
if(d.ok){toast(t('toast.userRejected'),'success');loadSharingPendingUsers();} else {toast(d.error||t('toast.rejectFail'),'error');}
|
|
4082
|
+
if(d.ok){toast(t('toast.userRejected'),'success');loadSharingPendingUsers();_lastAdminFingerprint='';loadAdminData();} else {toast(d.error||t('toast.rejectFail'),'error');}
|
|
4052
4083
|
}catch(e){toast(t('toast.rejectFail')+': '+e.message,'error');}
|
|
4053
4084
|
}
|
|
4054
4085
|
|
|
4055
4086
|
/* ─── Team Setup Guide ─── */
|
|
4056
|
-
var TEAM_GUIDE_DISMISSED_KEY='memos-team-guide-dismissed';
|
|
4057
4087
|
function updateTeamGuide(sharingData){
|
|
4058
4088
|
var el=document.getElementById('teamSetupGuide');
|
|
4059
4089
|
if(!el) return;
|
|
4060
|
-
if(localStorage.getItem(TEAM_GUIDE_DISMISSED_KEY)==='1'){el.style.display='none';return;}
|
|
4061
4090
|
var isConfigured=sharingData&&sharingData.enabled;
|
|
4062
4091
|
el.style.display=isConfigured?'none':'block';
|
|
4063
4092
|
}
|
|
4064
|
-
function dismissTeamGuide(){
|
|
4065
|
-
localStorage.setItem(TEAM_GUIDE_DISMISSED_KEY,'1');
|
|
4066
|
-
var el=document.getElementById('teamSetupGuide');
|
|
4067
|
-
if(el) el.style.display='none';
|
|
4068
|
-
}
|
|
4069
4093
|
function guideGoToHub(role){
|
|
4070
4094
|
switchSettingsTab('hub',document.querySelector('.settings-tab-btn[data-tab="hub"]'));
|
|
4071
4095
|
var chk=document.getElementById('cfgSharingEnabled');
|
|
@@ -4181,7 +4205,7 @@ async function loadAdminData(){
|
|
|
4181
4205
|
var _newMemories=Array.isArray(memoriesR.memories)?memoriesR.memories:[];
|
|
4182
4206
|
var pending=isAdmin?(Array.isArray(pendingR.users)?pendingR.users:[]):[];
|
|
4183
4207
|
var _fp=_newUsers.length+':'+_newTasks.length+':'+_newSkills.length+':'+_newMemories.length+':'+pending.length
|
|
4184
|
-
+':'+_newUsers.map(function(u){return u.id+'|'+(u.isOnline?1:0)+'|'+(u.role||'')+'|'+(u.username||'')+'|'+(u.memoryCount||0)+'|'+(u.taskCount||0)+'|'+(u.skillCount||0)}).join(',')
|
|
4208
|
+
+':'+_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(',')
|
|
4185
4209
|
+':'+_newMemories.map(function(m){return m.id}).join(',')
|
|
4186
4210
|
+':'+_newTasks.map(function(t){return t.id+'|'+(t.status||'')}).join(',')
|
|
4187
4211
|
+':'+_newSkills.map(function(s){return s.id+'|'+(s.status||'')}).join(',')
|
|
@@ -4377,7 +4401,7 @@ async function adminApproveUser(userId,username){
|
|
|
4377
4401
|
try{
|
|
4378
4402
|
var r=await fetch('/api/sharing/approve-user',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({userId:userId,username:username})});
|
|
4379
4403
|
var d=await r.json();
|
|
4380
|
-
if(d.ok){toast(t('toast.userApproved'),'success');loadAdminData();}else{toast(d.error||t('toast.approveFail'),'error');}
|
|
4404
|
+
if(d.ok){toast(t('toast.userApproved'),'success');_lastAdminFingerprint='';loadAdminData();}else{toast(d.error||t('toast.approveFail'),'error');}
|
|
4381
4405
|
}catch(e){toast(t('toast.approveFail')+': '+e.message,'error');}
|
|
4382
4406
|
}
|
|
4383
4407
|
async function adminRejectUser(userId){
|
|
@@ -4385,7 +4409,7 @@ async function adminRejectUser(userId){
|
|
|
4385
4409
|
try{
|
|
4386
4410
|
var r=await fetch('/api/sharing/reject-user',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({userId:userId})});
|
|
4387
4411
|
var d=await r.json();
|
|
4388
|
-
if(d.ok){toast(t('toast.userRejected'),'success');loadAdminData();}else{toast(d.error||t('toast.rejectFail'),'error');}
|
|
4412
|
+
if(d.ok){toast(t('toast.userRejected'),'success');_lastAdminFingerprint='';loadAdminData();}else{toast(d.error||t('toast.rejectFail'),'error');}
|
|
4389
4413
|
}catch(e){toast(t('toast.rejectFail')+': '+e.message,'error');}
|
|
4390
4414
|
}
|
|
4391
4415
|
async function adminToggleRole(userId,newRole){
|
|
@@ -4394,7 +4418,7 @@ async function adminToggleRole(userId,newRole){
|
|
|
4394
4418
|
try{
|
|
4395
4419
|
var r=await fetch('/api/sharing/change-role',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({userId:userId,role:newRole})});
|
|
4396
4420
|
var d=await r.json();
|
|
4397
|
-
if(d.ok){toast(t('toast.roleChanged'),'success');loadAdminData();}
|
|
4421
|
+
if(d.ok){toast(t('toast.roleChanged'),'success');_lastAdminFingerprint='';loadAdminData();}
|
|
4398
4422
|
else if(d.error==='cannot_demote_owner'){toast(t('admin.ownerHint'),'error');}
|
|
4399
4423
|
else{toast(d.error||t('toast.roleChangeFail'),'error');}
|
|
4400
4424
|
}catch(e){toast(t('toast.roleChangeFail')+': '+e.message,'error');}
|
|
@@ -4446,7 +4470,7 @@ async function adminRemoveUser(userId,username){
|
|
|
4446
4470
|
try{
|
|
4447
4471
|
var r=await fetch('/api/sharing/remove-user',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({userId:userId,cleanResources:clean})});
|
|
4448
4472
|
var d=await r.json();
|
|
4449
|
-
if(d.ok){toast(t('toast.userRemoved'),'success');loadAdminData();}
|
|
4473
|
+
if(d.ok){toast(t('toast.userRemoved'),'success');_lastAdminFingerprint='';loadAdminData();}
|
|
4450
4474
|
else if(d.error==='cannot_remove_owner'){toast(t('admin.ownerHint'),'error');}
|
|
4451
4475
|
else{toast(d.error||t('toast.removeFail'),'error');}
|
|
4452
4476
|
}catch(e){toast(t('toast.removeFail')+': '+e.message,'error');}
|
|
@@ -6578,16 +6602,16 @@ async function doSaveConfig(cfg, btnEl, savedId){
|
|
|
6578
6602
|
function done(){btnEl.disabled=false;btnEl.textContent=t('settings.save');}
|
|
6579
6603
|
try{
|
|
6580
6604
|
const r=await fetch('/api/config',{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(cfg)});
|
|
6581
|
-
if(r.status===401){done();toast(t('settings.session.expired'),'error');return
|
|
6605
|
+
if(r.status===401){done();toast(t('settings.session.expired'),'error');return null;}
|
|
6582
6606
|
if(!r.ok) throw new Error(await r.text());
|
|
6607
|
+
var data=await r.json().catch(function(){return {ok:true};});
|
|
6583
6608
|
flashSaved(savedId);
|
|
6584
|
-
toast(t('settings.saved'),'success');
|
|
6585
6609
|
done();
|
|
6586
|
-
return
|
|
6610
|
+
return data;
|
|
6587
6611
|
}catch(e){
|
|
6588
6612
|
toast(t('settings.save.fail')+': '+e.message,'error');
|
|
6589
6613
|
done();
|
|
6590
|
-
return
|
|
6614
|
+
return null;
|
|
6591
6615
|
}
|
|
6592
6616
|
}
|
|
6593
6617
|
|
|
@@ -6682,11 +6706,19 @@ async function saveModelsConfig(){
|
|
|
6682
6706
|
await doSaveConfig(cfg, saveBtn, 'modelsSaved');
|
|
6683
6707
|
}
|
|
6684
6708
|
|
|
6709
|
+
function _hubSaveBtnLabel(){
|
|
6710
|
+
var on=document.getElementById('cfgSharingEnabled');
|
|
6711
|
+
if(on&&on.checked&&_sharingRole==='client'){
|
|
6712
|
+
var prevClient=sharingStatusCache&&sharingStatusCache.enabled&&sharingStatusCache.role==='client';
|
|
6713
|
+
return prevClient?t('settings.save'):t('sharing.joinTeam');
|
|
6714
|
+
}
|
|
6715
|
+
return t('settings.save');
|
|
6716
|
+
}
|
|
6685
6717
|
async function saveHubConfig(){
|
|
6686
6718
|
var card=document.getElementById('settingsSharingConfig');
|
|
6687
6719
|
var saveBtn=card.querySelector('.settings-actions .btn-primary');
|
|
6688
6720
|
saveBtn.disabled=true;saveBtn.textContent=t('settings.test.loading');
|
|
6689
|
-
function done(){saveBtn.disabled=false;saveBtn.textContent=
|
|
6721
|
+
function done(){saveBtn.disabled=false;saveBtn.textContent=_hubSaveBtnLabel();}
|
|
6690
6722
|
|
|
6691
6723
|
const cfg={};
|
|
6692
6724
|
var sharingEnabled=document.getElementById('cfgSharingEnabled').checked;
|
|
@@ -6753,14 +6785,25 @@ async function saveHubConfig(){
|
|
|
6753
6785
|
if(!(await confirmModal(switchMsg,{danger:true}))){done();return;}
|
|
6754
6786
|
}
|
|
6755
6787
|
|
|
6756
|
-
var
|
|
6757
|
-
if(
|
|
6788
|
+
var result=await doSaveConfig(cfg, saveBtn, 'hubSaved');
|
|
6789
|
+
if(result){
|
|
6758
6790
|
if(sharingEnabled&&_sharingRole==='hub'){
|
|
6759
6791
|
var adminNameEl=document.getElementById('cfgHubAdminName');
|
|
6760
6792
|
if(adminNameEl&&adminNameEl.value.trim()){
|
|
6761
6793
|
try{await fetch('/api/sharing/update-username',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({username:adminNameEl.value.trim()})});}catch(e){}
|
|
6762
6794
|
}
|
|
6763
6795
|
}
|
|
6796
|
+
if(sharingEnabled&&_sharingRole==='client'&&result.joinStatus){
|
|
6797
|
+
if(result.joinStatus==='pending'){
|
|
6798
|
+
toast(t('sharing.joinSent.pending'),'success');
|
|
6799
|
+
}else if(result.joinStatus==='active'){
|
|
6800
|
+
toast(t('sharing.joinSent.active'),'success');
|
|
6801
|
+
}else{
|
|
6802
|
+
toast(t('settings.saved'),'success');
|
|
6803
|
+
}
|
|
6804
|
+
}else{
|
|
6805
|
+
toast(t('settings.saved'),'success');
|
|
6806
|
+
}
|
|
6764
6807
|
_lastSidebarFingerprint='';
|
|
6765
6808
|
_lastSettingsFingerprint='';
|
|
6766
6809
|
_lastSharingConnStatus='';
|
|
@@ -7335,6 +7378,12 @@ function notifTypeText(n){
|
|
|
7335
7378
|
if(n.type==='user_offline'){
|
|
7336
7379
|
return t('notif.userOffline');
|
|
7337
7380
|
}
|
|
7381
|
+
if(n.type==='membership_approved'){
|
|
7382
|
+
return t('notif.membershipApproved');
|
|
7383
|
+
}
|
|
7384
|
+
if(n.type==='membership_rejected'){
|
|
7385
|
+
return t('notif.membershipRejected');
|
|
7386
|
+
}
|
|
7338
7387
|
return n.message||n.type;
|
|
7339
7388
|
}
|
|
7340
7389
|
|
package/src/viewer/server.ts
CHANGED
|
@@ -1232,7 +1232,7 @@ export class ViewerServer {
|
|
|
1232
1232
|
body: JSON.stringify({ memory: { sourceChunkId: refreshedChunk.id, role: refreshedChunk.role, content: refreshedChunk.content, summary: refreshedChunk.summary, kind: refreshedChunk.kind, groupId: null, visibility: "public" } }),
|
|
1233
1233
|
});
|
|
1234
1234
|
if (!isLocalShared) this.store.markMemorySharedLocally(chunkId);
|
|
1235
|
-
if (hubClient.userId) {
|
|
1235
|
+
if (hubClient.userId && this.ctx?.config?.sharing?.role === "hub") {
|
|
1236
1236
|
const existing = this.store.getHubMemoryBySource(hubClient.userId, chunkId);
|
|
1237
1237
|
this.store.upsertHubMemory({
|
|
1238
1238
|
id: (response as any)?.memoryId ?? existing?.id ?? crypto.randomUUID(),
|
|
@@ -2080,14 +2080,13 @@ export class ViewerServer {
|
|
|
2080
2080
|
},
|
|
2081
2081
|
}),
|
|
2082
2082
|
});
|
|
2083
|
-
|
|
2084
|
-
if (hubUserId) {
|
|
2083
|
+
if (hubClient.userId && this.ctx?.config?.sharing?.role === "hub") {
|
|
2085
2084
|
const now = Date.now();
|
|
2086
|
-
const existing = this.store.getHubMemoryBySource(
|
|
2085
|
+
const existing = this.store.getHubMemoryBySource(hubClient.userId, chunk.id);
|
|
2087
2086
|
this.store.upsertHubMemory({
|
|
2088
2087
|
id: (response as any)?.memoryId ?? existing?.id ?? crypto.randomUUID(),
|
|
2089
2088
|
sourceChunkId: chunk.id,
|
|
2090
|
-
sourceUserId:
|
|
2089
|
+
sourceUserId: hubClient.userId,
|
|
2091
2090
|
role: chunk.role,
|
|
2092
2091
|
content: chunk.content,
|
|
2093
2092
|
summary: chunk.summary ?? "",
|
|
@@ -2441,6 +2440,7 @@ export class ViewerServer {
|
|
|
2441
2440
|
res.write("data: {\"type\":\"connected\"}\n\n");
|
|
2442
2441
|
this.notifSSEClients.push(res);
|
|
2443
2442
|
if (!this.notifPollTimer) this.startNotifPoll();
|
|
2443
|
+
else this.notifPollImmediate();
|
|
2444
2444
|
req.on("close", () => {
|
|
2445
2445
|
this.notifSSEClients = this.notifSSEClients.filter((c) => c !== res);
|
|
2446
2446
|
if (this.notifSSEClients.length === 0) this.stopNotifPoll();
|
|
@@ -2476,6 +2476,20 @@ export class ViewerServer {
|
|
|
2476
2476
|
if (this.notifPollTimer) { clearInterval(this.notifPollTimer); this.notifPollTimer = undefined; }
|
|
2477
2477
|
}
|
|
2478
2478
|
|
|
2479
|
+
private notifPollImmediate(): void {
|
|
2480
|
+
const hub = this.resolveHubConnection();
|
|
2481
|
+
if (!hub) return;
|
|
2482
|
+
hubRequestJson(hub.hubUrl, hub.userToken, "/api/v1/hub/notifications?unread=1")
|
|
2483
|
+
.then((data: any) => {
|
|
2484
|
+
const count = data?.unreadCount ?? 0;
|
|
2485
|
+
if (count !== this.lastKnownNotifCount) {
|
|
2486
|
+
this.lastKnownNotifCount = count;
|
|
2487
|
+
this.broadcastNotifSSE({ type: "update", unreadCount: count });
|
|
2488
|
+
}
|
|
2489
|
+
})
|
|
2490
|
+
.catch(() => {});
|
|
2491
|
+
}
|
|
2492
|
+
|
|
2479
2493
|
private startHubHeartbeat(): void {
|
|
2480
2494
|
this.stopHubHeartbeat();
|
|
2481
2495
|
const sendHeartbeat = async () => {
|
|
@@ -2661,11 +2675,16 @@ export class ViewerServer {
|
|
|
2661
2675
|
const finalSharing = config.sharing as Record<string, unknown> | undefined;
|
|
2662
2676
|
const nowClient = Boolean(finalSharing?.enabled) && finalSharing?.role === "client";
|
|
2663
2677
|
const previouslyClient = oldSharingEnabled && oldSharingRole === "client";
|
|
2678
|
+
let joinStatus: string | undefined;
|
|
2664
2679
|
if (nowClient && !previouslyClient) {
|
|
2665
|
-
|
|
2680
|
+
try {
|
|
2681
|
+
joinStatus = await this.autoJoinOnSave(finalSharing);
|
|
2682
|
+
} catch (e) {
|
|
2683
|
+
this.log.warn(`Auto-join on save failed: ${e}`);
|
|
2684
|
+
}
|
|
2666
2685
|
}
|
|
2667
2686
|
|
|
2668
|
-
this.jsonResponse(res, { ok: true });
|
|
2687
|
+
this.jsonResponse(res, { ok: true, joinStatus });
|
|
2669
2688
|
} catch (e) {
|
|
2670
2689
|
this.log.warn(`handleSaveConfig error: ${e}`);
|
|
2671
2690
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
@@ -2674,11 +2693,11 @@ export class ViewerServer {
|
|
|
2674
2693
|
});
|
|
2675
2694
|
}
|
|
2676
2695
|
|
|
2677
|
-
private async autoJoinOnSave(sharing: Record<string, unknown>): Promise<
|
|
2696
|
+
private async autoJoinOnSave(sharing: Record<string, unknown>): Promise<string | undefined> {
|
|
2678
2697
|
const clientCfg = sharing.client as Record<string, unknown> | undefined;
|
|
2679
2698
|
const hubAddress = String(clientCfg?.hubAddress || "");
|
|
2680
2699
|
const teamToken = String(clientCfg?.teamToken || "");
|
|
2681
|
-
if (!hubAddress || !teamToken) return;
|
|
2700
|
+
if (!hubAddress || !teamToken) return undefined;
|
|
2682
2701
|
const hubUrl = normalizeHubUrl(hubAddress);
|
|
2683
2702
|
const os = await import("os");
|
|
2684
2703
|
const nickname = String(clientCfg?.nickname || "");
|
|
@@ -2705,6 +2724,7 @@ export class ViewerServer {
|
|
|
2705
2724
|
if (result.userToken) {
|
|
2706
2725
|
this.startHubHeartbeat();
|
|
2707
2726
|
}
|
|
2727
|
+
return result.status;
|
|
2708
2728
|
}
|
|
2709
2729
|
|
|
2710
2730
|
private async notifyHubLeave(): Promise<void> {
|