mcp-memory-bucket 0.10.0 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -2000,7 +2000,7 @@ This removes the doc's key, tags, and status — it drops out of key-based looku
|
|
|
2000
2000
|
cursor: pointer;
|
|
2001
2001
|
}
|
|
2002
2002
|
.bulk-bar button.danger { border-color: var(--danger); color: var(--danger); }
|
|
2003
|
-
`}#e=an();#t=new u(this.#e.query??"");#s=new u(this.#e.typeFilter??"all");#r=new u(this.#e.activeTags??[]);#n=new u(this.#e.activeFolders??[]);#d=new u([]);#a=new u(sn);#i=new u(null);#l=new u(nn);#p=new u(!1);#h=new u("");#u=new u(!1);#o=new u(rn());#g=new u("");#y=new u(!1);#$=new u(this.#e.sort??"");#b=new u(this.#e.deprecatedFilter??"all");#m=new u(this.#e.pausedFilter??"all");#x=new u(this.#e.dateFrom??"");#v=new u(this.#e.dateTo??"");#f=new u(new Set);#w=new u(on());#_=new u(!1);#k=new u("entries");#R=new u([]);#P=new u([]);#C=new u(null);#A=new u(null);#E=new u(!1);#z=e=>this.#q(e);#L=()=>this.#U();constructor(){super(),new Y(this),kt(this.#w.value)}#I(e){this.#w.set(e),localStorage.setItem(Wt,e),kt(e)}#O(){const e=fe[(fe.indexOf(this.#w.value)+1)%fe.length];this.#I(e)}async#D(){if(!this.#_.value){this.#_.set(!0);try{await fetch("/api/rebuild-cache",{method:"POST"}),await Promise.all([this.#T(),this.#S(),this.#c()])}finally{this.#_.set(!1)}}}#N(e){e.preventDefault(),this.#y.set(!0),document.addEventListener("pointermove",this.#z),document.addEventListener("pointerup",this.#L)}#q(e){const t=this.renderRoot.querySelector(".body-region");if(!t)return;const s=t.getBoundingClientRect(),i=(e.clientX-s.left)/s.width*100;this.#o.set(Math.min(Zt,Math.max(Vt,i)))}#U(){this.#y.set(!1),document.removeEventListener("pointermove",this.#z),document.removeEventListener("pointerup",this.#L),localStorage.setItem(Kt,String(this.#o.value))}#j=new Ye(()=>{const e=new URLSearchParams;this.#s.value!=="all"&&e.set("type",this.#s.value),this.#t.value.trim()&&e.set("q",this.#t.value.trim());for(const t of this.#r.value)e.append("tag",t);for(const t of this.#n.value)e.append("folder",t);return this.#$.value&&e.set("sort",this.#$.value),this.#b.value==="hide"?e.set("deprecated","0"):this.#b.value==="only"&&e.set("deprecated","1"),this.#m.value==="hide"?e.set("paused","0"):this.#m.value==="only"&&e.set("paused","1"),this.#x.value&&e.set("date_from",this.#x.value),this.#v.value&&e.set("date_to",this.#v.value),e.toString()});#B=new Ye(()=>{const e=new URLSearchParams;return this.#s.value!=="all"&&e.set("type",this.#s.value),this.#t.value.trim()&&e.set("q",this.#t.value.trim()),this.#b.value==="hide"?e.set("deprecated","0"):this.#b.value==="only"&&e.set("deprecated","1"),this.#m.value==="hide"?e.set("paused","0"):this.#m.value==="only"&&e.set("paused","1"),this.#x.value&&e.set("date_from",this.#x.value),this.#v.value&&e.set("date_to",this.#v.value),e.toString()});#F=()=>this.#X();#Z=e=>this.#de(e);#W=e=>this.#he(e);#Q=()=>this.#J();#G;connectedCallback(){super.connectedCallback(),this.#c(),this.#S(),this.#T().then(()=>this.#X()),window.addEventListener("focus",this.#F),document.addEventListener("visibilitychange",this.#F),document.addEventListener("folderfoo-file-open",this.#Z),document.addEventListener("folderfoo-folder-changed",this.#W),window.addEventListener("folderfoo-auth-change",this.#Q),this.#
|
|
2003
|
+
`}#e=an();#t=new u(this.#e.query??"");#s=new u(this.#e.typeFilter??"all");#r=new u(this.#e.activeTags??[]);#n=new u(this.#e.activeFolders??[]);#d=new u([]);#a=new u(sn);#i=new u(null);#l=new u(nn);#p=new u(!1);#h=new u("");#u=new u(!1);#o=new u(rn());#g=new u("");#y=new u(!1);#$=new u(this.#e.sort??"");#b=new u(this.#e.deprecatedFilter??"all");#m=new u(this.#e.pausedFilter??"all");#x=new u(this.#e.dateFrom??"");#v=new u(this.#e.dateTo??"");#f=new u(new Set);#w=new u(on());#_=new u(!1);#k=new u("entries");#R=new u([]);#P=new u([]);#C=new u(null);#A=new u(null);#E=new u(!1);#z=e=>this.#q(e);#L=()=>this.#U();constructor(){super(),new Y(this),kt(this.#w.value)}#I(e){this.#w.set(e),localStorage.setItem(Wt,e),kt(e)}#O(){const e=fe[(fe.indexOf(this.#w.value)+1)%fe.length];this.#I(e)}async#D(){if(!this.#_.value){this.#_.set(!0);try{await fetch("/api/rebuild-cache",{method:"POST"}),await Promise.all([this.#T(),this.#S(),this.#c()])}finally{this.#_.set(!1)}}}#N(e){e.preventDefault(),this.#y.set(!0),document.addEventListener("pointermove",this.#z),document.addEventListener("pointerup",this.#L)}#q(e){const t=this.renderRoot.querySelector(".body-region");if(!t)return;const s=t.getBoundingClientRect(),i=(e.clientX-s.left)/s.width*100;this.#o.set(Math.min(Zt,Math.max(Vt,i)))}#U(){this.#y.set(!1),document.removeEventListener("pointermove",this.#z),document.removeEventListener("pointerup",this.#L),localStorage.setItem(Kt,String(this.#o.value))}#j=new Ye(()=>{const e=new URLSearchParams;this.#s.value!=="all"&&e.set("type",this.#s.value),this.#t.value.trim()&&e.set("q",this.#t.value.trim());for(const t of this.#r.value)e.append("tag",t);for(const t of this.#n.value)e.append("folder",t);return this.#$.value&&e.set("sort",this.#$.value),this.#b.value==="hide"?e.set("deprecated","0"):this.#b.value==="only"&&e.set("deprecated","1"),this.#m.value==="hide"?e.set("paused","0"):this.#m.value==="only"&&e.set("paused","1"),this.#x.value&&e.set("date_from",this.#x.value),this.#v.value&&e.set("date_to",this.#v.value),e.toString()});#B=new Ye(()=>{const e=new URLSearchParams;return this.#s.value!=="all"&&e.set("type",this.#s.value),this.#t.value.trim()&&e.set("q",this.#t.value.trim()),this.#b.value==="hide"?e.set("deprecated","0"):this.#b.value==="only"&&e.set("deprecated","1"),this.#m.value==="hide"?e.set("paused","0"):this.#m.value==="only"&&e.set("paused","1"),this.#x.value&&e.set("date_from",this.#x.value),this.#v.value&&e.set("date_to",this.#v.value),e.toString()});#F=()=>this.#X();#Z=e=>this.#de(e);#W=e=>this.#he(e);#Q=()=>this.#J();#G;connectedCallback(){super.connectedCallback(),this.#c(),this.#S(),this.#T().then(()=>this.#X()),window.addEventListener("focus",this.#F),document.addEventListener("visibilitychange",this.#F),document.addEventListener("folderfoo-file-open",this.#Z),document.addEventListener("folderfoo-folder-changed",this.#W),window.addEventListener("folderfoo-auth-change",this.#Q),this.#J(),en(),this.#G=Ht.subscribe(()=>this.#T())}async#de(e){const t=e.detail?.name;if(!t)return;const s=Xi(t);if(s.owner){this.#g.set(`"${s.name}" is from a shared folder — opening shared files here isn't supported yet.`);return}const{folderfooMode:i,folderfooHost:r}=await Z();if(!(i==="off"||!r))try{const o=await fetch("/api/folderfoo/resolve-open",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({server:r,tenantId:oe,folderPath:s.folderPath,name:s.name})}),a=await o.json();if(!o.ok){this.#g.set(a.error??`couldn't open "${s.name}"`);return}this.#g.set(""),this.#i.set({table:a.table,id:a.id})}catch(o){this.#g.set(o.message)}}async#he(e){const{path:t,action:s,newPath:i}=e.detail??{};if(!(t===void 0||!s)){if((s==="rename"||s==="move")&&i){const{folderfooHost:r}=await Z();if(!r)return;try{await fetch("/api/folders/renamed",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({server:r,oldPath:t,newPath:i})})}catch{}}this.#T()}}#Y(){return this.shadowRoot?.querySelector("app-toolbar")?.shadowRoot?.querySelector(".folderfoo-slot")??null}async#pe(){const e=this.#Y();if(!e||e.querySelector("folderfoo-profile-circle")||e.hasAttribute("data-ff-attempted"))return;e.setAttribute("data-ff-attempted","");const{folderfooMode:t,folderfooHost:s}=await Z();t==="off"||!s||$t(()=>import(`${s}/elements/folderfoo-profile-circle.js`),[]).then(async()=>{await this.updateComplete;const i=document.createElement("folderfoo-profile-circle");i.setAttribute("app-name","Memory Bucket"),i.setAttribute("tenant-id",oe),i.style.zoom="0.875",this.#Y()?.appendChild(i)}).catch(i=>{console.warn("folderfoo-profile-circle unavailable:",i.message)})}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("focus",this.#F),document.removeEventListener("visibilitychange",this.#F),document.removeEventListener("folderfoo-file-open",this.#Z),document.removeEventListener("folderfoo-folder-changed",this.#W),window.removeEventListener("folderfoo-auth-change",this.#Q),this.#G?.()}async#J(){let e=null;try{e=localStorage.getItem("folderfoo_token")}catch{return}if(!e){fetch("/api/folderfoo/logout",{method:"POST"}).catch(()=>{});return}const{folderfooMode:t,folderfooHost:s}=await Z();t==="off"||!s||fetch("/api/folderfoo/login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({server:s,token:e})}).catch(()=>{})}#H=!1;async#X(){if(document.visibilityState==="visible"){if(this.#re().some(e=>e.remote)&&!this.#H){this.#H=!0;try{await fetch("/api/remote-folders/resync-all",{method:"POST"})}catch{}finally{this.#H=!1}}this.#c(),this.#S(),this.#T(),this.renderRoot.querySelector("detail-panel")?.refresh?.()}}async#c(){const e=this.#j.value;history.replaceState(null,"",e?`#${e}`:location.pathname+location.search);const t=await fetch(`/api/entries?${e}`);this.#d.set(await t.json()),this.renderRoot.querySelector("result-list")?.scrollTo(0,0),this.#k.value==="folder-view"&&this.#ee()}async#ee(){const e=await fetch(`/api/entries?${this.#B.value}`);this.#R.set(await e.json())}async#S(){const e=this.#s.value==="all"?"":`?type=${this.#s.value}`,t=await fetch(`/api/facets${e}`);this.#a.set(await t.json())}async#T(){const t=await(await fetch("/api/folders")).json();this.#l.set(t),this.#u.set(!0);const s=new Set([...t.skill,...t.memory].map(r=>r.name)),i=this.#n.value.filter(r=>s.has(r));i.length!==this.#n.value.length&&(this.#n.set(i),this.#c())}#te(e){this.#k.set(e),e==="channels"?this.#se():e==="folder-view"&&this.#ee()}async#se(){const e=await fetch("/api/channels");this.#P.set(await e.json()),this.#C.value&&this.#ie(this.#C.value)}async#ie(e){this.#C.set(e),this.#E.set(!0);try{const t=await fetch(`/api/channels/${encodeURIComponent(e)}`);this.#A.set(t.ok?await t.json():null)}finally{this.#E.set(!1)}}#ue(e){const t=this.#n.value;this.#n.set(t.includes(e)?t.filter(s=>s!==e):[...t,e]),this.#c()}async#fe(e,t){if(t.stopPropagation(),window.prompt(`Type "${e.name}" to remove this ${e.kind} folder (files on disk are untouched):`)===e.name){this.#h.set(e.name);try{await fetch(`/api/folders/${e.kind}/${encodeURIComponent(e.name)}`,{method:"DELETE"}),this.#n.set(this.#n.value.filter(i=>i!==e.name)),await Promise.all([this.#T(),this.#S(),this.#c()])}finally{this.#h.set("")}}}#ne(){this.#p.set(!1),this.#T(),this.#S(),this.#c()}#re(){return[...this.#l.value.skill,...this.#l.value.memory].sort((e,t)=>Number(e.remote)-Number(t.remote))}#oe(e){this.#s.set(e),this.#r.set([]),this.#S(),this.#c()}#ge(e){const t=this.#r.value;this.#r.set(t.includes(e)?t.filter(s=>s!==e):[...t,e]),this.#c()}#be(e){this.#r.value.includes(e)||this.#r.set([...this.#r.value,e]),this.#c()}#me(e){this.#n.value.includes(e)||this.#n.set([...this.#n.value,e]),this.#c()}#ae(e){this.#x.set(e),this.#v.set(e),this.#c()}#ve(e){this.#t.set(e.target.value),this.#c()}#K(e){this.#t.set(e),this.#c()}#xe(){this.#t.set(""),this.#c()}#ye(e){this.#i.set({table:e._table,id:e.id})}#ke(e){this.#$.set(e.target.value),this.#c()}#$e(e){this.#b.set(e.target.value),this.#c()}#we(e){this.#m.set(e.target.value),this.#c()}#_e(e){this.#x.set(e.target.value),this.#c()}#Se(e){this.#v.set(e.target.value),this.#c()}#Ce(){this.#x.set(""),this.#v.set(""),this.#c()}#Te(e){const t=new Set(this.#f.value);t.has(e.id)?t.delete(e.id):t.add(e.id),this.#f.set(t)}#Ae(){return new Map(this.#d.value.map(e=>[e.id,e]))}#V(){const e=new Map,t=this.#Ae();for(const s of this.#f.value){const i=t.get(s);if(!i)continue;const r=e.get(i._table)??[];r.push(s),e.set(i._table,r)}return e}async#le(e){const t=this.#V();await Promise.all([...t.entries()].map(([s,i])=>fetch(`/api/entries/${s}/bulk/deprecated`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({ids:i,deprecated:e})}))),this.#f.set(new Set),await this.#c()}async#ce(e){const t=this.#V();await Promise.all([...t.entries()].map(([s,i])=>fetch(`/api/entries/${s}/bulk/paused`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({ids:i,paused:e})}))),this.#f.set(new Set),await this.#c()}async#Ee(){if(!window.confirm(`Delete ${this.#f.value.size} doc(s)? This can't be undone.`))return;const e=this.#V();await Promise.all([...e.entries()].map(([t,s])=>fetch(`/api/entries/${t}/bulk/delete`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({ids:s})}))),this.#f.set(new Set),await this.#c()}#M(e){return c`
|
|
2004
2004
|
<app-toolbar
|
|
2005
2005
|
.showReindex=${e}
|
|
2006
2006
|
.reindexing=${this.#_.value}
|
|
@@ -2012,7 +2012,7 @@ This removes the doc's key, tags, and status — it drops out of key-based looku
|
|
|
2012
2012
|
.onToggleFolderView=${()=>this.#te(this.#k.value==="folder-view"?"entries":"folder-view")}
|
|
2013
2013
|
.onCycleTheme=${()=>this.#O()}
|
|
2014
2014
|
></app-toolbar>
|
|
2015
|
-
`}render(){const e=this.#a.value,t=this.#re();return this.#k.value==="channels"?c`
|
|
2015
|
+
`}updated(){this.#pe()}render(){const e=this.#a.value,t=this.#re();return this.#k.value==="channels"?c`
|
|
2016
2016
|
<div class="toolbar-bar">${this.#M(!1)}</div>
|
|
2017
2017
|
<channel-view
|
|
2018
2018
|
.channels=${this.#P.value}
|
package/dist/client/index.html
CHANGED
package/dist/src/server.js
CHANGED
|
@@ -20,7 +20,8 @@ import { registerUiTool } from './web/ui-tool.js';
|
|
|
20
20
|
import { registerMemoryChannelTools } from './channels/tools.js';
|
|
21
21
|
import { startChannelSweep } from './channels/store.js';
|
|
22
22
|
import { startRemotePolling } from './remote/remote-sync.js';
|
|
23
|
-
import { IdentityTracker } from './remote/identity.js';
|
|
23
|
+
import { IdentityTracker, decodeUsername } from './remote/identity.js';
|
|
24
|
+
import { getCredential } from './remote/credentials.js';
|
|
24
25
|
// server.ts is rebuilt from `buildMcpServer()` on every /mcp request (see below),
|
|
25
26
|
// so tool schemas (which conditionally include `folder` based on folder count) always
|
|
26
27
|
// reflect the current folders — no restart needed after an add/remove-folder call.
|
|
@@ -38,6 +39,22 @@ const PORT = process.env.PORT ? Number(process.env.PORT) : 8767;
|
|
|
38
39
|
const config = loadConfig();
|
|
39
40
|
const db = openCache(config.cacheDbPath);
|
|
40
41
|
const identity = new IdentityTracker(config.folderfooMode);
|
|
42
|
+
// Restore the logged-in identity from a previously saved credential so a
|
|
43
|
+
// restarted process doesn't hide every remote folder (see isFolderVisible)
|
|
44
|
+
// until the user re-logs-in via the web UI - the JWT itself, not the config
|
|
45
|
+
// file's stored username, is the source of truth here since it's what
|
|
46
|
+
// login.ts's own handler decodes to call identity.setUsername() normally.
|
|
47
|
+
if (config.folderfooHost) {
|
|
48
|
+
const credential = getCredential(config.baseDir, config.folderfooHost);
|
|
49
|
+
if (credential) {
|
|
50
|
+
try {
|
|
51
|
+
identity.setUsername(decodeUsername(credential.jwt));
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// malformed/stale token - leave identity logged out, same as no credential at all
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
41
58
|
// Built ONCE and shared by reference with SkillRepository below — registerRemoteFolder/addFolder
|
|
42
59
|
// push into this same array in place, so skillSpec.sources (used by initialScan/watchSources/
|
|
43
60
|
// startRemotePolling/pollOne's upsertFile) sees a folder added live, without a restart. Evaluating
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-memory-bucket",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "MCP server exposing skill_* (reusable coding patterns) and memory_* (point-in-time working context) tools over a markdown+frontmatter source, cached into SQLite at runtime.",
|
|
6
6
|
"repository": {
|