@augmnt-sh/mindcache 0.1.1 → 0.2.0

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/cli.js CHANGED
@@ -1,107 +1,107 @@
1
1
  #!/usr/bin/env node
2
- import {StdioServerTransport}from'@modelcontextprotocol/sdk/server/stdio.js';import {McpServer}from'@modelcontextprotocol/sdk/server/mcp.js';import {existsSync,mkdirSync,writeFileSync,readFileSync,readdirSync,appendFileSync,unlinkSync}from'fs';import {dirname,join,relative,basename,extname,resolve}from'path';import {z as z$1}from'zod';import {fileURLToPath}from'url';import {homedir}from'os';import {createInterface}from'readline';function O(s,n){let c=s.split(`
3
- `),t=false,e=0,o=[];for(let r of c){let i=r.match(/^(#{1,6})\s+(.+)$/);if(i){let a=i[1].length,d=i[2].trim();if(t){if(a<=e)break;o.push(r);}else d.toLowerCase()===n.toLowerCase()&&(t=true,e=a,o.push(r));}else t&&o.push(r);}return o.length>0?o.join(`
4
- `).trim():null}function _(s,n,c){let t=s.split(`
5
- `),e=[],o=false,r=0;for(let i of t){let a=i.match(/^(#{1,6})\s+(.+)$/);if(a){let d=a[1].length,p=a[2].trim();o&&d<=r?(o=false,e.push(i)):p.toLowerCase()===n.toLowerCase()?(o=true,r=d,e.push(i),e.push(""),e.push(c),e.push("")):e.push(i);}else o||e.push(i);}return e.join(`
6
- `)}function S(s){let n=s.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);if(!n)return {frontmatter:{},body:s};let c={};for(let t of n[1].split(`
7
- `)){let e=t.indexOf(":");if(e>0){let o=t.slice(0,e).trim(),r=t.slice(e+1).trim();c[o]=r;}}return {frontmatter:c,body:n[2]}}function C(s){return [...s.matchAll(/\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/g)].map(c=>c[1])}function w(s){let n=s.matchAll(/(?:^|\s)#([a-zA-Z0-9_/-]+)/g);return [...new Set([...n].map(c=>c[1]))]}function G(s){let n=[],c=s.split(`
8
- `);for(let t=0;t<c.length;t++){let e=c[t].match(/^[\s]*-\s+\[([ xX])\]\s+(.+)$/);e&&n.push({text:e[2],done:e[1]!==" ",line:t+1});}return n}function K(s){let{body:n}=S(s);return n.split(/\s+/).filter(c=>c.length>0).length}var M=class{vaultPath;fileCache=null;fileCacheTime=0;CACHE_TTL=5e3;constructor(n){this.vaultPath=n.vault;}resolve(n){let c=join(this.vaultPath,n);if(!c.startsWith(this.vaultPath))throw new Error("Path traversal not allowed");return c}ensureDir(n){let c=dirname(n);existsSync(c)||mkdirSync(c,{recursive:true});}walkDir(n){let c=[],t;try{t=readdirSync(n,{withFileTypes:!0});}catch{return c}for(let e of t){if(e.name.startsWith(".")||e.name==="node_modules")continue;let o=join(n,e.name);e.isDirectory()?c.push(...this.walkDir(o)):c.push(o);}return c}async ping(){return existsSync(this.vaultPath)}async search(n){let t=(await this.listFiles()).filter(r=>r.extension==="md"),e=n.toLowerCase(),o=[];for(let r of t)try{let i=readFileSync(this.resolve(r.path),"utf-8"),a=i.toLowerCase(),d=a.indexOf(e);if(d>=0){let p=0,u=0;for(;(u=a.indexOf(e,u))!==-1;)p++,u+=e.length;let f=Math.max(0,d-50),l=Math.min(i.length,d+n.length+50),m=i.slice(f,l).replace(/\n/g," ").trim();o.push({filename:r.path,score:p*10+(r.name.toLowerCase().includes(e)?50:0),matches:[{match:{start:d,end:d+n.length},context:m}]});}}catch{}return o.sort((r,i)=>i.score-r.score)}async readNote(n){let c=this.resolve(n);if(!existsSync(c))throw new Error(`Note not found: ${n}`);return readFileSync(c,"utf-8")}async writeNote(n,c){let t=this.resolve(n);this.ensureDir(t),writeFileSync(t,c,"utf-8"),this.fileCache=null;}async appendToNote(n,c){let t=this.resolve(n);if(!existsSync(t))throw new Error(`Note not found: ${n}`);appendFileSync(t,c,"utf-8");}async patchNote(n,c,t){let e=this.resolve(n),o=readFileSync(e,"utf-8");if(t?.targetHeading){if(!O(o,t.targetHeading))throw new Error(`Heading "${t.targetHeading}" not found`);if(t.operation==="replace"){let i=_(o,t.targetHeading,c);writeFileSync(e,i,"utf-8");}else {let i=o.split(`
9
- `),a=t.targetHeading.toLowerCase(),d=-1;for(let p=0;p<i.length;p++){let u=i[p].match(/^#{1,6}\s+(.+)$/);if(u&&u[1].trim().toLowerCase()===a){let f=i[p].indexOf(" ");d=p+1;for(let l=p+1;l<i.length;l++){let m=i[l].match(/^(#{1,6})\s/);if(m&&m[1].length<=f)break;d=l+1;}break}}if(d>=0)i.splice(d,0,c),writeFileSync(e,i.join(`
10
- `),"utf-8");else throw new Error(`Heading "${t.targetHeading}" not found`)}}else if(t?.targetLine!==void 0){let r=o.split(`
11
- `);r.splice(t.targetLine,0,c),writeFileSync(e,r.join(`
12
- `),"utf-8");}else appendFileSync(e,c,"utf-8");}async deleteNote(n){let c=this.resolve(n);if(!existsSync(c))throw new Error(`Note not found: ${n}`);unlinkSync(c),this.fileCache=null;}async listFiles(){let n=Date.now();if(this.fileCache&&n-this.fileCacheTime<this.CACHE_TTL)return this.fileCache;let c=this.walkDir(this.vaultPath);return this.fileCache=c.map(t=>{let e=relative(this.vaultPath,t),o=basename(e,extname(e)),r=extname(e).slice(1);return {path:e,name:o,extension:r}}),this.fileCacheTime=n,this.fileCache}async getActiveNote(){throw new Error("Active note detection requires Obsidian to be running. Use search or read_note instead.")}async getActiveNotePath(){throw new Error("Active note detection requires Obsidian to be running. Use search or read_note instead.")}async searchWithContext(n,c=100){let e=(await this.listFiles()).filter(i=>i.extension==="md"),o=n.toLowerCase(),r=[];for(let i of e)try{let a=readFileSync(this.resolve(i.path),"utf-8"),d=a.toLowerCase(),p=[],u=0;for(;(u=d.indexOf(o,u))!==-1;){let f=Math.max(0,u-c),l=Math.min(a.length,u+n.length+c);if(p.push({match:{start:u,end:u+n.length},context:a.slice(f,l).replace(/\n/g," ").trim()}),u+=o.length,p.length>=5)break}p.length>0&&r.push({filename:i.path,score:p.length*10+(i.name.toLowerCase().includes(o)?50:0),matches:p});}catch{}return r.sort((i,a)=>a.score-i.score)}async health(){if(!this.vaultPath)return {ok:false,error:"No vault path configured. Run: mindcache init"};if(!existsSync(this.vaultPath))return {ok:false,error:`Vault not found at: ${this.vaultPath}`};try{return {ok:!0,noteCount:(await this.listFiles()).filter(t=>t.extension==="md").length}}catch(n){return {ok:false,error:`Cannot read vault: ${n instanceof Error?n.message:String(n)}`}}}};function X(s){let n=s.getFullYear(),c=String(s.getMonth()+1).padStart(2,"0"),t=String(s.getDate()).padStart(2,"0");return `${n}-${c}-${t}`}function y(){return X(new Date)}function H(s=new Date){let n=new Date(s),c=n.getDay(),t=n.getDate()-c+(c===0?-6:1);return n.setDate(t),n.setHours(0,0,0,0),n}function Z(s=new Date){let n=H(s),c=[];for(let t=0;t<7;t++){let e=new Date(n);e.setDate(n.getDate()+t),c.push(X(e));}return c}function tt(s){let n=new Date,c=s.toLowerCase().trim();if(c==="today"){let r=new Date(n);r.setHours(0,0,0,0);let i=new Date(n);return i.setHours(23,59,59,999),{from:r,to:i}}if(c==="yesterday"){let r=new Date(n);r.setDate(r.getDate()-1),r.setHours(0,0,0,0);let i=new Date(r);return i.setHours(23,59,59,999),{from:r,to:i}}if(c==="this week")return {from:H(n),to:n};if(c==="last week"){let r=H(n),i=new Date(r);i.setDate(i.getDate()-7);let a=new Date(r);return a.setMilliseconds(-1),{from:i,to:a}}if(c==="this month")return {from:new Date(n.getFullYear(),n.getMonth(),1),to:n};if(c==="last month"){let r=new Date(n.getFullYear(),n.getMonth()-1,1),i=new Date(n.getFullYear(),n.getMonth(),0,23,59,59,999);return {from:r,to:i}}let t=c.match(/(\d{4}-\d{2}-\d{2})\s+to\s+(\d{4}-\d{2}-\d{2})/);if(t)return {from:new Date(t[1]),to:new Date(t[2])};let e=c.match(/last\s+(\d+)\s+days?/);if(e){let r=new Date(n);return r.setDate(r.getDate()-parseInt(e[1])),r.setHours(0,0,0,0),{from:r,to:n}}let o=new Date(n);return o.setDate(o.getDate()-7),o.setHours(0,0,0,0),{from:o,to:n}}function et(s,n,c){s.tool("search",'Full-text search across your Obsidian vault. Supports Obsidian search operators: "exact phrase", path:folder, tag:#tag, file:filename. Returns matching notes with context snippets.',{query:z$1.string().describe("Search query \u2014 supports Obsidian search operators")},async({query:t})=>{try{let e=await n.searchWithContext(t,200);if(e.length===0)return {content:[{type:"text",text:`No results found for "${t}"`}]};let o=e.slice(0,20).map((r,i)=>{let a=r.matches.slice(0,3).map(d=>` > ${d.context.trim()}`).join(`
13
- `);return `${i+1}. **${r.filename}** (score: ${r.score.toFixed(1)})
2
+ import {StdioServerTransport}from'@modelcontextprotocol/sdk/server/stdio.js';import {McpServer}from'@modelcontextprotocol/sdk/server/mcp.js';import {existsSync,mkdirSync,writeFileSync,readFileSync,watch,readdirSync,statSync,appendFileSync,unlinkSync}from'fs';import {dirname,join,relative,basename,extname,resolve}from'path';import {z as z$1}from'zod';import {fileURLToPath}from'url';import {homedir}from'os';import {createInterface}from'readline';function A(s,o){let i=s.split(`
3
+ `),t=false,e=0,n=[];for(let r of i){let c=r.match(/^(#{1,6})\s+(.+)$/);if(c){let a=c[1].length,l=c[2].trim();if(t){if(a<=e)break;n.push(r);}else l.toLowerCase()===o.toLowerCase()&&(t=true,e=a,n.push(r));}else t&&n.push(r);}return n.length>0?n.join(`
4
+ `).trim():null}function L(s,o,i){let t=s.split(`
5
+ `),e=[],n=false,r=0;for(let c of t){let a=c.match(/^(#{1,6})\s+(.+)$/);if(a){let l=a[1].length,m=a[2].trim();n&&l<=r?(n=false,e.push(c)):m.toLowerCase()===o.toLowerCase()?(n=true,r=l,e.push(c),e.push(""),e.push(i),e.push("")):e.push(c);}else n||e.push(c);}return e.join(`
6
+ `)}function M(s){let o=s.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);if(!o)return {frontmatter:{},body:s};let i={};for(let t of o[1].split(`
7
+ `)){let e=t.indexOf(":");if(e>0){let n=t.slice(0,e).trim(),r=t.slice(e+1).trim();i[n]=r;}}return {frontmatter:i,body:o[2]}}function C(s){return [...s.matchAll(/\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/g)].map(i=>i[1])}function $(s){let o=s.matchAll(/(?:^|\s)#([a-zA-Z0-9_/-]+)/g);return [...new Set([...o].map(i=>i[1]))]}function B(s){let o=[],i=s.split(`
8
+ `);for(let t=0;t<i.length;t++){let e=i[t].match(/^[\s]*-\s+\[([ xX])\]\s+(.+)$/);e&&o.push({text:e[2],done:e[1]!==" ",line:t+1});}return o}function J(s){let{body:o}=M(s);return o.split(/\s+/).filter(i=>i.length>0).length}var E=class{vaultPath;fileCache=null;fileCacheTime=0;CACHE_TTL=5e3;watcher=null;constructor(o){this.vaultPath=o.vault,this.vaultPath&&existsSync(this.vaultPath)&&this.startWatcher();}startWatcher(){try{this.watcher=watch(this.vaultPath,{recursive:!0},(o,i)=>{i&&!i.startsWith(".")&&(this.fileCache=null);}),this.watcher.on("error",()=>{});}catch{}}resolve(o){let i=join(this.vaultPath,o);if(!i.startsWith(this.vaultPath))throw new Error("Path traversal not allowed");return i}ensureDir(o){let i=dirname(o);existsSync(i)||mkdirSync(i,{recursive:true});}walkDir(o){let i=[],t;try{t=readdirSync(o,{withFileTypes:!0});}catch{return i}for(let e of t){if(e.name.startsWith(".")||e.name==="node_modules")continue;let n=join(o,e.name);if(e.isDirectory())i.push(...this.walkDir(n));else try{let r=statSync(n);i.push({fullPath:n,mtime:r.mtimeMs});}catch{i.push({fullPath:n,mtime:0});}}return i}tokenize(o){return o.toLowerCase().split(/\s+/).filter(i=>i.length>1)}scoreMatch(o,i,t,e){let n=i.toLowerCase(),r=o.toLowerCase(),c=this.tokenize(o),a=[],l=0;if(n.indexOf(r)>=0){l+=100;let p=0,h=0;for(;(p=n.indexOf(r,p))!==-1&&h<5;){let y=Math.max(0,p-80),w=Math.min(i.length,p+o.length+80);a.push({start:p,end:p+o.length,context:i.slice(y,w).replace(/\n/g," ").trim()}),p+=r.length,h++;}l+=h*10;}if(c.length>1){let p=0;for(let y of c)if(n.includes(y)){p++;let w=0,_=0;for(;(w=n.indexOf(y,w))!==-1;)_++,w+=y.length;l+=_*3;}let h=p/c.length;if(l+=h*50,a.length===0&&p>0)for(let y of c){let w=n.indexOf(y);if(w>=0){let _=Math.max(0,w-80),$t=Math.min(i.length,w+y.length+80);a.push({start:w,end:w+y.length,context:i.slice(_,$t).replace(/\n/g," ").trim()});break}}}let u=t.toLowerCase();if(u.includes(r))l+=80;else for(let p of c)u.includes(p)&&(l+=25);let d=(Date.now()-e)/(1e3*60*60*24);return d<1?l+=20:d<7?l+=10:d<30&&(l+=5),{score:l,matchPositions:a}}async ping(){return existsSync(this.vaultPath)}async search(o){let t=(await this.listFiles()).filter(n=>n.extension==="md"),e=[];for(let n of t)try{let r=readFileSync(this.resolve(n.path),"utf-8"),{score:c,matchPositions:a}=this.scoreMatch(o,r,n.name,n.mtime);c>0&&a.length>0&&e.push({filename:n.path,score:c,matches:a.map(l=>({match:{start:l.start,end:l.end},context:l.context}))});}catch{}return e.sort((n,r)=>r.score-n.score)}async readNote(o){let i=this.resolve(o);if(!existsSync(i))throw new Error(`Note not found: ${o}`);return readFileSync(i,"utf-8")}async writeNote(o,i){let t=this.resolve(o);this.ensureDir(t),writeFileSync(t,i,"utf-8"),this.fileCache=null;}async appendToNote(o,i){let t=this.resolve(o);if(!existsSync(t))throw new Error(`Note not found: ${o}`);appendFileSync(t,i,"utf-8");}async patchNote(o,i,t){let e=this.resolve(o),n=readFileSync(e,"utf-8");if(t?.targetHeading){if(!A(n,t.targetHeading))throw new Error(`Heading "${t.targetHeading}" not found`);if(t.operation==="replace"){let c=L(n,t.targetHeading,i);writeFileSync(e,c,"utf-8");}else {let c=n.split(`
9
+ `),a=t.targetHeading.toLowerCase(),l=-1;for(let m=0;m<c.length;m++){let u=c[m].match(/^#{1,6}\s+(.+)$/);if(u&&u[1].trim().toLowerCase()===a){let f=c[m].indexOf(" ");l=m+1;for(let d=m+1;d<c.length;d++){let p=c[d].match(/^(#{1,6})\s/);if(p&&p[1].length<=f)break;l=d+1;}break}}if(l>=0)c.splice(l,0,i),writeFileSync(e,c.join(`
10
+ `),"utf-8");else throw new Error(`Heading "${t.targetHeading}" not found`)}}else if(t?.targetLine!==void 0){let r=n.split(`
11
+ `);r.splice(t.targetLine,0,i),writeFileSync(e,r.join(`
12
+ `),"utf-8");}else appendFileSync(e,i,"utf-8");}async deleteNote(o){let i=this.resolve(o);if(!existsSync(i))throw new Error(`Note not found: ${o}`);unlinkSync(i),this.fileCache=null;}async listFiles(){let o=Date.now();if(this.fileCache&&o-this.fileCacheTime<this.CACHE_TTL)return this.fileCache;let i=this.walkDir(this.vaultPath);return this.fileCache=i.map(({fullPath:t,mtime:e})=>{let n=relative(this.vaultPath,t),r=basename(n,extname(n)),c=extname(n).slice(1);return {path:n,name:r,extension:c,mtime:e}}).sort((t,e)=>e.mtime-t.mtime),this.fileCacheTime=o,this.fileCache}async getActiveNote(){throw new Error("Active note detection requires Obsidian to be running. Use search or read_note instead.")}async getActiveNotePath(){throw new Error("Active note detection requires Obsidian to be running. Use search or read_note instead.")}async searchWithContext(o,i=100){let e=(await this.listFiles()).filter(a=>a.extension==="md"),n=this.tokenize(o),r=o.toLowerCase(),c=[];for(let a of e)try{let l=readFileSync(this.resolve(a.path),"utf-8"),{score:m}=this.scoreMatch(o,l,a.name,a.mtime);if(m>0){let u=l.toLowerCase(),f=[],d=0;for(;(d=u.indexOf(r,d))!==-1&&f.length<5;){let p=Math.max(0,d-i),h=Math.min(l.length,d+o.length+i);f.push({match:{start:d,end:d+o.length},context:l.slice(p,h).replace(/\n/g," ").trim()}),d+=r.length;}if(f.length===0)for(let p of n){let h=u.indexOf(p);if(h>=0&&f.length<3){let y=Math.max(0,h-i),w=Math.min(l.length,h+p.length+i);f.push({match:{start:h,end:h+p.length},context:l.slice(y,w).replace(/\n/g," ").trim()});}}f.length>0&&c.push({filename:a.path,score:m,matches:f});}}catch{}return c.sort((a,l)=>l.score-a.score)}async health(){if(!this.vaultPath)return {ok:false,error:"No vault path configured. Run: mindcache init"};if(!existsSync(this.vaultPath))return {ok:false,error:`Vault not found at: ${this.vaultPath}`};try{return {ok:!0,noteCount:(await this.listFiles()).filter(t=>t.extension==="md").length}}catch(o){return {ok:false,error:`Cannot read vault: ${o instanceof Error?o.message:String(o)}`}}}close(){this.watcher&&(this.watcher.close(),this.watcher=null);}};function tt(s){let o=s.getFullYear(),i=String(s.getMonth()+1).padStart(2,"0"),t=String(s.getDate()).padStart(2,"0");return `${o}-${i}-${t}`}function x(){return tt(new Date)}function z(s=new Date){let o=new Date(s),i=o.getDay(),t=o.getDate()-i+(i===0?-6:1);return o.setDate(t),o.setHours(0,0,0,0),o}function et(s=new Date){let o=z(s),i=[];for(let t=0;t<7;t++){let e=new Date(o);e.setDate(o.getDate()+t),i.push(tt(e));}return i}function nt(s){let o=new Date,i=s.toLowerCase().trim();if(i==="today"){let r=new Date(o);r.setHours(0,0,0,0);let c=new Date(o);return c.setHours(23,59,59,999),{from:r,to:c}}if(i==="yesterday"){let r=new Date(o);r.setDate(r.getDate()-1),r.setHours(0,0,0,0);let c=new Date(r);return c.setHours(23,59,59,999),{from:r,to:c}}if(i==="this week")return {from:z(o),to:o};if(i==="last week"){let r=z(o),c=new Date(r);c.setDate(c.getDate()-7);let a=new Date(r);return a.setMilliseconds(-1),{from:c,to:a}}if(i==="this month")return {from:new Date(o.getFullYear(),o.getMonth(),1),to:o};if(i==="last month"){let r=new Date(o.getFullYear(),o.getMonth()-1,1),c=new Date(o.getFullYear(),o.getMonth(),0,23,59,59,999);return {from:r,to:c}}let t=i.match(/(\d{4}-\d{2}-\d{2})\s+to\s+(\d{4}-\d{2}-\d{2})/);if(t)return {from:new Date(t[1]),to:new Date(t[2])};let e=i.match(/last\s+(\d+)\s+days?/);if(e){let r=new Date(o);return r.setDate(r.getDate()-parseInt(e[1])),r.setHours(0,0,0,0),{from:r,to:o}}let n=new Date(o);return n.setDate(n.getDate()-7),n.setHours(0,0,0,0),{from:n,to:o}}function ot(s,o,i){s.tool("search",'Full-text search across your Obsidian vault. Supports Obsidian search operators: "exact phrase", path:folder, tag:#tag, file:filename. Returns matching notes with context snippets.',{query:z$1.string().describe("Search query \u2014 supports Obsidian search operators")},async({query:t})=>{try{let e=await o.searchWithContext(t,200);if(e.length===0)return {content:[{type:"text",text:`No results found for "${t}"`}]};let n=e.slice(0,20).map((r,c)=>{let a=r.matches.slice(0,3).map(l=>` > ${l.context.trim()}`).join(`
13
+ `);return `${c+1}. **${r.filename}** (score: ${r.score.toFixed(1)})
14
14
  ${a}`}).join(`
15
15
 
16
16
  `);return {content:[{type:"text",text:`Found ${e.length} results for "${t}":
17
17
 
18
- ${o}`}]}}catch(e){return {content:[{type:"text",text:`Search error: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("ask","Ask a natural language question about your vault. Searches for relevant notes and returns their content so you can synthesize an answer. Use this when you need to understand what the user knows about a topic.",{question:z$1.string().describe("Natural language question to answer from vault knowledge")},async({question:t})=>{try{let e=await n.searchWithContext(t,300);if(e.length===0)return {content:[{type:"text",text:`No relevant notes found for: "${t}"`}]};let o=e.slice(0,5),r=[];for(let i of o)try{let a=await n.readNote(i.filename),{frontmatter:d}=S(a),p=w(a),u=C(a),f=a.length>2e3?a.slice(0,2e3)+`
18
+ ${n}`}]}}catch(e){return {content:[{type:"text",text:`Search error: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("ask","Ask a natural language question about your vault. Searches for relevant notes and returns their content so you can synthesize an answer. Use this when you need to understand what the user knows about a topic.",{question:z$1.string().describe("Natural language question to answer from vault knowledge")},async({question:t})=>{try{let e=await o.searchWithContext(t,300);if(e.length===0)return {content:[{type:"text",text:`No relevant notes found for: "${t}"`}]};let n=e.slice(0,5),r=[];for(let c of n)try{let a=await o.readNote(c.filename),{frontmatter:l}=M(a),m=$(a),u=C(a),f=a.length>2e3?a.slice(0,2e3)+`
19
19
  ...(truncated)`:a;r.push(`---
20
- **${i.filename}**`+(p.length>0?` | Tags: ${p.map(l=>`#${l}`).join(", ")}`:"")+(u.length>0?` | Links: ${u.map(l=>`[[${l}]]`).join(", ")}`:"")+(d.type?` | Type: ${d.type}`:"")+`
20
+ **${c.filename}**`+(m.length>0?` | Tags: ${m.map(d=>`#${d}`).join(", ")}`:"")+(u.length>0?` | Links: ${u.map(d=>`[[${d}]]`).join(", ")}`:"")+(l.type?` | Type: ${l.type}`:"")+`
21
21
 
22
22
  ${f}`);}catch{}return {content:[{type:"text",text:`Found ${e.length} relevant notes for "${t}". Here are the top ${r.length}:
23
23
 
24
24
  ${r.join(`
25
25
 
26
- `)}`}]}}catch(e){return {content:[{type:"text",text:`Ask error: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("find_related","Find notes related to a given note via backlinks, shared tags, or shared wikilinks. Returns notes that are connected in the knowledge graph.",{path:z$1.string().describe('Path to the note (e.g., "Projects/My Project.md")')},async({path:t})=>{try{let e=await n.readNote(t),o=C(e),r=w(e),i=new Map;for(let f of o){let l=await n.search(`file:${f}`);for(let m of l.slice(0,3))m.filename!==t&&i.set(m.filename,{reason:`Linked from this note: [[${f}]]`,score:(i.get(m.filename)?.score??0)+2});}for(let f of r.slice(0,5)){let l=await n.search(`tag:#${f}`);for(let m of l.slice(0,5))if(m.filename!==t){let h=i.get(m.filename);i.set(m.filename,{reason:h?`${h.reason}; Shared tag: #${f}`:`Shared tag: #${f}`,score:(h?.score??0)+1});}}let a=t.replace(/\.md$/,"").split("/").pop()??t,d=await n.search(`"[[${a}]]"`);for(let f of d)if(f.filename!==t){let l=i.get(f.filename);i.set(f.filename,{reason:l?`${l.reason}; Links to this note`:"Links to this note",score:(l?.score??0)+3});}let p=[...i.entries()].sort((f,l)=>l[1].score-f[1].score).slice(0,15);if(p.length===0)return {content:[{type:"text",text:`No related notes found for "${t}"`}]};let u=p.map(([f,l],m)=>`${m+1}. **${f}** \u2014 ${l.reason}`).join(`
26
+ `)}`}]}}catch(e){return {content:[{type:"text",text:`Ask error: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("find_related","Find notes related to a given note via backlinks, shared tags, or shared wikilinks. Returns notes that are connected in the knowledge graph.",{path:z$1.string().describe('Path to the note (e.g., "Projects/My Project.md")')},async({path:t})=>{try{let e=await o.readNote(t),n=C(e),r=$(e),c=new Map;for(let f of n){let d=await o.search(`file:${f}`);for(let p of d.slice(0,3))p.filename!==t&&c.set(p.filename,{reason:`Linked from this note: [[${f}]]`,score:(c.get(p.filename)?.score??0)+2});}for(let f of r.slice(0,5)){let d=await o.search(`tag:#${f}`);for(let p of d.slice(0,5))if(p.filename!==t){let h=c.get(p.filename);c.set(p.filename,{reason:h?`${h.reason}; Shared tag: #${f}`:`Shared tag: #${f}`,score:(h?.score??0)+1});}}let a=t.replace(/\.md$/,"").split("/").pop()??t,l=await o.search(`"[[${a}]]"`);for(let f of l)if(f.filename!==t){let d=c.get(f.filename);c.set(f.filename,{reason:d?`${d.reason}; Links to this note`:"Links to this note",score:(d?.score??0)+3});}let m=[...c.entries()].sort((f,d)=>d[1].score-f[1].score).slice(0,15);if(m.length===0)return {content:[{type:"text",text:`No related notes found for "${t}"`}]};let u=m.map(([f,d],p)=>`${p+1}. **${f}** \u2014 ${d.reason}`).join(`
27
27
  `);return {content:[{type:"text",text:`Related notes for "${t}":
28
28
 
29
- ${u}`}]}}catch(e){return {content:[{type:"text",text:`Find related error: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("find_by_tag","Find all notes with specific tags. Supports multiple tags (all must match). Use without # prefix.",{tags:z$1.array(z$1.string()).describe('Tags to search for (without # prefix, e.g., ["project", "active"])'),limit:z$1.number().optional().default(20).describe("Maximum number of results")},async({tags:t,limit:e})=>{try{let o=t.map(a=>`tag:#${a}`).join(" "),r=await n.search(o);if(r.length===0)return {content:[{type:"text",text:`No notes found with tags: ${t.map(a=>`#${a}`).join(", ")}`}]};let i=r.slice(0,e).map((a,d)=>`${d+1}. ${a.filename}`).join(`
29
+ ${u}`}]}}catch(e){return {content:[{type:"text",text:`Find related error: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("find_by_tag","Find all notes with specific tags. Supports multiple tags (all must match). Use without # prefix.",{tags:z$1.array(z$1.string()).describe('Tags to search for (without # prefix, e.g., ["project", "active"])'),limit:z$1.number().optional().default(20).describe("Maximum number of results")},async({tags:t,limit:e})=>{try{let n=t.map(a=>`tag:#${a}`).join(" "),r=await o.search(n);if(r.length===0)return {content:[{type:"text",text:`No notes found with tags: ${t.map(a=>`#${a}`).join(", ")}`}]};let c=r.slice(0,e).map((a,l)=>`${l+1}. ${a.filename}`).join(`
30
30
  `);return {content:[{type:"text",text:`Notes tagged ${t.map(a=>`#${a}`).join(", ")} (${r.length} total):
31
31
 
32
- ${i}`}]}}catch(o){return {content:[{type:"text",text:`Tag search error: ${o instanceof Error?o.message:String(o)}`}],isError:true}}}),s.tool("find_by_date",'Find notes created or modified within a date range. Supports natural language like "today", "this week", "last month", "last 7 days", or explicit "YYYY-MM-DD to YYYY-MM-DD".',{range:z$1.string().describe('Date range \u2014 "today", "this week", "last month", "last 30 days", or "YYYY-MM-DD to YYYY-MM-DD"'),limit:z$1.number().optional().default(20).describe("Maximum results")},async({range:t,limit:e})=>{try{let{from:o,to:r}=tt(t),a=(await n.listFiles()).filter(l=>l.extension==="md"),d=o.toISOString().split("T")[0],p=r.toISOString().split("T")[0],f=(await n.search(`"${d}"`)).slice(0,e).map((l,m)=>`${m+1}. ${l.filename}`).join(`
33
- `);return {content:[{type:"text",text:`Notes from ${d} to ${p} (searched by date reference):
32
+ ${c}`}]}}catch(n){return {content:[{type:"text",text:`Tag search error: ${n instanceof Error?n.message:String(n)}`}],isError:true}}}),s.tool("find_by_date",'Find notes created or modified within a date range. Supports natural language like "today", "this week", "last month", "last 7 days", or explicit "YYYY-MM-DD to YYYY-MM-DD".',{range:z$1.string().describe('Date range \u2014 "today", "this week", "last month", "last 30 days", or "YYYY-MM-DD to YYYY-MM-DD"'),limit:z$1.number().optional().default(20).describe("Maximum results")},async({range:t,limit:e})=>{try{let{from:n,to:r}=nt(t),a=(await o.listFiles()).filter(d=>d.extension==="md"),l=n.toISOString().split("T")[0],m=r.toISOString().split("T")[0],f=(await o.search(`"${l}"`)).slice(0,e).map((d,p)=>`${p+1}. ${d.filename}`).join(`
33
+ `);return {content:[{type:"text",text:`Notes from ${l} to ${m} (searched by date reference):
34
34
 
35
35
  `+(f||"No notes found in this range.")+`
36
36
 
37
- Total markdown files in vault: ${a.length}`}]}}catch(o){return {content:[{type:"text",text:`Date search error: ${o instanceof Error?o.message:String(o)}`}],isError:true}}}),s.tool("find_recent","List notes in the vault. Returns markdown files from the vault file listing.",{limit:z$1.number().optional().default(10).describe("Number of recent notes to return")},async({limit:t})=>{try{let o=(await n.listFiles()).filter(a=>a.extension==="md"),i=o.slice(0,t).map((a,d)=>`${d+1}. ${a.path}`).join(`
38
- `);return {content:[{type:"text",text:`Vault files (${o.length} total markdown notes):
37
+ Total markdown files in vault: ${a.length}`}]}}catch(n){return {content:[{type:"text",text:`Date search error: ${n instanceof Error?n.message:String(n)}`}],isError:true}}}),s.tool("find_recent","Get recently modified notes in the vault, sorted by modification time (newest first).",{limit:z$1.number().optional().default(10).describe("Number of recent notes to return")},async({limit:t})=>{try{let n=(await o.listFiles()).filter(a=>a.extension==="md"),c=n.slice(0,t).map((a,l)=>{let m=Date.now()-a.mtime,u=Math.floor(m/6e4),f=Math.floor(u/60),d=Math.floor(f/24),p=d>0?`${d}d ago`:f>0?`${f}h ago`:`${u}m ago`;return `${l+1}. ${a.path} \u2014 ${p}`}).join(`
38
+ `);return {content:[{type:"text",text:`Recently modified notes (${n.length} total):
39
39
 
40
- ${i}`}]}}catch(e){return {content:[{type:"text",text:`Recent notes error: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("find_mentions","Find all notes that mention a specific term, concept, or person. Searches for exact text matches across the vault.",{term:z$1.string().describe("Term or concept to search for"),limit:z$1.number().optional().default(20).describe("Maximum results")},async({term:t,limit:e})=>{try{let o=await n.searchWithContext(t,150);if(o.length===0)return {content:[{type:"text",text:`"${t}" is not mentioned in any notes.`}]};let r=o.slice(0,e).map((i,a)=>{let d=i.matches[0]?.context?.trim()??"";return `${a+1}. **${i.filename}**
41
- > ${d}`}).join(`
40
+ ${c}`}]}}catch(e){return {content:[{type:"text",text:`Recent notes error: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("find_mentions","Find all notes that mention a specific term, concept, or person. Searches for exact text matches across the vault.",{term:z$1.string().describe("Term or concept to search for"),limit:z$1.number().optional().default(20).describe("Maximum results")},async({term:t,limit:e})=>{try{let n=await o.searchWithContext(t,150);if(n.length===0)return {content:[{type:"text",text:`"${t}" is not mentioned in any notes.`}]};let r=n.slice(0,e).map((c,a)=>{let l=c.matches[0]?.context?.trim()??"";return `${a+1}. **${c.filename}**
41
+ > ${l}`}).join(`
42
42
 
43
- `);return {content:[{type:"text",text:`"${t}" mentioned in ${o.length} notes:
43
+ `);return {content:[{type:"text",text:`"${t}" mentioned in ${n.length} notes:
44
44
 
45
- ${r}`}]}}catch(o){return {content:[{type:"text",text:`Mentions search error: ${o instanceof Error?o.message:String(o)}`}],isError:true}}});}function nt(s,n,c){s.tool("read_note","Read the full content of a note by its path. Returns the complete markdown including frontmatter.",{path:z$1.string().describe('Path to the note (e.g., "Projects/My Project.md")')},async({path:t})=>{try{return {content:[{type:"text",text:await n.readNote(t)}]}}catch(e){return {content:[{type:"text",text:`Could not read "${t}": ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("read_section","Read a specific section from a note, identified by its heading. Returns content from the heading to the next heading of the same or higher level.",{path:z$1.string().describe("Path to the note"),heading:z$1.string().describe('Heading text to extract (e.g., "Key Points", "Action Items")')},async({path:t,heading:e})=>{try{let o=await n.readNote(t),r=O(o,e);return r?{content:[{type:"text",text:r}]}:{content:[{type:"text",text:`No section "${e}" found in "${t}"`}]}}catch(o){return {content:[{type:"text",text:`Could not read section: ${o instanceof Error?o.message:String(o)}`}],isError:true}}}),s.tool("read_summary","Get a note with its metadata: frontmatter properties, tags, wikilinks, and word count. Useful for understanding a note without reading it fully.",{path:z$1.string().describe("Path to the note")},async({path:t})=>{try{let e=await n.readNote(t),{frontmatter:o}=S(e),r=w(e),i=C(e),a=K(e);return {content:[{type:"text",text:[`**${t}**`,"",`**Words:** ${a}`,r.length>0?`**Tags:** ${r.map(p=>`#${p}`).join(", ")}`:null,i.length>0?`**Links:** ${i.map(p=>`[[${p}]]`).join(", ")}`:null,Object.keys(o).length>0?`**Properties:**
46
- ${Object.entries(o).map(([p,u])=>` - ${p}: ${u}`).join(`
45
+ ${r}`}]}}catch(n){return {content:[{type:"text",text:`Mentions search error: ${n instanceof Error?n.message:String(n)}`}],isError:true}}});}function rt(s,o,i){s.tool("read_note","Read the full content of a note by its path. Returns the complete markdown including frontmatter.",{path:z$1.string().describe('Path to the note (e.g., "Projects/My Project.md")')},async({path:t})=>{try{return {content:[{type:"text",text:await o.readNote(t)}]}}catch(e){return {content:[{type:"text",text:`Could not read "${t}": ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("read_section","Read a specific section from a note, identified by its heading. Returns content from the heading to the next heading of the same or higher level.",{path:z$1.string().describe("Path to the note"),heading:z$1.string().describe('Heading text to extract (e.g., "Key Points", "Action Items")')},async({path:t,heading:e})=>{try{let n=await o.readNote(t),r=A(n,e);return r?{content:[{type:"text",text:r}]}:{content:[{type:"text",text:`No section "${e}" found in "${t}"`}]}}catch(n){return {content:[{type:"text",text:`Could not read section: ${n instanceof Error?n.message:String(n)}`}],isError:true}}}),s.tool("read_summary","Get a note with its metadata: frontmatter properties, tags, wikilinks, and word count. Useful for understanding a note without reading it fully.",{path:z$1.string().describe("Path to the note")},async({path:t})=>{try{let e=await o.readNote(t),{frontmatter:n}=M(e),r=$(e),c=C(e),a=J(e);return {content:[{type:"text",text:[`**${t}**`,"",`**Words:** ${a}`,r.length>0?`**Tags:** ${r.map(m=>`#${m}`).join(", ")}`:null,c.length>0?`**Links:** ${c.map(m=>`[[${m}]]`).join(", ")}`:null,Object.keys(n).length>0?`**Properties:**
46
+ ${Object.entries(n).map(([m,u])=>` - ${m}: ${u}`).join(`
47
47
  `)}`:null,"","---","",e].filter(Boolean).join(`
48
- `)}]}}catch(e){return {content:[{type:"text",text:`Could not read summary: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("read_properties","Read only the YAML frontmatter properties of a note. Fast way to check metadata without reading the full content.",{path:z$1.string().describe("Path to the note")},async({path:t})=>{try{let e=await n.readNote(t),{frontmatter:o}=S(e);if(Object.keys(o).length===0)return {content:[{type:"text",text:`No frontmatter found in "${t}"`}]};let r=Object.entries(o).map(([i,a])=>`${i}: ${a}`).join(`
48
+ `)}]}}catch(e){return {content:[{type:"text",text:`Could not read summary: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("read_properties","Read only the YAML frontmatter properties of a note. Fast way to check metadata without reading the full content.",{path:z$1.string().describe("Path to the note")},async({path:t})=>{try{let e=await o.readNote(t),{frontmatter:n}=M(e);if(Object.keys(n).length===0)return {content:[{type:"text",text:`No frontmatter found in "${t}"`}]};let r=Object.entries(n).map(([c,a])=>`${c}: ${a}`).join(`
49
49
  `);return {content:[{type:"text",text:`Properties of "${t}":
50
50
 
51
- ${r}`}]}}catch(e){return {content:[{type:"text",text:`Could not read properties: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("read_today","Read today's daily note. Returns the content of today's daily note based on your configured daily notes folder and format.",{},async()=>{try{let t=`${c.dailyNotes.folder}/${y()}.md`,e=await n.readNote(t);return {content:[{type:"text",text:`**Today's Daily Note (${y()}):**
51
+ ${r}`}]}}catch(e){return {content:[{type:"text",text:`Could not read properties: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("read_today","Read today's daily note. Returns the content of today's daily note based on your configured daily notes folder and format.",{},async()=>{try{let t=`${i.dailyNotes.folder}/${x()}.md`,e=await o.readNote(t);return {content:[{type:"text",text:`**Today's Daily Note (${x()}):**
52
52
 
53
- ${e}`}]}}catch{return {content:[{type:"text",text:`No daily note found for today (${y()}). Expected at: ${c.dailyNotes.folder}/${y()}.md`}]}}}),s.tool("read_this_week","Read all daily notes from the current week (Monday to Sunday). Useful for getting a weekly overview of activity.",{},async()=>{try{let t=Z(),e=[];for(let o of t){let r=`${c.dailyNotes.folder}/${o}.md`;try{let i=await n.readNote(r);e.push(`## ${o}
53
+ ${e}`}]}}catch{return {content:[{type:"text",text:`No daily note found for today (${x()}). Expected at: ${i.dailyNotes.folder}/${x()}.md`}]}}}),s.tool("read_this_week","Read all daily notes from the current week (Monday to Sunday). Useful for getting a weekly overview of activity.",{},async()=>{try{let t=et(),e=[];for(let n of t){let r=`${i.dailyNotes.folder}/${n}.md`;try{let c=await o.readNote(r);e.push(`## ${n}
54
54
 
55
- ${i}`);}catch{}}return e.length===0?{content:[{type:"text",text:`No daily notes found for this week (${t[0]} to ${t[6]}).`}]}:{content:[{type:"text",text:`**This Week's Daily Notes:**
55
+ ${c}`);}catch{}}return e.length===0?{content:[{type:"text",text:`No daily notes found for this week (${t[0]} to ${t[6]}).`}]}:{content:[{type:"text",text:`**This Week's Daily Notes:**
56
56
 
57
57
  ${e.join(`
58
58
 
59
59
  ---
60
60
 
61
- `)}`}]}}catch(t){return {content:[{type:"text",text:`Could not read weekly notes: ${t instanceof Error?t.message:String(t)}`}],isError:true}}}),s.tool("get_active_note","Get the currently active/open note in Obsidian. Returns both the path and content of the note the user is currently viewing.",{},async()=>{try{let t=await n.getActiveNote(),e="";try{e=await n.getActiveNotePath();}catch{}return {content:[{type:"text",text:e?`**Active Note: ${e}**
61
+ `)}`}]}}catch(t){return {content:[{type:"text",text:`Could not read weekly notes: ${t instanceof Error?t.message:String(t)}`}],isError:true}}}),s.tool("get_active_note","Get the currently active/open note in Obsidian. Returns both the path and content of the note the user is currently viewing.",{},async()=>{try{let t=await o.getActiveNote(),e="";try{e=await o.getActiveNotePath();}catch{}return {content:[{type:"text",text:e?`**Active Note: ${e}**
62
62
 
63
63
  ${t}`:`**Active Note:**
64
64
 
65
- ${t}`}]}}catch(t){return {content:[{type:"text",text:`Could not get active note: ${t instanceof Error?t.message:String(t)}`}],isError:true}}});}var Tt=dirname(fileURLToPath(import.meta.url)),Et=join(Tt,"..","templates"),U=new Map;function Ft(s){if(U.has(s))return U.get(s);let n=join(Et,`${s}.md`);if(!existsSync(n))throw new Error(`Template "${s}" not found at ${n}`);let c=readFileSync(n,"utf-8");return U.set(s,c),c}function Dt(s,n){let c=s,e={...{date:y(),timestamp:new Date().toISOString(),year:String(new Date().getFullYear()),month:String(new Date().getMonth()+1).padStart(2,"0"),day:String(new Date().getDate()).padStart(2,"0")},...n};for(let[o,r]of Object.entries(e))c=c.replaceAll(`{{${o}}}`,r??"");return c=c.replace(/\{\{[^}]+\}\}/g,""),c}function N(s,n={}){let c=Ft(s);return Dt(c,n)}function rt(s,n,c){s.tool("remember","Quick capture \u2014 save a thought, note, or piece of information to the vault. Auto-saves to the inbox folder. Use this for quick, unstructured captures.",{content:z$1.string().describe("The content to save"),title:z$1.string().optional().describe("Optional title for the note. If omitted, generates from content."),tags:z$1.array(z$1.string()).optional().describe("Optional tags to add (without # prefix)"),folder:z$1.string().optional().describe("Optional folder to save to (defaults to inbox)")},async({content:t,title:e,tags:o,folder:r})=>{try{let i=e??`Quick Note - ${y()} ${new Date().toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit"})}`,d=`${r??c.inbox.folder}/${i}.md`,p=o&&o.length>0?`tags:
66
- ${o.map(f=>` - ${f}`).join(`
65
+ ${t}`}]}}catch(t){return {content:[{type:"text",text:`Could not get active note: ${t instanceof Error?t.message:String(t)}`}],isError:true}}});}var Pt=dirname(fileURLToPath(import.meta.url)),Ot=join(Pt,"..","templates"),V=new Map;function jt(s){if(V.has(s))return V.get(s);let o=join(Ot,`${s}.md`);if(!existsSync(o))throw new Error(`Template "${s}" not found at ${o}`);let i=readFileSync(o,"utf-8");return V.set(s,i),i}function _t(s,o){let i=s,e={...{date:x(),timestamp:new Date().toISOString(),year:String(new Date().getFullYear()),month:String(new Date().getMonth()+1).padStart(2,"0"),day:String(new Date().getDate()).padStart(2,"0")},...o};for(let[n,r]of Object.entries(e))i=i.replaceAll(`{{${n}}}`,r??"");return i=i.replace(/\{\{[^}]+\}\}/g,""),i}function N(s,o={}){let i=jt(s);return _t(i,o)}function it(s,o,i){s.tool("remember","Quick capture \u2014 save a thought, note, or piece of information to the vault. Auto-saves to the inbox folder. Use this for quick, unstructured captures.",{content:z$1.string().describe("The content to save"),title:z$1.string().optional().describe("Optional title for the note. If omitted, generates from content."),tags:z$1.array(z$1.string()).optional().describe("Optional tags to add (without # prefix)"),folder:z$1.string().optional().describe("Optional folder to save to (defaults to inbox)")},async({content:t,title:e,tags:n,folder:r})=>{try{let c=e??`Quick Note - ${x()} ${new Date().toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit"})}`,l=`${r??i.inbox.folder}/${c}.md`,m=n&&n.length>0?`tags:
66
+ ${n.map(f=>` - ${f}`).join(`
67
67
  `)}`:`tags:
68
68
  - inbox`,u=`---
69
- date: ${y()}
70
- ${p}
69
+ date: ${x()}
70
+ ${m}
71
71
  ---
72
72
 
73
73
  ${t}
74
- `;return await n.writeNote(d,u),{content:[{type:"text",text:`Saved to "${d}"`}]}}catch(i){return {content:[{type:"text",text:`Could not save note: ${i instanceof Error?i.message:String(i)}`}],isError:true}}}),s.tool("remember_meeting","Create a structured meeting note with attendees, agenda, notes, and action items. Uses the meeting template.",{title:z$1.string().describe("Meeting title"),attendees:z$1.string().describe("Comma-separated list of attendees"),agenda:z$1.string().optional().default("").describe("Meeting agenda"),notes:z$1.string().optional().default("").describe("Meeting notes"),action_items:z$1.string().optional().default("").describe("Action items from the meeting"),follow_up:z$1.string().optional().default("").describe("Follow-up items"),folder:z$1.string().optional().describe("Folder to save to (defaults to inbox)")},async({title:t,attendees:e,agenda:o,notes:r,action_items:i,follow_up:a,folder:d})=>{try{let p=N("meeting",{title:t,attendees:e,agenda:o,notes:r,action_items:i,follow_up:a}),f=`${d??c.inbox.folder}/${t}.md`;return await n.writeNote(f,p),{content:[{type:"text",text:`Meeting note created at "${f}"`}]}}catch(p){return {content:[{type:"text",text:`Could not create meeting note: ${p instanceof Error?p.message:String(p)}`}],isError:true}}}),s.tool("remember_decision","Log a decision using the ADR (Architecture Decision Record) format. Captures the context, decision, consequences, and alternatives considered.",{title:z$1.string().describe("Decision title"),context:z$1.string().describe("Why this decision needed to be made"),decision:z$1.string().describe("What was decided"),consequences:z$1.string().optional().default("").describe("What happens as a result"),alternatives:z$1.string().optional().default("").describe("Other options that were considered"),related:z$1.string().optional().default("").describe("Related notes or concepts"),folder:z$1.string().optional().describe("Folder to save to")},async({title:t,context:e,decision:o,consequences:r,alternatives:i,related:a,folder:d})=>{try{let p=N("decision",{title:t,context:e,decision:o,consequences:r,alternatives:i,related:a}),f=`${d??c.inbox.folder}/${t}.md`;return await n.writeNote(f,p),{content:[{type:"text",text:`Decision logged at "${f}"`}]}}catch(p){return {content:[{type:"text",text:`Could not log decision: ${p instanceof Error?p.message:String(p)}`}],isError:true}}}),s.tool("remember_idea","Capture an idea with context on why it matters and potential next steps.",{title:z$1.string().describe("Idea title"),idea:z$1.string().describe("Description of the idea"),why:z$1.string().optional().default("").describe("Why this idea matters"),next_steps:z$1.string().optional().default("").describe("Potential next steps"),related:z$1.string().optional().default("").describe("Related notes or concepts"),tags:z$1.array(z$1.string()).optional().describe("Additional tags"),folder:z$1.string().optional().describe("Folder to save to")},async({title:t,idea:e,why:o,next_steps:r,related:i,folder:a})=>{try{let d=N("idea",{title:t,idea:e,why:o,next_steps:r,related:i}),u=`${a??c.inbox.folder}/${t}.md`;return await n.writeNote(u,d),{content:[{type:"text",text:`Idea captured at "${u}"`}]}}catch(d){return {content:[{type:"text",text:`Could not capture idea: ${d instanceof Error?d.message:String(d)}`}],isError:true}}}),s.tool("remember_learning","Save something new you learned \u2014 a concept, technique, insight, or skill with examples and application notes.",{title:z$1.string().describe("What was learned"),concept:z$1.string().describe("The concept or insight"),key_points:z$1.string().optional().default("").describe("Key points to remember"),examples:z$1.string().optional().default("").describe("Examples or illustrations"),application:z$1.string().optional().default("").describe("How to apply this learning"),source:z$1.string().optional().default("").describe("Where you learned this"),related:z$1.string().optional().default("").describe("Related notes"),folder:z$1.string().optional().describe("Folder to save to")},async({title:t,concept:e,key_points:o,examples:r,application:i,source:a,related:d,folder:p})=>{try{let u=N("learning",{title:t,concept:e,key_points:o,examples:r,application:i,source:a,related:d}),l=`${p??c.inbox.folder}/${t}.md`;return await n.writeNote(l,u),{content:[{type:"text",text:`Learning saved at "${l}"`}]}}catch(u){return {content:[{type:"text",text:`Could not save learning: ${u instanceof Error?u.message:String(u)}`}],isError:true}}}),s.tool("remember_person","Create or update a note about a person \u2014 their role, organization, context, and interactions.",{name:z$1.string().describe("Person's name"),role:z$1.string().optional().default("").describe("Their role or title"),organization:z$1.string().optional().default("").describe("Their organization"),contact:z$1.string().optional().default("").describe("Contact information"),context:z$1.string().optional().default("").describe("How you know them or relevant context"),interaction:z$1.string().optional().default("").describe("Notes from recent interaction"),notes:z$1.string().optional().default("").describe("Additional notes"),folder:z$1.string().optional().describe("Folder to save to")},async({name:t,role:e,organization:o,contact:r,context:i,interaction:a,notes:d,folder:p})=>{try{let u=N("person",{name:t,role:e,organization:o,contact:r,context:i,interaction:a,notes:d}),l=`${p??c.inbox.folder}/${t}.md`;return await n.writeNote(l,u),{content:[{type:"text",text:`Person note created at "${l}"`}]}}catch(u){return {content:[{type:"text",text:`Could not create person note: ${u instanceof Error?u.message:String(u)}`}],isError:true}}}),s.tool("remember_reference","Bookmark a URL or resource with a summary, tags, and personal notes. Great for saving articles, videos, tools, or documentation.",{title:z$1.string().describe("Title of the resource"),url:z$1.string().describe("URL of the resource"),source:z$1.string().optional().default("").describe('Source (e.g., "Hacker News", "Twitter")'),summary:z$1.string().optional().default("").describe("Brief summary"),takeaways:z$1.string().optional().default("").describe("Key takeaways"),thoughts:z$1.string().optional().default("").describe("Your personal thoughts"),related:z$1.string().optional().default("").describe("Related notes"),tags:z$1.array(z$1.string()).optional().describe("Tags for categorization"),folder:z$1.string().optional().describe("Folder to save to")},async({title:t,url:e,source:o,summary:r,takeaways:i,thoughts:a,related:d,folder:p})=>{try{let u=N("article",{title:t,url:e,source:o,summary:r,takeaways:i,thoughts:a,related:d}),l=`${p??c.inbox.folder}/${t}.md`;return await n.writeNote(l,u),{content:[{type:"text",text:`Reference saved at "${l}"`}]}}catch(u){return {content:[{type:"text",text:`Could not save reference: ${u instanceof Error?u.message:String(u)}`}],isError:true}}});}function st(s,n,c){s.tool("log","Append an entry to today's daily note. Creates the daily note if it doesn't exist. Adds entries under a configurable heading with timestamps.",{entry:z$1.string().describe("The entry to add to the daily note"),heading:z$1.string().optional().default("Log").describe('Heading to add the entry under (default: "Log")')},async({entry:t,heading:e})=>{try{let o=`${c.dailyNotes.folder}/${y()}.md`,i=`
75
- - ${new Date().toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit"})} \u2014 ${t}`;try{await n.readNote(o);try{await n.patchNote(o,i,{operation:"append",targetHeading:e});}catch{await n.appendToNote(o,`
74
+ `;return await o.writeNote(l,u),{content:[{type:"text",text:`Saved to "${l}"`}]}}catch(c){return {content:[{type:"text",text:`Could not save note: ${c instanceof Error?c.message:String(c)}`}],isError:true}}}),s.tool("remember_meeting","Create a structured meeting note with attendees, agenda, notes, and action items. Uses the meeting template.",{title:z$1.string().describe("Meeting title"),attendees:z$1.string().describe("Comma-separated list of attendees"),agenda:z$1.string().optional().default("").describe("Meeting agenda"),notes:z$1.string().optional().default("").describe("Meeting notes"),action_items:z$1.string().optional().default("").describe("Action items from the meeting"),follow_up:z$1.string().optional().default("").describe("Follow-up items"),folder:z$1.string().optional().describe("Folder to save to (defaults to inbox)")},async({title:t,attendees:e,agenda:n,notes:r,action_items:c,follow_up:a,folder:l})=>{try{let m=N("meeting",{title:t,attendees:e,agenda:n,notes:r,action_items:c,follow_up:a}),f=`${l??i.inbox.folder}/${t}.md`;return await o.writeNote(f,m),{content:[{type:"text",text:`Meeting note created at "${f}"`}]}}catch(m){return {content:[{type:"text",text:`Could not create meeting note: ${m instanceof Error?m.message:String(m)}`}],isError:true}}}),s.tool("remember_decision","Log a decision using the ADR (Architecture Decision Record) format. Captures the context, decision, consequences, and alternatives considered.",{title:z$1.string().describe("Decision title"),context:z$1.string().describe("Why this decision needed to be made"),decision:z$1.string().describe("What was decided"),consequences:z$1.string().optional().default("").describe("What happens as a result"),alternatives:z$1.string().optional().default("").describe("Other options that were considered"),related:z$1.string().optional().default("").describe("Related notes or concepts"),folder:z$1.string().optional().describe("Folder to save to")},async({title:t,context:e,decision:n,consequences:r,alternatives:c,related:a,folder:l})=>{try{let m=N("decision",{title:t,context:e,decision:n,consequences:r,alternatives:c,related:a}),f=`${l??i.inbox.folder}/${t}.md`;return await o.writeNote(f,m),{content:[{type:"text",text:`Decision logged at "${f}"`}]}}catch(m){return {content:[{type:"text",text:`Could not log decision: ${m instanceof Error?m.message:String(m)}`}],isError:true}}}),s.tool("remember_idea","Capture an idea with context on why it matters and potential next steps.",{title:z$1.string().describe("Idea title"),idea:z$1.string().describe("Description of the idea"),why:z$1.string().optional().default("").describe("Why this idea matters"),next_steps:z$1.string().optional().default("").describe("Potential next steps"),related:z$1.string().optional().default("").describe("Related notes or concepts"),tags:z$1.array(z$1.string()).optional().describe("Additional tags"),folder:z$1.string().optional().describe("Folder to save to")},async({title:t,idea:e,why:n,next_steps:r,related:c,folder:a})=>{try{let l=N("idea",{title:t,idea:e,why:n,next_steps:r,related:c}),u=`${a??i.inbox.folder}/${t}.md`;return await o.writeNote(u,l),{content:[{type:"text",text:`Idea captured at "${u}"`}]}}catch(l){return {content:[{type:"text",text:`Could not capture idea: ${l instanceof Error?l.message:String(l)}`}],isError:true}}}),s.tool("remember_learning","Save something new you learned \u2014 a concept, technique, insight, or skill with examples and application notes.",{title:z$1.string().describe("What was learned"),concept:z$1.string().describe("The concept or insight"),key_points:z$1.string().optional().default("").describe("Key points to remember"),examples:z$1.string().optional().default("").describe("Examples or illustrations"),application:z$1.string().optional().default("").describe("How to apply this learning"),source:z$1.string().optional().default("").describe("Where you learned this"),related:z$1.string().optional().default("").describe("Related notes"),folder:z$1.string().optional().describe("Folder to save to")},async({title:t,concept:e,key_points:n,examples:r,application:c,source:a,related:l,folder:m})=>{try{let u=N("learning",{title:t,concept:e,key_points:n,examples:r,application:c,source:a,related:l}),d=`${m??i.inbox.folder}/${t}.md`;return await o.writeNote(d,u),{content:[{type:"text",text:`Learning saved at "${d}"`}]}}catch(u){return {content:[{type:"text",text:`Could not save learning: ${u instanceof Error?u.message:String(u)}`}],isError:true}}}),s.tool("remember_person","Create or update a note about a person \u2014 their role, organization, context, and interactions.",{name:z$1.string().describe("Person's name"),role:z$1.string().optional().default("").describe("Their role or title"),organization:z$1.string().optional().default("").describe("Their organization"),contact:z$1.string().optional().default("").describe("Contact information"),context:z$1.string().optional().default("").describe("How you know them or relevant context"),interaction:z$1.string().optional().default("").describe("Notes from recent interaction"),notes:z$1.string().optional().default("").describe("Additional notes"),folder:z$1.string().optional().describe("Folder to save to")},async({name:t,role:e,organization:n,contact:r,context:c,interaction:a,notes:l,folder:m})=>{try{let u=N("person",{name:t,role:e,organization:n,contact:r,context:c,interaction:a,notes:l}),d=`${m??i.inbox.folder}/${t}.md`;return await o.writeNote(d,u),{content:[{type:"text",text:`Person note created at "${d}"`}]}}catch(u){return {content:[{type:"text",text:`Could not create person note: ${u instanceof Error?u.message:String(u)}`}],isError:true}}}),s.tool("remember_reference","Bookmark a URL or resource with a summary, tags, and personal notes. Great for saving articles, videos, tools, or documentation.",{title:z$1.string().describe("Title of the resource"),url:z$1.string().describe("URL of the resource"),source:z$1.string().optional().default("").describe('Source (e.g., "Hacker News", "Twitter")'),summary:z$1.string().optional().default("").describe("Brief summary"),takeaways:z$1.string().optional().default("").describe("Key takeaways"),thoughts:z$1.string().optional().default("").describe("Your personal thoughts"),related:z$1.string().optional().default("").describe("Related notes"),tags:z$1.array(z$1.string()).optional().describe("Tags for categorization"),folder:z$1.string().optional().describe("Folder to save to")},async({title:t,url:e,source:n,summary:r,takeaways:c,thoughts:a,related:l,folder:m})=>{try{let u=N("article",{title:t,url:e,source:n,summary:r,takeaways:c,thoughts:a,related:l}),d=`${m??i.inbox.folder}/${t}.md`;return await o.writeNote(d,u),{content:[{type:"text",text:`Reference saved at "${d}"`}]}}catch(u){return {content:[{type:"text",text:`Could not save reference: ${u instanceof Error?u.message:String(u)}`}],isError:true}}});}function at(s,o,i){s.tool("log","Append an entry to today's daily note. Creates the daily note if it doesn't exist. Adds entries under a configurable heading with timestamps.",{entry:z$1.string().describe("The entry to add to the daily note"),heading:z$1.string().optional().default("Log").describe('Heading to add the entry under (default: "Log")')},async({entry:t,heading:e})=>{try{let n=`${i.dailyNotes.folder}/${x()}.md`,c=`
75
+ - ${new Date().toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit"})} \u2014 ${t}`;try{await o.readNote(n);try{await o.patchNote(n,c,{operation:"append",targetHeading:e});}catch{await o.appendToNote(n,`
76
76
  ## ${e}
77
- ${i}
77
+ ${c}
78
78
  `);}}catch{let a=`---
79
- date: ${y()}
79
+ date: ${x()}
80
80
  tags:
81
81
  - daily
82
82
  ---
83
83
 
84
- # ${y()}
84
+ # ${x()}
85
85
 
86
86
  ## ${e}
87
- ${i}
88
- `;await n.writeNote(o,a);}return {content:[{type:"text",text:`Logged to daily note (${y()}): ${t}`}]}}catch(o){return {content:[{type:"text",text:`Could not log entry: ${o instanceof Error?o.message:String(o)}`}],isError:true}}}),s.tool("log_task","Add a task (checkbox item) to today's daily note. Creates the daily note if it doesn't exist.",{task:z$1.string().describe("The task description"),heading:z$1.string().optional().default("Tasks").describe('Heading to add the task under (default: "Tasks")')},async({task:t,heading:e})=>{try{let o=`${c.dailyNotes.folder}/${y()}.md`,r=`
89
- - [ ] ${t}`;try{await n.readNote(o);try{await n.patchNote(o,r,{operation:"append",targetHeading:e});}catch{await n.appendToNote(o,`
87
+ ${c}
88
+ `;await o.writeNote(n,a);}return {content:[{type:"text",text:`Logged to daily note (${x()}): ${t}`}]}}catch(n){return {content:[{type:"text",text:`Could not log entry: ${n instanceof Error?n.message:String(n)}`}],isError:true}}}),s.tool("log_task","Add a task (checkbox item) to today's daily note. Creates the daily note if it doesn't exist.",{task:z$1.string().describe("The task description"),heading:z$1.string().optional().default("Tasks").describe('Heading to add the task under (default: "Tasks")')},async({task:t,heading:e})=>{try{let n=`${i.dailyNotes.folder}/${x()}.md`,r=`
89
+ - [ ] ${t}`;try{await o.readNote(n);try{await o.patchNote(n,r,{operation:"append",targetHeading:e});}catch{await o.appendToNote(n,`
90
90
  ## ${e}
91
91
  ${r}
92
- `);}}catch{let i=`---
93
- date: ${y()}
92
+ `);}}catch{let c=`---
93
+ date: ${x()}
94
94
  tags:
95
95
  - daily
96
96
  ---
97
97
 
98
- # ${y()}
98
+ # ${x()}
99
99
 
100
100
  ## ${e}
101
101
  ${r}
102
- `;await n.writeNote(o,i);}return {content:[{type:"text",text:`Task added to daily note: ${t}`}]}}catch(o){return {content:[{type:"text",text:`Could not add task: ${o instanceof Error?o.message:String(o)}`}],isError:true}}}),s.tool("reflect","Generate reflection prompts based on recent vault activity. Reads today's and recent daily notes to suggest areas for reflection.",{},async()=>{try{let t="";try{let d=`${c.dailyNotes.folder}/${y()}.md`;t=await n.readNote(d);}catch{}let o=(await n.listFiles()).filter(d=>d.extension==="md"),i=["What was the most important thing you learned today?","What decision did you make that you want to remember?","What are you most proud of from today's work?","What would you do differently next time?","What's one thing you want to explore further?","Who helped you today, and how?","What's blocking you right now?","What's one thing you're grateful for today?"].sort(()=>Math.random()-.5).slice(0,4),a=`**Reflection Prompts for ${y()}:**
102
+ `;await o.writeNote(n,c);}return {content:[{type:"text",text:`Task added to daily note: ${t}`}]}}catch(n){return {content:[{type:"text",text:`Could not add task: ${n instanceof Error?n.message:String(n)}`}],isError:true}}}),s.tool("reflect","Generate reflection prompts based on recent vault activity. Reads today's and recent daily notes to suggest areas for reflection.",{},async()=>{try{let t="";try{let l=`${i.dailyNotes.folder}/${x()}.md`;t=await o.readNote(l);}catch{}let n=(await o.listFiles()).filter(l=>l.extension==="md"),c=["What was the most important thing you learned today?","What decision did you make that you want to remember?","What are you most proud of from today's work?","What would you do differently next time?","What's one thing you want to explore further?","Who helped you today, and how?","What's blocking you right now?","What's one thing you're grateful for today?"].sort(()=>Math.random()-.5).slice(0,4),a=`**Reflection Prompts for ${x()}:**
103
103
 
104
- `;return a+=i.map((d,p)=>`${p+1}. ${d}`).join(`
104
+ `;return a+=c.map((l,m)=>`${m+1}. ${l}`).join(`
105
105
  `),t&&(a+=`
106
106
 
107
107
  ---
@@ -111,89 +111,89 @@ ${t.slice(0,500)}`),a+=`
111
111
 
112
112
  ---
113
113
 
114
- Vault stats: ${o.length} notes total.`,a+="\n\nTip: Use `log` to add your reflections to today's daily note.",{content:[{type:"text",text:a}]}}catch(t){return {content:[{type:"text",text:`Reflection error: ${t instanceof Error?t.message:String(t)}`}],isError:true}}});}function it(s,n,c){s.tool("create_note","Create a new note in the vault. Supports optional templates, folder routing, and frontmatter. Will not overwrite existing notes unless explicitly requested.",{path:z$1.string().describe('Path for the new note (e.g., "Projects/My Project.md")'),content:z$1.string().describe("Markdown content for the note"),template:z$1.enum(["decision","meeting","learning","idea","person","project","book","article","weekly-review","session"]).optional().describe("Optional template to use"),variables:z$1.record(z$1.string()).optional().describe("Template variables as key-value pairs"),overwrite:z$1.boolean().optional().default(false).describe("Whether to overwrite if note already exists")},async({path:t,content:e,template:o,variables:r,overwrite:i})=>{try{if(!i)try{return await n.readNote(t),{content:[{type:"text",text:`Note already exists at "${t}". Set overwrite=true to replace it.`}]}}catch{}let a=e;return o&&(a=N(o,{...r,content:e})),await n.writeNote(t,a),{content:[{type:"text",text:`Note created at "${t}"`}]}}catch(a){return {content:[{type:"text",text:`Could not create note: ${a instanceof Error?a.message:String(a)}`}],isError:true}}}),s.tool("append_to_note","Append content to the end of an existing note. The note must already exist.",{path:z$1.string().describe("Path to the note to append to"),content:z$1.string().describe("Content to append")},async({path:t,content:e})=>{try{return await n.appendToNote(t,`
114
+ Vault stats: ${n.length} notes total.`,a+="\n\nTip: Use `log` to add your reflections to today's daily note.",{content:[{type:"text",text:a}]}}catch(t){return {content:[{type:"text",text:`Reflection error: ${t instanceof Error?t.message:String(t)}`}],isError:true}}});}function ct(s,o,i){s.tool("create_note","Create a new note in the vault. Supports optional templates, folder routing, and frontmatter. Will not overwrite existing notes unless explicitly requested.",{path:z$1.string().describe('Path for the new note (e.g., "Projects/My Project.md")'),content:z$1.string().describe("Markdown content for the note"),template:z$1.enum(["decision","meeting","learning","idea","person","project","book","article","weekly-review","session"]).optional().describe("Optional template to use"),variables:z$1.record(z$1.string()).optional().describe("Template variables as key-value pairs"),overwrite:z$1.boolean().optional().default(false).describe("Whether to overwrite if note already exists")},async({path:t,content:e,template:n,variables:r,overwrite:c})=>{try{if(!c)try{return await o.readNote(t),{content:[{type:"text",text:`Note already exists at "${t}". Set overwrite=true to replace it.`}]}}catch{}let a=e;return n&&(a=N(n,{...r,content:e})),await o.writeNote(t,a),{content:[{type:"text",text:`Note created at "${t}"`}]}}catch(a){return {content:[{type:"text",text:`Could not create note: ${a instanceof Error?a.message:String(a)}`}],isError:true}}}),s.tool("append_to_note","Append content to the end of an existing note. The note must already exist.",{path:z$1.string().describe("Path to the note to append to"),content:z$1.string().describe("Content to append")},async({path:t,content:e})=>{try{return await o.appendToNote(t,`
115
115
  ${e}
116
- `),{content:[{type:"text",text:`Content appended to "${t}"`}]}}catch(o){return {content:[{type:"text",text:`Could not append to note: ${o instanceof Error?o.message:String(o)}`}],isError:true}}}),s.tool("update_section","Replace the content under a specific heading in a note. Useful for updating a section without modifying the rest of the note.",{path:z$1.string().describe("Path to the note"),heading:z$1.string().describe("Heading text of the section to replace"),content:z$1.string().describe("New content for the section")},async({path:t,heading:e,content:o})=>{try{let r=await n.readNote(t),i=_(r,e,o);return await n.writeNote(t,i),{content:[{type:"text",text:`Section "${e}" updated in "${t}"`}]}}catch(r){return {content:[{type:"text",text:`Could not update section: ${r instanceof Error?r.message:String(r)}`}],isError:true}}});}function at(s,n,c){s.tool("add_link",'Add a [[wikilink]] to a note, connecting it to another note in the vault. Appends the link under a "Related" heading or at the end of the note.',{path:z$1.string().describe("Path of the note to add the link to"),target:z$1.string().describe("Name of the note to link to (without .md extension)"),context:z$1.string().optional().describe("Optional context for why these notes are related")},async({path:t,target:e,context:o})=>{try{let r=await n.readNote(t);if(C(r).includes(e))return {content:[{type:"text",text:`"${t}" already links to [[${e}]]`}]};let a=o?`
117
- - [[${e}]] \u2014 ${o}`:`
118
- - [[${e}]]`;try{await n.patchNote(t,a,{operation:"append",targetHeading:"Related"});}catch{await n.appendToNote(t,`
116
+ `),{content:[{type:"text",text:`Content appended to "${t}"`}]}}catch(n){return {content:[{type:"text",text:`Could not append to note: ${n instanceof Error?n.message:String(n)}`}],isError:true}}}),s.tool("update_section","Replace the content under a specific heading in a note. Useful for updating a section without modifying the rest of the note.",{path:z$1.string().describe("Path to the note"),heading:z$1.string().describe("Heading text of the section to replace"),content:z$1.string().describe("New content for the section")},async({path:t,heading:e,content:n})=>{try{let r=await o.readNote(t),c=L(r,e,n);return await o.writeNote(t,c),{content:[{type:"text",text:`Section "${e}" updated in "${t}"`}]}}catch(r){return {content:[{type:"text",text:`Could not update section: ${r instanceof Error?r.message:String(r)}`}],isError:true}}});}function lt(s,o,i){s.tool("add_link",'Add a [[wikilink]] to a note, connecting it to another note in the vault. Appends the link under a "Related" heading or at the end of the note.',{path:z$1.string().describe("Path of the note to add the link to"),target:z$1.string().describe("Name of the note to link to (without .md extension)"),context:z$1.string().optional().describe("Optional context for why these notes are related")},async({path:t,target:e,context:n})=>{try{let r=await o.readNote(t);if(C(r).includes(e))return {content:[{type:"text",text:`"${t}" already links to [[${e}]]`}]};let a=n?`
117
+ - [[${e}]] \u2014 ${n}`:`
118
+ - [[${e}]]`;try{await o.patchNote(t,a,{operation:"append",targetHeading:"Related"});}catch{await o.appendToNote(t,`
119
119
  ## Related
120
120
  ${a}
121
- `);}return {content:[{type:"text",text:`Added link to [[${e}]] in "${t}"`}]}}catch(r){return {content:[{type:"text",text:`Could not add link: ${r instanceof Error?r.message:String(r)}`}],isError:true}}}),s.tool("suggest_connections","Analyze a note and suggest other notes that could be linked to it. Uses shared tags, mentions, and content similarity to find connections.",{path:z$1.string().describe("Path to the note to analyze"),limit:z$1.number().optional().default(10).describe("Maximum suggestions to return")},async({path:t,limit:e})=>{try{let o=await n.readNote(t),r=C(o),i=w(o),a=new Map;for(let f of i.slice(0,5))try{let l=await n.search(`tag:#${f}`);for(let m of l)if(m.filename!==t&&!r.includes(m.filename.replace(/\.md$/,""))){let h=a.get(m.filename)??[];h.push(`Shared tag: #${f}`),a.set(m.filename,h);}}catch{}let d=o.split(/\s+/).filter(f=>f.length>5).slice(0,10);for(let f of d.slice(0,3))try{let l=await n.search(f);for(let m of l.slice(0,5))if(m.filename!==t&&!r.includes(m.filename.replace(/\.md$/,""))){let h=a.get(m.filename)??[];h.some(x=>x.startsWith("Mentions:"))||(h.push(`Mentions: "${f}"`),a.set(m.filename,h));}}catch{}let p=[...a.entries()].sort((f,l)=>l[1].length-f[1].length).slice(0,e);if(p.length===0)return {content:[{type:"text",text:`No connection suggestions found for "${t}". The note may be well-connected already!`}]};let u=p.map(([f,l],m)=>`${m+1}. **${f}**
122
- ${l.join(", ")}`).join(`
121
+ `);}return {content:[{type:"text",text:`Added link to [[${e}]] in "${t}"`}]}}catch(r){return {content:[{type:"text",text:`Could not add link: ${r instanceof Error?r.message:String(r)}`}],isError:true}}}),s.tool("suggest_connections","Analyze a note and suggest other notes that could be linked to it. Uses shared tags, mentions, and content similarity to find connections.",{path:z$1.string().describe("Path to the note to analyze"),limit:z$1.number().optional().default(10).describe("Maximum suggestions to return")},async({path:t,limit:e})=>{try{let n=await o.readNote(t),r=C(n),c=$(n),a=new Map;for(let f of c.slice(0,5))try{let d=await o.search(`tag:#${f}`);for(let p of d)if(p.filename!==t&&!r.includes(p.filename.replace(/\.md$/,""))){let h=a.get(p.filename)??[];h.push(`Shared tag: #${f}`),a.set(p.filename,h);}}catch{}let l=n.split(/\s+/).filter(f=>f.length>5).slice(0,10);for(let f of l.slice(0,3))try{let d=await o.search(f);for(let p of d.slice(0,5))if(p.filename!==t&&!r.includes(p.filename.replace(/\.md$/,""))){let h=a.get(p.filename)??[];h.some(y=>y.startsWith("Mentions:"))||(h.push(`Mentions: "${f}"`),a.set(p.filename,h));}}catch{}let m=[...a.entries()].sort((f,d)=>d[1].length-f[1].length).slice(0,e);if(m.length===0)return {content:[{type:"text",text:`No connection suggestions found for "${t}". The note may be well-connected already!`}]};let u=m.map(([f,d],p)=>`${p+1}. **${f}**
122
+ ${d.join(", ")}`).join(`
123
123
 
124
124
  `);return {content:[{type:"text",text:`Suggested connections for "${t}":
125
125
 
126
126
  ${u}
127
127
 
128
- Use \`add_link\` to connect any of these notes.`}]}}catch(o){return {content:[{type:"text",text:`Could not suggest connections: ${o instanceof Error?o.message:String(o)}`}],isError:true}}}),s.tool("find_gaps","Find broken links in the vault \u2014 [[wikilinks]] that point to notes that don't exist. These represent knowledge gaps or notes waiting to be written.",{limit:z$1.number().optional().default(20).describe("Maximum gaps to return")},async({limit:t})=>{try{let e=await n.listFiles(),o=new Set(e.filter(f=>f.extension==="md").map(f=>f.name.toLowerCase())),r=new Map,i=e.filter(f=>f.extension==="md"),a=Math.min(i.length,100),d=i.sort(()=>Math.random()-.5).slice(0,a);for(let f of d)try{let l=await n.readNote(f.path),m=C(l);for(let h of m)if(!o.has(h.toLowerCase())){let x=r.get(h)??[];x.push(f.path),r.set(h,x);}}catch{}let p=[...r.entries()].sort((f,l)=>l[1].length-f[1].length).slice(0,t);return p.length===0?{content:[{type:"text",text:`No broken links found (sampled ${a} of ${i.length} notes).`}]}:{content:[{type:"text",text:`Knowledge gaps (broken links) found in vault:
128
+ Use \`add_link\` to connect any of these notes.`}]}}catch(n){return {content:[{type:"text",text:`Could not suggest connections: ${n instanceof Error?n.message:String(n)}`}],isError:true}}}),s.tool("find_gaps","Find broken links in the vault \u2014 [[wikilinks]] that point to notes that don't exist. These represent knowledge gaps or notes waiting to be written.",{limit:z$1.number().optional().default(20).describe("Maximum gaps to return")},async({limit:t})=>{try{let e=await o.listFiles(),n=new Set(e.filter(f=>f.extension==="md").map(f=>f.name.toLowerCase())),r=new Map,c=e.filter(f=>f.extension==="md"),a=Math.min(c.length,100),l=c.sort(()=>Math.random()-.5).slice(0,a);for(let f of l)try{let d=await o.readNote(f.path),p=C(d);for(let h of p)if(!n.has(h.toLowerCase())){let y=r.get(h)??[];y.push(f.path),r.set(h,y);}}catch{}let m=[...r.entries()].sort((f,d)=>d[1].length-f[1].length).slice(0,t);return m.length===0?{content:[{type:"text",text:`No broken links found (sampled ${a} of ${c.length} notes).`}]}:{content:[{type:"text",text:`Knowledge gaps (broken links) found in vault:
129
129
 
130
- ${p.map(([f,l],m)=>`${m+1}. **[[${f}]]** \u2014 referenced by ${l.length} note(s): ${l.slice(0,3).join(", ")}${l.length>3?"...":""}`).join(`
130
+ ${m.map(([f,d],p)=>`${p+1}. **[[${f}]]** \u2014 referenced by ${d.length} note(s): ${d.slice(0,3).join(", ")}${d.length>3?"...":""}`).join(`
131
131
  `)}
132
132
 
133
- These are concepts referenced but not yet written about. Use \`create_note\` to fill them in.`}]}}catch(e){return {content:[{type:"text",text:`Could not find gaps: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("find_orphans","Find orphan notes \u2014 notes with no incoming or outgoing links. These are disconnected from the knowledge graph and might need connecting.",{limit:z$1.number().optional().default(20).describe("Maximum orphans to return")},async({limit:t})=>{try{let o=(await n.listFiles()).filter(u=>u.extension==="md"),r=new Set,i=Math.min(o.length,100),a=o.sort(()=>Math.random()-.5).slice(0,i);for(let u of a)try{let f=await n.readNote(u.path),l=C(f);if(l.length>0){r.add(u.path);for(let m of l){let h=o.find(x=>x.name.toLowerCase()===m.toLowerCase());h&&r.add(h.path);}}}catch{}let d=a.filter(u=>!r.has(u.path)).slice(0,t);return d.length===0?{content:[{type:"text",text:`No orphan notes found (sampled ${i} notes). Your vault is well-connected!`}]}:{content:[{type:"text",text:`Orphan notes (no links in or out):
133
+ These are concepts referenced but not yet written about. Use \`create_note\` to fill them in.`}]}}catch(e){return {content:[{type:"text",text:`Could not find gaps: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("find_orphans","Find orphan notes \u2014 notes with no incoming or outgoing links. These are disconnected from the knowledge graph and might need connecting.",{limit:z$1.number().optional().default(20).describe("Maximum orphans to return")},async({limit:t})=>{try{let n=(await o.listFiles()).filter(u=>u.extension==="md"),r=new Set,c=Math.min(n.length,100),a=n.sort(()=>Math.random()-.5).slice(0,c);for(let u of a)try{let f=await o.readNote(u.path),d=C(f);if(d.length>0){r.add(u.path);for(let p of d){let h=n.find(y=>y.name.toLowerCase()===p.toLowerCase());h&&r.add(h.path);}}}catch{}let l=a.filter(u=>!r.has(u.path)).slice(0,t);return l.length===0?{content:[{type:"text",text:`No orphan notes found (sampled ${c} notes). Your vault is well-connected!`}]}:{content:[{type:"text",text:`Orphan notes (no links in or out):
134
134
 
135
- ${d.map((u,f)=>`${f+1}. ${u.path}`).join(`
135
+ ${l.map((u,f)=>`${f+1}. ${u.path}`).join(`
136
136
  `)}
137
137
 
138
- Consider linking these to related notes using \`add_link\` or \`suggest_connections\`.`}]}}catch(e){return {content:[{type:"text",text:`Could not find orphans: ${e instanceof Error?e.message:String(e)}`}],isError:true}}});}function ct(s,n,c){s.tool("add_tag","Add one or more tags to a note. Tags are added to the YAML frontmatter. If the note has no frontmatter, it will be created.",{path:z$1.string().describe("Path to the note"),tags:z$1.array(z$1.string()).describe("Tags to add (without # prefix)")},async({path:t,tags:e})=>{try{let o=await n.readNote(t),{frontmatter:r,body:i}=S(o),a=[];if(r.tags){let l=r.tags;l.startsWith("[")?a.push(...l.slice(1,-1).split(",").map(m=>m.trim())):a.push(l);}let p=[...new Set([...a,...e])].map(l=>` - ${l}`).join(`
139
- `),u=Object.entries(r).filter(([l])=>l!=="tags").map(([l,m])=>`${l}: ${m}`).join(`
138
+ Consider linking these to related notes using \`add_link\` or \`suggest_connections\`.`}]}}catch(e){return {content:[{type:"text",text:`Could not find orphans: ${e instanceof Error?e.message:String(e)}`}],isError:true}}});}function dt(s,o,i){s.tool("add_tag","Add one or more tags to a note. Tags are added to the YAML frontmatter. If the note has no frontmatter, it will be created.",{path:z$1.string().describe("Path to the note"),tags:z$1.array(z$1.string()).describe("Tags to add (without # prefix)")},async({path:t,tags:e})=>{try{let n=await o.readNote(t),{frontmatter:r,body:c}=M(n),a=[];if(r.tags){let d=r.tags;d.startsWith("[")?a.push(...d.slice(1,-1).split(",").map(p=>p.trim())):a.push(d);}let m=[...new Set([...a,...e])].map(d=>` - ${d}`).join(`
139
+ `),u=Object.entries(r).filter(([d])=>d!=="tags").map(([d,p])=>`${d}: ${p}`).join(`
140
140
  `),f=`---
141
141
  ${u}${u?`
142
142
  `:""}tags:
143
- ${p}
143
+ ${m}
144
144
  ---
145
145
 
146
- ${i}`;return await n.writeNote(t,f),{content:[{type:"text",text:`Added tags ${e.map(l=>`#${l}`).join(", ")} to "${t}"`}]}}catch(o){return {content:[{type:"text",text:`Could not add tags: ${o instanceof Error?o.message:String(o)}`}],isError:true}}}),s.tool("update_properties","Update YAML frontmatter properties of a note. Can add new properties or modify existing ones.",{path:z$1.string().describe("Path to the note"),properties:z$1.record(z$1.string()).describe('Properties to set as key-value pairs (e.g., {"status": "done", "priority": "high"})')},async({path:t,properties:e})=>{try{let o=await n.readNote(t),{frontmatter:r,body:i}=S(o),a={...r,...e},p=`---
147
- ${Object.entries(a).map(([f,l])=>`${f}: ${l}`).join(`
146
+ ${c}`;return await o.writeNote(t,f),{content:[{type:"text",text:`Added tags ${e.map(d=>`#${d}`).join(", ")} to "${t}"`}]}}catch(n){return {content:[{type:"text",text:`Could not add tags: ${n instanceof Error?n.message:String(n)}`}],isError:true}}}),s.tool("update_properties","Update YAML frontmatter properties of a note. Can add new properties or modify existing ones.",{path:z$1.string().describe("Path to the note"),properties:z$1.record(z$1.string()).describe('Properties to set as key-value pairs (e.g., {"status": "done", "priority": "high"})')},async({path:t,properties:e})=>{try{let n=await o.readNote(t),{frontmatter:r,body:c}=M(n),a={...r,...e},m=`---
147
+ ${Object.entries(a).map(([f,d])=>`${f}: ${d}`).join(`
148
148
  `)}
149
149
  ---
150
150
 
151
- ${i}`;await n.writeNote(t,p);let u=Object.entries(e).map(([f,l])=>`${f}: ${l}`).join(", ");return {content:[{type:"text",text:`Updated properties in "${t}": ${u}`}]}}catch(o){return {content:[{type:"text",text:`Could not update properties: ${o instanceof Error?o.message:String(o)}`}],isError:true}}}),s.tool("rename_note","Rename a note by creating a copy at the new path and deleting the original. Note: Obsidian will update backlinks if the app is running.",{old_path:z$1.string().describe("Current path of the note"),new_path:z$1.string().describe("New path for the note")},async({old_path:t,new_path:e})=>{try{let o=await n.readNote(t);try{return await n.readNote(e),{content:[{type:"text",text:`A note already exists at "${e}". Choose a different name.`}]}}catch{}return await n.writeNote(e,o),await n.deleteNote(t),{content:[{type:"text",text:`Renamed "${t}" to "${e}"`}]}}catch(o){return {content:[{type:"text",text:`Could not rename note: ${o instanceof Error?o.message:String(o)}`}],isError:true}}}),s.tool("move_note","Move a note to a different folder in the vault. Preserves the filename.",{path:z$1.string().describe("Current path of the note"),destination:z$1.string().describe('Destination folder (e.g., "Projects", "Archive")')},async({path:t,destination:e})=>{try{let o=await n.readNote(t),r=t.split("/").pop()??t,i=`${e}/${r}`;try{return await n.readNote(i),{content:[{type:"text",text:`A note already exists at "${i}". Rename the note first.`}]}}catch{}return await n.writeNote(i,o),await n.deleteNote(t),{content:[{type:"text",text:`Moved "${t}" to "${i}"`}]}}catch(o){return {content:[{type:"text",text:`Could not move note: ${o instanceof Error?o.message:String(o)}`}],isError:true}}});}function lt(s,n,c){s.tool("vault_overview","Get an overview of your Obsidian vault: total notes, folder structure, tag distribution, and general statistics.",{},async()=>{try{let t=await n.listFiles(),e=t.filter(l=>l.extension==="md"),o=t.filter(l=>l.extension!=="md"),r=new Map;for(let l of e){let m=l.path.split("/"),h=m.length>1?m.slice(0,-1).join("/"):"(root)";r.set(h,(r.get(h)??0)+1);}let i=[...r.entries()].sort((l,m)=>m[1]-l[1]).slice(0,15),a=new Map,d=Math.min(e.length,50),p=e.slice(0,d);for(let l of p)try{let m=await n.readNote(l.path),h=w(m);for(let x of h)a.set(x,(a.get(x)??0)+1);}catch{}let u=[...a.entries()].sort((l,m)=>m[1]-l[1]).slice(0,15),f=`**Vault Overview**
151
+ ${c}`;await o.writeNote(t,m);let u=Object.entries(e).map(([f,d])=>`${f}: ${d}`).join(", ");return {content:[{type:"text",text:`Updated properties in "${t}": ${u}`}]}}catch(n){return {content:[{type:"text",text:`Could not update properties: ${n instanceof Error?n.message:String(n)}`}],isError:true}}}),s.tool("rename_note","Rename a note by creating a copy at the new path and deleting the original. Note: Obsidian will update backlinks if the app is running.",{old_path:z$1.string().describe("Current path of the note"),new_path:z$1.string().describe("New path for the note")},async({old_path:t,new_path:e})=>{try{let n=await o.readNote(t);try{return await o.readNote(e),{content:[{type:"text",text:`A note already exists at "${e}". Choose a different name.`}]}}catch{}return await o.writeNote(e,n),await o.deleteNote(t),{content:[{type:"text",text:`Renamed "${t}" to "${e}"`}]}}catch(n){return {content:[{type:"text",text:`Could not rename note: ${n instanceof Error?n.message:String(n)}`}],isError:true}}}),s.tool("move_note","Move a note to a different folder in the vault. Preserves the filename.",{path:z$1.string().describe("Current path of the note"),destination:z$1.string().describe('Destination folder (e.g., "Projects", "Archive")')},async({path:t,destination:e})=>{try{let n=await o.readNote(t),r=t.split("/").pop()??t,c=`${e}/${r}`;try{return await o.readNote(c),{content:[{type:"text",text:`A note already exists at "${c}". Rename the note first.`}]}}catch{}return await o.writeNote(c,n),await o.deleteNote(t),{content:[{type:"text",text:`Moved "${t}" to "${c}"`}]}}catch(n){return {content:[{type:"text",text:`Could not move note: ${n instanceof Error?n.message:String(n)}`}],isError:true}}});}function ft(s,o,i){s.tool("vault_overview","Get an overview of your Obsidian vault: total notes, folder structure, tag distribution, and general statistics.",{},async()=>{try{let t=await o.listFiles(),e=t.filter(d=>d.extension==="md"),n=t.filter(d=>d.extension!=="md"),r=new Map;for(let d of e){let p=d.path.split("/"),h=p.length>1?p.slice(0,-1).join("/"):"(root)";r.set(h,(r.get(h)??0)+1);}let c=[...r.entries()].sort((d,p)=>p[1]-d[1]).slice(0,15),a=new Map,l=Math.min(e.length,50),m=e.slice(0,l);for(let d of m)try{let p=await o.readNote(d.path),h=$(p);for(let y of h)a.set(y,(a.get(y)??0)+1);}catch{}let u=[...a.entries()].sort((d,p)=>p[1]-d[1]).slice(0,15),f=`**Vault Overview**
152
152
 
153
153
  `;return f+=`- **Total notes:** ${e.length}
154
- `,f+=`- **Other files:** ${o.length} (images, PDFs, etc.)
154
+ `,f+=`- **Other files:** ${n.length} (images, PDFs, etc.)
155
155
  `,f+=`- **Folders:** ${r.size}
156
156
 
157
157
  `,f+=`**Top Folders:**
158
- `,f+=i.map(([l,m])=>` - ${l}: ${m} notes`).join(`
158
+ `,f+=c.map(([d,p])=>` - ${d}: ${p} notes`).join(`
159
159
  `),u.length>0&&(f+=`
160
160
 
161
- **Top Tags** (sampled from ${d} notes):
162
- `,f+=u.map(([l,m])=>` - #${l}: ${m}`).join(`
163
- `)),{content:[{type:"text",text:f}]}}catch(t){return {content:[{type:"text",text:`Could not get vault overview: ${t instanceof Error?t.message:String(t)}`}],isError:true}}}),s.tool("list_tags","List all tags used in the vault with their occurrence counts. Samples notes to build the tag list.",{limit:z$1.number().optional().default(50).describe("Maximum tags to return")},async({limit:t})=>{try{let o=(await n.listFiles()).filter(u=>u.extension==="md"),r=new Map,i=Math.min(o.length,200),a=o.slice(0,i);for(let u of a)try{let f=await n.readNote(u.path),l=w(f);for(let m of l)r.set(m,(r.get(m)??0)+1);}catch{}let d=[...r.entries()].sort((u,f)=>f[1]-u[1]).slice(0,t);if(d.length===0)return {content:[{type:"text",text:"No tags found in vault."}]};let p=d.map(([u,f])=>`#${u} (${f})`).join(`
164
- `);return {content:[{type:"text",text:`**Tags in vault** (sampled ${i} of ${o.length} notes):
161
+ **Top Tags** (sampled from ${l} notes):
162
+ `,f+=u.map(([d,p])=>` - #${d}: ${p}`).join(`
163
+ `)),{content:[{type:"text",text:f}]}}catch(t){return {content:[{type:"text",text:`Could not get vault overview: ${t instanceof Error?t.message:String(t)}`}],isError:true}}}),s.tool("list_tags","List all tags used in the vault with their occurrence counts. Samples notes to build the tag list.",{limit:z$1.number().optional().default(50).describe("Maximum tags to return")},async({limit:t})=>{try{let n=(await o.listFiles()).filter(u=>u.extension==="md"),r=new Map,c=Math.min(n.length,200),a=n.slice(0,c);for(let u of a)try{let f=await o.readNote(u.path),d=$(f);for(let p of d)r.set(p,(r.get(p)??0)+1);}catch{}let l=[...r.entries()].sort((u,f)=>f[1]-u[1]).slice(0,t);if(l.length===0)return {content:[{type:"text",text:"No tags found in vault."}]};let m=l.map(([u,f])=>`#${u} (${f})`).join(`
164
+ `);return {content:[{type:"text",text:`**Tags in vault** (sampled ${c} of ${n.length} notes):
165
165
 
166
- ${p}`}]}}catch(e){return {content:[{type:"text",text:`Could not list tags: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("get_vault_structure","Get the folder structure of the vault as a tree with note counts per folder. Useful for understanding vault organization.",{},async()=>{try{let e=(await n.listFiles()).filter(a=>a.extension==="md"),o=new Map;for(let a of e){let d=a.path.split("/");if(d.length>1)for(let p=1;p<d.length;p++){let u=d.slice(0,p).join("/");p===d.length-1?o.set(u,(o.get(u)??0)+1):o.has(u)||o.set(u,0);}else o.set("(root)",(o.get("(root)")??0)+1);}let i=[...o.entries()].sort((a,d)=>a[0].localeCompare(d[0])).map(([a,d])=>{let p=a.split("/").length-1,u=" ".repeat(p),f=a.split("/").pop()??a;return `${u}${f}/ (${d} notes)`}).join(`
166
+ ${m}`}]}}catch(e){return {content:[{type:"text",text:`Could not list tags: ${e instanceof Error?e.message:String(e)}`}],isError:true}}}),s.tool("get_vault_structure","Get the folder structure of the vault as a tree with note counts per folder. Useful for understanding vault organization.",{},async()=>{try{let e=(await o.listFiles()).filter(a=>a.extension==="md"),n=new Map;for(let a of e){let l=a.path.split("/");if(l.length>1)for(let m=1;m<l.length;m++){let u=l.slice(0,m).join("/");m===l.length-1?n.set(u,(n.get(u)??0)+1):n.has(u)||n.set(u,0);}else n.set("(root)",(n.get("(root)")??0)+1);}let c=[...n.entries()].sort((a,l)=>a[0].localeCompare(l[0])).map(([a,l])=>{let m=a.split("/").length-1,u=" ".repeat(m),f=a.split("/").pop()??a;return `${u}${f}/ (${l} notes)`}).join(`
167
167
  `);return {content:[{type:"text",text:`**Vault Structure** (${e.length} total notes):
168
168
 
169
- ${i}`}]}}catch(t){return {content:[{type:"text",text:`Could not get vault structure: ${t instanceof Error?t.message:String(t)}`}],isError:true}}});}function dt(s,n,c){s.tool("find_tasks","Find all checkbox tasks across the vault. Filter by status (open, done, or all). Returns tasks with their source note and line number.",{status:z$1.enum(["open","done","all"]).optional().default("open").describe("Filter by task status"),query:z$1.string().optional().describe("Optional search query to filter tasks by text"),limit:z$1.number().optional().default(30).describe("Maximum tasks to return")},async({status:t,query:e,limit:o})=>{try{let i=(await n.listFiles()).filter(l=>l.extension==="md"),a=[],d=Math.min(i.length,100),p=i.slice(0,d);for(let l of p)try{let m=await n.readNote(l.path),h=G(m);for(let x of h)e&&!x.text.toLowerCase().includes(e.toLowerCase())||t==="open"&&x.done||t==="done"&&!x.done||a.push({text:x.text,done:x.done,file:l.path,line:x.line});}catch{}if(a.length===0)return {content:[{type:"text",text:`No ${t==="all"?"":t+" "}tasks found${e?` matching "${e}"`:""}.`}]};let u=a.slice(0,o),f=u.map((l,m)=>`${m+1}. [${l.done?"x":" "}] ${l.text}
170
- *${l.file}:${l.line}*`).join(`
169
+ ${c}`}]}}catch(t){return {content:[{type:"text",text:`Could not get vault structure: ${t instanceof Error?t.message:String(t)}`}],isError:true}}});}function ut(s,o,i){s.tool("find_tasks","Find all checkbox tasks across the vault. Filter by status (open, done, or all). Returns tasks with their source note and line number.",{status:z$1.enum(["open","done","all"]).optional().default("open").describe("Filter by task status"),query:z$1.string().optional().describe("Optional search query to filter tasks by text"),limit:z$1.number().optional().default(30).describe("Maximum tasks to return")},async({status:t,query:e,limit:n})=>{try{let c=(await o.listFiles()).filter(d=>d.extension==="md"),a=[],l=Math.min(c.length,100),m=c.slice(0,l);for(let d of m)try{let p=await o.readNote(d.path),h=B(p);for(let y of h)e&&!y.text.toLowerCase().includes(e.toLowerCase())||t==="open"&&y.done||t==="done"&&!y.done||a.push({text:y.text,done:y.done,file:d.path,line:y.line});}catch{}if(a.length===0)return {content:[{type:"text",text:`No ${t==="all"?"":t+" "}tasks found${e?` matching "${e}"`:""}.`}]};let u=a.slice(0,n),f=u.map((d,p)=>`${p+1}. [${d.done?"x":" "}] ${d.text}
170
+ *${d.file}:${d.line}*`).join(`
171
171
 
172
172
  `);return {content:[{type:"text",text:`**${t==="all"?"All":t==="open"?"Open":"Completed"} Tasks** (${a.length} found, showing ${u.length}):
173
173
 
174
- ${f}`}]}}catch(r){return {content:[{type:"text",text:`Could not find tasks: ${r instanceof Error?r.message:String(r)}`}],isError:true}}}),s.tool("complete_task","Mark a specific task as done by replacing [ ] with [x] at the given line in a note.",{path:z$1.string().describe("Path to the note containing the task"),line:z$1.number().describe("Line number of the task (1-based)")},async({path:t,line:e})=>{try{let r=(await n.readNote(t)).split(`
175
- `);if(e<1||e>r.length)return {content:[{type:"text",text:`Line ${e} is out of range (note has ${r.length} lines)`}],isError:!0};let i=r[e-1],a=i.match(/^(\s*-\s+)\[[ ]\](\s+.+)$/);return a?(r[e-1]=`${a[1]}[x]${a[2]}`,await n.writeNote(t,r.join(`
176
- `)),{content:[{type:"text",text:`Completed task: "${a[2].trim()}" in "${t}"`}]}):{content:[{type:"text",text:`Line ${e} is not an open task: "${i.trim()}"`}],isError:!0}}catch(o){return {content:[{type:"text",text:`Could not complete task: ${o instanceof Error?o.message:String(o)}`}],isError:true}}});}function ft(s,n,c){s.resource("today","vault://today",{description:"Today's daily note content. Auto-updates with the current day's note.",mimeType:"text/markdown"},async t=>{try{let e=`${c.dailyNotes.folder}/${y()}.md`,o=await n.readNote(e);return {contents:[{uri:t.href,text:`# Today's Daily Note (${y()})
174
+ ${f}`}]}}catch(r){return {content:[{type:"text",text:`Could not find tasks: ${r instanceof Error?r.message:String(r)}`}],isError:true}}}),s.tool("complete_task","Mark a specific task as done by replacing [ ] with [x] at the given line in a note.",{path:z$1.string().describe("Path to the note containing the task"),line:z$1.number().describe("Line number of the task (1-based)")},async({path:t,line:e})=>{try{let r=(await o.readNote(t)).split(`
175
+ `);if(e<1||e>r.length)return {content:[{type:"text",text:`Line ${e} is out of range (note has ${r.length} lines)`}],isError:!0};let c=r[e-1],a=c.match(/^(\s*-\s+)\[[ ]\](\s+.+)$/);return a?(r[e-1]=`${a[1]}[x]${a[2]}`,await o.writeNote(t,r.join(`
176
+ `)),{content:[{type:"text",text:`Completed task: "${a[2].trim()}" in "${t}"`}]}):{content:[{type:"text",text:`Line ${e} is not an open task: "${c.trim()}"`}],isError:!0}}catch(n){return {content:[{type:"text",text:`Could not complete task: ${n instanceof Error?n.message:String(n)}`}],isError:true}}});}function mt(s,o,i){s.resource("today","vault://today",{description:"Today's daily note content. Auto-updates with the current day's note.",mimeType:"text/markdown"},async t=>{try{let e=`${i.dailyNotes.folder}/${x()}.md`,n=await o.readNote(e);return {contents:[{uri:t.href,text:`# Today's Daily Note (${x()})
177
177
 
178
- ${o}`,mimeType:"text/markdown"}]}}catch{return {contents:[{uri:t.href,text:`No daily note for today (${y()}).`,mimeType:"text/plain"}]}}}),s.resource("recent","vault://recent",{description:"Summary of recently modified notes in the vault.",mimeType:"text/markdown"},async t=>{try{let r=(await n.listFiles()).filter(i=>i.extension==="md").slice(0,10).map((i,a)=>`${a+1}. ${i.path}`).join(`
178
+ ${n}`,mimeType:"text/markdown"}]}}catch{return {contents:[{uri:t.href,text:`No daily note for today (${x()}).`,mimeType:"text/plain"}]}}}),s.resource("recent","vault://recent",{description:"Summary of recently modified notes in the vault.",mimeType:"text/markdown"},async t=>{try{let r=(await o.listFiles()).filter(c=>c.extension==="md").slice(0,10).map((c,a)=>`${a+1}. ${c.path}`).join(`
179
179
  `);return {contents:[{uri:t.href,text:`# Recent Notes
180
180
 
181
- ${r}`,mimeType:"text/markdown"}]}}catch{return {contents:[{uri:t.href,text:"Could not fetch recent notes.",mimeType:"text/plain"}]}}}),s.resource("tags","vault://tags",{description:"Tag cloud with counts from the vault.",mimeType:"text/markdown"},async t=>{try{let o=(await n.listFiles()).filter(p=>p.extension==="md"),r=new Map,i=Math.min(o.length,50);for(let p of o.slice(0,i))try{let u=await n.readNote(p.path);for(let f of w(u))r.set(f,(r.get(f)??0)+1);}catch{}let d=[...r.entries()].sort((p,u)=>u[1]-p[1]).slice(0,30).map(([p,u])=>`- #${p} (${u})`).join(`
181
+ ${r}`,mimeType:"text/markdown"}]}}catch{return {contents:[{uri:t.href,text:"Could not fetch recent notes.",mimeType:"text/plain"}]}}}),s.resource("tags","vault://tags",{description:"Tag cloud with counts from the vault.",mimeType:"text/markdown"},async t=>{try{let n=(await o.listFiles()).filter(m=>m.extension==="md"),r=new Map,c=Math.min(n.length,50);for(let m of n.slice(0,c))try{let u=await o.readNote(m.path);for(let f of $(u))r.set(f,(r.get(f)??0)+1);}catch{}let l=[...r.entries()].sort((m,u)=>u[1]-m[1]).slice(0,30).map(([m,u])=>`- #${m} (${u})`).join(`
182
182
  `);return {contents:[{uri:t.href,text:`# Vault Tags
183
183
 
184
- ${d||"No tags found."}`,mimeType:"text/markdown"}]}}catch{return {contents:[{uri:t.href,text:"Could not fetch tags.",mimeType:"text/plain"}]}}}),s.resource("context","vault://context",{description:"Contextual notes relevant to the current working directory or project. Auto-infers which notes may be useful.",mimeType:"text/markdown"},async t=>{try{let o=process.cwd().split("/").pop()??"",r=[];if(o)try{r=(await n.search(o)).slice(0,5).map(d=>d.filename);}catch{}if(r.length===0)return {contents:[{uri:t.href,text:`# Context
184
+ ${l||"No tags found."}`,mimeType:"text/markdown"}]}}catch{return {contents:[{uri:t.href,text:"Could not fetch tags.",mimeType:"text/plain"}]}}}),s.resource("context","vault://context",{description:"Contextual notes relevant to the current working directory or project. Auto-infers which notes may be useful.",mimeType:"text/markdown"},async t=>{try{let n=process.cwd().split("/").pop()??"",r=[];if(n)try{r=(await o.search(n)).slice(0,5).map(l=>l.filename);}catch{}if(r.length===0)return {contents:[{uri:t.href,text:`# Context
185
185
 
186
- No vault notes found related to the current project "${o}".`,mimeType:"text/markdown"}]};let i=r.map((a,d)=>`${d+1}. ${a}`).join(`
187
- `);return {contents:[{uri:t.href,text:`# Context for "${o}"
186
+ No vault notes found related to the current project "${n}".`,mimeType:"text/markdown"}]};let c=r.map((a,l)=>`${l+1}. ${a}`).join(`
187
+ `);return {contents:[{uri:t.href,text:`# Context for "${n}"
188
188
 
189
189
  Relevant vault notes:
190
190
 
191
- ${i}`,mimeType:"text/markdown"}]}}catch{return {contents:[{uri:t.href,text:"Could not determine context.",mimeType:"text/plain"}]}}});}var z="mindcache";function k(s){process.stderr.write(`[${z}] ${s}
192
- `);}function P(s){process.stderr.write(`[${z}] ERROR: ${s}
193
- `);}function ut(s){process.stderr.write(`[${z}] WARN: ${s}
194
- `);}var F="0.1.1";function pt(s){let n=new McpServer({name:"mindcache",version:F},{instructions:["MindCache connects your Obsidian vault to AI.","Use the search and ask tools to find information in the user's personal knowledge base.","Use the remember tools to capture decisions, meetings, ideas, learnings, and references.","Use the log tool to add entries to the daily note.","Use the connect tools to build links between related notes.","Always check the vault before asking the user to repeat information they may have already documented.","When creating notes, use appropriate templates and add relevant tags."].join(" ")}),c=new M(s);return k("Registering tools..."),et(n,c),nt(n,c,s),rt(n,c,s),st(n,c,s),it(n,c),at(n,c),ct(n,c),lt(n,c),dt(n,c),k("Registering resources..."),ft(n,c,s),k("Server configured with 40 tools and 4 resources"),n}var Y={vault:"",dailyNotes:{folder:"Daily",format:"YYYY-MM-DD"},templates:{folder:"Templates/MindCache"},inbox:{folder:"MindCache/Inbox",requireReview:false}};function Ot(s){let n={},c="";for(let t of s.split(`
195
- `)){let e=t.replace(/#.*$/,"").trimEnd();if(!e.trim())continue;let o=e.length-e.trimStart().length,r=e.trim(),i=r.indexOf(":");if(i<0)continue;let a=r.slice(0,i).trim(),d=r.slice(i+1).trim();o===0&&!d?(c=a,n[c]||(n[c]={})):o>0&&c?n[c][a]=d:n[a]=d;}return n}function _t(){let s=[resolve(process.cwd(),".mindcache.yml"),resolve(process.cwd(),".mindcache.yaml"),join(homedir(),".config","mindcache","config.yml"),join(homedir(),".config","mindcache","config.yaml"),join(homedir(),".mindcache.yml")];for(let n of s)if(existsSync(n))return n;return null}function j(){let s={vault:Y.vault,dailyNotes:{...Y.dailyNotes},templates:{...Y.templates},inbox:{...Y.inbox}};process.env.MINDCACHE_VAULT&&(s.vault=process.env.MINDCACHE_VAULT);let n=process.env.MINDCACHE_CONFIG||_t();if(n&&existsSync(n)){k(`Loading config from ${n}`);try{let c=readFileSync(n,"utf-8"),t=Ot(c);typeof t.vault=="string"&&(s.vault=t.vault);let e=t.daily_notes??t.dailyNotes;e&&(e.folder&&(s.dailyNotes.folder=e.folder),e.format&&(s.dailyNotes.format=e.format));let o=t.templates;o&&o.folder&&(s.templates.folder=o.folder);let r=t.inbox;r&&(r.folder&&(s.inbox.folder=r.folder),r.require_review&&(s.inbox.requireReview=r.require_review==="true"));}catch(c){ut(`Failed to parse config: ${c instanceof Error?c.message:String(c)}`);}}return s.vault.startsWith("~")&&(s.vault=s.vault.replace("~",homedir())),s}var Ht=`
196
- MindCache v${F} \u2014 Your Obsidian vault, connected to AI.
191
+ ${c}`,mimeType:"text/markdown"}]}}catch{return {contents:[{uri:t.href,text:"Could not determine context.",mimeType:"text/plain"}]}}});}var q="mindcache";function S(s){process.stderr.write(`[${q}] ${s}
192
+ `);}function O(s){process.stderr.write(`[${q}] ERROR: ${s}
193
+ `);}function pt(s){process.stderr.write(`[${q}] WARN: ${s}
194
+ `);}var D="0.2.0";function gt(s){let o=new McpServer({name:"mindcache",version:D},{instructions:["MindCache connects your Obsidian vault to AI.","Use the search and ask tools to find information in the user's personal knowledge base.","Use the remember tools to capture decisions, meetings, ideas, learnings, and references.","Use the log tool to add entries to the daily note.","Use the connect tools to build links between related notes.","Always check the vault before asking the user to repeat information they may have already documented.","When creating notes, use appropriate templates and add relevant tags."].join(" ")}),i=new E(s);return S("Registering tools..."),ot(o,i),rt(o,i,s),it(o,i,s),at(o,i,s),ct(o,i),lt(o,i),dt(o,i),ft(o,i),ut(o,i),S("Registering resources..."),mt(o,i,s),S("Server configured with 40 tools and 4 resources"),o}var H={vault:"",dailyNotes:{folder:"Daily",format:"YYYY-MM-DD"},templates:{folder:"Templates/MindCache"},inbox:{folder:"MindCache/Inbox",requireReview:false}};function It(s){let o={},i="";for(let t of s.split(`
195
+ `)){let e=t.replace(/#.*$/,"").trimEnd();if(!e.trim())continue;let n=e.length-e.trimStart().length,r=e.trim(),c=r.indexOf(":");if(c<0)continue;let a=r.slice(0,c).trim(),l=r.slice(c+1).trim();n===0&&!l?(i=a,o[i]||(o[i]={})):n>0&&i?o[i][a]=l:o[a]=l;}return o}function Yt(){let s=[resolve(process.cwd(),".mindcache.yml"),resolve(process.cwd(),".mindcache.yaml"),join(homedir(),".config","mindcache","config.yml"),join(homedir(),".config","mindcache","config.yaml"),join(homedir(),".mindcache.yml")];for(let o of s)if(existsSync(o))return o;return null}function j(){let s={vault:H.vault,dailyNotes:{...H.dailyNotes},templates:{...H.templates},inbox:{...H.inbox}};process.env.MINDCACHE_VAULT&&(s.vault=process.env.MINDCACHE_VAULT);let o=process.env.MINDCACHE_CONFIG||Yt();if(o&&existsSync(o)){S(`Loading config from ${o}`);try{let i=readFileSync(o,"utf-8"),t=It(i);typeof t.vault=="string"&&(s.vault=t.vault);let e=t.daily_notes??t.dailyNotes;e&&(e.folder&&(s.dailyNotes.folder=e.folder),e.format&&(s.dailyNotes.format=e.format));let n=t.templates;n&&n.folder&&(s.templates.folder=n.folder);let r=t.inbox;r&&(r.folder&&(s.inbox.folder=r.folder),r.require_review&&(s.inbox.requireReview=r.require_review==="true"));}catch(i){pt(`Failed to parse config: ${i instanceof Error?i.message:String(i)}`);}}return s.vault.startsWith("~")&&(s.vault=s.vault.replace("~",homedir())),s}var Gt=`
196
+ MindCache v${D} \u2014 Your Obsidian vault, connected to AI.
197
197
 
198
198
  Usage:
199
199
  mindcache Start the MCP server (default)
@@ -213,18 +213,18 @@ Config file locations (checked in order):
213
213
  ~/.mindcache.yml
214
214
 
215
215
  Learn more: https://usemindcache.com
216
- `;async function yt(s){let n=createInterface({input:process.stdin,output:process.stderr});return new Promise(c=>{n.question(s,t=>{n.close(),c(t.trim());});})}async function Ut(){process.stderr.write(`
216
+ `;async function wt(s){let o=createInterface({input:process.stdin,output:process.stderr});return new Promise(i=>{o.question(s,t=>{o.close(),i(t.trim());});})}async function Kt(){process.stderr.write(`
217
217
  MindCache Setup
218
218
  `),process.stderr.write(`===============
219
219
 
220
220
  `),process.stderr.write(`MindCache reads your Obsidian vault directly from the filesystem.
221
221
  `),process.stderr.write(`No plugins required \u2014 just point it at your vault folder.
222
222
 
223
- `);let s=join(homedir(),"Documents","Obsidian Vault"),n=await yt(`Obsidian vault path [${s}]: `)||s,c=await yt("Daily notes folder [Daily]: ")||"Daily",t=`# MindCache Configuration
224
- vault: ${n}
223
+ `);let s=join(homedir(),"Documents","Obsidian Vault"),o=await wt(`Obsidian vault path [${s}]: `)||s,i=await wt("Daily notes folder [Daily]: ")||"Daily",t=`# MindCache Configuration
224
+ vault: ${o}
225
225
 
226
226
  daily_notes:
227
- folder: ${c}
227
+ folder: ${i}
228
228
  format: YYYY-MM-DD
229
229
 
230
230
  templates:
@@ -233,11 +233,11 @@ templates:
233
233
  inbox:
234
234
  folder: MindCache/Inbox
235
235
  require_review: false
236
- `,e=join(homedir(),".config","mindcache");existsSync(e)||mkdirSync(e,{recursive:true});let o=join(e,"config.yml");writeFileSync(o,t),process.stderr.write(`
237
- Config saved to: ${o}
236
+ `,e=join(homedir(),".config","mindcache");existsSync(e)||mkdirSync(e,{recursive:true});let n=join(e,"config.yml");writeFileSync(n,t),process.stderr.write(`
237
+ Config saved to: ${n}
238
238
 
239
239
  `),process.stderr.write(`Checking vault...
240
- `);let r=j(),a=await new M(r).health();a.ok?process.stderr.write(` Found ${a.noteCount} notes in vault
240
+ `);let r=j(),a=await new E(r).health();a.ok?process.stderr.write(` Found ${a.noteCount} notes in vault
241
241
 
242
242
  `):(process.stderr.write(` ${a.error}
243
243
  `),process.stderr.write(` Check that the vault path is correct.
@@ -245,8 +245,8 @@ Config saved to: ${o}
245
245
  `)),process.stderr.write(`Add MindCache to Claude Code:
246
246
  `),process.stderr.write(` claude mcp add --scope user mindcache -- npx @augmnt-sh/mindcache
247
247
 
248
- `),process.exit(0);}async function zt(){process.stderr.write(`
249
- MindCache Doctor v${F}
248
+ `),process.exit(0);}async function Bt(){process.stderr.write(`
249
+ MindCache Doctor v${D}
250
250
  `),process.stderr.write(`==========================
251
251
 
252
252
  `);let s=j();process.stderr.write(`Checking configuration...
@@ -257,16 +257,16 @@ MindCache Doctor v${F}
257
257
  `),process.stderr.write(` [OK] Inbox: ${s.inbox.folder}/
258
258
  `),process.stderr.write(`
259
259
  Checking vault access...
260
- `);let c=await new M(s).health();c.ok?(process.stderr.write(` [OK] Vault readable
261
- `),process.stderr.write(` [OK] Found ${c.noteCount} markdown notes
262
- `)):(process.stderr.write(` [FAIL] ${c.error}
260
+ `);let i=await new E(s).health();i.ok?(process.stderr.write(` [OK] Vault readable
261
+ `),process.stderr.write(` [OK] Found ${i.noteCount} markdown notes
262
+ `)):(process.stderr.write(` [FAIL] ${i.error}
263
263
  `),process.stderr.write(`
264
264
  Troubleshooting:
265
265
  `),process.stderr.write(` 1. Check that the vault path is correct
266
266
  `),process.stderr.write(` 2. Check file permissions
267
267
  `),process.stderr.write(` 3. Run: mindcache init
268
268
  `)),process.stderr.write(`
269
- `),process.exit(c.ok?0:1);}function Vt(){let s=j();process.stderr.write(`
269
+ `),process.exit(i.ok?0:1);}function Jt(){let s=j();process.stderr.write(`
270
270
  MindCache Configuration
271
271
  `),process.stderr.write(`=======================
272
272
 
@@ -277,6 +277,6 @@ MindCache Configuration
277
277
  `),process.stderr.write(`Inbox: ${s.inbox.folder}
278
278
  `),process.stderr.write(`Review mode: ${s.inbox.requireReview?"on":"off"}
279
279
  `),process.stderr.write(`
280
- `),process.exit(0);}async function qt(){let s=process.version;parseInt(s.slice(1))<18&&(P(`Node.js >= 18 required, found ${s}`),process.exit(1)),k(`mindcache v${F} | Node ${s} | ${process.platform}`);let c=j();c.vault||k('WARN: No vault path configured. Run "mindcache init" for setup.');let t=pt(c),e=new StdioServerTransport,o=async()=>{k("Shutting down..."),await t.close(),process.exit(0);};process.on("SIGINT",o),process.on("SIGTERM",o),await t.connect(e);}var Gt=process.argv[2];switch(Gt){case "init":Ut().catch(s=>{P(s instanceof Error?s.message:String(s)),process.exit(1);});break;case "doctor":zt().catch(s=>{P(s instanceof Error?s.message:String(s)),process.exit(1);});break;case "config":Vt();break;case "--version":case "-v":process.stderr.write(`mindcache v${F}
281
- `),process.exit(0);break;case "--help":case "-h":process.stderr.write(Ht),process.exit(0);break;default:qt().catch(s=>{P(`Fatal: ${s instanceof Error?s.message:String(s)}`),process.exit(1);});}//# sourceMappingURL=cli.js.map
280
+ `),process.exit(0);}async function Qt(){let s=process.version;parseInt(s.slice(1))<18&&(O(`Node.js >= 18 required, found ${s}`),process.exit(1)),S(`mindcache v${D} | Node ${s} | ${process.platform}`);let i=j();i.vault||S('WARN: No vault path configured. Run "mindcache init" for setup.');let t=gt(i),e=new StdioServerTransport,n=async()=>{S("Shutting down..."),await t.close(),process.exit(0);};process.on("SIGINT",n),process.on("SIGTERM",n),await t.connect(e);}var Xt=process.argv[2];switch(Xt){case "init":Kt().catch(s=>{O(s instanceof Error?s.message:String(s)),process.exit(1);});break;case "doctor":Bt().catch(s=>{O(s instanceof Error?s.message:String(s)),process.exit(1);});break;case "config":Jt();break;case "--version":case "-v":process.stderr.write(`mindcache v${D}
281
+ `),process.exit(0);break;case "--help":case "-h":process.stderr.write(Gt),process.exit(0);break;default:Qt().catch(s=>{O(`Fatal: ${s instanceof Error?s.message:String(s)}`),process.exit(1);});}//# sourceMappingURL=cli.js.map
282
282
  //# sourceMappingURL=cli.js.map