@vpxa/aikit 0.1.296 → 0.1.298

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.
Files changed (26) hide show
  1. package/bin/aikit.mjs +27 -2
  2. package/package.json +1 -1
  3. package/packages/blocks-core/dist/index.mjs +54 -36
  4. package/packages/cli/dist/index.js +18 -18
  5. package/packages/cli/dist/{init-DWIr_CT8.js → init-WmQoeitD.js} +1 -1
  6. package/packages/cli/dist/{templates-Cc3Rn_zv.js → templates-BQ1J4HzY.js} +13 -13
  7. package/packages/present/dist/index.html +39 -22
  8. package/packages/server/dist/bin.js +3 -3
  9. package/packages/server/dist/{curated-manager-C5uOPept.js → curated-manager-i5QA4c79.js} +2 -2
  10. package/packages/server/dist/index.d.ts +30 -3
  11. package/packages/server/dist/index.js +1 -1
  12. package/packages/server/dist/promotion-DmwIVl0c.js +2 -0
  13. package/packages/server/dist/promotion-bQutAIz-.js +3 -0
  14. package/packages/server/dist/{server-BRinO5Fx.js → server-CYLGfaH1.js} +156 -155
  15. package/packages/server/dist/{server-CyERdqK0.js → server-R054LFb1.js} +156 -155
  16. package/packages/server/viewers/canvas.html +85 -68
  17. package/packages/server/viewers/report-template.html +21 -4
  18. package/packages/server/viewers/tour-viewer.html +25 -8
  19. package/packages/store/dist/index.js +2 -2
  20. package/scaffold/definitions/mcp-entry.json +1 -1
  21. package/scaffold/dist/definitions/mcp-entry.json +1 -1
  22. package/scaffold/dist/definitions/skills/c4-architecture.mjs +1 -1
  23. package/scaffold/dist/definitions/skills/docs.mjs +1 -1
  24. package/scaffold/dist/definitions/skills/present.mjs +1 -1
  25. package/packages/server/dist/promotion-CJFYv4Ye.js +0 -3
  26. package/packages/server/dist/promotion-D9anNXv8.js +0 -2
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import{createHash as e,randomUUID as t}from"node:crypto";import{readFileSync as n}from"node:fs";import{dirname as r,isAbsolute as i,join as a,resolve as o}from"node:path";import{fileURLToPath as s,pathToFileURL as c}from"node:url";import{parseArgs as l}from"node:util";import{HealthBus as u,createLogger as d,serializeError as f,setDetailedErrorLoggingEnabled as p}from"../../core/dist/index.js";import{GIT_REF_SLUG_PATTERN as m,gitAvailable as h,gitCommitToRef as g,gitExec as _,slugForRef as v}from"../../tools/dist/index.js";import{mkdir as y,readFile as b,readdir as x,stat as S,unlink as C,writeFile as w}from"node:fs/promises";var T=class{baseDir;constructor(e){this.baseDir=e}async initialize(){await y(this.baseDir,{recursive:!0})}async read(e){let t=a(this.baseDir,e);try{return await b(t,`utf-8`)}catch(e){if(e.code===`ENOENT`)return null;throw e}}async write(e,t,n){let i=a(this.baseDir,e);await y(r(i),{recursive:!0}),await w(i,t,{encoding:`utf-8`,flag:n?.exclusive?`wx`:`w`})}async delete(e){let t=a(this.baseDir,e);try{return await C(t),!0}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async list(e){let t=[],n=e?[e]:await this.listDirectories();for(let e of n){let n=a(this.baseDir,e),r;try{r=await x(n)}catch{continue}for(let n of r){if(!n.endsWith(`.md`))continue;let r=`${e}/${n}`,i=a(this.baseDir,r);try{let e=await S(i);t.push({path:r,size:e.size})}catch{}}}return t}async exists(e){let t=a(this.baseDir,e);try{return await S(t),!0}catch{return!1}}async listDirectories(){try{return(await x(this.baseDir,{withFileTypes:!0})).filter(e=>e.isDirectory()&&/^[a-z][a-z0-9-]*$/.test(e.name)).map(e=>e.name)}catch{return[]}}async close(){}};const E=50*1024,D=`refs/aikit/knowledge`,O=d(`server`);var k=class{curatedDir;store;embedder;adapter;constructor(e,t,n,r=new T(e)){this.curatedDir=e,this.store=t,this.embedder=n,this.adapter=r}async remember(e,t,n,r=[]){this.validateCategoryName(n),this.validateContentSize(t);let i=this.normalizeTags(r),a=this.slugify(e),o=await this.uniqueRelativePath(n,a),s=new Date().toISOString(),c={title:e,category:n,tags:i,created:s,updated:s,version:1,origin:`curated`,changelog:[{version:1,date:s,reason:`Initial creation`}]},l=this.serializeFile(t,c);try{await this.adapter.write(o,l,{exclusive:!0})}catch(e){throw e.code===`EEXIST`?Error(`Concurrent write collision for "${o}" — retry the operation`):e}return this.gitCommitKnowledge(o,l,`remember: ${e}\n\nCategory: ${n}\nTags: ${i.join(`, `)}`),await this.indexCuratedFileBestEffort(o,t,c,`remember`),{path:o}}async upsertAutoKnowledge(e,t,n,r,i=[],a=`Auto-knowledge refresh`){e=this.guardPath(e),this.validateCategoryName(r),this.validateContentSize(n),this.ensureCategoryPath(e,r);let o=this.normalizeTags(i),s=await this.adapter.read(e);if(s==null){let i=new Date().toISOString(),a={title:t,category:r,tags:o,created:i,updated:i,version:1,origin:`curated`,changelog:[{version:1,date:i,reason:`Initial creation`}]},s=this.serializeFile(n,a);try{await this.adapter.write(e,s,{exclusive:!0})}catch(t){throw t.code===`EEXIST`?Error(`Concurrent write collision for "${e}" — retry the operation`):t}return this.gitCommitKnowledge(e,s,`remember: ${t}\n\nCategory: ${r}\nTags: ${o.join(`, `)}`),await this.indexCuratedFileBestEffort(e,n,a,`remember`),{path:e,status:`created`,version:1}}let{frontmatter:c,content:l}=this.parseFile(s),u=this.normalizeTags(c.tags??[]),d=t.trim()||c.title;if(l===n&&c.category===r&&c.title===d&&this.sameTags(u,o))return{path:e,status:`unchanged`,version:c.version??1};let f=(c.version??1)+1,p=new Date().toISOString();c.title=d,c.category=r,c.tags=o,c.version=f,c.updated=p,c.changelog=[...c.changelog??[],{version:f,date:p,reason:a}];let m=this.serializeFile(n,c);return await this.adapter.write(e,m),this.gitCommitKnowledge(e,m,`update(v${f}): ${c.title}\n\nReason: ${a}\nVersion: ${f}`),await this.indexCuratedFileBestEffort(e,n,c,`update`),{path:e,status:`updated`,version:f}}async update(e,t,n){e=this.guardPath(e),this.validateContentSize(t);let r=await this.adapter.read(e);if(r==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:i}=this.parseFile(r),a=(i.version??1)+1,o=new Date().toISOString();i.version=a,i.updated=o,i.changelog=[...i.changelog??[],{version:a,date:o,reason:n}];let s=this.serializeFile(t,i);return await this.adapter.write(e,s),this.gitCommitKnowledge(e,s,`update(v${a}): ${i.title}\n\nReason: ${n}\nVersion: ${a}`),await this.indexCuratedFileBestEffort(e,t,i,`update`),{path:e,version:a}}async forget(e,t){if(e=this.guardPath(e),!await this.adapter.delete(e))throw Error(`Curated entry not found: ${e}`);let n=`.ai/curated/${e}`;return await this.store.deleteBySourcePath(n).catch(e=>{O.warn(`File deleted but vector cleanup failed`,{sourcePath:n,...f(e)})}),this.gitDeleteKnowledgeRef(e),{path:e}}async history(e,t=20){if(e=this.guardPath(e),!h(this.curatedDir))return[];let n=this.knowledgeRefForPath(e);if(!n)return[];let r=_([`log`,`--format=%H|%aI|%s`,n,`-n`,String(t)],this.curatedDir);return r?r.split(`
2
+ import{createHash as e,randomUUID as t}from"node:crypto";import{readFileSync as n}from"node:fs";import{dirname as r,isAbsolute as i,join as a,resolve as o}from"node:path";import{fileURLToPath as s,pathToFileURL as c}from"node:url";import{parseArgs as l}from"node:util";import{HealthBus as u,createLogger as d,serializeError as f,setDetailedErrorLoggingEnabled as p}from"../../core/dist/index.js";import{GIT_REF_SLUG_PATTERN as m,gitAvailable as h,gitCommitToRef as g,gitExec as _,slugForRef as v}from"../../tools/dist/index.js";import{mkdir as y,readFile as b,readdir as x,stat as S,unlink as C,writeFile as w}from"node:fs/promises";var T=class{baseDir;constructor(e){this.baseDir=e}async initialize(){await y(this.baseDir,{recursive:!0})}async read(e){let t=a(this.baseDir,e);try{return await b(t,`utf-8`)}catch(e){if(e.code===`ENOENT`)return null;throw e}}async write(e,t,n){let i=a(this.baseDir,e);await y(r(i),{recursive:!0}),await w(i,t,{encoding:`utf-8`,flag:n?.exclusive?`wx`:`w`})}async delete(e){let t=a(this.baseDir,e);try{return await C(t),!0}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async list(e){let t=[],n=e?[e]:await this.listDirectories();for(let e of n){let n=a(this.baseDir,e),r;try{r=await x(n)}catch{continue}for(let n of r){if(!n.endsWith(`.md`))continue;let r=`${e}/${n}`,i=a(this.baseDir,r);try{let e=await S(i);t.push({path:r,size:e.size,mtimeMs:e.mtimeMs})}catch{}}}return t}async exists(e){let t=a(this.baseDir,e);try{return await S(t),!0}catch{return!1}}async listDirectories(){try{return(await x(this.baseDir,{withFileTypes:!0})).filter(e=>e.isDirectory()&&/^[a-z][a-z0-9-]*$/.test(e.name)).map(e=>e.name)}catch{return[]}}async close(){}};const E=50*1024,D=`refs/aikit/knowledge`,O=d(`server`);var k=class{curatedDir;store;embedder;adapter;constructor(e,t,n,r=new T(e)){this.curatedDir=e,this.store=t,this.embedder=n,this.adapter=r}async remember(e,t,n,r=[]){this.validateCategoryName(n),this.validateContentSize(t);let i=this.normalizeTags(r),a=this.slugify(e),o=await this.uniqueRelativePath(n,a),s=new Date().toISOString(),c={title:e,category:n,tags:i,created:s,updated:s,version:1,origin:`curated`,changelog:[{version:1,date:s,reason:`Initial creation`}]},l=this.serializeFile(t,c);try{await this.adapter.write(o,l,{exclusive:!0})}catch(e){throw e.code===`EEXIST`?Error(`Concurrent write collision for "${o}" — retry the operation`):e}return this.gitCommitKnowledge(o,l,`remember: ${e}\n\nCategory: ${n}\nTags: ${i.join(`, `)}`),await this.indexCuratedFileBestEffort(o,t,c,`remember`),{path:o}}async upsertAutoKnowledge(e,t,n,r,i=[],a=`Auto-knowledge refresh`){e=this.guardPath(e),this.validateCategoryName(r),this.validateContentSize(n),this.ensureCategoryPath(e,r);let o=this.normalizeTags(i),s=await this.adapter.read(e);if(s==null){let i=new Date().toISOString(),a={title:t,category:r,tags:o,created:i,updated:i,version:1,origin:`curated`,changelog:[{version:1,date:i,reason:`Initial creation`}]},s=this.serializeFile(n,a);try{await this.adapter.write(e,s,{exclusive:!0})}catch(t){throw t.code===`EEXIST`?Error(`Concurrent write collision for "${e}" — retry the operation`):t}return this.gitCommitKnowledge(e,s,`remember: ${t}\n\nCategory: ${r}\nTags: ${o.join(`, `)}`),await this.indexCuratedFileBestEffort(e,n,a,`remember`),{path:e,status:`created`,version:1}}let{frontmatter:c,content:l}=this.parseFile(s),u=this.normalizeTags(c.tags??[]),d=t.trim()||c.title;if(l===n&&c.category===r&&c.title===d&&this.sameTags(u,o))return{path:e,status:`unchanged`,version:c.version??1};let f=(c.version??1)+1,p=new Date().toISOString();c.title=d,c.category=r,c.tags=o,c.version=f,c.updated=p,c.changelog=[...c.changelog??[],{version:f,date:p,reason:a}];let m=this.serializeFile(n,c);return await this.adapter.write(e,m),this.gitCommitKnowledge(e,m,`update(v${f}): ${c.title}\n\nReason: ${a}\nVersion: ${f}`),await this.indexCuratedFileBestEffort(e,n,c,`update`),{path:e,status:`updated`,version:f}}async update(e,t,n){e=this.guardPath(e),this.validateContentSize(t);let r=await this.adapter.read(e);if(r==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:i}=this.parseFile(r),a=(i.version??1)+1,o=new Date().toISOString();i.version=a,i.updated=o,i.changelog=[...i.changelog??[],{version:a,date:o,reason:n}];let s=this.serializeFile(t,i);return await this.adapter.write(e,s),this.gitCommitKnowledge(e,s,`update(v${a}): ${i.title}\n\nReason: ${n}\nVersion: ${a}`),await this.indexCuratedFileBestEffort(e,t,i,`update`),{path:e,version:a}}async forget(e,t){if(e=this.guardPath(e),!await this.adapter.delete(e))throw Error(`Curated entry not found: ${e}`);let n=`.ai/curated/${e}`;return await this.store.deleteBySourcePath(n).catch(e=>{O.warn(`File deleted but vector cleanup failed`,{sourcePath:n,...f(e)})}),this.gitDeleteKnowledgeRef(e),{path:e}}async history(e,t=20){if(e=this.guardPath(e),!h(this.curatedDir))return[];let n=this.knowledgeRefForPath(e);if(!n)return[];let r=_([`log`,`--format=%H|%aI|%s`,n,`-n`,String(t)],this.curatedDir);return r?r.split(`
3
3
  `).filter(Boolean).map(e=>{let[t,n,...r]=e.split(`|`);return{sha:t,date:n,message:r.join(`|`)}}):[]}async diff(e,t,n){if(e=this.guardPath(e),!h(this.curatedDir))return``;if(!n){let r=await this.history(e,2);if(r.length===0)return``;n=r[0].sha,r.length>1&&!t&&(t=r[1].sha)}return t&&n?_([`diff`,`${t}:entry.md`,`${n}:entry.md`],this.curatedDir)??``:n?_([`show`,`${n}:entry.md`],this.curatedDir)??``:``}async recover(e){if(e=this.guardPath(e),await this.adapter.exists(e))throw Error(`Entry already exists on filesystem: ${e}. Use update() instead.`);if(!h(this.curatedDir))return null;let t=this.knowledgeRefForPath(e);if(!t)return null;let n=_([`show`,`${t}:entry.md`],this.curatedDir);if(!n)return null;await this.adapter.write(e,n);let{frontmatter:r,content:i}=this.parseFile(n);return await this.indexCuratedFile(e,i,r),{path:e,version:r.version??1}}async listOrphaned(){if(!h(this.curatedDir))return[];let e=_([`for-each-ref`,`--format=%(refname)|%(subject)`,`${D}/`],this.curatedDir);if(!e)return[];let t=[];for(let n of e.split(`
4
- `).filter(Boolean)){let[e,...r]=n.split(`|`),i=r.join(`|`),a=`${e.replace(`${D}/`,``)}.md`;await this.adapter.exists(a)||t.push({ref:e,path:a,lastMessage:i})}return t}async read(e){e=this.guardPath(e);let t=await this.adapter.read(e);if(t==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:n,content:r}=this.parseFile(t),i=e.split(`/`)[0];return{path:e,title:n.title??e,category:i,tags:n.tags??[],version:n.version??1,created:n.created??``,updated:n.updated??``,contentPreview:r.slice(0,200),content:r}}async list(e){let t=[],n=e?.category?[e.category]:await this.discoverCategories();for(let r of n){let n=await this.adapter.list(r);for(let i of n){let n=await this.adapter.read(i.path);if(n==null)continue;let{frontmatter:a,content:o}=this.parseFile(n);e?.tag&&!(a.tags??[]).includes(e.tag)||t.push({path:i.path,title:a.title??i.path,category:r,tags:a.tags??[],version:a.version??1,created:a.created??``,updated:a.updated??``,contentPreview:o.slice(0,200)})}}return t}async reindexAll(){let e=await this.discoverCategories(),t=[],n=[];for(let r of e){let e=await this.adapter.list(r);for(let r of e){let e=r.path;try{let r=await this.adapter.read(e);if(r==null){t.push(`${e}: read failed`);continue}let{frontmatter:i,content:a}=this.parseFile(r);n.push({relativePath:e,content:a,frontmatter:i})}catch(n){O.error(`Failed to read curated file`,{relativePath:e,...f(n)}),t.push(`${e}: read failed`)}}}if(n.length===0)return{indexed:0,errors:t};let r=new Date().toISOString(),i=0;for(let e=0;e<n.length;e+=16){let a=n.slice(e,e+16);i+=await this.embedAndUpsertBatch(a,r,t)}return{indexed:i,errors:t}}async embedAndUpsertBatch(e,t,n){try{let r=await this.embedder.embedBatch(e.map(e=>e.content)),i=e.map(e=>{let n=`.ai/curated/${e.relativePath}`;return{id:this.hashId(n,0),content:e.content,sourcePath:n,contentType:`curated-knowledge`,headingPath:e.frontmatter.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:e.content.split(`
4
+ `).filter(Boolean)){let[e,...r]=n.split(`|`),i=r.join(`|`),a=`${e.replace(`${D}/`,``)}.md`;await this.adapter.exists(a)||t.push({ref:e,path:a,lastMessage:i})}return t}async read(e){e=this.guardPath(e);let t=await this.adapter.read(e);if(t==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:n,content:r}=this.parseFile(t),i=e.split(`/`)[0];return{path:e,title:n.title??e,category:i,tags:n.tags??[],version:n.version??1,created:n.created??``,updated:n.updated??``,contentPreview:r.slice(0,200),content:r}}async list(e){return(await this.listPage(e)).entries}async listPage(e){let t=e?.category?[e.category]:await this.discoverCategories(),n=[];for(let e of t){let t=await this.adapter.list(e);for(let r of t)n.push({path:r.path,category:e,mtimeMs:r.mtimeMs??0})}let r=Math.max(0,e?.offset??0),i=e?.limit==null?null:Math.max(1,e.limit),a=(e?.order??`asc`)===`desc`?-1:1,o=e?.orderBy??`path`;if(o===`path`||o===`updated`){let t=this.sortCandidateMetadata(n,o,a);if(e?.tag){let n=i==null?void 0:r+i+1,{entries:a,scannedAll:o}=await this.readCandidateEntries(t,{tag:e.tag,maxMatches:n}),s=i==null?a.slice(r):a.slice(r,r+i),c=i!=null&&(a.length>r+s.length||!o);return{entries:s,totalCount:o?a.length:r+s.length+ +!!c,totalCountIsExact:o,limit:i,offset:r,hasMore:c}}let s=i==null?t.slice(r):t.slice(r,r+i),{entries:c}=await this.readCandidateEntries(s);return{entries:c,totalCount:t.length,totalCountIsExact:!0,limit:i,offset:r,hasMore:i!=null&&r+c.length<t.length}}let{entries:s}=await this.readCandidateEntries(n,{tag:e?.tag}),c=s.sort((e,t)=>{switch(o){case`created`:return(Date.parse(e.created)-Date.parse(t.created))*a;case`updated`:return(Date.parse(e.updated)-Date.parse(t.updated))*a;case`path`:return e.path.localeCompare(t.path)*a;default:return 0}}),l=i==null?c.slice(r):c.slice(r,r+i);return{entries:l,totalCount:c.length,totalCountIsExact:!0,limit:i,offset:r,hasMore:i!=null&&r+l.length<c.length}}async count(e){if(e?.tag)return(await this.listPage({...e,limit:void 0})).totalCount;let t=e?.category?[e.category]:await this.discoverCategories(),n=0;for(let e of t)n+=(await this.adapter.list(e)).length;return n}async listPaths(e){let t=e?.category?[e.category]:await this.discoverCategories(),n=[];for(let e of t){let t=await this.adapter.list(e);n.push(...t.map(e=>e.path))}n.sort((e,t)=>e.localeCompare(t));let r=Math.max(0,e?.offset??0),i=e?.limit==null?null:Math.max(1,e.limit);return i==null?n.slice(r):n.slice(r,r+i)}sortCandidateMetadata(e,t,n){return[...e].sort((e,r)=>t===`updated`?(e.mtimeMs-r.mtimeMs)*n:e.path.localeCompare(r.path)*n)}async readCandidateEntries(e,t){let n=[];for(let r of e){let e=await this.adapter.read(r.path);if(e==null)continue;let{frontmatter:i,content:a}=this.parseFile(e),o=i.tags??[];if(!(t?.tag&&!o.includes(t.tag))&&(n.push({path:r.path,title:i.title??r.path,category:r.category,tags:o,version:i.version??1,created:i.created??``,updated:i.updated??``,contentPreview:a.slice(0,200)}),t?.maxMatches!=null&&n.length>=t.maxMatches))return{entries:n,scannedAll:!1}}return{entries:n,scannedAll:!0}}async reindexAll(){let e=await this.discoverCategories(),t=[],n=[];for(let r of e){let e=await this.adapter.list(r);for(let r of e){let e=r.path;try{let r=await this.adapter.read(e);if(r==null){t.push(`${e}: read failed`);continue}let{frontmatter:i,content:a}=this.parseFile(r);n.push({relativePath:e,content:a,frontmatter:i})}catch(n){O.error(`Failed to read curated file`,{relativePath:e,...f(n)}),t.push(`${e}: read failed`)}}}if(n.length===0)return{indexed:0,errors:t};let r=new Date().toISOString(),i=0;for(let e=0;e<n.length;e+=16){let a=n.slice(e,e+16);i+=await this.embedAndUpsertBatch(a,r,t)}return{indexed:i,errors:t}}async embedAndUpsertBatch(e,t,n){try{let r=await this.embedder.embedBatch(e.map(e=>e.content)),i=e.map(e=>{let n=`.ai/curated/${e.relativePath}`;return{id:this.hashId(n,0),content:e.content,sourcePath:n,contentType:`curated-knowledge`,headingPath:e.frontmatter.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:e.content.split(`
5
5
  `).length,fileHash:this.hash(e.content),indexedAt:t,origin:`curated`,tags:e.frontmatter.tags,category:e.frontmatter.category,version:e.frontmatter.version}});try{return await this.store.upsert(i,r),e.length}catch(t){O.error(`Failed to upsert curated batch`,{batchSize:e.length,...f(t)});for(let t of e)n.push(`${t.relativePath}: upsert failed`);return 0}}catch(r){if(e.length===1)return O.error(`Failed to embed curated item`,{relativePath:e[0].relativePath,...f(r)}),n.push(`${e[0].relativePath}: reindex failed`),0;O.warn(`Curated embed batch failed, retrying with smaller chunks`,{batchSize:e.length,...f(r)});let i=Math.ceil(e.length/2),a=e.slice(0,i),o=e.slice(i);return await this.embedAndUpsertBatch(a,t,n)+await this.embedAndUpsertBatch(o,t,n)}}gitCommitKnowledge(e,t,n){try{if(!h(this.curatedDir))return;let r=this.knowledgeRefForPath(e);if(!r)return;g(r,`entry.md`,t,n,this.curatedDir)}catch{}}gitDeleteKnowledgeRef(e){try{if(!h(this.curatedDir))return;let t=this.knowledgeRefForPath(e);if(!t)return;_([`update-ref`,`-d`,t],this.curatedDir)}catch{}}knowledgeRefForPath(e){let t=e.replace(/\.md$/,``).split(`/`).map(e=>v(e)).join(`/`);return t.split(`/`).every(e=>m.test(e))?`${D}/${t}`:null}async indexCuratedFile(e,t,n){let r=await this.embedder.embed(t),i=`.ai/curated/${e}`,a=new Date().toISOString(),o={id:this.hashId(i,0),content:t,sourcePath:i,contentType:`curated-knowledge`,headingPath:n.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:t.split(`
6
6
  `).length,fileHash:this.hash(t),indexedAt:a,origin:`curated`,tags:n.tags,category:n.category,version:n.version};await this.store.upsert([o],[r])}async indexCuratedFileBestEffort(e,t,n,r){if(u.instance().isDegraded(`embedder`)){O.debug(`Skipping vector indexing — embedder degraded`,{relativePath:e,operation:r,subsystem:`embedder`});return}try{await this.indexCuratedFile(e,t,n)}catch(t){O.warn(`Curated file persisted but vector indexing deferred`,{relativePath:e,operation:r,...f(t)})}}async discoverCategories(){return this.adapter.listDirectories()}guardPath(e){let t=e.replace(/^\.ai\/curated\//,``);if(t.endsWith(`.md`)||(t+=`.md`),t.includes(`..`)||i(t))throw Error(`Invalid path: ${t}. Must be relative within .ai/curated/ directory.`);let n=t.split(`/`)[0];return this.validateCategoryName(n),t}validateCategoryName(e){if(!/^[a-z][a-z0-9-]*$/.test(e))throw Error(`Invalid category name: "${e}". Must be lowercase kebab-case (e.g., "decisions", "api-contracts").`)}validateContentSize(e){if(Buffer.byteLength(e,`utf-8`)>E)throw Error(`Content exceeds maximum size of ${E/1024}KB`)}slugify(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-|-$/g,``).slice(0,80)}normalizeTags(e){return[...new Set(e.map(e=>e.trim()).filter(Boolean))]}sameTags(e,t){if(e.length!==t.length)return!1;let n=new Set(e);return t.every(e=>n.has(e))}ensureCategoryPath(e,t){if(!e.startsWith(`${t}/`))throw Error(`Curated path "${e}" must stay within category "${t}"`)}async uniqueRelativePath(e,t){let n=`${e}/${t}.md`;if(!await this.adapter.exists(n))return n;for(let n=2;n<=100;n++){let r=`${e}/${t}-${n}.md`;if(!await this.adapter.exists(r))return r}throw Error(`Too many entries with slug "${t}" in category "${e}"`)}hash(t){return e(`sha256`).update(t).digest(`hex`).slice(0,16)}hashId(e,t){return this.hash(`${e}::${t}`)}serializeFile(e,t){return`${[`---`,`title: "${t.title.replace(/"/g,`\\"`)}"`,`category: ${t.category}`,`tags: [${t.tags.map(e=>`"${e}"`).join(`, `)}]`,`created: ${t.created}`,`updated: ${t.updated}`,`version: ${t.version}`,`origin: ${t.origin}`,`changelog:`,...t.changelog.map(e=>` - version: ${e.version}\n date: ${e.date}\n reason: "${e.reason.replace(/"/g,`\\"`)}"`),`---`].join(`
7
7
  `)}\n\n${e}\n`}parseFile(e){let t=e.match(/^---\n([\s\S]*?)\n---\n\n?([\s\S]*)$/);if(!t)return{frontmatter:{title:`Untitled`,category:`notes`,tags:[],created:``,updated:``,version:1,origin:`curated`,changelog:[]},content:e};let n=t[1],r=t[2].trim(),i={},a=[],o=n.split(`
8
- `),s=!1,c={};for(let e of o){if(/^changelog:\s*$/.test(e)){s=!0;continue}if(s){let t=e.match(/^\s+-\s+version:\s*(\d+)$/);if(t){c.version!=null&&a.push(c),c={version:parseInt(t[1],10)};continue}let n=e.match(/^\s+date:\s*(.+)$/);if(n){c.date=n[1].trim();continue}let r=e.match(/^\s+reason:\s*"?(.*?)"?\s*$/);if(r){c.reason=r[1];continue}/^\w/.test(e)&&(s=!1,c.version!=null&&a.push(c),c={});continue}let t=e.match(/^(\w+):\s*(.*)$/);if(t){let e=t[1],n=t[2];typeof n==`string`&&n.startsWith(`[`)&&n.endsWith(`]`)?n=n.slice(1,-1).split(`,`).map(e=>e.trim().replace(/^"|"$/g,``)).filter(e=>e.length>0):typeof n==`string`&&/^\d+$/.test(n)?n=parseInt(n,10):typeof n==`string`&&n.startsWith(`"`)&&n.endsWith(`"`)&&(n=n.slice(1,-1)),i[e]=n}}return c.version!=null&&a.push(c),{frontmatter:{title:i.title??`Untitled`,category:i.category??`notes`,tags:i.tags??[],created:i.created??``,updated:i.updated??``,version:i.version??1,origin:`curated`,changelog:a},content:r}}};const A=`__pending__:`;function j(e){return e.startsWith(A)}function M(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function N(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var P=class{options;runtimes=new Map;maxSessions;sessionTimeoutMs;now;constructor(e){this.options=e,this.maxSessions=e.maxSessions??8,this.sessionTimeoutMs=(e.sessionTimeoutMinutes??30)*60*1e3,this.now=e.now??(()=>Date.now())}hasSession(e){return this.runtimes.has(e)}getSessionCount(){return this.runtimes.size}async handleRequest(e,t,n=e.body){let r=M(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){N(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){N(t,400,-32e3,`Session required`);return}if(i=await this.createRuntime(t),!i)return}await this.withRuntimeLock(i,async()=>{await i.transport.handleRequest(e,t,n),i.lastAccessAt=this.now();let r=i.transport.sessionId??i.id;e.method!==`DELETE`&&!j(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!j(r)&&await this.closeSession(r,{closeTransport:!1})})}async closeExpiredSessions(){let e=[...this.runtimes.values()].filter(e=>this.now()-e.lastAccessAt>=this.sessionTimeoutMs).map(e=>e.id);for(let t of e)await this.closeSession(t);return e.length}async closeSession(e,t={}){let n=this.runtimes.get(e);return n?(this.runtimes.delete(e),t.notifySessionEnd!==!1&&!j(e)&&this.options.onSessionEnd?.(e),t.closeTransport!==!1&&await n.transport.close().catch(()=>void 0),await n.server.close().catch(()=>void 0),!0):!1}async closeAll(){let e=[...this.runtimes.keys()];for(let t of e)await this.closeSession(t)}async createRuntime(e){if(await this.closeExpiredSessions(),this.runtimes.size>=this.maxSessions){N(e,503,-32003,`Session capacity reached`);return}let n=this.now(),r=await this.options.createServer(),i={id:`${A}${t()}`,transport:void 0,createdAt:n,lastAccessAt:n,server:r,requestChain:Promise.resolve()},a=this.options.createTransport({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{this.runtimes.delete(i.id),i.id=e,this.runtimes.set(e,i),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return i.transport=a,a.onclose=()=>{let e=i.transport.sessionId??i.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(i.id,i),await r.connect(a),i}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function F(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var I=class{stateStore;options;gcTimer=null;constructor(e,t={}){this.stateStore=e,this.options=t}onSessionStart(e,t){this.stateStore.sessionCreate(e,t)}onSessionActivity(e){this.stateStore.sessionTouch(e)}onSessionEnd(e){this.stateStore.sessionDelete(e),Promise.resolve(this.options.onSessionEndMaintenance?.(e)).catch(()=>{})}startGC(){if(this.gcTimer)return;let e=(this.options.gcIntervalMinutes??5)*60*1e3;this.gcTimer=setInterval(()=>{this.runGC()},e),this.gcTimer.unref()}runGC(){let e=this.getStaleSessionIds();for(let t of e)this.options.onBeforeSessionDelete?.(t),Promise.resolve(this.options.onSessionEndMaintenance?.(t)).catch(()=>{}),this.stateStore.sessionDelete(t);return e.length}stop(){this.gcTimer&&=(clearInterval(this.gcTimer),null)}getActiveSessions(){return this.stateStore.sessionList().length}listSessions(){return this.stateStore.sessionList()}getStaleSessionIds(e=Date.now()){let t=(this.options.staleTimeoutMinutes??30)*60*1e3;return this.stateStore.sessionList().filter(n=>{let r=F(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};function L(){try{let e=o(r(s(import.meta.url)),`..`,`..`,`..`,`package.json`);return JSON.parse(n(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}const R=d(`server`);function z(e,t){return t?{version:e,...f(t)}:{version:e}}const B=/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;function V({requestOrigin:e,configuredOrigin:t,allowAnyOrigin:n,fallbackOrigin:r}){let i=t??r;return i===`*`?n?{allowOrigin:`*`,warn:!1}:e?B.test(e)?{allowOrigin:e,warn:!1}:{allowOrigin:null,warn:!0}:{allowOrigin:r,warn:!1}:{allowOrigin:i,warn:!1}}function H({limit:e,windowMs:t}){let n=new Map,r=(e,r)=>{let i=r-t,a=n.get(e)?.filter(e=>e>i)??[];return a.length===0?(n.delete(e),[]):(n.set(e,a),a)};return{allow(t,i=Date.now()){let a=r(t,i);return a.length>=e?!1:(a.push(i),n.set(t,a),!0)},getRetryAfterMs(n,i=Date.now()){let a=r(n,i);return a.length<e?0:Math.max(0,a[0]+t-i)}}}function U(e){return e.startsWith(`file://`)?s(e):e}function W(e){let t=o(e);return process.platform===`win32`?t.toLowerCase():t}function G(e){let t=new Map;for(let n of e){let e=U(n.uri);t.set(W(e),e)}return[...t.values()].sort((e,t)=>W(e).localeCompare(W(t)))}function K({config:e,roots:t}){let n=G(t);if(n.length===0)return null;let r=e.sources?.[0]?.path;if(r){let e=W(r),t=n.find(t=>W(t)===e);if(t)return t}return n[0]}function q({config:e,log:t,reconfigureForWorkspace:n,roots:r}){let i=G(r);if(i.length===0)return!1;let a=K({config:e,roots:i.map(e=>({uri:e}))});if(!a)return!1;let o=e.sources?.[0]?.path,s=o&&W(o)===W(a)?`configured-source`:`stable-sorted-root`;return t.debug(`MCP roots resolved`,{rootPath:a,rootCount:i.length,selectedBy:s}),n(e,a),e.allRoots=i,!0}async function J({config:e,indexMode:t,log:n,rootsChangedNotificationSchema:r,reconfigureForWorkspace:i,runInitialIndex:a,server:o,startInit:s,timeoutMs:c=5e3,getCwd:l=()=>process.cwd()}){let u=L(),d=!1,p=!1,m,h=o.server,g=e=>{let t=f(e),n=`${String(e)} ${String(t.message??``)}`.toLowerCase();return n.includes(`method not found`)||n.includes(`not supported`)||n.includes(`unsupported`)||n.includes(`unknown method`)||n.includes(`roots/list`)},_=()=>{d||(d=!0,s())},v=()=>{p||t!==`auto`||(p=!0,(async()=>{try{await a()}catch(e){n.error(`Initial index failed`,z(u,e))}})())},y=t=>t.length===0||(m&&=(clearTimeout(m),void 0),!q({config:e,log:n,reconfigureForWorkspace:i,roots:t}))?!1:(_(),v(),!0);try{if(y((await h.listRoots()).roots))return;n.debug(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(e){if(g(e)){n.warn(`MCP roots/list not supported by client; using cwd fallback`,{version:u,cwd:l(),...f(e)}),_(),v();return}n.warn(`MCP roots/list failed during bootstrap; waiting for roots/list_changed notification`,{version:u,cwd:l(),...f(e)})}h.setNotificationHandler(r,async()=>{try{y((await h.listRoots()).roots)}catch(e){n.warn(`roots/list retry failed after notification`,z(u,e))}}),m=setTimeout(()=>{let t=l();n.debug(`Timed out waiting for MCP roots/list_changed; falling back to cwd workspace`,{cwd:t}),q({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:t}]})&&(_(),v())},c)}function Y(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function X(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===c(e).href}catch{return!1}}function Z(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function Q(e,t){let n=process.env[e];if(!n)return t;let r=Number.parseInt(n,10);return Number.isFinite(r)&&r>0?r:t}function $(){return X()?l({allowPositionals:!0,options:{transport:{type:`string`,default:Y()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:Y(),port:process.env.AIKIT_PORT??`3210`}}async function ee(){let e=L(),n=$();process.on(`unhandledRejection`,t=>{R.error(`Unhandled rejection`,z(e,t))}),process.on(`uncaughtException`,t=>{R.error(`Uncaught exception — exiting`,z(e,t)),process.exit(1)});let r=(t,n)=>{t.then(async()=>{try{let{markPromoteRun:e,markPruneRun:t,prune:r,shouldRunStartupPrune:i,shouldRunWeeklyPromote:a}=await import(`../../tools/dist/index.js`),o=n();if(!o)return;if(i()){let e=await r({});t(),e.totalBytesFreed>0&&R.info(`Storage maintenance complete`,{forgeOrphans:e.forgeGroundOrphans.count,legacyLance:e.legacyLance.count,bytesFreed:e.totalBytesFreed});let{groupLessons:n,pruneLessons:i}=await import(`./evolution-DWaEE6XW.js`).then(e=>e.t),a=await i(o.curated,o.stateStore,{dryRun:!1});a.pruned.length>0&&R.info(`Startup lesson prune complete`,{pruned:a.pruned.length});let s=await n(o.curated,o.stateStore,{dryRun:!1});(s.groupsCreated>0||s.lessonsGrouped>0)&&R.info(`Startup lesson grouping complete`,{groupsCreated:s.groupsCreated,lessonsGrouped:s.lessonsGrouped})}if(a()){let{DEFAULT_PROMOTE_CONFIG:t,collectWorkspaceLessons:n,getGlobalCuratedDir:r,promoteLessons:i,scanForDuplicates:a}=await import(`./promotion-CJFYv4Ye.js`).then(e=>e.o),s=o.curated,c=new k(r(),s.store,s.embedder),l=await n(),u={...t,dryRun:!1},d=await i(a(l,u),c,u);e(),d.promoted.length>0&&R.info(`Weekly lesson promotion complete`,{promoted:d.promoted.length,candidates:d.candidates.length})}}catch(t){R.warn(`Startup maintenance failed (non-critical)`,z(e,t))}}).catch(()=>{})};if(R.info(`Starting MCP AI Kit server`,{version:e}),n.transport===`http`){let[{default:i},{loadConfig:a,resolveIndexMode:o},{registerDashboardRoutes:s,resolveDashboardDir:c},{registerSettingsRoutes:l,resolveSettingsDir:u},{createSettingsRouter:d},{authMiddleware:m,getOrCreateToken:h}]=await Promise.all([import(`express`),import(`./config-DK_lqZRv.js`),import(`./dashboard-static-CRfR1yKU.js`),import(`./settings-static-B3lnYvcb.js`),import(`./routes-KC-D2U8n.js`),import(`./auth-lzZKfxlV.js`)]),g=a();p(g.logging?.errorDetails===!0),g.configError&&R.warn(`Config load failure`,{error:g.configError}),R.info(`Config loaded`,{sourceCount:g.sources.length,storePath:g.store.path});let _=i();_.use(i.json({limit:`1mb`}));let v=Number(n.port),y=`http://localhost:${v}`,b=process.env.AIKIT_CORS_ORIGIN??y,x=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,S=Q(`AIKIT_HTTP_MAX_SESSIONS`,8),C=Q(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),w=Q(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),T=H({limit:100,windowMs:6e4}),E=!1;_.use((e,t,n)=>{let r=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,i=V({requestOrigin:r,configuredOrigin:b,allowAnyOrigin:x,fallbackOrigin:y});if(i.warn&&!E&&(E=!0,R.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:r,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),r&&!i.allowOrigin){t.status(403).json({error:`Origin not allowed`});return}if(i.allowOrigin&&t.setHeader(`Access-Control-Allow-Origin`,i.allowOrigin),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID`),t.setHeader(`Access-Control-Expose-Headers`,`Mcp-Session-Id`),e.method===`OPTIONS`){t.status(204).end();return}n()});let D=h();_.use(m(D)),_.use(`/mcp`,(e,t,n)=>{let r=Z(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(T.allow(r)){n();return}let i=Math.max(1,Math.ceil(T.getRetryAfterMs(r)/1e3));t.setHeader(`Retry-After`,String(i)),t.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})});let O=!1;_.use(`/mcp`,(e,t,n)=>{if(!O){let t=e.headers[`x-workspace-root`];typeof t==`string`&&t.length>0&&(g.sources[0]={path:t,excludePatterns:g.sources[0]?.excludePatterns??[]},g.allRoots=[t],O=!0,R.debug(`Workspace root applied from proxy header`,{wsRoot:t}))}n()}),s(_,c(),R);let k=new Date().toISOString();_.use(`/settings/api`,d({log:R,mcpInfo:()=>({transport:`http`,port:v,pid:process.pid,startedAt:k})})),l(_,u(),R),_.get(`/health`,(e,t)=>{t.json({status:`ok`})});let A=!1,j=null,M=null,N=null,F=null,L=null,B=null,U=null,W=Promise.resolve(),G=async(e,n)=>{if(!A||!N||!F){n.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=W,i;W=new Promise(e=>{i=e}),await r;try{let r=Z(e);if(!B){if(r){n.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new F({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{U=e,M?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&M?.onSessionEnd(e),U=null}});e.onclose=()=>{B===e&&(B=null),U===e.sessionId&&(U=null)},B=e,await N.connect(e)}let i=B;await i.handleRequest(e,n,e.body),e.method!==`DELETE`&&(!r&&i.sessionId?(U=i.sessionId,M?.onSessionStart(i.sessionId,{transport:`http`}),M?.onSessionActivity(i.sessionId)):r&&M?.onSessionActivity(r))}catch(e){if(R.error(`MCP handler error`,f(e)),!n.headersSent){let t=e instanceof Error?e.message:String(e),r=t.includes(`Not Acceptable`);n.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?t:`Internal server error`},id:null})}}finally{i()}},K=async(e,t)=>{let n=Z(e);if(L&&(!B||n!==U)){await L.handleRequest(e,t,e.body);return}await G(e,t)};_.post(`/mcp`,K),_.get(`/mcp`,K),_.delete(`/mcp`,K);let q=_.listen(v,`127.0.0.1`,()=>{R.info(`MCP server listening`,{url:`http://127.0.0.1:${v}/mcp`,port:v}),setTimeout(async()=>{try{let[{createLazyServer:t,createMcpServer:n,ALL_TOOL_NAMES:i},{StreamableHTTPServerTransport:a},{checkForUpdates:s,autoUpgradeScaffold:c}]=await Promise.all([import(`./server-BRinO5Fx.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-CJK1Fwmy.js`)]);s(),c(),setInterval(s,1440*60*1e3).unref();let l=o(g),u=t(g,l);N=u.server,F=a,A=!0,R.debug(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:i.length,resourceCount:2}),u.startInit(),u.ready.then(()=>{if(!u.aikit)throw Error(`AI Kit components are not available after initialization`);M=new I(u.aikit.stateStore,{staleTimeoutMinutes:C,gcIntervalMinutes:w,onBeforeSessionDelete:e=>{if(U===e&&B){let e=B;B=null,U=null,e.close().catch(()=>void 0)}L?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!u.aikit?.curated||!u.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-DWaEE6XW.js`).then(e=>e.t),t=await e(u.aikit.curated,u.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&R.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),L=new P({createServer:()=>{if(!u.aikit)throw Error(`AI Kit components are not available after initialization`);return n(u.aikit,g)},createTransport:e=>new a(e),maxSessions:S,sessionTimeoutMinutes:C,onSessionStart:e=>M?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>M?.onSessionActivity(e),onSessionEnd:e=>M?.onSessionEnd(e)}),M.startGC(),U&&(M.onSessionStart(U,{transport:`http`}),M.onSessionActivity(U)),R.info(`HTTP session runtime ready`,{maxSessions:S,sessionTimeoutMinutes:C,gcIntervalMinutes:w})}).catch(e=>R.error(`Failed to start session manager`,f(e))),l===`auto`?u.ready.then(async()=>{try{let e=g.sources.map(e=>e.path).join(`, `);R.info(`Running initial index`,{sourcePaths:e}),await u.runInitialIndex(),R.info(`Initial index complete`)}catch(t){R.error(`Initial index failed; will retry on aikit_reindex`,z(e,t))}}).catch(t=>R.error(`AI Kit init or indexing failed`,z(e,t))):l===`smart`?u.ready.then(async()=>{try{if(!u.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(u.aikit.indexer,g,u.aikit.store),n=u.aikit.store;j=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),u.setSmartScheduler(t),R.debug(`Smart index scheduler started (HTTP mode)`)}catch(t){R.error(`Failed to start smart index scheduler`,z(e,t))}}).catch(t=>R.error(`AI Kit initialization failed`,z(e,t))):(u.ready.catch(t=>R.error(`AI Kit initialization failed`,z(e,t))),R.info(`Initial full indexing skipped in HTTP mode`,{indexMode:l})),r(u.ready,()=>u.aikit?{curated:u.aikit.curated,stateStore:u.aikit.stateStore}:null)}catch(t){R.error(`Failed to load server modules`,z(e,t))}},100)}),J=async e=>{R.info(`Shutdown signal received`,{signal:e}),j?.stop(),M?.stop(),await L?.closeAll().catch(()=>void 0),U&&M?.onSessionEnd(U),B&&(await B.close().catch(()=>void 0),B=null,U=null),q.close(),N&&await N.close(),process.exit(0)};process.on(`SIGINT`,()=>J(`SIGINT`)),process.on(`SIGTERM`,()=>J(`SIGTERM`))}else{let[{loadConfig:t,reconfigureForWorkspace:n,resolveIndexMode:i},{createLazyServer:a},{checkForUpdates:o,autoUpgradeScaffold:s},{RootsListChangedNotificationSchema:c}]=await Promise.all([import(`./config-DK_lqZRv.js`),import(`./server-BRinO5Fx.js`),import(`./version-check-CJK1Fwmy.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=t();p(l.logging?.errorDetails===!0),l.configError&&R.warn(`Config load failure`,{error:l.configError}),R.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),o(),s(),setInterval(o,1440*60*1e3).unref();let u=i(l),d=a(l,u),{server:f,startInit:m,ready:h,runInitialIndex:g}=d,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await f.connect(v),R.debug(`MCP server started`,{transport:`stdio`}),await J({config:l,indexMode:u,log:R,rootsChangedNotificationSchema:c,reconfigureForWorkspace:n,runInitialIndex:g,server:f,startInit:m});let y=null,b=()=>{y&&clearTimeout(y),y=setTimeout(async()=>{R.info(`Auto-shutdown: no activity for 30 minutes — releasing resources`);try{let e=d.aikit;e&&(e.embedder.shutdown?.().catch(()=>{}),e.store.releaseMemory?.(),e.graphStore.releaseMemory?.())}catch{}},18e5),y.unref&&y.unref()};b(),process.stdin.on(`data`,()=>b()),h.catch(t=>{R.error(`Initialization failed — server will continue with limited tools`,z(e,t))}),u===`smart`?h.then(async()=>{try{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(d.aikit.indexer,l,d.aikit.store),n=d.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),d.setSmartScheduler(t),R.debug(`Smart index scheduler started (stdio mode)`)}catch(t){R.error(`Failed to start smart index scheduler`,z(e,t))}}).catch(t=>R.error(`AI Kit init failed for smart scheduler`,z(e,t))):R.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:u}),r(h,()=>d.aikit?{curated:d.aikit.curated,stateStore:d.aikit.stateStore}:null)}}ee();export{T as n,k as t};
8
+ `),s=!1,c={};for(let e of o){if(/^changelog:\s*$/.test(e)){s=!0;continue}if(s){let t=e.match(/^\s+-\s+version:\s*(\d+)$/);if(t){c.version!=null&&a.push(c),c={version:parseInt(t[1],10)};continue}let n=e.match(/^\s+date:\s*(.+)$/);if(n){c.date=n[1].trim();continue}let r=e.match(/^\s+reason:\s*"?(.*?)"?\s*$/);if(r){c.reason=r[1];continue}/^\w/.test(e)&&(s=!1,c.version!=null&&a.push(c),c={});continue}let t=e.match(/^(\w+):\s*(.*)$/);if(t){let e=t[1],n=t[2];typeof n==`string`&&n.startsWith(`[`)&&n.endsWith(`]`)?n=n.slice(1,-1).split(`,`).map(e=>e.trim().replace(/^"|"$/g,``)).filter(e=>e.length>0):typeof n==`string`&&/^\d+$/.test(n)?n=parseInt(n,10):typeof n==`string`&&n.startsWith(`"`)&&n.endsWith(`"`)&&(n=n.slice(1,-1)),i[e]=n}}return c.version!=null&&a.push(c),{frontmatter:{title:i.title??`Untitled`,category:i.category??`notes`,tags:i.tags??[],created:i.created??``,updated:i.updated??``,version:i.version??1,origin:`curated`,changelog:a},content:r}}};const A=`__pending__:`;function j(e){return e.startsWith(A)}function M(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function N(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var P=class{options;runtimes=new Map;maxSessions;sessionTimeoutMs;now;constructor(e){this.options=e,this.maxSessions=e.maxSessions??8,this.sessionTimeoutMs=(e.sessionTimeoutMinutes??30)*60*1e3,this.now=e.now??(()=>Date.now())}hasSession(e){return this.runtimes.has(e)}getSessionCount(){return this.runtimes.size}async handleRequest(e,t,n=e.body){let r=M(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){N(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){N(t,400,-32e3,`Session required`);return}if(i=await this.createRuntime(t),!i)return}await this.withRuntimeLock(i,async()=>{await i.transport.handleRequest(e,t,n),i.lastAccessAt=this.now();let r=i.transport.sessionId??i.id;e.method!==`DELETE`&&!j(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!j(r)&&await this.closeSession(r,{closeTransport:!1})})}async closeExpiredSessions(){let e=[...this.runtimes.values()].filter(e=>this.now()-e.lastAccessAt>=this.sessionTimeoutMs).map(e=>e.id);for(let t of e)await this.closeSession(t);return e.length}async closeSession(e,t={}){let n=this.runtimes.get(e);return n?(this.runtimes.delete(e),t.notifySessionEnd!==!1&&!j(e)&&this.options.onSessionEnd?.(e),t.closeTransport!==!1&&await n.transport.close().catch(()=>void 0),await n.server.close().catch(()=>void 0),!0):!1}async closeAll(){let e=[...this.runtimes.keys()];for(let t of e)await this.closeSession(t)}async createRuntime(e){if(await this.closeExpiredSessions(),this.runtimes.size>=this.maxSessions){N(e,503,-32003,`Session capacity reached`);return}let n=this.now(),r=await this.options.createServer(),i={id:`${A}${t()}`,transport:void 0,createdAt:n,lastAccessAt:n,server:r,requestChain:Promise.resolve()},a=this.options.createTransport({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{this.runtimes.delete(i.id),i.id=e,this.runtimes.set(e,i),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return i.transport=a,a.onclose=()=>{let e=i.transport.sessionId??i.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(i.id,i),await r.connect(a),i}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function F(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var I=class{stateStore;options;gcTimer=null;constructor(e,t={}){this.stateStore=e,this.options=t}onSessionStart(e,t){this.stateStore.sessionCreate(e,t)}onSessionActivity(e){this.stateStore.sessionTouch(e)}onSessionEnd(e){this.stateStore.sessionDelete(e),Promise.resolve(this.options.onSessionEndMaintenance?.(e)).catch(()=>{})}startGC(){if(this.gcTimer)return;let e=(this.options.gcIntervalMinutes??5)*60*1e3;this.gcTimer=setInterval(()=>{this.runGC()},e),this.gcTimer.unref()}runGC(){let e=this.getStaleSessionIds();for(let t of e)this.options.onBeforeSessionDelete?.(t),Promise.resolve(this.options.onSessionEndMaintenance?.(t)).catch(()=>{}),this.stateStore.sessionDelete(t);return e.length}stop(){this.gcTimer&&=(clearInterval(this.gcTimer),null)}getActiveSessions(){return this.stateStore.sessionList().length}listSessions(){return this.stateStore.sessionList()}getStaleSessionIds(e=Date.now()){let t=(this.options.staleTimeoutMinutes??30)*60*1e3;return this.stateStore.sessionList().filter(n=>{let r=F(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};function L(){try{let e=o(r(s(import.meta.url)),`..`,`..`,`..`,`package.json`);return JSON.parse(n(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}const R=d(`server`);function z(e,t){return t?{version:e,...f(t)}:{version:e}}const B=/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;function V({requestOrigin:e,configuredOrigin:t,allowAnyOrigin:n,fallbackOrigin:r}){let i=t??r;return i===`*`?n?{allowOrigin:`*`,warn:!1}:e?B.test(e)?{allowOrigin:e,warn:!1}:{allowOrigin:null,warn:!0}:{allowOrigin:r,warn:!1}:{allowOrigin:i,warn:!1}}function H({limit:e,windowMs:t}){let n=new Map,r=(e,r)=>{let i=r-t,a=n.get(e)?.filter(e=>e>i)??[];return a.length===0?(n.delete(e),[]):(n.set(e,a),a)};return{allow(t,i=Date.now()){let a=r(t,i);return a.length>=e?!1:(a.push(i),n.set(t,a),!0)},getRetryAfterMs(n,i=Date.now()){let a=r(n,i);return a.length<e?0:Math.max(0,a[0]+t-i)}}}function U(e){return e.startsWith(`file://`)?s(e):e}function W(e){let t=o(e);return process.platform===`win32`?t.toLowerCase():t}function G(e){let t=new Map;for(let n of e){let e=U(n.uri);t.set(W(e),e)}return[...t.values()].sort((e,t)=>W(e).localeCompare(W(t)))}function K({config:e,roots:t}){let n=G(t);if(n.length===0)return null;let r=e.sources?.[0]?.path;if(r){let e=W(r),t=n.find(t=>W(t)===e);if(t)return t}return n[0]}function q({config:e,log:t,reconfigureForWorkspace:n,roots:r}){let i=G(r);if(i.length===0)return!1;let a=K({config:e,roots:i.map(e=>({uri:e}))});if(!a)return!1;let o=e.sources?.[0]?.path,s=o&&W(o)===W(a)?`configured-source`:`stable-sorted-root`;return t.debug(`MCP roots resolved`,{rootPath:a,rootCount:i.length,selectedBy:s}),n(e,a),e.allRoots=i,!0}async function J({config:e,indexMode:t,log:n,rootsChangedNotificationSchema:r,reconfigureForWorkspace:i,runInitialIndex:a,server:o,startInit:s,timeoutMs:c=5e3,getCwd:l=()=>process.cwd()}){let u=L(),d=!1,p=!1,m,h=o.server,g=e=>{let t=f(e),n=`${String(e)} ${String(t.message??``)}`.toLowerCase();return n.includes(`method not found`)||n.includes(`not supported`)||n.includes(`unsupported`)||n.includes(`unknown method`)||n.includes(`roots/list`)},_=()=>{d||(d=!0,s())},v=()=>{p||t!==`auto`||(p=!0,(async()=>{try{await a()}catch(e){n.error(`Initial index failed`,z(u,e))}})())},y=t=>t.length===0||(m&&=(clearTimeout(m),void 0),!q({config:e,log:n,reconfigureForWorkspace:i,roots:t}))?!1:(_(),v(),!0);try{if(y((await h.listRoots()).roots))return;n.debug(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(t){if(g(t)){n.warn(`MCP roots/list not supported by client; using cwd fallback`,{version:u,cwd:l(),...f(t)}),q({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:l()}]})&&(_(),v());return}n.warn(`MCP roots/list failed during bootstrap; waiting for roots/list_changed notification`,{version:u,cwd:l(),...f(t)})}h.setNotificationHandler(r,async()=>{try{y((await h.listRoots()).roots)}catch(e){n.warn(`roots/list retry failed after notification`,z(u,e))}}),m=setTimeout(()=>{let t=l();n.debug(`Timed out waiting for MCP roots/list_changed; falling back to cwd workspace`,{cwd:t}),q({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:t}]})&&(_(),v())},c)}function Y(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function X(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===c(e).href}catch{return!1}}function Z(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function Q(e,t){let n=process.env[e];if(!n)return t;let r=Number.parseInt(n,10);return Number.isFinite(r)&&r>0?r:t}function $(){return X()?l({allowPositionals:!0,options:{transport:{type:`string`,default:Y()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:Y(),port:process.env.AIKIT_PORT??`3210`}}async function ee(){let e=L(),n=$();process.on(`unhandledRejection`,t=>{R.error(`Unhandled rejection`,z(e,t))}),process.on(`uncaughtException`,t=>{R.error(`Uncaught exception — exiting`,z(e,t)),process.exit(1)});let r=(t,n)=>{t.then(async()=>{try{let{markPromoteRun:e,markPruneRun:t,prune:r,shouldRunStartupPrune:i,shouldRunWeeklyPromote:a}=await import(`../../tools/dist/index.js`),o=n();if(!o)return;if(i()){let e=await r({});t(),e.totalBytesFreed>0&&R.info(`Storage maintenance complete`,{forgeOrphans:e.forgeGroundOrphans.count,legacyLance:e.legacyLance.count,bytesFreed:e.totalBytesFreed});let{groupLessons:n,pruneLessons:i}=await import(`./evolution-DWaEE6XW.js`).then(e=>e.t),a=await i(o.curated,o.stateStore,{dryRun:!1});a.pruned.length>0&&R.info(`Startup lesson prune complete`,{pruned:a.pruned.length});let s=await n(o.curated,o.stateStore,{dryRun:!1});(s.groupsCreated>0||s.lessonsGrouped>0)&&R.info(`Startup lesson grouping complete`,{groupsCreated:s.groupsCreated,lessonsGrouped:s.lessonsGrouped})}if(a()){let{DEFAULT_PROMOTE_CONFIG:t,collectWorkspaceLessons:n,getGlobalCuratedDir:r,promoteLessons:i,scanForDuplicates:a}=await import(`./promotion-bQutAIz-.js`).then(e=>e.o),s=o.curated,c=new k(r(),s.store,s.embedder),l=await n(),u={...t,dryRun:!1},d=await i(a(l,u),c,u);e(),d.promoted.length>0&&R.info(`Weekly lesson promotion complete`,{promoted:d.promoted.length,candidates:d.candidates.length})}}catch(t){R.warn(`Startup maintenance failed (non-critical)`,z(e,t))}}).catch(()=>{})};if(R.info(`Starting MCP AI Kit server`,{version:e}),n.transport===`http`){let[{default:i},{loadConfig:a,resolveIndexMode:o},{registerDashboardRoutes:s,resolveDashboardDir:c},{registerSettingsRoutes:l,resolveSettingsDir:u},{createSettingsRouter:d},{authMiddleware:m,getOrCreateToken:h}]=await Promise.all([import(`express`),import(`./config-DK_lqZRv.js`),import(`./dashboard-static-CRfR1yKU.js`),import(`./settings-static-B3lnYvcb.js`),import(`./routes-KC-D2U8n.js`),import(`./auth-lzZKfxlV.js`)]),g=a();p(g.logging?.errorDetails===!0),g.configError&&R.warn(`Config load failure`,{error:g.configError}),R.info(`Config loaded`,{sourceCount:g.sources.length,storePath:g.store.path});let _=i();_.use(i.json({limit:`1mb`}));let v=Number(n.port),y=`http://localhost:${v}`,b=process.env.AIKIT_CORS_ORIGIN??y,x=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,S=Q(`AIKIT_HTTP_MAX_SESSIONS`,8),C=Q(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),w=Q(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),T=H({limit:100,windowMs:6e4}),E=!1;_.use((e,t,n)=>{let r=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,i=V({requestOrigin:r,configuredOrigin:b,allowAnyOrigin:x,fallbackOrigin:y});if(i.warn&&!E&&(E=!0,R.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:r,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),r&&!i.allowOrigin){t.status(403).json({error:`Origin not allowed`});return}if(i.allowOrigin&&t.setHeader(`Access-Control-Allow-Origin`,i.allowOrigin),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID`),t.setHeader(`Access-Control-Expose-Headers`,`Mcp-Session-Id`),e.method===`OPTIONS`){t.status(204).end();return}n()});let D=h();_.use(m(D)),_.use(`/mcp`,(e,t,n)=>{let r=Z(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(T.allow(r)){n();return}let i=Math.max(1,Math.ceil(T.getRetryAfterMs(r)/1e3));t.setHeader(`Retry-After`,String(i)),t.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})});let O=!1;_.use(`/mcp`,(e,t,n)=>{if(!O){let t=e.headers[`x-workspace-root`];typeof t==`string`&&t.length>0&&(g.sources[0]={path:t,excludePatterns:g.sources[0]?.excludePatterns??[]},g.allRoots=[t],O=!0,R.debug(`Workspace root applied from proxy header`,{wsRoot:t}))}n()}),s(_,c(),R);let k=new Date().toISOString();_.use(`/settings/api`,d({log:R,mcpInfo:()=>({transport:`http`,port:v,pid:process.pid,startedAt:k})})),l(_,u(),R),_.get(`/health`,(e,t)=>{t.json({status:`ok`})});let A=!1,j=null,M=null,N=null,F=null,L=null,B=null,U=null,W=null,G=Promise.resolve(),K=async(e,n)=>{if(!A||!N||!F){n.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=G,i;G=new Promise(e=>{i=e}),await r;try{let r=Z(e);if(!B){if(r){n.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new F({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{U=e,M?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&M?.onSessionEnd(e),U=null}});e.onclose=()=>{B===e&&(B=null),U===e.sessionId&&(U=null)},B=e,await N.connect(e)}let i=B;await i.handleRequest(e,n,e.body),e.method!==`DELETE`&&(!r&&i.sessionId?(U=i.sessionId,M?.onSessionStart(i.sessionId,{transport:`http`}),M?.onSessionActivity(i.sessionId)):r&&M?.onSessionActivity(r))}catch(e){if(R.error(`MCP handler error`,f(e)),!n.headersSent){let t=e instanceof Error?e.message:String(e),r=t.includes(`Not Acceptable`);n.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?t:`Internal server error`},id:null})}}finally{i()}},q=async(e,t)=>{let n=Z(e);if(L&&(!B||n!==U)){await L.handleRequest(e,t,e.body);return}await K(e,t)};_.post(`/mcp`,q),_.get(`/mcp`,q),_.delete(`/mcp`,q);let J=_.listen(v,`127.0.0.1`,()=>{R.info(`MCP server listening`,{url:`http://127.0.0.1:${v}/mcp`,port:v}),setTimeout(async()=>{try{let[{createLazyServer:t,createMcpServer:n,ALL_TOOL_NAMES:i},{StreamableHTTPServerTransport:a},{checkForUpdates:s,autoUpgradeScaffold:c}]=await Promise.all([import(`./server-CYLGfaH1.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-CJK1Fwmy.js`)]);s(),c(),setInterval(s,1440*60*1e3).unref();let l=o(g),u=t(g,l);W=async()=>{u.aikit&&await Promise.all([u.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),u.aikit.graphStore.close().catch(()=>{}),u.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),u.aikit.store.close().catch(()=>{})])},N=u.server,F=a,A=!0,R.debug(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:i.length,resourceCount:2}),u.startInit(),u.ready.then(()=>{if(!u.aikit)throw Error(`AI Kit components are not available after initialization`);M=new I(u.aikit.stateStore,{staleTimeoutMinutes:C,gcIntervalMinutes:w,onBeforeSessionDelete:e=>{if(U===e&&B){let e=B;B=null,U=null,e.close().catch(()=>void 0)}L?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!u.aikit?.curated||!u.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-DWaEE6XW.js`).then(e=>e.t),t=await e(u.aikit.curated,u.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&R.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),L=new P({createServer:()=>{if(!u.aikit)throw Error(`AI Kit components are not available after initialization`);return n(u.aikit,g)},createTransport:e=>new a(e),maxSessions:S,sessionTimeoutMinutes:C,onSessionStart:e=>M?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>M?.onSessionActivity(e),onSessionEnd:e=>M?.onSessionEnd(e)}),M.startGC(),U&&(M.onSessionStart(U,{transport:`http`}),M.onSessionActivity(U)),R.info(`HTTP session runtime ready`,{maxSessions:S,sessionTimeoutMinutes:C,gcIntervalMinutes:w})}).catch(e=>R.error(`Failed to start session manager`,f(e))),l===`auto`?u.ready.then(async()=>{try{let e=g.sources.map(e=>e.path).join(`, `);R.info(`Running initial index`,{sourcePaths:e}),await u.runInitialIndex(),R.info(`Initial index complete`)}catch(t){R.error(`Initial index failed; will retry on aikit_reindex`,z(e,t))}}).catch(t=>R.error(`AI Kit init or indexing failed`,z(e,t))):l===`smart`?u.ready.then(async()=>{try{if(!u.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(u.aikit.indexer,g,u.aikit.store),n=u.aikit.store;j=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),u.setSmartScheduler(t),R.debug(`Smart index scheduler started (HTTP mode)`)}catch(t){R.error(`Failed to start smart index scheduler`,z(e,t))}}).catch(t=>R.error(`AI Kit initialization failed`,z(e,t))):(u.ready.catch(t=>R.error(`AI Kit initialization failed`,z(e,t))),R.info(`Initial full indexing skipped in HTTP mode`,{indexMode:l})),r(u.ready,()=>u.aikit?{curated:u.aikit.curated,stateStore:u.aikit.stateStore}:null)}catch(t){R.error(`Failed to load server modules`,z(e,t))}},100)}),Y=!1,X=async e=>{Y||(Y=!0,R.info(`Shutdown signal received`,{signal:e}),j?.stop(),M?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await L?.closeAll().catch(()=>void 0),U&&M?.onSessionEnd(U),B&&(await B.close().catch(()=>void 0),B=null,U=null),J.close(),N&&await N.close(),await W?.().catch(()=>void 0),process.exit(0))};process.on(`SIGINT`,()=>X(`SIGINT`)),process.on(`SIGTERM`,()=>X(`SIGTERM`))}else{let[{loadConfig:t,reconfigureForWorkspace:n,resolveIndexMode:i},{createLazyServer:a},{checkForUpdates:o,autoUpgradeScaffold:s},{RootsListChangedNotificationSchema:c}]=await Promise.all([import(`./config-DK_lqZRv.js`),import(`./server-CYLGfaH1.js`),import(`./version-check-CJK1Fwmy.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=t();p(l.logging?.errorDetails===!0),l.configError&&R.warn(`Config load failure`,{error:l.configError}),R.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),o(),s(),setInterval(o,1440*60*1e3).unref();let u=i(l),d=a(l,u),{server:f,startInit:m,ready:h,runInitialIndex:g}=d,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await f.connect(v),R.debug(`MCP server started`,{transport:`stdio`}),await J({config:l,indexMode:u,log:R,rootsChangedNotificationSchema:c,reconfigureForWorkspace:n,runInitialIndex:g,server:f,startInit:m});let y=null,b=null,x=!1,S=async e=>{x||(x=!0,R.info(`Shutdown signal received`,{signal:e}),y&&=(clearTimeout(y),null),b?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await v.close().catch(()=>void 0),await f.close().catch(()=>void 0),d.aikit&&await Promise.all([d.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),d.aikit.graphStore.close().catch(()=>{}),d.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),d.aikit.store.close().catch(()=>{})]),process.exit(0))},C=()=>{y&&clearTimeout(y),y=setTimeout(async()=>{R.info(`Auto-shutdown: no activity for 30 minutes — releasing resources`);try{let e=d.aikit;e&&(e.embedder.shutdown?.().catch(()=>{}),e.store.releaseMemory?.(),e.graphStore.releaseMemory?.())}catch{}},18e5),y.unref&&y.unref()};C(),process.stdin.on(`data`,()=>C()),process.stdin.on(`end`,()=>void S(`stdin-end`)),process.stdin.on(`close`,()=>void S(`stdin-close`)),process.stdin.on(`error`,()=>void S(`stdin-error`)),process.on(`SIGINT`,()=>void S(`SIGINT`)),process.on(`SIGTERM`,()=>void S(`SIGTERM`)),h.catch(t=>{R.error(`Initialization failed — server will continue with limited tools`,z(e,t))}),u===`smart`?h.then(async()=>{try{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(d.aikit.indexer,l,d.aikit.store);b=t;let n=d.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),d.setSmartScheduler(t),R.debug(`Smart index scheduler started (stdio mode)`)}catch(t){R.error(`Failed to start smart index scheduler`,z(e,t))}}).catch(t=>R.error(`AI Kit init failed for smart scheduler`,z(e,t))):R.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:u}),r(h,()=>d.aikit?{curated:d.aikit.curated,stateStore:d.aikit.stateStore}:null)}}ee();export{T as n,k as t};
@@ -1,6 +1,6 @@
1
- import{createHash as e}from"node:crypto";import{dirname as t,isAbsolute as n,join as r}from"node:path";import{HealthBus as i,createLogger as a,serializeError as o}from"../../core/dist/index.js";import{GIT_REF_SLUG_PATTERN as s,gitAvailable as c,gitCommitToRef as l,gitExec as u,slugForRef as d}from"../../tools/dist/index.js";import{mkdir as f,readFile as p,readdir as m,stat as h,unlink as g,writeFile as _}from"node:fs/promises";var v=class{baseDir;constructor(e){this.baseDir=e}async initialize(){await f(this.baseDir,{recursive:!0})}async read(e){let t=r(this.baseDir,e);try{return await p(t,`utf-8`)}catch(e){if(e.code===`ENOENT`)return null;throw e}}async write(e,n,i){let a=r(this.baseDir,e);await f(t(a),{recursive:!0}),await _(a,n,{encoding:`utf-8`,flag:i?.exclusive?`wx`:`w`})}async delete(e){let t=r(this.baseDir,e);try{return await g(t),!0}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async list(e){let t=[],n=e?[e]:await this.listDirectories();for(let e of n){let n=r(this.baseDir,e),i;try{i=await m(n)}catch{continue}for(let n of i){if(!n.endsWith(`.md`))continue;let i=`${e}/${n}`,a=r(this.baseDir,i);try{let e=await h(a);t.push({path:i,size:e.size})}catch{}}}return t}async exists(e){let t=r(this.baseDir,e);try{return await h(t),!0}catch{return!1}}async listDirectories(){try{return(await m(this.baseDir,{withFileTypes:!0})).filter(e=>e.isDirectory()&&/^[a-z][a-z0-9-]*$/.test(e.name)).map(e=>e.name)}catch{return[]}}async close(){}};const y=50*1024,b=`refs/aikit/knowledge`,x=a(`server`);var S=class{curatedDir;store;embedder;adapter;constructor(e,t,n,r=new v(e)){this.curatedDir=e,this.store=t,this.embedder=n,this.adapter=r}async remember(e,t,n,r=[]){this.validateCategoryName(n),this.validateContentSize(t);let i=this.normalizeTags(r),a=this.slugify(e),o=await this.uniqueRelativePath(n,a),s=new Date().toISOString(),c={title:e,category:n,tags:i,created:s,updated:s,version:1,origin:`curated`,changelog:[{version:1,date:s,reason:`Initial creation`}]},l=this.serializeFile(t,c);try{await this.adapter.write(o,l,{exclusive:!0})}catch(e){throw e.code===`EEXIST`?Error(`Concurrent write collision for "${o}" — retry the operation`):e}return this.gitCommitKnowledge(o,l,`remember: ${e}\n\nCategory: ${n}\nTags: ${i.join(`, `)}`),await this.indexCuratedFileBestEffort(o,t,c,`remember`),{path:o}}async upsertAutoKnowledge(e,t,n,r,i=[],a=`Auto-knowledge refresh`){e=this.guardPath(e),this.validateCategoryName(r),this.validateContentSize(n),this.ensureCategoryPath(e,r);let o=this.normalizeTags(i),s=await this.adapter.read(e);if(s==null){let i=new Date().toISOString(),a={title:t,category:r,tags:o,created:i,updated:i,version:1,origin:`curated`,changelog:[{version:1,date:i,reason:`Initial creation`}]},s=this.serializeFile(n,a);try{await this.adapter.write(e,s,{exclusive:!0})}catch(t){throw t.code===`EEXIST`?Error(`Concurrent write collision for "${e}" — retry the operation`):t}return this.gitCommitKnowledge(e,s,`remember: ${t}\n\nCategory: ${r}\nTags: ${o.join(`, `)}`),await this.indexCuratedFileBestEffort(e,n,a,`remember`),{path:e,status:`created`,version:1}}let{frontmatter:c,content:l}=this.parseFile(s),u=this.normalizeTags(c.tags??[]),d=t.trim()||c.title;if(l===n&&c.category===r&&c.title===d&&this.sameTags(u,o))return{path:e,status:`unchanged`,version:c.version??1};let f=(c.version??1)+1,p=new Date().toISOString();c.title=d,c.category=r,c.tags=o,c.version=f,c.updated=p,c.changelog=[...c.changelog??[],{version:f,date:p,reason:a}];let m=this.serializeFile(n,c);return await this.adapter.write(e,m),this.gitCommitKnowledge(e,m,`update(v${f}): ${c.title}\n\nReason: ${a}\nVersion: ${f}`),await this.indexCuratedFileBestEffort(e,n,c,`update`),{path:e,status:`updated`,version:f}}async update(e,t,n){e=this.guardPath(e),this.validateContentSize(t);let r=await this.adapter.read(e);if(r==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:i}=this.parseFile(r),a=(i.version??1)+1,o=new Date().toISOString();i.version=a,i.updated=o,i.changelog=[...i.changelog??[],{version:a,date:o,reason:n}];let s=this.serializeFile(t,i);return await this.adapter.write(e,s),this.gitCommitKnowledge(e,s,`update(v${a}): ${i.title}\n\nReason: ${n}\nVersion: ${a}`),await this.indexCuratedFileBestEffort(e,t,i,`update`),{path:e,version:a}}async forget(e,t){if(e=this.guardPath(e),!await this.adapter.delete(e))throw Error(`Curated entry not found: ${e}`);let n=`.ai/curated/${e}`;return await this.store.deleteBySourcePath(n).catch(e=>{x.warn(`File deleted but vector cleanup failed`,{sourcePath:n,...o(e)})}),this.gitDeleteKnowledgeRef(e),{path:e}}async history(e,t=20){if(e=this.guardPath(e),!c(this.curatedDir))return[];let n=this.knowledgeRefForPath(e);if(!n)return[];let r=u([`log`,`--format=%H|%aI|%s`,n,`-n`,String(t)],this.curatedDir);return r?r.split(`
1
+ import{createHash as e}from"node:crypto";import{dirname as t,isAbsolute as n,join as r}from"node:path";import{HealthBus as i,createLogger as a,serializeError as o}from"../../core/dist/index.js";import{GIT_REF_SLUG_PATTERN as s,gitAvailable as c,gitCommitToRef as l,gitExec as u,slugForRef as d}from"../../tools/dist/index.js";import{mkdir as f,readFile as p,readdir as m,stat as h,unlink as g,writeFile as _}from"node:fs/promises";var v=class{baseDir;constructor(e){this.baseDir=e}async initialize(){await f(this.baseDir,{recursive:!0})}async read(e){let t=r(this.baseDir,e);try{return await p(t,`utf-8`)}catch(e){if(e.code===`ENOENT`)return null;throw e}}async write(e,n,i){let a=r(this.baseDir,e);await f(t(a),{recursive:!0}),await _(a,n,{encoding:`utf-8`,flag:i?.exclusive?`wx`:`w`})}async delete(e){let t=r(this.baseDir,e);try{return await g(t),!0}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async list(e){let t=[],n=e?[e]:await this.listDirectories();for(let e of n){let n=r(this.baseDir,e),i;try{i=await m(n)}catch{continue}for(let n of i){if(!n.endsWith(`.md`))continue;let i=`${e}/${n}`,a=r(this.baseDir,i);try{let e=await h(a);t.push({path:i,size:e.size,mtimeMs:e.mtimeMs})}catch{}}}return t}async exists(e){let t=r(this.baseDir,e);try{return await h(t),!0}catch{return!1}}async listDirectories(){try{return(await m(this.baseDir,{withFileTypes:!0})).filter(e=>e.isDirectory()&&/^[a-z][a-z0-9-]*$/.test(e.name)).map(e=>e.name)}catch{return[]}}async close(){}};const y=50*1024,b=`refs/aikit/knowledge`,x=a(`server`);var S=class{curatedDir;store;embedder;adapter;constructor(e,t,n,r=new v(e)){this.curatedDir=e,this.store=t,this.embedder=n,this.adapter=r}async remember(e,t,n,r=[]){this.validateCategoryName(n),this.validateContentSize(t);let i=this.normalizeTags(r),a=this.slugify(e),o=await this.uniqueRelativePath(n,a),s=new Date().toISOString(),c={title:e,category:n,tags:i,created:s,updated:s,version:1,origin:`curated`,changelog:[{version:1,date:s,reason:`Initial creation`}]},l=this.serializeFile(t,c);try{await this.adapter.write(o,l,{exclusive:!0})}catch(e){throw e.code===`EEXIST`?Error(`Concurrent write collision for "${o}" — retry the operation`):e}return this.gitCommitKnowledge(o,l,`remember: ${e}\n\nCategory: ${n}\nTags: ${i.join(`, `)}`),await this.indexCuratedFileBestEffort(o,t,c,`remember`),{path:o}}async upsertAutoKnowledge(e,t,n,r,i=[],a=`Auto-knowledge refresh`){e=this.guardPath(e),this.validateCategoryName(r),this.validateContentSize(n),this.ensureCategoryPath(e,r);let o=this.normalizeTags(i),s=await this.adapter.read(e);if(s==null){let i=new Date().toISOString(),a={title:t,category:r,tags:o,created:i,updated:i,version:1,origin:`curated`,changelog:[{version:1,date:i,reason:`Initial creation`}]},s=this.serializeFile(n,a);try{await this.adapter.write(e,s,{exclusive:!0})}catch(t){throw t.code===`EEXIST`?Error(`Concurrent write collision for "${e}" — retry the operation`):t}return this.gitCommitKnowledge(e,s,`remember: ${t}\n\nCategory: ${r}\nTags: ${o.join(`, `)}`),await this.indexCuratedFileBestEffort(e,n,a,`remember`),{path:e,status:`created`,version:1}}let{frontmatter:c,content:l}=this.parseFile(s),u=this.normalizeTags(c.tags??[]),d=t.trim()||c.title;if(l===n&&c.category===r&&c.title===d&&this.sameTags(u,o))return{path:e,status:`unchanged`,version:c.version??1};let f=(c.version??1)+1,p=new Date().toISOString();c.title=d,c.category=r,c.tags=o,c.version=f,c.updated=p,c.changelog=[...c.changelog??[],{version:f,date:p,reason:a}];let m=this.serializeFile(n,c);return await this.adapter.write(e,m),this.gitCommitKnowledge(e,m,`update(v${f}): ${c.title}\n\nReason: ${a}\nVersion: ${f}`),await this.indexCuratedFileBestEffort(e,n,c,`update`),{path:e,status:`updated`,version:f}}async update(e,t,n){e=this.guardPath(e),this.validateContentSize(t);let r=await this.adapter.read(e);if(r==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:i}=this.parseFile(r),a=(i.version??1)+1,o=new Date().toISOString();i.version=a,i.updated=o,i.changelog=[...i.changelog??[],{version:a,date:o,reason:n}];let s=this.serializeFile(t,i);return await this.adapter.write(e,s),this.gitCommitKnowledge(e,s,`update(v${a}): ${i.title}\n\nReason: ${n}\nVersion: ${a}`),await this.indexCuratedFileBestEffort(e,t,i,`update`),{path:e,version:a}}async forget(e,t){if(e=this.guardPath(e),!await this.adapter.delete(e))throw Error(`Curated entry not found: ${e}`);let n=`.ai/curated/${e}`;return await this.store.deleteBySourcePath(n).catch(e=>{x.warn(`File deleted but vector cleanup failed`,{sourcePath:n,...o(e)})}),this.gitDeleteKnowledgeRef(e),{path:e}}async history(e,t=20){if(e=this.guardPath(e),!c(this.curatedDir))return[];let n=this.knowledgeRefForPath(e);if(!n)return[];let r=u([`log`,`--format=%H|%aI|%s`,n,`-n`,String(t)],this.curatedDir);return r?r.split(`
2
2
  `).filter(Boolean).map(e=>{let[t,n,...r]=e.split(`|`);return{sha:t,date:n,message:r.join(`|`)}}):[]}async diff(e,t,n){if(e=this.guardPath(e),!c(this.curatedDir))return``;if(!n){let r=await this.history(e,2);if(r.length===0)return``;n=r[0].sha,r.length>1&&!t&&(t=r[1].sha)}return t&&n?u([`diff`,`${t}:entry.md`,`${n}:entry.md`],this.curatedDir)??``:n?u([`show`,`${n}:entry.md`],this.curatedDir)??``:``}async recover(e){if(e=this.guardPath(e),await this.adapter.exists(e))throw Error(`Entry already exists on filesystem: ${e}. Use update() instead.`);if(!c(this.curatedDir))return null;let t=this.knowledgeRefForPath(e);if(!t)return null;let n=u([`show`,`${t}:entry.md`],this.curatedDir);if(!n)return null;await this.adapter.write(e,n);let{frontmatter:r,content:i}=this.parseFile(n);return await this.indexCuratedFile(e,i,r),{path:e,version:r.version??1}}async listOrphaned(){if(!c(this.curatedDir))return[];let e=u([`for-each-ref`,`--format=%(refname)|%(subject)`,`${b}/`],this.curatedDir);if(!e)return[];let t=[];for(let n of e.split(`
3
- `).filter(Boolean)){let[e,...r]=n.split(`|`),i=r.join(`|`),a=`${e.replace(`${b}/`,``)}.md`;await this.adapter.exists(a)||t.push({ref:e,path:a,lastMessage:i})}return t}async read(e){e=this.guardPath(e);let t=await this.adapter.read(e);if(t==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:n,content:r}=this.parseFile(t),i=e.split(`/`)[0];return{path:e,title:n.title??e,category:i,tags:n.tags??[],version:n.version??1,created:n.created??``,updated:n.updated??``,contentPreview:r.slice(0,200),content:r}}async list(e){let t=[],n=e?.category?[e.category]:await this.discoverCategories();for(let r of n){let n=await this.adapter.list(r);for(let i of n){let n=await this.adapter.read(i.path);if(n==null)continue;let{frontmatter:a,content:o}=this.parseFile(n);e?.tag&&!(a.tags??[]).includes(e.tag)||t.push({path:i.path,title:a.title??i.path,category:r,tags:a.tags??[],version:a.version??1,created:a.created??``,updated:a.updated??``,contentPreview:o.slice(0,200)})}}return t}async reindexAll(){let e=await this.discoverCategories(),t=[],n=[];for(let r of e){let e=await this.adapter.list(r);for(let r of e){let e=r.path;try{let r=await this.adapter.read(e);if(r==null){t.push(`${e}: read failed`);continue}let{frontmatter:i,content:a}=this.parseFile(r);n.push({relativePath:e,content:a,frontmatter:i})}catch(n){x.error(`Failed to read curated file`,{relativePath:e,...o(n)}),t.push(`${e}: read failed`)}}}if(n.length===0)return{indexed:0,errors:t};let r=new Date().toISOString(),i=0;for(let e=0;e<n.length;e+=16){let a=n.slice(e,e+16);i+=await this.embedAndUpsertBatch(a,r,t)}return{indexed:i,errors:t}}async embedAndUpsertBatch(e,t,n){try{let r=await this.embedder.embedBatch(e.map(e=>e.content)),i=e.map(e=>{let n=`.ai/curated/${e.relativePath}`;return{id:this.hashId(n,0),content:e.content,sourcePath:n,contentType:`curated-knowledge`,headingPath:e.frontmatter.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:e.content.split(`
3
+ `).filter(Boolean)){let[e,...r]=n.split(`|`),i=r.join(`|`),a=`${e.replace(`${b}/`,``)}.md`;await this.adapter.exists(a)||t.push({ref:e,path:a,lastMessage:i})}return t}async read(e){e=this.guardPath(e);let t=await this.adapter.read(e);if(t==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:n,content:r}=this.parseFile(t),i=e.split(`/`)[0];return{path:e,title:n.title??e,category:i,tags:n.tags??[],version:n.version??1,created:n.created??``,updated:n.updated??``,contentPreview:r.slice(0,200),content:r}}async list(e){return(await this.listPage(e)).entries}async listPage(e){let t=e?.category?[e.category]:await this.discoverCategories(),n=[];for(let e of t){let t=await this.adapter.list(e);for(let r of t)n.push({path:r.path,category:e,mtimeMs:r.mtimeMs??0})}let r=Math.max(0,e?.offset??0),i=e?.limit==null?null:Math.max(1,e.limit),a=(e?.order??`asc`)===`desc`?-1:1,o=e?.orderBy??`path`;if(o===`path`||o===`updated`){let t=this.sortCandidateMetadata(n,o,a);if(e?.tag){let n=i==null?void 0:r+i+1,{entries:a,scannedAll:o}=await this.readCandidateEntries(t,{tag:e.tag,maxMatches:n}),s=i==null?a.slice(r):a.slice(r,r+i),c=i!=null&&(a.length>r+s.length||!o);return{entries:s,totalCount:o?a.length:r+s.length+ +!!c,totalCountIsExact:o,limit:i,offset:r,hasMore:c}}let s=i==null?t.slice(r):t.slice(r,r+i),{entries:c}=await this.readCandidateEntries(s);return{entries:c,totalCount:t.length,totalCountIsExact:!0,limit:i,offset:r,hasMore:i!=null&&r+c.length<t.length}}let{entries:s}=await this.readCandidateEntries(n,{tag:e?.tag}),c=s.sort((e,t)=>{switch(o){case`created`:return(Date.parse(e.created)-Date.parse(t.created))*a;case`updated`:return(Date.parse(e.updated)-Date.parse(t.updated))*a;case`path`:return e.path.localeCompare(t.path)*a;default:return 0}}),l=i==null?c.slice(r):c.slice(r,r+i);return{entries:l,totalCount:c.length,totalCountIsExact:!0,limit:i,offset:r,hasMore:i!=null&&r+l.length<c.length}}async count(e){if(e?.tag)return(await this.listPage({...e,limit:void 0})).totalCount;let t=e?.category?[e.category]:await this.discoverCategories(),n=0;for(let e of t)n+=(await this.adapter.list(e)).length;return n}async listPaths(e){let t=e?.category?[e.category]:await this.discoverCategories(),n=[];for(let e of t){let t=await this.adapter.list(e);n.push(...t.map(e=>e.path))}n.sort((e,t)=>e.localeCompare(t));let r=Math.max(0,e?.offset??0),i=e?.limit==null?null:Math.max(1,e.limit);return i==null?n.slice(r):n.slice(r,r+i)}sortCandidateMetadata(e,t,n){return[...e].sort((e,r)=>t===`updated`?(e.mtimeMs-r.mtimeMs)*n:e.path.localeCompare(r.path)*n)}async readCandidateEntries(e,t){let n=[];for(let r of e){let e=await this.adapter.read(r.path);if(e==null)continue;let{frontmatter:i,content:a}=this.parseFile(e),o=i.tags??[];if(!(t?.tag&&!o.includes(t.tag))&&(n.push({path:r.path,title:i.title??r.path,category:r.category,tags:o,version:i.version??1,created:i.created??``,updated:i.updated??``,contentPreview:a.slice(0,200)}),t?.maxMatches!=null&&n.length>=t.maxMatches))return{entries:n,scannedAll:!1}}return{entries:n,scannedAll:!0}}async reindexAll(){let e=await this.discoverCategories(),t=[],n=[];for(let r of e){let e=await this.adapter.list(r);for(let r of e){let e=r.path;try{let r=await this.adapter.read(e);if(r==null){t.push(`${e}: read failed`);continue}let{frontmatter:i,content:a}=this.parseFile(r);n.push({relativePath:e,content:a,frontmatter:i})}catch(n){x.error(`Failed to read curated file`,{relativePath:e,...o(n)}),t.push(`${e}: read failed`)}}}if(n.length===0)return{indexed:0,errors:t};let r=new Date().toISOString(),i=0;for(let e=0;e<n.length;e+=16){let a=n.slice(e,e+16);i+=await this.embedAndUpsertBatch(a,r,t)}return{indexed:i,errors:t}}async embedAndUpsertBatch(e,t,n){try{let r=await this.embedder.embedBatch(e.map(e=>e.content)),i=e.map(e=>{let n=`.ai/curated/${e.relativePath}`;return{id:this.hashId(n,0),content:e.content,sourcePath:n,contentType:`curated-knowledge`,headingPath:e.frontmatter.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:e.content.split(`
4
4
  `).length,fileHash:this.hash(e.content),indexedAt:t,origin:`curated`,tags:e.frontmatter.tags,category:e.frontmatter.category,version:e.frontmatter.version}});try{return await this.store.upsert(i,r),e.length}catch(t){x.error(`Failed to upsert curated batch`,{batchSize:e.length,...o(t)});for(let t of e)n.push(`${t.relativePath}: upsert failed`);return 0}}catch(r){if(e.length===1)return x.error(`Failed to embed curated item`,{relativePath:e[0].relativePath,...o(r)}),n.push(`${e[0].relativePath}: reindex failed`),0;x.warn(`Curated embed batch failed, retrying with smaller chunks`,{batchSize:e.length,...o(r)});let i=Math.ceil(e.length/2),a=e.slice(0,i),s=e.slice(i);return await this.embedAndUpsertBatch(a,t,n)+await this.embedAndUpsertBatch(s,t,n)}}gitCommitKnowledge(e,t,n){try{if(!c(this.curatedDir))return;let r=this.knowledgeRefForPath(e);if(!r)return;l(r,`entry.md`,t,n,this.curatedDir)}catch{}}gitDeleteKnowledgeRef(e){try{if(!c(this.curatedDir))return;let t=this.knowledgeRefForPath(e);if(!t)return;u([`update-ref`,`-d`,t],this.curatedDir)}catch{}}knowledgeRefForPath(e){let t=e.replace(/\.md$/,``).split(`/`).map(e=>d(e)).join(`/`);return t.split(`/`).every(e=>s.test(e))?`${b}/${t}`:null}async indexCuratedFile(e,t,n){let r=await this.embedder.embed(t),i=`.ai/curated/${e}`,a=new Date().toISOString(),o={id:this.hashId(i,0),content:t,sourcePath:i,contentType:`curated-knowledge`,headingPath:n.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:t.split(`
5
5
  `).length,fileHash:this.hash(t),indexedAt:a,origin:`curated`,tags:n.tags,category:n.category,version:n.version};await this.store.upsert([o],[r])}async indexCuratedFileBestEffort(e,t,n,r){if(i.instance().isDegraded(`embedder`)){x.debug(`Skipping vector indexing — embedder degraded`,{relativePath:e,operation:r,subsystem:`embedder`});return}try{await this.indexCuratedFile(e,t,n)}catch(t){x.warn(`Curated file persisted but vector indexing deferred`,{relativePath:e,operation:r,...o(t)})}}async discoverCategories(){return this.adapter.listDirectories()}guardPath(e){let t=e.replace(/^\.ai\/curated\//,``);if(t.endsWith(`.md`)||(t+=`.md`),t.includes(`..`)||n(t))throw Error(`Invalid path: ${t}. Must be relative within .ai/curated/ directory.`);let r=t.split(`/`)[0];return this.validateCategoryName(r),t}validateCategoryName(e){if(!/^[a-z][a-z0-9-]*$/.test(e))throw Error(`Invalid category name: "${e}". Must be lowercase kebab-case (e.g., "decisions", "api-contracts").`)}validateContentSize(e){if(Buffer.byteLength(e,`utf-8`)>y)throw Error(`Content exceeds maximum size of ${y/1024}KB`)}slugify(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-|-$/g,``).slice(0,80)}normalizeTags(e){return[...new Set(e.map(e=>e.trim()).filter(Boolean))]}sameTags(e,t){if(e.length!==t.length)return!1;let n=new Set(e);return t.every(e=>n.has(e))}ensureCategoryPath(e,t){if(!e.startsWith(`${t}/`))throw Error(`Curated path "${e}" must stay within category "${t}"`)}async uniqueRelativePath(e,t){let n=`${e}/${t}.md`;if(!await this.adapter.exists(n))return n;for(let n=2;n<=100;n++){let r=`${e}/${t}-${n}.md`;if(!await this.adapter.exists(r))return r}throw Error(`Too many entries with slug "${t}" in category "${e}"`)}hash(t){return e(`sha256`).update(t).digest(`hex`).slice(0,16)}hashId(e,t){return this.hash(`${e}::${t}`)}serializeFile(e,t){return`${[`---`,`title: "${t.title.replace(/"/g,`\\"`)}"`,`category: ${t.category}`,`tags: [${t.tags.map(e=>`"${e}"`).join(`, `)}]`,`created: ${t.created}`,`updated: ${t.updated}`,`version: ${t.version}`,`origin: ${t.origin}`,`changelog:`,...t.changelog.map(e=>` - version: ${e.version}\n date: ${e.date}\n reason: "${e.reason.replace(/"/g,`\\"`)}"`),`---`].join(`
6
6
  `)}\n\n${e}\n`}parseFile(e){let t=e.match(/^---\n([\s\S]*?)\n---\n\n?([\s\S]*)$/);if(!t)return{frontmatter:{title:`Untitled`,category:`notes`,tags:[],created:``,updated:``,version:1,origin:`curated`,changelog:[]},content:e};let n=t[1],r=t[2].trim(),i={},a=[],o=n.split(`
@@ -28,11 +28,13 @@ interface ICuratedAdapter {
28
28
  delete(relativePath: string): Promise<boolean>;
29
29
  /**
30
30
  * List entries, optionally filtered by a category prefix.
31
- * Returns objects with the relative path and file size in bytes.
31
+ * Returns objects with the relative path, file size in bytes, and optional
32
+ * filesystem modification timestamp.
32
33
  */
33
34
  list(categoryPrefix?: string): Promise<Array<{
34
35
  path: string;
35
36
  size: number;
37
+ mtimeMs?: number;
36
38
  }>>;
37
39
  /**
38
40
  * Check whether a path exists.
@@ -59,6 +61,22 @@ interface CuratedEntry {
59
61
  updated: string;
60
62
  contentPreview: string;
61
63
  }
64
+ interface CuratedListFilters {
65
+ category?: CuratedCategory;
66
+ tag?: string;
67
+ limit?: number;
68
+ offset?: number;
69
+ orderBy?: 'path' | 'created' | 'updated';
70
+ order?: 'asc' | 'desc';
71
+ }
72
+ interface CuratedListPage {
73
+ entries: CuratedEntry[];
74
+ totalCount: number;
75
+ totalCountIsExact: boolean;
76
+ limit: number | null;
77
+ offset: number;
78
+ hasMore: boolean;
79
+ }
62
80
  interface CuratedFrontmatter {
63
81
  title: string;
64
82
  category: string;
@@ -136,10 +154,19 @@ declare class CuratedKnowledgeManager {
136
154
  read(relativePath: string): Promise<CuratedEntry & {
137
155
  content: string;
138
156
  }>;
139
- list(filters?: {
157
+ list(filters?: CuratedListFilters): Promise<CuratedEntry[]>;
158
+ listPage(filters?: CuratedListFilters): Promise<CuratedListPage>;
159
+ count(filters?: {
140
160
  category?: CuratedCategory;
141
161
  tag?: string;
142
- }): Promise<CuratedEntry[]>;
162
+ }): Promise<number>;
163
+ listPaths(filters?: {
164
+ category?: CuratedCategory;
165
+ limit?: number;
166
+ offset?: number;
167
+ }): Promise<string[]>;
168
+ private sortCandidateMetadata;
169
+ private readCandidateEntries;
143
170
  /**
144
171
  * Re-index all curated files into the vector store.
145
172
  * Call this after the indexer has run to restore curated vectors
@@ -1 +1 @@
1
- import{t as e}from"./curated-manager-C5uOPept.js";import{randomUUID as t}from"node:crypto";import{readFileSync as n}from"node:fs";import{dirname as r,resolve as i}from"node:path";import{fileURLToPath as a,pathToFileURL as o}from"node:url";import{parseArgs as s}from"node:util";import{createLogger as c,serializeError as l,setDetailedErrorLoggingEnabled as u}from"../../core/dist/index.js";const d=`__pending__:`;function f(e){return e.startsWith(d)}function p(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function m(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var h=class{options;runtimes=new Map;maxSessions;sessionTimeoutMs;now;constructor(e){this.options=e,this.maxSessions=e.maxSessions??8,this.sessionTimeoutMs=(e.sessionTimeoutMinutes??30)*60*1e3,this.now=e.now??(()=>Date.now())}hasSession(e){return this.runtimes.has(e)}getSessionCount(){return this.runtimes.size}async handleRequest(e,t,n=e.body){let r=p(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){m(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){m(t,400,-32e3,`Session required`);return}if(i=await this.createRuntime(t),!i)return}await this.withRuntimeLock(i,async()=>{await i.transport.handleRequest(e,t,n),i.lastAccessAt=this.now();let r=i.transport.sessionId??i.id;e.method!==`DELETE`&&!f(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!f(r)&&await this.closeSession(r,{closeTransport:!1})})}async closeExpiredSessions(){let e=[...this.runtimes.values()].filter(e=>this.now()-e.lastAccessAt>=this.sessionTimeoutMs).map(e=>e.id);for(let t of e)await this.closeSession(t);return e.length}async closeSession(e,t={}){let n=this.runtimes.get(e);return n?(this.runtimes.delete(e),t.notifySessionEnd!==!1&&!f(e)&&this.options.onSessionEnd?.(e),t.closeTransport!==!1&&await n.transport.close().catch(()=>void 0),await n.server.close().catch(()=>void 0),!0):!1}async closeAll(){let e=[...this.runtimes.keys()];for(let t of e)await this.closeSession(t)}async createRuntime(e){if(await this.closeExpiredSessions(),this.runtimes.size>=this.maxSessions){m(e,503,-32003,`Session capacity reached`);return}let n=this.now(),r=await this.options.createServer(),i={id:`${d}${t()}`,transport:void 0,createdAt:n,lastAccessAt:n,server:r,requestChain:Promise.resolve()},a=this.options.createTransport({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{this.runtimes.delete(i.id),i.id=e,this.runtimes.set(e,i),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return i.transport=a,a.onclose=()=>{let e=i.transport.sessionId??i.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(i.id,i),await r.connect(a),i}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function g(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var _=class{stateStore;options;gcTimer=null;constructor(e,t={}){this.stateStore=e,this.options=t}onSessionStart(e,t){this.stateStore.sessionCreate(e,t)}onSessionActivity(e){this.stateStore.sessionTouch(e)}onSessionEnd(e){this.stateStore.sessionDelete(e),Promise.resolve(this.options.onSessionEndMaintenance?.(e)).catch(()=>{})}startGC(){if(this.gcTimer)return;let e=(this.options.gcIntervalMinutes??5)*60*1e3;this.gcTimer=setInterval(()=>{this.runGC()},e),this.gcTimer.unref()}runGC(){let e=this.getStaleSessionIds();for(let t of e)this.options.onBeforeSessionDelete?.(t),Promise.resolve(this.options.onSessionEndMaintenance?.(t)).catch(()=>{}),this.stateStore.sessionDelete(t);return e.length}stop(){this.gcTimer&&=(clearInterval(this.gcTimer),null)}getActiveSessions(){return this.stateStore.sessionList().length}listSessions(){return this.stateStore.sessionList()}getStaleSessionIds(e=Date.now()){let t=(this.options.staleTimeoutMinutes??30)*60*1e3;return this.stateStore.sessionList().filter(n=>{let r=g(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};function v(){try{let e=i(r(a(import.meta.url)),`..`,`..`,`..`,`package.json`);return JSON.parse(n(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}const y=c(`server`);function b(e,t){return t?{version:e,...l(t)}:{version:e}}const x=/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;function S({requestOrigin:e,configuredOrigin:t,allowAnyOrigin:n,fallbackOrigin:r}){let i=t??r;return i===`*`?n?{allowOrigin:`*`,warn:!1}:e?x.test(e)?{allowOrigin:e,warn:!1}:{allowOrigin:null,warn:!0}:{allowOrigin:r,warn:!1}:{allowOrigin:i,warn:!1}}function C({limit:e,windowMs:t}){let n=new Map,r=(e,r)=>{let i=r-t,a=n.get(e)?.filter(e=>e>i)??[];return a.length===0?(n.delete(e),[]):(n.set(e,a),a)};return{allow(t,i=Date.now()){let a=r(t,i);return a.length>=e?!1:(a.push(i),n.set(t,a),!0)},getRetryAfterMs(n,i=Date.now()){let a=r(n,i);return a.length<e?0:Math.max(0,a[0]+t-i)}}}function w(e){return e.startsWith(`file://`)?a(e):e}function T(e){let t=i(e);return process.platform===`win32`?t.toLowerCase():t}function E(e){let t=new Map;for(let n of e){let e=w(n.uri);t.set(T(e),e)}return[...t.values()].sort((e,t)=>T(e).localeCompare(T(t)))}function D({config:e,roots:t}){let n=E(t);if(n.length===0)return null;let r=e.sources?.[0]?.path;if(r){let e=T(r),t=n.find(t=>T(t)===e);if(t)return t}return n[0]}function O({config:e,log:t,reconfigureForWorkspace:n,roots:r}){let i=E(r);if(i.length===0)return!1;let a=D({config:e,roots:i.map(e=>({uri:e}))});if(!a)return!1;let o=e.sources?.[0]?.path,s=o&&T(o)===T(a)?`configured-source`:`stable-sorted-root`;return t.debug(`MCP roots resolved`,{rootPath:a,rootCount:i.length,selectedBy:s}),n(e,a),e.allRoots=i,!0}async function k({config:e,indexMode:t,log:n,rootsChangedNotificationSchema:r,reconfigureForWorkspace:i,runInitialIndex:a,server:o,startInit:s,timeoutMs:c=5e3,getCwd:u=()=>process.cwd()}){let d=v(),f=!1,p=!1,m,h=o.server,g=e=>{let t=l(e),n=`${String(e)} ${String(t.message??``)}`.toLowerCase();return n.includes(`method not found`)||n.includes(`not supported`)||n.includes(`unsupported`)||n.includes(`unknown method`)||n.includes(`roots/list`)},_=()=>{f||(f=!0,s())},y=()=>{p||t!==`auto`||(p=!0,(async()=>{try{await a()}catch(e){n.error(`Initial index failed`,b(d,e))}})())},x=t=>t.length===0||(m&&=(clearTimeout(m),void 0),!O({config:e,log:n,reconfigureForWorkspace:i,roots:t}))?!1:(_(),y(),!0);try{if(x((await h.listRoots()).roots))return;n.debug(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(e){if(g(e)){n.warn(`MCP roots/list not supported by client; using cwd fallback`,{version:d,cwd:u(),...l(e)}),_(),y();return}n.warn(`MCP roots/list failed during bootstrap; waiting for roots/list_changed notification`,{version:d,cwd:u(),...l(e)})}h.setNotificationHandler(r,async()=>{try{x((await h.listRoots()).roots)}catch(e){n.warn(`roots/list retry failed after notification`,b(d,e))}}),m=setTimeout(()=>{let t=u();n.debug(`Timed out waiting for MCP roots/list_changed; falling back to cwd workspace`,{cwd:t}),O({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:t}]})&&(_(),y())},c)}function A(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function j(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===o(e).href}catch{return!1}}function M(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function N(e,t){let n=process.env[e];if(!n)return t;let r=Number.parseInt(n,10);return Number.isFinite(r)&&r>0?r:t}function P(){return j()?s({allowPositionals:!0,options:{transport:{type:`string`,default:A()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:A(),port:process.env.AIKIT_PORT??`3210`}}async function F(){let n=v(),r=P();process.on(`unhandledRejection`,e=>{y.error(`Unhandled rejection`,b(n,e))}),process.on(`uncaughtException`,e=>{y.error(`Uncaught exception — exiting`,b(n,e)),process.exit(1)});let i=(t,r)=>{t.then(async()=>{try{let{markPromoteRun:t,markPruneRun:n,prune:i,shouldRunStartupPrune:a,shouldRunWeeklyPromote:o}=await import(`../../tools/dist/index.js`),s=r();if(!s)return;if(a()){let e=await i({});n(),e.totalBytesFreed>0&&y.info(`Storage maintenance complete`,{forgeOrphans:e.forgeGroundOrphans.count,legacyLance:e.legacyLance.count,bytesFreed:e.totalBytesFreed});let{groupLessons:t,pruneLessons:r}=await import(`./evolution-BX_zTSdj.js`).then(e=>e.t),a=await r(s.curated,s.stateStore,{dryRun:!1});a.pruned.length>0&&y.info(`Startup lesson prune complete`,{pruned:a.pruned.length});let o=await t(s.curated,s.stateStore,{dryRun:!1});(o.groupsCreated>0||o.lessonsGrouped>0)&&y.info(`Startup lesson grouping complete`,{groupsCreated:o.groupsCreated,lessonsGrouped:o.lessonsGrouped})}if(o()){let{DEFAULT_PROMOTE_CONFIG:n,collectWorkspaceLessons:r,getGlobalCuratedDir:i,promoteLessons:a,scanForDuplicates:o}=await import(`./promotion-D9anNXv8.js`).then(e=>e.o),c=s.curated,l=new e(i(),c.store,c.embedder),u=await r(),d={...n,dryRun:!1},f=await a(o(u,d),l,d);t(),f.promoted.length>0&&y.info(`Weekly lesson promotion complete`,{promoted:f.promoted.length,candidates:f.candidates.length})}}catch(e){y.warn(`Startup maintenance failed (non-critical)`,b(n,e))}}).catch(()=>{})};if(y.info(`Starting MCP AI Kit server`,{version:n}),r.transport===`http`){let[{default:e},{loadConfig:a,resolveIndexMode:o},{registerDashboardRoutes:s,resolveDashboardDir:c},{registerSettingsRoutes:d,resolveSettingsDir:f},{createSettingsRouter:p},{authMiddleware:m,getOrCreateToken:g}]=await Promise.all([import(`express`),import(`./config-BkWFC9ah.js`),import(`./dashboard-static-FmfoS46e.js`),import(`./settings-static-BtvyIrza.js`),import(`./routes-1wkXLxXe.js`),import(`./auth-Bz5dmZgR.js`).then(e=>e.t)]),v=a();u(v.logging?.errorDetails===!0),v.configError&&y.warn(`Config load failure`,{error:v.configError}),y.info(`Config loaded`,{sourceCount:v.sources.length,storePath:v.store.path});let x=e();x.use(e.json({limit:`1mb`}));let w=Number(r.port),T=`http://localhost:${w}`,E=process.env.AIKIT_CORS_ORIGIN??T,D=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,O=N(`AIKIT_HTTP_MAX_SESSIONS`,8),k=N(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),A=N(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),j=C({limit:100,windowMs:6e4}),P=!1;x.use((e,t,n)=>{let r=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,i=S({requestOrigin:r,configuredOrigin:E,allowAnyOrigin:D,fallbackOrigin:T});if(i.warn&&!P&&(P=!0,y.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:r,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),r&&!i.allowOrigin){t.status(403).json({error:`Origin not allowed`});return}if(i.allowOrigin&&t.setHeader(`Access-Control-Allow-Origin`,i.allowOrigin),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID`),t.setHeader(`Access-Control-Expose-Headers`,`Mcp-Session-Id`),e.method===`OPTIONS`){t.status(204).end();return}n()});let F=g();x.use(m(F)),x.use(`/mcp`,(e,t,n)=>{let r=M(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(j.allow(r)){n();return}let i=Math.max(1,Math.ceil(j.getRetryAfterMs(r)/1e3));t.setHeader(`Retry-After`,String(i)),t.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})});let I=!1;x.use(`/mcp`,(e,t,n)=>{if(!I){let t=e.headers[`x-workspace-root`];typeof t==`string`&&t.length>0&&(v.sources[0]={path:t,excludePatterns:v.sources[0]?.excludePatterns??[]},v.allRoots=[t],I=!0,y.debug(`Workspace root applied from proxy header`,{wsRoot:t}))}n()}),s(x,c(),y);let L=new Date().toISOString();x.use(`/settings/api`,p({log:y,mcpInfo:()=>({transport:`http`,port:w,pid:process.pid,startedAt:L})})),d(x,f(),y),x.get(`/health`,(e,t)=>{t.json({status:`ok`})});let R=!1,z=null,B=null,V=null,H=null,U=null,W=null,G=null,K=Promise.resolve(),q=async(e,n)=>{if(!R||!V||!H){n.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=K,i;K=new Promise(e=>{i=e}),await r;try{let r=M(e);if(!W){if(r){n.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new H({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{G=e,B?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&B?.onSessionEnd(e),G=null}});e.onclose=()=>{W===e&&(W=null),G===e.sessionId&&(G=null)},W=e,await V.connect(e)}let i=W;await i.handleRequest(e,n,e.body),e.method!==`DELETE`&&(!r&&i.sessionId?(G=i.sessionId,B?.onSessionStart(i.sessionId,{transport:`http`}),B?.onSessionActivity(i.sessionId)):r&&B?.onSessionActivity(r))}catch(e){if(y.error(`MCP handler error`,l(e)),!n.headersSent){let t=e instanceof Error?e.message:String(e),r=t.includes(`Not Acceptable`);n.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?t:`Internal server error`},id:null})}}finally{i()}},J=async(e,t)=>{let n=M(e);if(U&&(!W||n!==G)){await U.handleRequest(e,t,e.body);return}await q(e,t)};x.post(`/mcp`,J),x.get(`/mcp`,J),x.delete(`/mcp`,J);let Y=x.listen(w,`127.0.0.1`,()=>{y.info(`MCP server listening`,{url:`http://127.0.0.1:${w}/mcp`,port:w}),setTimeout(async()=>{try{let[{createLazyServer:e,createMcpServer:t,ALL_TOOL_NAMES:r},{StreamableHTTPServerTransport:a},{checkForUpdates:s,autoUpgradeScaffold:c}]=await Promise.all([import(`./server-CyERdqK0.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-yzdUDXHC.js`)]);s(),c(),setInterval(s,1440*60*1e3).unref();let u=o(v),d=e(v,u);V=d.server,H=a,R=!0,y.debug(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:r.length,resourceCount:2}),d.startInit(),d.ready.then(()=>{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);B=new _(d.aikit.stateStore,{staleTimeoutMinutes:k,gcIntervalMinutes:A,onBeforeSessionDelete:e=>{if(G===e&&W){let e=W;W=null,G=null,e.close().catch(()=>void 0)}U?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!d.aikit?.curated||!d.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-BX_zTSdj.js`).then(e=>e.t),t=await e(d.aikit.curated,d.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&y.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),U=new h({createServer:()=>{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);return t(d.aikit,v)},createTransport:e=>new a(e),maxSessions:O,sessionTimeoutMinutes:k,onSessionStart:e=>B?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>B?.onSessionActivity(e),onSessionEnd:e=>B?.onSessionEnd(e)}),B.startGC(),G&&(B.onSessionStart(G,{transport:`http`}),B.onSessionActivity(G)),y.info(`HTTP session runtime ready`,{maxSessions:O,sessionTimeoutMinutes:k,gcIntervalMinutes:A})}).catch(e=>y.error(`Failed to start session manager`,l(e))),u===`auto`?d.ready.then(async()=>{try{let e=v.sources.map(e=>e.path).join(`, `);y.info(`Running initial index`,{sourcePaths:e}),await d.runInitialIndex(),y.info(`Initial index complete`)}catch(e){y.error(`Initial index failed; will retry on aikit_reindex`,b(n,e))}}).catch(e=>y.error(`AI Kit init or indexing failed`,b(n,e))):u===`smart`?d.ready.then(async()=>{try{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(d.aikit.indexer,v,d.aikit.store),n=d.aikit.store;z=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),d.setSmartScheduler(t),y.debug(`Smart index scheduler started (HTTP mode)`)}catch(e){y.error(`Failed to start smart index scheduler`,b(n,e))}}).catch(e=>y.error(`AI Kit initialization failed`,b(n,e))):(d.ready.catch(e=>y.error(`AI Kit initialization failed`,b(n,e))),y.info(`Initial full indexing skipped in HTTP mode`,{indexMode:u})),i(d.ready,()=>d.aikit?{curated:d.aikit.curated,stateStore:d.aikit.stateStore}:null)}catch(e){y.error(`Failed to load server modules`,b(n,e))}},100)}),X=async e=>{y.info(`Shutdown signal received`,{signal:e}),z?.stop(),B?.stop(),await U?.closeAll().catch(()=>void 0),G&&B?.onSessionEnd(G),W&&(await W.close().catch(()=>void 0),W=null,G=null),Y.close(),V&&await V.close(),process.exit(0)};process.on(`SIGINT`,()=>X(`SIGINT`)),process.on(`SIGTERM`,()=>X(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:r},{createLazyServer:a},{checkForUpdates:o,autoUpgradeScaffold:s},{RootsListChangedNotificationSchema:c}]=await Promise.all([import(`./config-BkWFC9ah.js`),import(`./server-CyERdqK0.js`),import(`./version-check-yzdUDXHC.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=e();u(l.logging?.errorDetails===!0),l.configError&&y.warn(`Config load failure`,{error:l.configError}),y.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),o(),s(),setInterval(o,1440*60*1e3).unref();let d=r(l),f=a(l,d),{server:p,startInit:m,ready:h,runInitialIndex:g}=f,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await p.connect(v),y.debug(`MCP server started`,{transport:`stdio`}),await k({config:l,indexMode:d,log:y,rootsChangedNotificationSchema:c,reconfigureForWorkspace:t,runInitialIndex:g,server:p,startInit:m});let x=null,S=()=>{x&&clearTimeout(x),x=setTimeout(async()=>{y.info(`Auto-shutdown: no activity for 30 minutes — releasing resources`);try{let e=f.aikit;e&&(e.embedder.shutdown?.().catch(()=>{}),e.store.releaseMemory?.(),e.graphStore.releaseMemory?.())}catch{}},18e5),x.unref&&x.unref()};S(),process.stdin.on(`data`,()=>S()),h.catch(e=>{y.error(`Initialization failed — server will continue with limited tools`,b(n,e))}),d===`smart`?h.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.aikit.indexer,l,f.aikit.store),n=f.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),f.setSmartScheduler(t),y.debug(`Smart index scheduler started (stdio mode)`)}catch(e){y.error(`Failed to start smart index scheduler`,b(n,e))}}).catch(e=>y.error(`AI Kit init failed for smart scheduler`,b(n,e))):y.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:d}),i(h,()=>f.aikit?{curated:f.aikit.curated,stateStore:f.aikit.stateStore}:null)}}export{e as CuratedKnowledgeManager,O as applyWorkspaceRoots,k as bootstrapWorkspaceRoots,C as createSlidingWindowRateLimiter,F as main,S as resolveCorsOrigin,D as selectWorkspaceRoot};
1
+ import{t as e}from"./curated-manager-i5QA4c79.js";import{randomUUID as t}from"node:crypto";import{readFileSync as n}from"node:fs";import{dirname as r,resolve as i}from"node:path";import{fileURLToPath as a,pathToFileURL as o}from"node:url";import{parseArgs as s}from"node:util";import{createLogger as c,serializeError as l,setDetailedErrorLoggingEnabled as u}from"../../core/dist/index.js";const d=`__pending__:`;function f(e){return e.startsWith(d)}function p(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function m(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var h=class{options;runtimes=new Map;maxSessions;sessionTimeoutMs;now;constructor(e){this.options=e,this.maxSessions=e.maxSessions??8,this.sessionTimeoutMs=(e.sessionTimeoutMinutes??30)*60*1e3,this.now=e.now??(()=>Date.now())}hasSession(e){return this.runtimes.has(e)}getSessionCount(){return this.runtimes.size}async handleRequest(e,t,n=e.body){let r=p(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){m(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){m(t,400,-32e3,`Session required`);return}if(i=await this.createRuntime(t),!i)return}await this.withRuntimeLock(i,async()=>{await i.transport.handleRequest(e,t,n),i.lastAccessAt=this.now();let r=i.transport.sessionId??i.id;e.method!==`DELETE`&&!f(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!f(r)&&await this.closeSession(r,{closeTransport:!1})})}async closeExpiredSessions(){let e=[...this.runtimes.values()].filter(e=>this.now()-e.lastAccessAt>=this.sessionTimeoutMs).map(e=>e.id);for(let t of e)await this.closeSession(t);return e.length}async closeSession(e,t={}){let n=this.runtimes.get(e);return n?(this.runtimes.delete(e),t.notifySessionEnd!==!1&&!f(e)&&this.options.onSessionEnd?.(e),t.closeTransport!==!1&&await n.transport.close().catch(()=>void 0),await n.server.close().catch(()=>void 0),!0):!1}async closeAll(){let e=[...this.runtimes.keys()];for(let t of e)await this.closeSession(t)}async createRuntime(e){if(await this.closeExpiredSessions(),this.runtimes.size>=this.maxSessions){m(e,503,-32003,`Session capacity reached`);return}let n=this.now(),r=await this.options.createServer(),i={id:`${d}${t()}`,transport:void 0,createdAt:n,lastAccessAt:n,server:r,requestChain:Promise.resolve()},a=this.options.createTransport({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{this.runtimes.delete(i.id),i.id=e,this.runtimes.set(e,i),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return i.transport=a,a.onclose=()=>{let e=i.transport.sessionId??i.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(i.id,i),await r.connect(a),i}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function g(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var _=class{stateStore;options;gcTimer=null;constructor(e,t={}){this.stateStore=e,this.options=t}onSessionStart(e,t){this.stateStore.sessionCreate(e,t)}onSessionActivity(e){this.stateStore.sessionTouch(e)}onSessionEnd(e){this.stateStore.sessionDelete(e),Promise.resolve(this.options.onSessionEndMaintenance?.(e)).catch(()=>{})}startGC(){if(this.gcTimer)return;let e=(this.options.gcIntervalMinutes??5)*60*1e3;this.gcTimer=setInterval(()=>{this.runGC()},e),this.gcTimer.unref()}runGC(){let e=this.getStaleSessionIds();for(let t of e)this.options.onBeforeSessionDelete?.(t),Promise.resolve(this.options.onSessionEndMaintenance?.(t)).catch(()=>{}),this.stateStore.sessionDelete(t);return e.length}stop(){this.gcTimer&&=(clearInterval(this.gcTimer),null)}getActiveSessions(){return this.stateStore.sessionList().length}listSessions(){return this.stateStore.sessionList()}getStaleSessionIds(e=Date.now()){let t=(this.options.staleTimeoutMinutes??30)*60*1e3;return this.stateStore.sessionList().filter(n=>{let r=g(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};function v(){try{let e=i(r(a(import.meta.url)),`..`,`..`,`..`,`package.json`);return JSON.parse(n(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}const y=c(`server`);function b(e,t){return t?{version:e,...l(t)}:{version:e}}const x=/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;function S({requestOrigin:e,configuredOrigin:t,allowAnyOrigin:n,fallbackOrigin:r}){let i=t??r;return i===`*`?n?{allowOrigin:`*`,warn:!1}:e?x.test(e)?{allowOrigin:e,warn:!1}:{allowOrigin:null,warn:!0}:{allowOrigin:r,warn:!1}:{allowOrigin:i,warn:!1}}function C({limit:e,windowMs:t}){let n=new Map,r=(e,r)=>{let i=r-t,a=n.get(e)?.filter(e=>e>i)??[];return a.length===0?(n.delete(e),[]):(n.set(e,a),a)};return{allow(t,i=Date.now()){let a=r(t,i);return a.length>=e?!1:(a.push(i),n.set(t,a),!0)},getRetryAfterMs(n,i=Date.now()){let a=r(n,i);return a.length<e?0:Math.max(0,a[0]+t-i)}}}function w(e){return e.startsWith(`file://`)?a(e):e}function T(e){let t=i(e);return process.platform===`win32`?t.toLowerCase():t}function E(e){let t=new Map;for(let n of e){let e=w(n.uri);t.set(T(e),e)}return[...t.values()].sort((e,t)=>T(e).localeCompare(T(t)))}function D({config:e,roots:t}){let n=E(t);if(n.length===0)return null;let r=e.sources?.[0]?.path;if(r){let e=T(r),t=n.find(t=>T(t)===e);if(t)return t}return n[0]}function O({config:e,log:t,reconfigureForWorkspace:n,roots:r}){let i=E(r);if(i.length===0)return!1;let a=D({config:e,roots:i.map(e=>({uri:e}))});if(!a)return!1;let o=e.sources?.[0]?.path,s=o&&T(o)===T(a)?`configured-source`:`stable-sorted-root`;return t.debug(`MCP roots resolved`,{rootPath:a,rootCount:i.length,selectedBy:s}),n(e,a),e.allRoots=i,!0}async function k({config:e,indexMode:t,log:n,rootsChangedNotificationSchema:r,reconfigureForWorkspace:i,runInitialIndex:a,server:o,startInit:s,timeoutMs:c=5e3,getCwd:u=()=>process.cwd()}){let d=v(),f=!1,p=!1,m,h=o.server,g=e=>{let t=l(e),n=`${String(e)} ${String(t.message??``)}`.toLowerCase();return n.includes(`method not found`)||n.includes(`not supported`)||n.includes(`unsupported`)||n.includes(`unknown method`)||n.includes(`roots/list`)},_=()=>{f||(f=!0,s())},y=()=>{p||t!==`auto`||(p=!0,(async()=>{try{await a()}catch(e){n.error(`Initial index failed`,b(d,e))}})())},x=t=>t.length===0||(m&&=(clearTimeout(m),void 0),!O({config:e,log:n,reconfigureForWorkspace:i,roots:t}))?!1:(_(),y(),!0);try{if(x((await h.listRoots()).roots))return;n.debug(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(t){if(g(t)){n.warn(`MCP roots/list not supported by client; using cwd fallback`,{version:d,cwd:u(),...l(t)}),O({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:u()}]})&&(_(),y());return}n.warn(`MCP roots/list failed during bootstrap; waiting for roots/list_changed notification`,{version:d,cwd:u(),...l(t)})}h.setNotificationHandler(r,async()=>{try{x((await h.listRoots()).roots)}catch(e){n.warn(`roots/list retry failed after notification`,b(d,e))}}),m=setTimeout(()=>{let t=u();n.debug(`Timed out waiting for MCP roots/list_changed; falling back to cwd workspace`,{cwd:t}),O({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:t}]})&&(_(),y())},c)}function A(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function j(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===o(e).href}catch{return!1}}function M(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function N(e,t){let n=process.env[e];if(!n)return t;let r=Number.parseInt(n,10);return Number.isFinite(r)&&r>0?r:t}function P(){return j()?s({allowPositionals:!0,options:{transport:{type:`string`,default:A()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:A(),port:process.env.AIKIT_PORT??`3210`}}async function F(){let n=v(),r=P();process.on(`unhandledRejection`,e=>{y.error(`Unhandled rejection`,b(n,e))}),process.on(`uncaughtException`,e=>{y.error(`Uncaught exception — exiting`,b(n,e)),process.exit(1)});let i=(t,r)=>{t.then(async()=>{try{let{markPromoteRun:t,markPruneRun:n,prune:i,shouldRunStartupPrune:a,shouldRunWeeklyPromote:o}=await import(`../../tools/dist/index.js`),s=r();if(!s)return;if(a()){let e=await i({});n(),e.totalBytesFreed>0&&y.info(`Storage maintenance complete`,{forgeOrphans:e.forgeGroundOrphans.count,legacyLance:e.legacyLance.count,bytesFreed:e.totalBytesFreed});let{groupLessons:t,pruneLessons:r}=await import(`./evolution-BX_zTSdj.js`).then(e=>e.t),a=await r(s.curated,s.stateStore,{dryRun:!1});a.pruned.length>0&&y.info(`Startup lesson prune complete`,{pruned:a.pruned.length});let o=await t(s.curated,s.stateStore,{dryRun:!1});(o.groupsCreated>0||o.lessonsGrouped>0)&&y.info(`Startup lesson grouping complete`,{groupsCreated:o.groupsCreated,lessonsGrouped:o.lessonsGrouped})}if(o()){let{DEFAULT_PROMOTE_CONFIG:n,collectWorkspaceLessons:r,getGlobalCuratedDir:i,promoteLessons:a,scanForDuplicates:o}=await import(`./promotion-DmwIVl0c.js`).then(e=>e.o),c=s.curated,l=new e(i(),c.store,c.embedder),u=await r(),d={...n,dryRun:!1},f=await a(o(u,d),l,d);t(),f.promoted.length>0&&y.info(`Weekly lesson promotion complete`,{promoted:f.promoted.length,candidates:f.candidates.length})}}catch(e){y.warn(`Startup maintenance failed (non-critical)`,b(n,e))}}).catch(()=>{})};if(y.info(`Starting MCP AI Kit server`,{version:n}),r.transport===`http`){let[{default:e},{loadConfig:a,resolveIndexMode:o},{registerDashboardRoutes:s,resolveDashboardDir:c},{registerSettingsRoutes:d,resolveSettingsDir:f},{createSettingsRouter:p},{authMiddleware:m,getOrCreateToken:g}]=await Promise.all([import(`express`),import(`./config-BkWFC9ah.js`),import(`./dashboard-static-FmfoS46e.js`),import(`./settings-static-BtvyIrza.js`),import(`./routes-1wkXLxXe.js`),import(`./auth-Bz5dmZgR.js`).then(e=>e.t)]),v=a();u(v.logging?.errorDetails===!0),v.configError&&y.warn(`Config load failure`,{error:v.configError}),y.info(`Config loaded`,{sourceCount:v.sources.length,storePath:v.store.path});let x=e();x.use(e.json({limit:`1mb`}));let w=Number(r.port),T=`http://localhost:${w}`,E=process.env.AIKIT_CORS_ORIGIN??T,D=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,O=N(`AIKIT_HTTP_MAX_SESSIONS`,8),k=N(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),A=N(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),j=C({limit:100,windowMs:6e4}),P=!1;x.use((e,t,n)=>{let r=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,i=S({requestOrigin:r,configuredOrigin:E,allowAnyOrigin:D,fallbackOrigin:T});if(i.warn&&!P&&(P=!0,y.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:r,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),r&&!i.allowOrigin){t.status(403).json({error:`Origin not allowed`});return}if(i.allowOrigin&&t.setHeader(`Access-Control-Allow-Origin`,i.allowOrigin),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID`),t.setHeader(`Access-Control-Expose-Headers`,`Mcp-Session-Id`),e.method===`OPTIONS`){t.status(204).end();return}n()});let F=g();x.use(m(F)),x.use(`/mcp`,(e,t,n)=>{let r=M(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(j.allow(r)){n();return}let i=Math.max(1,Math.ceil(j.getRetryAfterMs(r)/1e3));t.setHeader(`Retry-After`,String(i)),t.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})});let I=!1;x.use(`/mcp`,(e,t,n)=>{if(!I){let t=e.headers[`x-workspace-root`];typeof t==`string`&&t.length>0&&(v.sources[0]={path:t,excludePatterns:v.sources[0]?.excludePatterns??[]},v.allRoots=[t],I=!0,y.debug(`Workspace root applied from proxy header`,{wsRoot:t}))}n()}),s(x,c(),y);let L=new Date().toISOString();x.use(`/settings/api`,p({log:y,mcpInfo:()=>({transport:`http`,port:w,pid:process.pid,startedAt:L})})),d(x,f(),y),x.get(`/health`,(e,t)=>{t.json({status:`ok`})});let R=!1,z=null,B=null,V=null,H=null,U=null,W=null,G=null,K=null,q=Promise.resolve(),J=async(e,n)=>{if(!R||!V||!H){n.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=q,i;q=new Promise(e=>{i=e}),await r;try{let r=M(e);if(!W){if(r){n.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new H({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{G=e,B?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&B?.onSessionEnd(e),G=null}});e.onclose=()=>{W===e&&(W=null),G===e.sessionId&&(G=null)},W=e,await V.connect(e)}let i=W;await i.handleRequest(e,n,e.body),e.method!==`DELETE`&&(!r&&i.sessionId?(G=i.sessionId,B?.onSessionStart(i.sessionId,{transport:`http`}),B?.onSessionActivity(i.sessionId)):r&&B?.onSessionActivity(r))}catch(e){if(y.error(`MCP handler error`,l(e)),!n.headersSent){let t=e instanceof Error?e.message:String(e),r=t.includes(`Not Acceptable`);n.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?t:`Internal server error`},id:null})}}finally{i()}},Y=async(e,t)=>{let n=M(e);if(U&&(!W||n!==G)){await U.handleRequest(e,t,e.body);return}await J(e,t)};x.post(`/mcp`,Y),x.get(`/mcp`,Y),x.delete(`/mcp`,Y);let X=x.listen(w,`127.0.0.1`,()=>{y.info(`MCP server listening`,{url:`http://127.0.0.1:${w}/mcp`,port:w}),setTimeout(async()=>{try{let[{createLazyServer:e,createMcpServer:t,ALL_TOOL_NAMES:r},{StreamableHTTPServerTransport:a},{checkForUpdates:s,autoUpgradeScaffold:c}]=await Promise.all([import(`./server-R054LFb1.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-yzdUDXHC.js`)]);s(),c(),setInterval(s,1440*60*1e3).unref();let u=o(v),d=e(v,u);K=async()=>{d.aikit&&await Promise.all([d.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),d.aikit.graphStore.close().catch(()=>{}),d.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),d.aikit.store.close().catch(()=>{})])},V=d.server,H=a,R=!0,y.debug(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:r.length,resourceCount:2}),d.startInit(),d.ready.then(()=>{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);B=new _(d.aikit.stateStore,{staleTimeoutMinutes:k,gcIntervalMinutes:A,onBeforeSessionDelete:e=>{if(G===e&&W){let e=W;W=null,G=null,e.close().catch(()=>void 0)}U?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!d.aikit?.curated||!d.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-BX_zTSdj.js`).then(e=>e.t),t=await e(d.aikit.curated,d.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&y.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),U=new h({createServer:()=>{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);return t(d.aikit,v)},createTransport:e=>new a(e),maxSessions:O,sessionTimeoutMinutes:k,onSessionStart:e=>B?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>B?.onSessionActivity(e),onSessionEnd:e=>B?.onSessionEnd(e)}),B.startGC(),G&&(B.onSessionStart(G,{transport:`http`}),B.onSessionActivity(G)),y.info(`HTTP session runtime ready`,{maxSessions:O,sessionTimeoutMinutes:k,gcIntervalMinutes:A})}).catch(e=>y.error(`Failed to start session manager`,l(e))),u===`auto`?d.ready.then(async()=>{try{let e=v.sources.map(e=>e.path).join(`, `);y.info(`Running initial index`,{sourcePaths:e}),await d.runInitialIndex(),y.info(`Initial index complete`)}catch(e){y.error(`Initial index failed; will retry on aikit_reindex`,b(n,e))}}).catch(e=>y.error(`AI Kit init or indexing failed`,b(n,e))):u===`smart`?d.ready.then(async()=>{try{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(d.aikit.indexer,v,d.aikit.store),n=d.aikit.store;z=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),d.setSmartScheduler(t),y.debug(`Smart index scheduler started (HTTP mode)`)}catch(e){y.error(`Failed to start smart index scheduler`,b(n,e))}}).catch(e=>y.error(`AI Kit initialization failed`,b(n,e))):(d.ready.catch(e=>y.error(`AI Kit initialization failed`,b(n,e))),y.info(`Initial full indexing skipped in HTTP mode`,{indexMode:u})),i(d.ready,()=>d.aikit?{curated:d.aikit.curated,stateStore:d.aikit.stateStore}:null)}catch(e){y.error(`Failed to load server modules`,b(n,e))}},100)}),Z=!1,Q=async e=>{Z||(Z=!0,y.info(`Shutdown signal received`,{signal:e}),z?.stop(),B?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await U?.closeAll().catch(()=>void 0),G&&B?.onSessionEnd(G),W&&(await W.close().catch(()=>void 0),W=null,G=null),X.close(),V&&await V.close(),await K?.().catch(()=>void 0),process.exit(0))};process.on(`SIGINT`,()=>Q(`SIGINT`)),process.on(`SIGTERM`,()=>Q(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:r},{createLazyServer:a},{checkForUpdates:o,autoUpgradeScaffold:s},{RootsListChangedNotificationSchema:c}]=await Promise.all([import(`./config-BkWFC9ah.js`),import(`./server-R054LFb1.js`),import(`./version-check-yzdUDXHC.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=e();u(l.logging?.errorDetails===!0),l.configError&&y.warn(`Config load failure`,{error:l.configError}),y.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),o(),s(),setInterval(o,1440*60*1e3).unref();let d=r(l),f=a(l,d),{server:p,startInit:m,ready:h,runInitialIndex:g}=f,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await p.connect(v),y.debug(`MCP server started`,{transport:`stdio`}),await k({config:l,indexMode:d,log:y,rootsChangedNotificationSchema:c,reconfigureForWorkspace:t,runInitialIndex:g,server:p,startInit:m});let x=null,S=null,C=!1,w=async e=>{C||(C=!0,y.info(`Shutdown signal received`,{signal:e}),x&&=(clearTimeout(x),null),S?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await v.close().catch(()=>void 0),await p.close().catch(()=>void 0),f.aikit&&await Promise.all([f.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),f.aikit.graphStore.close().catch(()=>{}),f.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),f.aikit.store.close().catch(()=>{})]),process.exit(0))},T=()=>{x&&clearTimeout(x),x=setTimeout(async()=>{y.info(`Auto-shutdown: no activity for 30 minutes — releasing resources`);try{let e=f.aikit;e&&(e.embedder.shutdown?.().catch(()=>{}),e.store.releaseMemory?.(),e.graphStore.releaseMemory?.())}catch{}},18e5),x.unref&&x.unref()};T(),process.stdin.on(`data`,()=>T()),process.stdin.on(`end`,()=>void w(`stdin-end`)),process.stdin.on(`close`,()=>void w(`stdin-close`)),process.stdin.on(`error`,()=>void w(`stdin-error`)),process.on(`SIGINT`,()=>void w(`SIGINT`)),process.on(`SIGTERM`,()=>void w(`SIGTERM`)),h.catch(e=>{y.error(`Initialization failed — server will continue with limited tools`,b(n,e))}),d===`smart`?h.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.aikit.indexer,l,f.aikit.store);S=t;let n=f.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),f.setSmartScheduler(t),y.debug(`Smart index scheduler started (stdio mode)`)}catch(e){y.error(`Failed to start smart index scheduler`,b(n,e))}}).catch(e=>y.error(`AI Kit init failed for smart scheduler`,b(n,e))):y.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:d}),i(h,()=>f.aikit?{curated:f.aikit.curated,stateStore:f.aikit.stateStore}:null)}}export{e as CuratedKnowledgeManager,O as applyWorkspaceRoots,k as bootstrapWorkspaceRoots,C as createSlidingWindowRateLimiter,F as main,S as resolveCorsOrigin,D as selectWorkspaceRoot};
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./rolldown-runtime-DT7IzrpZ.js";import{t}from"./curated-manager-i5QA4c79.js";import{f as n,r,u as i}from"./supersession-CWEne3av.js";import{existsSync as a,mkdirSync as o}from"node:fs";import{join as s}from"node:path";import{getGlobalDataDir as c,isUserInstalled as l,listWorkspaces as u}from"../../core/dist/index.js";var d=e({DEFAULT_PROMOTE_CONFIG:()=>f,collectWorkspaceLessons:()=>w,demoteLesson:()=>D,getGlobalCuratedDir:()=>C,promoteLessons:()=>E,scanForDuplicates:()=>T});const f={minWorkspaces:2,minAvgConfidence:80,similarityThreshold:.7,dryRun:!0};function p(e){return{minWorkspaces:Math.max(2,Math.trunc(e?.minWorkspaces??f.minWorkspaces)),minAvgConfidence:Math.min(100,Math.max(0,Math.trunc(e?.minAvgConfidence??f.minAvgConfidence))),similarityThreshold:Math.min(1,Math.max(0,e?.similarityThreshold??f.similarityThreshold)),dryRun:e?.dryRun??f.dryRun}}function m(e,t){let n=e.map(()=>[]);for(let i=0;i<e.length;i+=1)for(let a=i+1;a<e.length;a+=1)r(e[i].insight,e[a].insight)>=t&&(n[i].push(a),n[a].push(i));return n}function h(e){let t=new Set,n=[];for(let r=0;r<e.length;r+=1){if(t.has(r))continue;let i=[r],a=[];for(t.add(r);i.length>0;){let n=i.pop();if(n!==void 0){a.push(n);for(let r of e[n])t.has(r)||(t.add(r),i.push(r))}}n.push(a)}return n}function g(e){return new t(e,null,null)}function _(e){return(e??``).replace(/\s+/g,` `).trim()}function v(e){let t=_(e);return t.length<=80?t:`${t.slice(0,77).replace(/\s+\S*$/,``)}...`}function y(e){return i({title:v(e.insight),context:`Observed across ${e.foundIn.length} workspaces: ${e.foundIn.join(`, `)}`,insight:e.insight,evidence:[`Promoted from workspaces: ${e.foundIn.join(`, `)}`,`Average confidence: ${e.avgConfidence}/100`,`Reason: ${e.reason}`].join(`
2
+ `),confidence:e.avgConfidence,tags:[`lesson`,`promoted`,`global`]})}async function b(e,t){let r=await e.list({category:`lessons`,limit:1e3,orderBy:`updated`,order:`desc`});return(await Promise.all(r.map(async r=>{let i=await e.read(r.path),a=n(i.content),o=_(a.insight);return o?{workspace:t,path:r.path,title:a.title??i.title??r.title,insight:o,confidence:a.confidence??0}:null}))).filter(e=>e!==null)}async function x(e){return(await b(e,`global`)).map(e=>e.insight)}function S(e,t,n){return t.some(t=>r(t,e)>=n)}function C(){let e=s(c(),`global-knowledge`,`.ai`,`curated`);return a(e)||o(e,{recursive:!0}),e}async function w(e){let t=new Map;if(!l())return t;for(let e of u()){let n=s(e.workspacePath,`.ai`,`curated`);if(!a(n))continue;let r=await b(g(n),e.partition);r.length>0&&t.set(e.partition,r)}return t}function T(e,t=f){let n=p(t),r=[...e.values()].flat();if(r.length===0)return[];let i=h(m(r,n.similarityThreshold)),a=[];for(let e of i){let t=e.map(e=>r[e]),i=[...new Set(t.map(e=>e.workspace))].sort();if(i.length<n.minWorkspaces)continue;let o=Math.round(t.reduce((e,t)=>e+t.confidence,0)/t.length),s=[...t].sort((e,t)=>t.confidence-e.confidence||e.title.localeCompare(t.title)||e.path.localeCompare(t.path))[0];a.push({insight:s.insight,foundIn:i,avgConfidence:o,action:o>=n.minAvgConfidence?`promote`:`skip`,reason:o>=n.minAvgConfidence?`Shared across ${i.length} workspaces`:`Below confidence threshold`})}return a.sort((e,t)=>Number(t.action===`promote`)-Number(e.action===`promote`)||t.foundIn.length-e.foundIn.length||t.avgConfidence-e.avgConfidence||e.insight.localeCompare(t.insight))}async function E(e,t,n=f){let r=p(n),i=[],a=await x(t);for(let n of e){if(n.action!==`promote`||S(n.insight,a,r.similarityThreshold)||r.dryRun)continue;let e=await t.remember(v(n.insight),y(n),`lessons`,[`lesson`,`promoted`,`global`]);i.push(e.path),a.push(n.insight)}return{candidates:e,promoted:i}}async function D(e,t){try{return await e.forget(t,`Demoted from global knowledge partition`),{removed:!0,path:t}}catch(e){if(e instanceof Error&&/not found/i.test(e.message))return{removed:!1,path:t};throw e}}export{E as a,C as i,w as n,d as o,D as r,T as s,f as t};
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import{t as e}from"./rolldown-runtime-yuFVEuWy.js";import{t}from"./bin.js";import{f as n,r,u as i}from"./supersession-DO_ZROFl.js";import{existsSync as a,mkdirSync as o}from"node:fs";import{join as s}from"node:path";import{getGlobalDataDir as c,isUserInstalled as l,listWorkspaces as u}from"../../core/dist/index.js";var d=e({DEFAULT_PROMOTE_CONFIG:()=>f,collectWorkspaceLessons:()=>w,demoteLesson:()=>D,getGlobalCuratedDir:()=>C,promoteLessons:()=>E,scanForDuplicates:()=>T});const f={minWorkspaces:2,minAvgConfidence:80,similarityThreshold:.7,dryRun:!0};function p(e){return{minWorkspaces:Math.max(2,Math.trunc(e?.minWorkspaces??f.minWorkspaces)),minAvgConfidence:Math.min(100,Math.max(0,Math.trunc(e?.minAvgConfidence??f.minAvgConfidence))),similarityThreshold:Math.min(1,Math.max(0,e?.similarityThreshold??f.similarityThreshold)),dryRun:e?.dryRun??f.dryRun}}function m(e,t){let n=e.map(()=>[]);for(let i=0;i<e.length;i+=1)for(let a=i+1;a<e.length;a+=1)r(e[i].insight,e[a].insight)>=t&&(n[i].push(a),n[a].push(i));return n}function h(e){let t=new Set,n=[];for(let r=0;r<e.length;r+=1){if(t.has(r))continue;let i=[r],a=[];for(t.add(r);i.length>0;){let n=i.pop();if(n!==void 0){a.push(n);for(let r of e[n])t.has(r)||(t.add(r),i.push(r))}}n.push(a)}return n}function g(e){return new t(e,null,null)}function _(e){return(e??``).replace(/\s+/g,` `).trim()}function v(e){let t=_(e);return t.length<=80?t:`${t.slice(0,77).replace(/\s+\S*$/,``)}...`}function y(e){return i({title:v(e.insight),context:`Observed across ${e.foundIn.length} workspaces: ${e.foundIn.join(`, `)}`,insight:e.insight,evidence:[`Promoted from workspaces: ${e.foundIn.join(`, `)}`,`Average confidence: ${e.avgConfidence}/100`,`Reason: ${e.reason}`].join(`
3
+ `),confidence:e.avgConfidence,tags:[`lesson`,`promoted`,`global`]})}async function b(e,t){let r=await e.list({category:`lessons`,limit:1e3,orderBy:`updated`,order:`desc`});return(await Promise.all(r.map(async r=>{let i=await e.read(r.path),a=n(i.content),o=_(a.insight);return o?{workspace:t,path:r.path,title:a.title??i.title??r.title,insight:o,confidence:a.confidence??0}:null}))).filter(e=>e!==null)}async function x(e){return(await b(e,`global`)).map(e=>e.insight)}function S(e,t,n){return t.some(t=>r(t,e)>=n)}function C(){let e=s(c(),`global-knowledge`,`.ai`,`curated`);return a(e)||o(e,{recursive:!0}),e}async function w(e){let t=new Map;if(!l())return t;for(let e of u()){let n=s(e.workspacePath,`.ai`,`curated`);if(!a(n))continue;let r=await b(g(n),e.partition);r.length>0&&t.set(e.partition,r)}return t}function T(e,t=f){let n=p(t),r=[...e.values()].flat();if(r.length===0)return[];let i=h(m(r,n.similarityThreshold)),a=[];for(let e of i){let t=e.map(e=>r[e]),i=[...new Set(t.map(e=>e.workspace))].sort();if(i.length<n.minWorkspaces)continue;let o=Math.round(t.reduce((e,t)=>e+t.confidence,0)/t.length),s=[...t].sort((e,t)=>t.confidence-e.confidence||e.title.localeCompare(t.title)||e.path.localeCompare(t.path))[0];a.push({insight:s.insight,foundIn:i,avgConfidence:o,action:o>=n.minAvgConfidence?`promote`:`skip`,reason:o>=n.minAvgConfidence?`Shared across ${i.length} workspaces`:`Below confidence threshold`})}return a.sort((e,t)=>Number(t.action===`promote`)-Number(e.action===`promote`)||t.foundIn.length-e.foundIn.length||t.avgConfidence-e.avgConfidence||e.insight.localeCompare(t.insight))}async function E(e,t,n=f){let r=p(n),i=[],a=await x(t);for(let n of e){if(n.action!==`promote`||S(n.insight,a,r.similarityThreshold)||r.dryRun)continue;let e=await t.remember(v(n.insight),y(n),`lessons`,[`lesson`,`promoted`,`global`]);i.push(e.path),a.push(n.insight)}return{candidates:e,promoted:i}}async function D(e,t){try{return await e.forget(t,`Demoted from global knowledge partition`),{removed:!0,path:t}}catch(e){if(e instanceof Error&&/not found/i.test(e.message))return{removed:!1,path:t};throw e}}export{E as a,C as i,w as n,d as o,D as r,T as s,f as t};