@memtensor/memos-local-openclaw-plugin 1.0.8-beta.6 → 1.0.8-beta.8

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.
@@ -3,7 +3,7 @@
3
3
  "name": "MemOS Local Memory",
4
4
  "description": "Full-write local conversation memory with hybrid search (RRF + MMR + recency), task summarization, skill evolution, and team sharing (Hub-Client). Provides memory_search, memory_get, task_summary, skill_search, task_share, network_skill_pull, network_team_info, memory_viewer for layered retrieval and team collaboration.",
5
5
  "kind": "memory",
6
- "version": "1.0.8-beta.6",
6
+ "version": "1.0.8-beta.7",
7
7
  "skills": [
8
8
  "skill/memos-memory-guide"
9
9
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memtensor/memos-local-openclaw-plugin",
3
- "version": "1.0.8-beta.6",
3
+ "version": "1.0.8-beta.8",
4
4
  "description": "MemOS Local memory plugin for OpenClaw — full-write, hybrid-recall, progressive retrieval",
5
5
  "type": "module",
6
6
  "main": "index.ts",
package/src/client/hub.ts CHANGED
@@ -177,6 +177,8 @@ function getClientIp(): string {
177
177
  return "";
178
178
  }
179
179
 
180
+ const HUB_FETCH_TIMEOUT_MS = 25_000;
181
+
180
182
  export async function hubRequestJson(
181
183
  hubUrl: string,
182
184
  userToken: string,
@@ -184,8 +186,17 @@ export async function hubRequestJson(
184
186
  init: RequestInit = {},
185
187
  ): Promise<unknown> {
186
188
  const clientIp = getClientIp();
189
+ const timeoutSignal =
190
+ typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function"
191
+ ? AbortSignal.timeout(HUB_FETCH_TIMEOUT_MS)
192
+ : undefined;
193
+ const mergedSignal =
194
+ timeoutSignal && init.signal
195
+ ? AbortSignal.any([timeoutSignal, init.signal])
196
+ : (timeoutSignal ?? init.signal);
187
197
  const res = await fetch(`${normalizeHubUrl(hubUrl)}${route}`, {
188
198
  ...init,
199
+ ...(mergedSignal ? { signal: mergedSignal } : {}),
189
200
  headers: {
190
201
  authorization: `Bearer ${userToken}`,
191
202
  ...(clientIp ? { "x-client-ip": clientIp } : {}),
@@ -650,7 +650,7 @@ input,textarea,select{font-family:inherit;font-size:inherit}
650
650
  .task-detail-meta{display:flex;flex-wrap:wrap;gap:12px;margin-bottom:20px;font-size:12px;color:var(--text-sec)}
651
651
  .task-detail-meta .meta-item{display:flex;align-items:center;gap:5px;background:var(--bg-card);border:1px solid var(--border);border-radius:8px;padding:5px 12px}
652
652
  .task-detail-summary{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:20px;margin-bottom:20px;font-size:13px;line-height:1.7;color:var(--text);word-break:break-word}
653
- .task-detail-summary:empty::after{content:'Summary not yet generated (task still active)';color:var(--text-muted);font-style:italic}
653
+ #taskDetailSummary:empty::after{content:'Summary not yet generated (task still active)';color:var(--text-muted);font-style:italic}
654
654
  .task-detail-summary .summary-section-title{font-size:14px;font-weight:700;color:var(--text);margin:14px 0 6px 0;padding-bottom:4px;border-bottom:1px solid var(--border)}
655
655
  .task-detail-summary .summary-section-title:first-child{margin-top:0}
656
656
  .task-detail-summary ul{margin:4px 0 8px 0;padding-left:20px}
@@ -2127,6 +2127,9 @@ const I18N={
2127
2127
  'skills.search.noresult':'No matching skills found',
2128
2128
  'skills.load.error':'Failed to load skills',
2129
2129
  'skills.hub.title':'\u{1F310} Team Skills',
2130
+ 'skills.hub.empty':'No extra team skills to list here — either the hub has none yet, or every hub skill already appears in your local list above (same source skill).',
2131
+ 'skills.hub.loadError':'Failed to load team skills',
2132
+ 'skills.hub.timeout':'Team skills request timed out. Check that the Hub is running and connected.',
2130
2133
  'scope.local':'Local',
2131
2134
  'scope.thisAgent':'This Agent Only',
2132
2135
  'scope.thisDevice':'All Local Agents',
@@ -2431,6 +2434,7 @@ const I18N={
2431
2434
  'skills.noversions':'No versions recorded',
2432
2435
  'skills.norelated':'No related tasks',
2433
2436
  'skills.nocontent':'No content available',
2437
+ 'skills.hub.markdownPending':'Full SKILL.md is not included in the team list response. Use “Pull to local”, then open the skill from your local list to view markdown, files, and versions.',
2434
2438
  'skills.nochangelog':'No changelog',
2435
2439
  'skills.status.active':'Active',
2436
2440
  'skills.status.draft':'Draft',
@@ -2631,7 +2635,7 @@ const I18N={
2631
2635
  'admin.visibility':'Visibility: ',
2632
2636
  'admin.session':'Session',
2633
2637
  'admin.content':'Content',
2634
- 'admin.chunks':'Chunks: ',
2638
+ 'admin.chunks':'{n} memory segments',
2635
2639
  'admin.updated':'Updated: ',
2636
2640
  'admin.sharedSkills':'Shared Skills',
2637
2641
  'admin.noSharedSkills':'No shared skills in team.',
@@ -2896,6 +2900,9 @@ const I18N={
2896
2900
  'skills.search.noresult':'未找到匹配的技能',
2897
2901
  'skills.load.error':'加载技能失败',
2898
2902
  'skills.hub.title':'\u{1F310} 团队共享技能',
2903
+ 'skills.hub.empty':'下方只列出「Hub 上有、但上方本机列表尚未包含」的技能;若 Hub 条目已与本机同源同步,则只会在上方显示,此处为空属正常。',
2904
+ 'skills.hub.loadError':'加载团队技能失败',
2905
+ 'skills.hub.timeout':'加载团队技能超时,请确认团队服务已启动且已连接。',
2899
2906
  'scope.local':'本地',
2900
2907
  'scope.thisAgent':'仅本智能体',
2901
2908
  'scope.thisDevice':'本机所有智能体',
@@ -3200,6 +3207,7 @@ const I18N={
3200
3207
  'skills.noversions':'暂无版本记录',
3201
3208
  'skills.norelated':'暂无关联任务',
3202
3209
  'skills.nocontent':'暂无内容',
3210
+ 'skills.hub.markdownPending':'团队列表未返回完整 SKILL.md 正文。请先「拉取到本地」,再在本机技能里打开该技能即可查看正文、文件与版本。',
3203
3211
  'skills.nochangelog':'暂无变更记录',
3204
3212
  'skills.status.active':'生效中',
3205
3213
  'skills.status.draft':'草稿',
@@ -3400,7 +3408,7 @@ const I18N={
3400
3408
  'admin.visibility':'可见性:',
3401
3409
  'admin.session':'会话',
3402
3410
  'admin.content':'内容',
3403
- 'admin.chunks':'记忆片段:',
3411
+ 'admin.chunks':'{n}段记忆片段',
3404
3412
  'admin.updated':'更新于:',
3405
3413
  'admin.sharedSkills':'共享技能',
3406
3414
  'admin.noSharedSkills':'团队暂无共享技能。',
@@ -4834,7 +4842,7 @@ function renderAdminTasks(tasks){
4834
4842
  '<div class="admin-card-tags-left">'+
4835
4843
  '<span class="admin-card-tag tag-owner">\u{1F464} '+fmtOwner(tk)+'</span>'+
4836
4844
  (tk.status?'<span class="admin-card-tag tag-status">'+esc(tk.status)+'</span>':'')+
4837
- (tk.chunkCount!=null?'<span class="admin-card-tag tag-kind">\u{1F4DD} '+tk.chunkCount+' '+t('admin.chunks')+'</span>':'')+
4845
+ (tk.chunkCount!=null?'<span class="admin-card-tag tag-kind">\u{1F4DD} '+t('admin.chunks').replace('{n}',String(tk.chunkCount))+'</span>':'')+
4838
4846
  '</div>'+
4839
4847
  '<span class="admin-card-actions" onclick="event.stopPropagation()">'+
4840
4848
  (window._isHubAdmin?'<button class="btn btn-sm btn-ghost" onclick="adminDeleteTask(&quot;'+escAttr(tk.id)+'&quot;,&quot;'+escAttr(tk.title||tk.id)+'&quot;)" style="color:var(--rose)">'+t('admin.remove')+'</button>':'')+
@@ -5155,7 +5163,7 @@ async function toggleAdminSkillCard(cardId,idx){
5155
5163
  if(files.length>0){
5156
5164
  var fileIcons={'skill':'\u{1F4D6}','script':'\u{2699}','reference':'\u{1F4CE}','file':'\u{1F4C4}'};
5157
5165
  filesHtml='<div class="admin-card-detail-section"><div class="detail-label" style="display:flex;align-items:center;justify-content:space-between">'+t('skills.files')+
5158
- '<button class="btn btn-sm btn-ghost" onclick="event.stopPropagation();window.open(\\x27/api/skill/'+encodeURIComponent(localSkillId)+'/download\\x27,\\x27_blank\\x27)" style="font-size:11px">\u2B07 '+t('skills.download')+'</button>'+
5166
+ '<button class="btn btn-sm btn-ghost" onclick="event.stopPropagation();window.open(\\x27/api/skill/'+encodeURIComponent(localSkillId)+'/download\\x27,\\x27_blank\\x27)" style="font-size:11px">'+t('skills.download')+'</button>'+
5159
5167
  '</div><div class="skill-files-list">'+
5160
5168
  files.map(function(f){return '<div class="skill-file-item">'+
5161
5169
  '<span class="skill-file-icon">'+(fileIcons[f.type]||'\u{1F4C4}')+'</span>'+
@@ -5343,7 +5351,7 @@ function openHubSkillDetailFromCache(cacheKey,idx){
5343
5351
  document.getElementById('skillDetailMeta').innerHTML=meta.join('');
5344
5352
  document.getElementById('skillDetailDesc').textContent=skill.description||'';
5345
5353
  document.getElementById('skillFilesList').innerHTML='';
5346
- document.getElementById('skillDetailContent').innerHTML=skill.content?renderSkillMarkdown(skill.content):'';
5354
+ document.getElementById('skillDetailContent').innerHTML=skill.content?renderSkillMarkdown(skill.content):('<span style="color:var(--text-muted);font-size:13px;line-height:1.6">'+t('skills.hub.markdownPending')+'</span>');
5347
5355
  document.getElementById('skillVersionsList').innerHTML='';
5348
5356
  document.getElementById('skillRelatedTasks').innerHTML='';
5349
5357
  var visBtn=document.getElementById('skillVisibilityBtn');
@@ -5577,6 +5585,10 @@ function renderSkillShareActions(skill){
5577
5585
  }
5578
5586
  function openSkillScopeModal(){
5579
5587
  if(!currentSkillDetail) return;
5588
+ if(currentSkillDetail.status!=='active'){
5589
+ toast(t('share.scope.skillNotActive'),'warn');
5590
+ return;
5591
+ }
5580
5592
  var skill=currentSkillDetail;
5581
5593
  var isLocalShared=skill.visibility==='public';
5582
5594
  var isTeamShared=!!skill.sharingVisibility;
@@ -6644,7 +6656,6 @@ async function loadSkills(silent){
6644
6656
  (tags.length>0?'<div class="skill-card-tags">'+tags.map(tg=>'<span class="skill-tag">'+esc(tg)+'</span>').join('')+'</div>':'')+
6645
6657
  '<span class="card-actions-inline" onclick="event.stopPropagation()">'+
6646
6658
  '<button class="btn btn-sm btn-ghost" onclick="openSkillDetail(&quot;'+escAttr(skill.id)+'&quot;)">'+t('card.expand')+'</button>'+
6647
- '<button class="btn btn-sm btn-danger" onclick="deleteSkill(&quot;'+escAttr(skill.id)+'&quot;)">'+t('skill.delete')+'</button>'+
6648
6659
  (skill.status==='active'
6649
6660
  ?'<button class="btn btn-sm btn-ghost" onclick="openSkillScopeModalFromList(&quot;'+escAttr(skill.id)+'&quot;,&quot;'+skillScope+'&quot;)">\\u270F '+t('share.shareBtn')+'</button>'
6650
6661
  :'<button class="btn btn-sm btn-ghost" style="opacity:0.45;cursor:not-allowed" onclick="toast(t(\\x27share.scope.skillNotActive\\x27),\\x27warn\\x27)">\\u270F '+t('share.shareBtn')+'</button>')+
@@ -6684,7 +6695,7 @@ async function loadSkills(silent){
6684
6695
  if(!query){
6685
6696
  if(hubSection) hubSection.style.display='block';
6686
6697
  var localIds=new Set(localSkills.map(function(s){return s.id;}));
6687
- if(hubList){ loadHubSkills(hubList, localIds); }
6698
+ if(hubList){ await loadHubSkills(hubList, localIds); }
6688
6699
  _st('skillsTotalCount',formatNum(localSkills.length));
6689
6700
  _st('skillsActiveCount',formatNum(localSkills.filter(s=>s.status==='active').length));
6690
6701
  _st('skillsDraftCount',formatNum(localSkills.filter(s=>s.status==='draft').length));
@@ -6805,19 +6816,31 @@ async function loadHubSkills(hubList, localIds){
6805
6816
  if(!hubList) return;
6806
6817
  var hubSection=document.getElementById('hubSkillsSection');
6807
6818
  hubList.innerHTML='<div class="spinner"></div>';
6819
+ if(hubSection) hubSection.style.display='block';
6808
6820
  try{
6809
- const r=await fetch('/api/sharing/skills/list?limit=40');
6821
+ var ctrl=new AbortController();
6822
+ var to=setTimeout(function(){try{ctrl.abort();}catch(x){}},25000);
6823
+ var r;
6824
+ try{
6825
+ r=await fetch('/api/sharing/skills/list?limit=40',{signal:ctrl.signal});
6826
+ }finally{
6827
+ clearTimeout(to);
6828
+ }
6829
+ if(!r.ok){
6830
+ var errBody='';
6831
+ try{errBody=await r.text();}catch(x2){errBody=r.statusText;}
6832
+ throw new Error(errBody||String(r.status));
6833
+ }
6810
6834
  const d=await r.json();
6811
6835
  var allSkills=Array.isArray(d.skills)?d.skills:[];
6812
6836
  const skills=localIds?allSkills.filter(function(s){return !localIds.has(s.sourceSkillId);}):allSkills;
6813
6837
  hubSkillsCache=skills;
6814
6838
  if(!skills.length){
6815
- if(hubSection) hubSection.style.display='none';
6839
+ hubList.innerHTML='<div style="text-align:center;padding:32px;color:var(--text-muted);font-size:14px">'+t('skills.hub.empty')+'</div>';
6816
6840
  return;
6817
6841
  }
6818
- if(hubSection) hubSection.style.display='block';
6819
6842
  hubList.innerHTML=skills.map(function(skill,idx){
6820
- return '<div class="hub-skill-card" onclick="openHubSkillDetailFromCache(\\\'hub\\\',' +idx+')" style="cursor:pointer">'+
6843
+ return '<div class="hub-skill-card" onclick="openHubSkillDetailFromCache(\\x27hub\\x27,'+idx+')" style="cursor:pointer">'+
6821
6844
  '<div class="summary">'+esc(skill.name)+'</div>'+
6822
6845
  '<div class="excerpt">'+esc(skill.description||'')+'</div>'+
6823
6846
  '<div class="hub-skill-meta">'+
@@ -6830,8 +6853,8 @@ async function loadHubSkills(hubList, localIds){
6830
6853
  '</div>';
6831
6854
  }).join('');
6832
6855
  }catch(e){
6833
- if(hubSection) hubSection.style.display='none';
6834
- hubList.innerHTML='';
6856
+ var msg=String((e&&e.name==='AbortError')?t('skills.hub.timeout'):(e&&e.message)||e);
6857
+ hubList.innerHTML='<div style="text-align:center;padding:32px;color:var(--rose);font-size:13px">'+esc(t('skills.hub.loadError')+': '+msg)+'</div>';
6835
6858
  }
6836
6859
  }
6837
6860
 
@@ -6896,7 +6919,17 @@ async function openSkillDetail(skillId){
6896
6919
  visBtn.className='skill-vis-btn';
6897
6920
  visBtn.textContent='\\u270F '+t('share.shareBtn');
6898
6921
  visBtn.dataset.vis=detailSkillScope;
6899
- visBtn.onclick=function(){openSkillScopeModal();};
6922
+ visBtn.style.opacity='';
6923
+ visBtn.style.cursor='';
6924
+ visBtn.style.pointerEvents='';
6925
+ if(skill.status==='active'){
6926
+ visBtn.onclick=function(){openSkillScopeModal();};
6927
+ }else{
6928
+ visBtn.style.opacity='0.45';
6929
+ visBtn.style.cursor='not-allowed';
6930
+ visBtn.style.pointerEvents='auto';
6931
+ visBtn.onclick=function(e){e.stopPropagation();toast(t('share.scope.skillNotActive'),'warn');};
6932
+ }
6900
6933
 
6901
6934
  document.getElementById('skillDetailDesc').textContent=skill.description;
6902
6935
  currentSkillDetail=skill;
@@ -4912,8 +4912,8 @@ export class ViewerServer {
4912
4912
  res.writeHead(statusCode, { "Content-Type": "application/json; charset=utf-8" });
4913
4913
  res.end(JSON.stringify(data), () => {
4914
4914
  setTimeout(() => {
4915
- this.log.info(`${source}: triggering gateway restart via process.exit (LaunchAgent will respawn)...`);
4916
- try { process.exit(0); } catch (e) { this.log.warn(`process.exit failed: ${e}`); }
4915
+ this.log.info(`${source}: triggering gateway restart via SIGUSR1...`);
4916
+ try { process.kill(process.pid, "SIGUSR1"); } catch (sig) { this.log.warn(`SIGUSR1 failed: ${sig}`); }
4917
4917
  }, delayMs);
4918
4918
  });
4919
4919
  }
@@ -0,0 +1,5 @@
1
+ {
2
+ "endpoint": "https://proj-xtrace-e218d9316b328f196a3c640cc7ca84-cn-hangzhou.cn-hangzhou.log.aliyuncs.com/rum/web/v2?workspace=default-cms-1026429231103299-cn-hangzhou&service_id=a3u72ukxmr@066657d42a13a9a9f337f",
3
+ "pid": "a3u72ukxmr@066657d42a13a9a9f337f",
4
+ "env": "prod"
5
+ }