@vpxa/aikit 0.1.112 → 0.1.113
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packages/indexer/dist/index.js +1 -1
- package/packages/server/dist/index.js +1 -1
- package/packages/server/dist/{server-BzPxuGzZ.js → server-qD-mw6RP.js} +1 -1
- package/packages/store/dist/index.d.ts +19 -0
- package/packages/store/dist/index.js +2 -2
- package/packages/store/dist/{sqlite-vec-store-DQE-A0rY.js → sqlite-vec-store-DuGaWATy.js} +2 -2
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash as e}from"node:crypto";import{existsSync as t,readFileSync as n,realpathSync as r,statSync as i,writeFileSync as a}from"node:fs";import{lstat as o,readFile as s,readdir as c,stat as l}from"node:fs/promises";import{dirname as u,extname as d,join as f,relative as p,resolve as m}from"node:path";import{AIKIT_PATHS as h,FILE_LIMITS as g,createLogger as _,detectContentType as v,serializeError as y}from"../../core/dist/index.js";import{minimatch as b}from"minimatch";import{availableParallelism as x,loadavg as S}from"node:os";import{createChunkerSync as C}from"../../chunker/dist/index.js";function w(t){return e(`sha256`).update(t).digest(`hex`).slice(0,16)}function T(t,n){let r=`${t}:${n}`;return e(`sha256`).update(r).digest(`hex`).slice(0,16)}const E=_(`indexer`);var D=class e{static BINARY_EXTENSIONS=new Set(`.node,.so,.dylib,.dll,.wasm,.bin,.exe,.png,.jpg,.jpeg,.gif,.bmp,.ico,.webp,.svg,.mp3,.mp4,.wav,.avi,.mov,.flac,.zip,.gz,.tar,.bz2,.7z,.rar,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.ttf,.otf,.woff,.woff2,.eot,.pyc,.class,.o,.obj,.a,.lib`.split(`,`));async crawl(e){let t=[],n=new Set;return await this.walkDir(e.rootDir,e.rootDir,e.excludePatterns,t,n),t}async walkDir(t,n,i,a,u){let m;try{m=await c(t,{withFileTypes:!0})}catch(e){let n=e.code;(n===`EACCES`||n===`EPERM`)&&E.warn(`Permission denied, skipping directory`,{dir:t});return}for(let c of m){let m=f(t,c.name),_=p(n,m).replace(/\\/g,`/`);if(!this.isExcluded(_,i)){if(c.isDirectory()){if(c.name.startsWith(`.`)&&!(c.name===h.ai.slice(1)&&_.startsWith(h.ai)))continue;try{if((await o(m)).isSymbolicLink())continue}catch{continue}let e;try{e=r(m)}catch{continue}if(u.has(e))continue;u.add(e),await this.walkDir(m,n,i,a,u)}else if(c.isFile()){let t=d(c.name).toLowerCase();if(e.BINARY_EXTENSIONS.has(t))continue;try{if((await l(m)).size>g.maxFileSizeBytes)continue;let e=await s(m,`utf-8`);if(e.includes(`\0`))continue;a.push({relativePath:_,absolutePath:m,content:e,extension:t})}catch{}}}}}isExcluded(e,t){return t.some(t=>b(e,t,{dot:!0}))}};const O=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.mjs`,`.cjs`]),k=[{pattern:/^export\s+(?:async\s+)?function\s+(\w+)/gm,kind:`function`,exported:!0},{pattern:/^export\s+(?:default\s+)?class\s+(\w+)/gm,kind:`class`,exported:!0},{pattern:/^export\s+interface\s+(\w+)/gm,kind:`interface`,exported:!0},{pattern:/^export\s+type\s+(\w+)/gm,kind:`type`,exported:!0},{pattern:/^export\s+(?:const|let)\s+(\w+)/gm,kind:`const`,exported:!0},{pattern:/^export\s+enum\s+(\w+)/gm,kind:`enum`,exported:!0},{pattern:/^(?:async\s+)?function\s+(\w+)/gm,kind:`function`,exported:!1},{pattern:/^class\s+(\w+)/gm,kind:`class`,exported:!1},{pattern:/^interface\s+(\w+)/gm,kind:`interface`,exported:!1},{pattern:/^type\s+(\w+)/gm,kind:`type`,exported:!1},{pattern:/^enum\s+(\w+)/gm,kind:`enum`,exported:!1}],A=[/import\s+(?:(?:type\s+)?(?:(?:\{[^}]*\}|[\w*]+)\s+from\s+)?)['"]([^'"]+)['"]/g,/import\(\s*['"]([^'"]+)['"]\s*\)/g,/require\(\s*['"]([^'"]+)['"]\s*\)/g];function j(t,n,r){return e(`sha256`).update(`${t}:${n}:${r}`).digest(`hex`).slice(0,16)}function M(t,n,r){return e(`sha256`).update(`${t}-${r}-${n}`).digest(`hex`).slice(0,16)}function N(e,t){return f(u(t),e).replace(/\\/g,`/`).replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,``)}function P(e){return e.replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,``)}function F(e,t,n){let r=d(t).toLowerCase();if(!O.has(r))return{nodes:[],edges:[]};let i=[],a=[],o=new Date().toISOString(),s=new Set,c=P(t),l=j(`module`,c,c);i.push({id:l,type:`module`,name:t,properties:{ext:r},sourcePath:t,createdAt:o});for(let{pattern:n,kind:r,exported:c}of k){let u=new RegExp(n.source,n.flags),d;for(;(d=u.exec(e))!==null;){let e=d[1],n=`${r}:${e}`;if(s.has(n))continue;s.add(n);let u=j(r,e,t);i.push({id:u,type:r,name:e,properties:{exported:c},sourcePath:t,createdAt:o}),a.push({id:M(l,u,`defines`),fromId:l,toId:u,type:`defines`,weight:c?1:.5})}}let u=n?.workspacePackages,f=new Set;for(let n of A){let r=new RegExp(n.source,n.flags),i;for(;(i=r.exec(e))!==null;){let e=i[1];if(f.has(e))continue;let n;if(e.startsWith(`.`))n=N(e,t);else if(u){let t=e.startsWith(`@`)?e.split(`/`).slice(0,2).join(`/`):e.split(`/`)[0],r=u.get(t);if(!r)continue;n=r}else continue;f.add(e);let r=P(n),o=j(`module`,r,r);a.push({id:M(l,o,`imports`),fromId:l,toId:o,type:`imports`,properties:{source:e}})}}return{nodes:i,edges:a}}const I=_(`hash-cache`);var L=class{cache;filePath;dirty=!1;constructor(e){this.filePath=m(e,`file-hashes.json`),this.cache=new Map}load(){if(t(this.filePath))try{let e=n(this.filePath,`utf-8`),t=JSON.parse(e);this.cache=new Map(Object.entries(t)),I.info(`Hash cache loaded`,{entries:this.cache.size})}catch(e){I.warn(`Hash cache load failed, starting fresh`,{err:e}),this.cache=new Map}}get(e){return this.cache.get(e)}set(e,t){this.cache.set(e,t),this.dirty=!0}delete(e){this.cache.delete(e)&&(this.dirty=!0)}flush(){if(this.dirty)try{let e={};for(let[t,n]of this.cache)e[t]=n;a(this.filePath,JSON.stringify(e),`utf-8`),this.dirty=!1}catch(e){I.warn(`Hash cache flush failed`,{err:e})}}clear(){this.cache.clear(),this.dirty=!0,this.flush()}get size(){return this.cache.size}};const R=_(`indexer`),z=()=>new Promise(e=>setImmediate(e));async function B(e,t,n,r){let i=0;async function a(){for(;i<e.length;){let n=i++;try{await t(e[n])}catch(t){r?.(e[n],t)}n%10==0&&await z()}}await Promise.all(Array.from({length:Math.min(n,e.length)},()=>a()))}function V(e){let t=x(),n=S()[0]/t;return n>1.5?2:n>1?Math.max(2,Math.floor(e/2)):e}const H=Math.max(2,Math.min(4,Math.floor(x()*.5)));var U=class{crawler;indexing=!1;graphStore;hashCache;get isIndexing(){return this.indexing}constructor(e,t){this.embedder=e,this.store=t,this.crawler=new D}normalizeChunkText(e){return e.replace(/^\/\/ File: [^\n]*\n?/,``).toLowerCase().replace(/\s+/g,` `).trim()}setGraphStore(e){this.graphStore=e}setHashCache(e){this.hashCache=e}async index(e,t){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{return await this.doIndex(e,t,{})}finally{this.indexing=!1}}async getChangedFiles(e){let t=e.indexing.concurrency??H,n=await this.crawlSources(e),{filesToProcess:r}=await this.planIndexWork(n,t,{});return r.map(e=>e.relativePath)}async indexFiles(e,t,n){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{return await this.doIndexFiles(e,t,n)}finally{this.indexing=!1}}async doIndex(e,t,n={}){let r=Date.now(),i=e.indexing.concurrency??H;t?.({phase:`crawling`,filesTotal:0,filesProcessed:0,chunksTotal:0,chunksProcessed:0});let a=await this.crawlSources(e),{filesToProcess:o,filesSkipped:s,pathsToRemove:c}=await this.planIndexWork(a,i,{skipHashCheck:n.skipHashCheck}),{filesProcessed:l,chunksCreated:u,chunksDeduped:d}=await this.processFiles(a,o,i,t,{graphCleared:n.graphCleared}),f=await this.cleanupRemovedFiles(c,i,o.length,l,u,t);return this.hashCache?.flush(),t?.({phase:`done`,filesTotal:o.length,filesProcessed:l,chunksTotal:u,chunksProcessed:u}),{filesProcessed:l,filesSkipped:s,chunksCreated:u,chunksDeduped:d,filesRemoved:f,durationMs:Date.now()-r}}async doIndexFiles(e,t,n){let r=Date.now(),i=e.indexing.concurrency??H,a=new Set(t);if(a.size===0)return{filesProcessed:0,filesSkipped:0,chunksCreated:0,chunksDeduped:0,filesRemoved:0,durationMs:Date.now()-r};n?.({phase:`crawling`,filesTotal:0,filesProcessed:0,chunksTotal:0,chunksProcessed:0});let o=await this.crawlSources(e),{filesToProcess:s,filesSkipped:c}=await this.planIndexWork(o,i,{requestedPaths:a}),{filesProcessed:l,chunksCreated:u,chunksDeduped:d}=await this.processFiles(o,s,i,n,{});return this.hashCache?.flush(),n?.({phase:`done`,filesTotal:s.length,filesProcessed:l,chunksTotal:u,chunksProcessed:u}),{filesProcessed:l,filesSkipped:c,chunksCreated:u,chunksDeduped:d,filesRemoved:0,durationMs:Date.now()-r}}async crawlSources(e){return(await Promise.all(e.sources.map(e=>this.crawler.crawl({rootDir:e.path,excludePatterns:e.excludePatterns})))).flat()}async planIndexWork(e,t,n){let r=n.requestedPaths,i=r?e.filter(e=>r.has(e.relativePath)):e;if(n.skipHashCheck)return{filesToProcess:i,filesSkipped:0,pathsToRemove:[]};let a=r?[]:await this.getPathsToRemove(e),o=0,s=[];return await B(i,async e=>{let t=w(e.content);if(this.hashCache){if(this.hashCache.get(e.relativePath)===t){o++;return}}else{let n=await this.store.getBySourcePath(e.relativePath);if(n.length>0&&n[0].fileHash===t){o++;return}}s.push(e)},V(t),(e,t)=>R.error(`Hash check failed`,{sourcePath:e.relativePath,...y(t)})),{filesToProcess:s,filesSkipped:o,pathsToRemove:a}}async getPathsToRemove(e){let t=await this.store.listSourcePaths(),n=new Set(e.map(e=>e.relativePath));return t.filter(e=>!n.has(e)&&!e.startsWith(`${h.aiCurated}/`))}async buildWorkspacePackageMap(e){let t=new Map;for(let n of e)if(n.relativePath.endsWith(`package.json`))try{let e=JSON.parse(n.content);if(typeof e.name!=`string`||e.name.length===0)continue;let r=n.relativePath===`package.json`?``:n.relativePath.replace(/\/package\.json$/,``),i=``;if(typeof e.exports==`string`)i=e.exports;else if(e.exports&&typeof e.exports==`object`){let t=e.exports,n=t[`.`]??t;if(typeof n==`string`)i=n;else if(n&&typeof n==`object`){let e=n,t=e.import??e.module??e.default??e.require;typeof t==`string`&&(i=t)}}!i&&typeof e.module==`string`&&(i=e.module),!i&&typeof e.main==`string`&&(i=e.main);let a=i.replace(/^\.\//,``).replace(/^dist\//,`src/`).replace(/\.(ts|js|mjs|cjs|tsx|jsx)$/,``),o=a?r?`${r}/${a}`:a:r?`${r}/src/index`:`src/index`;t.set(e.name,o)}catch{}return t}async processFiles(t,n,r,i,a={}){let o=0,s=0,c=0,l=n.length,u=this.graphStore?await this.buildWorkspacePackageMap(t):void 0,d=new Map,f=[],p=[],m=0,h=[],g=[],_=new Map,b=0,x=async()=>{if(h.length===0)return;let e=h,t=g,n=_;h=[],g=[],_=new Map,b=0,await this.store.upsert(e,t);for(let[e,t]of n)this.hashCache?.set(e,t)},S=async()=>{if(this.graphStore){try{f.length>0&&await this.graphStore.upsertNodes(f),p.length>0&&await this.graphStore.upsertEdges(p)}catch(e){R.warn(`Graph batch flush failed`,y(e))}f=[],p=[],m=0}};return await B(n,async t=>{i?.({phase:`chunking`,filesTotal:l,filesProcessed:o,chunksTotal:s,chunksProcessed:s,currentFile:t.relativePath});let n=v(t.relativePath),r=C(t.extension).chunk(t.content,{sourcePath:t.relativePath,contentType:n});if(r.length===0)return;let E=w(t.content),D=new Date().toISOString(),O=(e,n,r)=>({id:T(t.relativePath,n),content:e.text,sourcePath:e.sourcePath,contentType:e.contentType,headingPath:e.headingPath,chunkIndex:e.chunkIndex,totalChunks:e.totalChunks,startLine:e.startLine,endLine:e.endLine,fileHash:E,contentHash:r,indexedAt:D,origin:`indexed`,tags:[],version:1}),k=[],A=[];for(let t=0;t<r.length;t++){let n=r[t],i=e(`sha256`).update(this.normalizeChunkText(n.text)).digest(`hex`),a=O(n,t,i),o=d.get(i);if(o&&this.store.upsertWithoutVector){A.push({record:a,sourceRecordId:o}),c++;continue}d.set(i,a.id),k.push({chunk:n,record:a})}i?.({phase:`embedding`,filesTotal:l,filesProcessed:o,chunksTotal:s+r.length,chunksProcessed:s,currentFile:t.relativePath});let j=k.length>0?await this.embedder.embedBatch(k.map(({chunk:e})=>e.text)):[],M=k.map(({record:e})=>e);if(i?.({phase:`storing`,filesTotal:l,filesProcessed:o,chunksTotal:s+r.length,chunksProcessed:s,currentFile:t.relativePath}),M.length>0&&(h.push(...M),g.push(...j),_.set(t.relativePath,E),b++,b>=20&&await x()),A.length>0&&h.length>0&&await x(),this.store.upsertWithoutVector)for(let{record:e,sourceRecordId:t}of A)await this.store.upsertWithoutVector(e,t);if(M.length===0&&A.length>0&&this.hashCache?.set(t.relativePath,E),this.graphStore)try{a.graphCleared||await this.graphStore.deleteBySourcePath(t.relativePath);let e=F(t.content,t.relativePath,{workspacePackages:u});e.nodes.length>0&&f.push(...e.nodes),e.edges.length>0&&p.push(...e.edges),m++,m>=50&&await S()}catch(e){R.warn(`Graph extraction failed`,{sourcePath:t.relativePath,...y(e)})}o++,s+=r.length},V(r),(e,t)=>R.error(`Processing failed`,{sourcePath:e.relativePath,...y(t)})),await x(),await S(),{filesProcessed:o,chunksCreated:s,chunksDeduped:c}}async cleanupRemovedFiles(e,t,n,r,i,a){if(e.length===0)return 0;let o=0;return a?.({phase:`cleanup`,filesTotal:n,filesProcessed:r,chunksTotal:i,chunksProcessed:i}),await B(e,async e=>{await this.store.deleteBySourcePath(e),this.hashCache?.delete(e),this.graphStore&&await this.graphStore.deleteBySourcePath(e).catch(t=>R.warn(`Graph cleanup failed`,{sourcePath:e,...y(t)})),o++},V(t),(e,t)=>R.error(`Cleanup failed`,{sourcePath:e,...y(t)})),o}async reindexAll(e,t){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{if(await this.store.dropTable(),this.graphStore)try{let e=await this.graphStore.getStats();e.nodeCount>0&&(await this.graphStore.clear(),R.info(`Graph store cleared`,{nodeCount:e.nodeCount,edgeCount:e.edgeCount}))}catch(e){R.warn(`Graph store clear failed`,y(e))}return await this.doReindex(e,t)}catch(e){throw this.indexing=!1,e}}async doReindex(e,t){try{return await this.doIndex(e,t,{skipHashCheck:!0,graphCleared:!0})}finally{this.indexing=!1}}async getStats(){return this.store.getStats()}};const W=_(`smart-index`),G=1.5;var K=class{trickleTimer=null;stopped=!1;trickleIntervalMs;batchSize;priorityQueue=[];changedFiles=[];lastRefreshTime=0;refreshing=!1;constructor(e,t,n){this.indexer=e,this.config=t,this.store=n,this.trickleIntervalMs=t.indexing.trickleIntervalMs??this.readPositiveIntEnv(`AIKIT_SMART_TRICKLE_MS`,3e4),this.batchSize=t.indexing.trickleBatchSize??this.readPositiveIntEnv(`AIKIT_SMART_BATCH_SIZE`,1)}start(){this.trickleTimer&&=(clearTimeout(this.trickleTimer),null),this.stopped=!1,W.info(`Smart index scheduler started (trickle mode)`,{intervalMs:this.trickleIntervalMs,batchSize:this.batchSize}),this.scheduleTick()}stop(){this.stopped=!0,this.trickleTimer&&=(clearTimeout(this.trickleTimer),null)}prioritize(...e){let t=[...new Set(e.filter(Boolean))].filter(e=>{try{return!i(e).isDirectory()}catch{return W.debug(`Skipping non-existent path`,{path:e}),!1}});for(let e of t){let t=this.priorityQueue.indexOf(e);t>=0&&this.priorityQueue.splice(t,1)}for(let e of t.reverse())this.priorityQueue.unshift(e);this.priorityQueue.length>500&&(this.priorityQueue.length=500),t.length>0&&W.info(`Files prioritized for trickle indexing`,{added:t.length,queued:this.priorityQueue.length})}getState(){return{mode:`smart`,queueSize:this.priorityQueue.length,changedFilesSize:this.changedFiles.length,intervalMs:this.trickleIntervalMs,batchSize:this.batchSize,running:this.trickleTimer!==null}}readPositiveIntEnv(e,t){let n=Number(process.env[e]);return Number.isFinite(n)&&n>0?n:t}scheduleTick(){this.trickleTimer=setTimeout(()=>void this.tick(),this.trickleIntervalMs),this.trickleTimer.unref&&this.trickleTimer.unref()}async tick(){if(!this.stopped)try{if(this.indexer.isIndexing){W.info(`Skipping trickle tick — indexing already in progress`);return}let e=this.getCpuCount(),t=S()[0];if(e>0&&t/e>G){W.info(`Skipping trickle tick — system load too high`,{load:t.toFixed(2),cpuCount:e,threshold:G});return}let n=await this.pickFiles();if(n.length===0){await this.maybeRefreshChangedFiles();return}W.info(`Trickle indexing tick started`,{count:n.length,files:n});let r=await this.indexer.indexFiles(this.config,n);if(this.store)try{await this.store.createFtsIndex()}catch(e){W.warn(`FTS index rebuild failed after trickle tick`,{error:String(e)})}this.changedFiles=this.changedFiles.filter(e=>!n.includes(e)),W.info(`Trickle indexing tick complete`,{filesProcessed:r.filesProcessed,filesSkipped:r.filesSkipped,chunksCreated:r.chunksCreated})}catch(e){W.error(`Trickle indexing tick failed`,{error:String(e)})}finally{this.stopped||this.scheduleTick()}}getCpuCount(){try{return typeof x==`function`?x():4}catch{return 4}}async pickFiles(){let e=[];for(;e.length<this.batchSize&&this.priorityQueue.length>0;){let t=this.priorityQueue.shift();t&&!e.includes(t)&&e.push(t)}if(e.length<this.batchSize)for(await this.maybeRefreshChangedFiles();e.length<this.batchSize&&this.changedFiles.length>0;){let t=this.changedFiles.shift();t&&!e.includes(t)&&e.push(t)}return e}async maybeRefreshChangedFiles(){let e=Date.now();if(!(this.refreshing||this.changedFiles.length>0&&e-this.lastRefreshTime<6e5)){this.refreshing=!0;try{this.changedFiles=await this.indexer.getChangedFiles(this.config),this.lastRefreshTime=e,this.changedFiles.length>0&&W.info(`Refreshed changed files for trickle indexing`,{count:this.changedFiles.length})}catch(e){W.error(`Failed to refresh changed files for trickle indexing`,{error:String(e)})}finally{this.refreshing=!1}}}};export{L as FileHashCache,D as FilesystemCrawler,U as IncrementalIndexer,K as SmartIndexScheduler,F as extractGraph,T as generateRecordId,w as hashContent};
|
|
1
|
+
import{createHash as e}from"node:crypto";import{existsSync as t,readFileSync as n,realpathSync as r,statSync as i,writeFileSync as a}from"node:fs";import{lstat as o,readFile as s,readdir as c,stat as l}from"node:fs/promises";import{dirname as u,extname as d,join as f,relative as p,resolve as m}from"node:path";import{AIKIT_PATHS as h,FILE_LIMITS as g,createLogger as _,detectContentType as v,serializeError as y}from"../../core/dist/index.js";import{minimatch as b}from"minimatch";import{availableParallelism as x,loadavg as S}from"node:os";import{createChunkerSync as C}from"../../chunker/dist/index.js";function w(t){return e(`sha256`).update(t).digest(`hex`).slice(0,16)}function T(t,n){let r=`${t}:${n}`;return e(`sha256`).update(r).digest(`hex`).slice(0,16)}const E=_(`indexer`);var D=class e{static BINARY_EXTENSIONS=new Set(`.node,.so,.dylib,.dll,.wasm,.bin,.exe,.png,.jpg,.jpeg,.gif,.bmp,.ico,.webp,.svg,.mp3,.mp4,.wav,.avi,.mov,.flac,.zip,.gz,.tar,.bz2,.7z,.rar,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.ttf,.otf,.woff,.woff2,.eot,.pyc,.class,.o,.obj,.a,.lib`.split(`,`));async crawl(e){let t=[],n=new Set;return await this.walkDir(e.rootDir,e.rootDir,e.excludePatterns,t,n),t}async walkDir(t,n,i,a,u){let m;try{m=await c(t,{withFileTypes:!0})}catch(e){let n=e.code;(n===`EACCES`||n===`EPERM`)&&E.warn(`Permission denied, skipping directory`,{dir:t});return}for(let c of m){let m=f(t,c.name),_=p(n,m).replace(/\\/g,`/`);if(!this.isExcluded(_,i)){if(c.isDirectory()){if(c.name.startsWith(`.`)&&!(c.name===h.ai.slice(1)&&_.startsWith(h.ai)))continue;try{if((await o(m)).isSymbolicLink())continue}catch{continue}let e;try{e=r(m)}catch{continue}if(u.has(e))continue;u.add(e),await this.walkDir(m,n,i,a,u)}else if(c.isFile()){let t=d(c.name).toLowerCase();if(e.BINARY_EXTENSIONS.has(t))continue;try{if((await l(m)).size>g.maxFileSizeBytes)continue;let e=await s(m,`utf-8`);if(e.includes(`\0`))continue;a.push({relativePath:_,absolutePath:m,content:e,extension:t})}catch{}}}}}isExcluded(e,t){return t.some(t=>b(e,t,{dot:!0}))}};const O=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.mjs`,`.cjs`]),k=[{pattern:/^export\s+(?:async\s+)?function\s+(\w+)/gm,kind:`function`,exported:!0},{pattern:/^export\s+(?:default\s+)?class\s+(\w+)/gm,kind:`class`,exported:!0},{pattern:/^export\s+interface\s+(\w+)/gm,kind:`interface`,exported:!0},{pattern:/^export\s+type\s+(\w+)/gm,kind:`type`,exported:!0},{pattern:/^export\s+(?:const|let)\s+(\w+)/gm,kind:`const`,exported:!0},{pattern:/^export\s+enum\s+(\w+)/gm,kind:`enum`,exported:!0},{pattern:/^(?:async\s+)?function\s+(\w+)/gm,kind:`function`,exported:!1},{pattern:/^class\s+(\w+)/gm,kind:`class`,exported:!1},{pattern:/^interface\s+(\w+)/gm,kind:`interface`,exported:!1},{pattern:/^type\s+(\w+)/gm,kind:`type`,exported:!1},{pattern:/^enum\s+(\w+)/gm,kind:`enum`,exported:!1}],A=[/import\s+(?:(?:type\s+)?(?:(?:\{[^}]*\}|[\w*]+)\s+from\s+)?)['"]([^'"]+)['"]/g,/import\(\s*['"]([^'"]+)['"]\s*\)/g,/require\(\s*['"]([^'"]+)['"]\s*\)/g];function j(t,n,r){return e(`sha256`).update(`${t}:${n}:${r}`).digest(`hex`).slice(0,16)}function M(t,n,r){return e(`sha256`).update(`${t}-${r}-${n}`).digest(`hex`).slice(0,16)}function N(e,t){return f(u(t),e).replace(/\\/g,`/`).replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,``)}function P(e){return e.replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,``)}function F(e,t,n){let r=d(t).toLowerCase();if(!O.has(r))return{nodes:[],edges:[]};let i=[],a=[],o=new Date().toISOString(),s=new Set,c=P(t),l=j(`module`,c,c);i.push({id:l,type:`module`,name:t,properties:{ext:r},sourcePath:t,createdAt:o});for(let{pattern:n,kind:r,exported:c}of k){let u=new RegExp(n.source,n.flags),d;for(;(d=u.exec(e))!==null;){let e=d[1],n=`${r}:${e}`;if(s.has(n))continue;s.add(n);let u=j(r,e,t);i.push({id:u,type:r,name:e,properties:{exported:c},sourcePath:t,createdAt:o}),a.push({id:M(l,u,`defines`),fromId:l,toId:u,type:`defines`,weight:c?1:.5})}}let u=n?.workspacePackages,f=new Set;for(let n of A){let r=new RegExp(n.source,n.flags),i;for(;(i=r.exec(e))!==null;){let e=i[1];if(f.has(e))continue;let n;if(e.startsWith(`.`))n=N(e,t);else if(u){let t=e.startsWith(`@`)?e.split(`/`).slice(0,2).join(`/`):e.split(`/`)[0],r=u.get(t);if(!r)continue;n=r}else continue;f.add(e);let r=P(n),o=j(`module`,r,r);a.push({id:M(l,o,`imports`),fromId:l,toId:o,type:`imports`,properties:{source:e}})}}return{nodes:i,edges:a}}const I=_(`hash-cache`);var L=class{cache;filePath;dirty=!1;constructor(e){this.filePath=m(e,`file-hashes.json`),this.cache=new Map}load(){if(t(this.filePath))try{let e=n(this.filePath,`utf-8`),t=JSON.parse(e);this.cache=new Map(Object.entries(t)),I.info(`Hash cache loaded`,{entries:this.cache.size})}catch(e){I.warn(`Hash cache load failed, starting fresh`,{err:e}),this.cache=new Map}}get(e){return this.cache.get(e)}set(e,t){this.cache.set(e,t),this.dirty=!0}delete(e){this.cache.delete(e)&&(this.dirty=!0)}flush(){if(this.dirty)try{let e={};for(let[t,n]of this.cache)e[t]=n;a(this.filePath,JSON.stringify(e),`utf-8`),this.dirty=!1}catch(e){I.warn(`Hash cache flush failed`,{err:e})}}clear(){this.cache.clear(),this.dirty=!0,this.flush()}get size(){return this.cache.size}};const R=_(`indexer`),z=()=>new Promise(e=>setImmediate(e));async function B(e,t,n,r){let i=0;async function a(){for(;i<e.length;){let n=i++;try{await t(e[n])}catch(t){r?.(e[n],t)}n%10==0&&await z()}}await Promise.all(Array.from({length:Math.min(n,e.length)},()=>a()))}function V(e){let t=x(),n=S()[0]/t;return n>1.5?2:n>1?Math.max(2,Math.floor(e/2)):e}const H=Math.max(2,Math.min(4,Math.floor(x()*.5)));var U=class{crawler;indexing=!1;graphStore;hashCache;get isIndexing(){return this.indexing}constructor(e,t){this.embedder=e,this.store=t,this.crawler=new D}normalizeChunkText(e){return e.replace(/^\/\/ File: [^\n]*\n?/,``).toLowerCase().replace(/\s+/g,` `).trim()}setGraphStore(e){this.graphStore=e}setHashCache(e){this.hashCache=e}async index(e,t){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{return await this.doIndex(e,t,{})}finally{this.indexing=!1}}async getChangedFiles(e){let t=e.indexing.concurrency??H,n=await this.crawlSources(e),{filesToProcess:r}=await this.planIndexWork(n,t,{});return r.map(e=>e.relativePath)}async indexFiles(e,t,n){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{return await this.doIndexFiles(e,t,n)}finally{this.indexing=!1}}async doIndex(e,t,n={}){let r=Date.now(),i=e.indexing.concurrency??H;t?.({phase:`crawling`,filesTotal:0,filesProcessed:0,chunksTotal:0,chunksProcessed:0});let a=await this.crawlSources(e),{filesToProcess:o,filesSkipped:s,pathsToRemove:c}=await this.planIndexWork(a,i,{skipHashCheck:n.skipHashCheck}),{filesProcessed:l,chunksCreated:u,chunksDeduped:d}=await this.processFiles(a,o,i,t,{graphCleared:n.graphCleared}),f=await this.cleanupRemovedFiles(c,i,o.length,l,u,t);return this.hashCache?.flush(),t?.({phase:`done`,filesTotal:o.length,filesProcessed:l,chunksTotal:u,chunksProcessed:u}),{filesProcessed:l,filesSkipped:s,chunksCreated:u,chunksDeduped:d,filesRemoved:f,durationMs:Date.now()-r}}async doIndexFiles(e,t,n){let r=Date.now(),i=e.indexing.concurrency??H,a=new Set(t);if(a.size===0)return{filesProcessed:0,filesSkipped:0,chunksCreated:0,chunksDeduped:0,filesRemoved:0,durationMs:Date.now()-r};n?.({phase:`crawling`,filesTotal:0,filesProcessed:0,chunksTotal:0,chunksProcessed:0});let o=await this.crawlSources(e),{filesToProcess:s,filesSkipped:c}=await this.planIndexWork(o,i,{requestedPaths:a}),{filesProcessed:l,chunksCreated:u,chunksDeduped:d}=await this.processFiles(o,s,i,n,{});return this.hashCache?.flush(),n?.({phase:`done`,filesTotal:s.length,filesProcessed:l,chunksTotal:u,chunksProcessed:u}),{filesProcessed:l,filesSkipped:c,chunksCreated:u,chunksDeduped:d,filesRemoved:0,durationMs:Date.now()-r}}async crawlSources(e){return(await Promise.all(e.sources.map(e=>this.crawler.crawl({rootDir:e.path,excludePatterns:e.excludePatterns})))).flat()}async planIndexWork(e,t,n){let r=n.requestedPaths,i=r?e.filter(e=>r.has(e.relativePath)):e;if(n.skipHashCheck)return{filesToProcess:i,filesSkipped:0,pathsToRemove:[]};let a=r?[]:await this.getPathsToRemove(e),o=0,s=[];return await B(i,async e=>{let t=w(e.content);if(this.hashCache){if(this.hashCache.get(e.relativePath)===t){o++;return}}else{let n=await this.store.getBySourcePath(e.relativePath);if(n.length>0&&n[0].fileHash===t){o++;return}}s.push(e)},V(t),(e,t)=>R.error(`Hash check failed`,{sourcePath:e.relativePath,...y(t)})),{filesToProcess:s,filesSkipped:o,pathsToRemove:a}}async getPathsToRemove(e){let t=await this.store.listSourcePaths(),n=new Set(e.map(e=>e.relativePath));return t.filter(e=>!n.has(e)&&!e.startsWith(`${h.aiCurated}/`))}async buildWorkspacePackageMap(e){let t=new Map;for(let n of e)if(n.relativePath.endsWith(`package.json`))try{let e=JSON.parse(n.content);if(typeof e.name!=`string`||e.name.length===0)continue;let r=n.relativePath===`package.json`?``:n.relativePath.replace(/\/package\.json$/,``),i=``;if(typeof e.exports==`string`)i=e.exports;else if(e.exports&&typeof e.exports==`object`){let t=e.exports,n=t[`.`]??t;if(typeof n==`string`)i=n;else if(n&&typeof n==`object`){let e=n,t=e.import??e.module??e.default??e.require;typeof t==`string`&&(i=t)}}!i&&typeof e.module==`string`&&(i=e.module),!i&&typeof e.main==`string`&&(i=e.main);let a=i.replace(/^\.\//,``).replace(/^dist\//,`src/`).replace(/\.(ts|js|mjs|cjs|tsx|jsx)$/,``),o=a?r?`${r}/${a}`:a:r?`${r}/src/index`:`src/index`;t.set(e.name,o)}catch{}return t}async processFiles(t,n,r,i,a={}){let o=0,s=0,c=0,l=n.length,u=this.graphStore?await this.buildWorkspacePackageMap(t):void 0,d=new Map,f=[],p=[],m=0,h=[],g=[],_=new Map,b=0,x=async()=>{if(h.length===0)return;let e=h,t=g,n=_;h=[],g=[],_=new Map,b=0,await this.store.upsert(e,t);for(let[e,t]of n)this.hashCache?.set(e,t)},S=async()=>{if(this.graphStore){try{f.length>0&&await this.graphStore.upsertNodes(f),p.length>0&&await this.graphStore.upsertEdges(p)}catch(e){R.warn(`Graph batch flush failed`,y(e))}f=[],p=[],m=0}};return await B(n,async t=>{i?.({phase:`chunking`,filesTotal:l,filesProcessed:o,chunksTotal:s,chunksProcessed:s,currentFile:t.relativePath});let n=v(t.relativePath),r=C(t.extension).chunk(t.content,{sourcePath:t.relativePath,contentType:n});if(r.length===0)return;let E=w(t.content),D=new Date().toISOString(),O=(e,n,r)=>({id:T(t.relativePath,n),content:e.text,sourcePath:e.sourcePath,contentType:e.contentType,headingPath:e.headingPath,chunkIndex:e.chunkIndex,totalChunks:e.totalChunks,startLine:e.startLine,endLine:e.endLine,fileHash:E,contentHash:r,indexedAt:D,origin:`indexed`,tags:[],version:1}),k=[],A=[];for(let t=0;t<r.length;t++){let n=r[t],i=e(`sha256`).update(this.normalizeChunkText(n.text)).digest(`hex`),a=O(n,t,i),o=d.get(i);if(o&&this.store.upsertWithoutVector){A.push({record:a,sourceRecordId:o}),c++;continue}d.set(i,a.id),k.push({chunk:n,record:a})}i?.({phase:`embedding`,filesTotal:l,filesProcessed:o,chunksTotal:s+r.length,chunksProcessed:s,currentFile:t.relativePath});let j=k.length>0?await this.embedder.embedBatch(k.map(({chunk:e})=>e.text)):[],M=k.map(({record:e})=>e);if(i?.({phase:`storing`,filesTotal:l,filesProcessed:o,chunksTotal:s+r.length,chunksProcessed:s,currentFile:t.relativePath}),M.length>0&&(h.push(...M),g.push(...j),_.set(t.relativePath,E),b++,b>=20&&await x()),A.length>0&&h.length>0&&await x(),this.store.upsertWithoutVector)for(let{record:e,sourceRecordId:t}of A)await this.store.upsertWithoutVector(e,t);if(M.length===0&&A.length>0&&this.hashCache?.set(t.relativePath,E),this.graphStore)try{a.graphCleared||await this.graphStore.deleteBySourcePath(t.relativePath);let e=F(t.content,t.relativePath,{workspacePackages:u});e.nodes.length>0&&f.push(...e.nodes),e.edges.length>0&&p.push(...e.edges),m++,m>=50&&await S()}catch(e){R.warn(`Graph extraction failed`,{sourcePath:t.relativePath,...y(e)})}o++,s+=r.length},V(r),(e,t)=>R.error(`Processing failed`,{sourcePath:e.relativePath,...y(t)})),await x(),await S(),{filesProcessed:o,chunksCreated:s,chunksDeduped:c}}async cleanupRemovedFiles(e,t,n,r,i,a){if(e.length===0)return 0;let o=0;return a?.({phase:`cleanup`,filesTotal:n,filesProcessed:r,chunksTotal:i,chunksProcessed:i}),await B(e,async e=>{await this.store.deleteBySourcePath(e),this.hashCache?.delete(e),this.graphStore&&await this.graphStore.deleteBySourcePath(e).catch(t=>R.warn(`Graph cleanup failed`,{sourcePath:e,...y(t)})),o++},V(t),(e,t)=>R.error(`Cleanup failed`,{sourcePath:e,...y(t)})),o}async reindexAll(e,t){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{if(await this.store.dropTable(),this.graphStore)try{let e=await this.graphStore.getStats();e.nodeCount>0&&(await this.graphStore.clear(),R.info(`Graph store cleared`,{nodeCount:e.nodeCount,edgeCount:e.edgeCount}))}catch(e){R.warn(`Graph store clear failed`,y(e))}return await this.doReindex(e,t)}catch(e){throw this.indexing=!1,e}}async doReindex(e,t){try{return await this.doIndex(e,t,{skipHashCheck:!0,graphCleared:!0})}finally{this.indexing=!1}}async getStats(){return this.store.getStats()}};const W=_(`smart-index`),G=1.5;var K=class{trickleTimer=null;stopped=!1;trickleIntervalMs;batchSize;priorityQueue=[];changedFiles=[];lastRefreshTime=0;refreshing=!1;constructor(e,t,n){this.indexer=e,this.config=t,this.store=n,this.trickleIntervalMs=t.indexing.trickleIntervalMs??this.readPositiveIntEnv(`AIKIT_SMART_TRICKLE_MS`,3e4),this.batchSize=t.indexing.trickleBatchSize??this.readPositiveIntEnv(`AIKIT_SMART_BATCH_SIZE`,1)}start(){this.trickleTimer&&=(clearTimeout(this.trickleTimer),null),this.stopped=!1,W.info(`Smart index scheduler started (trickle mode)`,{intervalMs:this.trickleIntervalMs,batchSize:this.batchSize}),this.scheduleTick()}stop(){this.stopped=!0,this.trickleTimer&&=(clearTimeout(this.trickleTimer),null)}prioritize(...e){let t=[...new Set(e.filter(Boolean))].filter(e=>{try{return!i(e).isDirectory()}catch{return W.debug(`Skipping non-existent path`,{path:e}),!1}});for(let e of t){let t=this.priorityQueue.indexOf(e);t>=0&&this.priorityQueue.splice(t,1)}for(let e of t.reverse())this.priorityQueue.unshift(e);this.priorityQueue.length>500&&(this.priorityQueue.length=500),t.length>0&&W.info(`Files prioritized for trickle indexing`,{added:t.length,queued:this.priorityQueue.length})}getState(){return{mode:`smart`,queueSize:this.priorityQueue.length,changedFilesSize:this.changedFiles.length,intervalMs:this.trickleIntervalMs,batchSize:this.batchSize,running:this.trickleTimer!==null}}readPositiveIntEnv(e,t){let n=Number(process.env[e]);return Number.isFinite(n)&&n>0?n:t}scheduleTick(){this.trickleTimer=setTimeout(()=>void this.tick(),this.trickleIntervalMs),this.trickleTimer.unref&&this.trickleTimer.unref()}async tick(){if(!this.stopped)try{if(this.indexer.isIndexing){W.info(`Skipping trickle tick — indexing already in progress`);return}let e=this.getCpuCount(),t=S()[0];if(e>0&&t/e>G){W.info(`Skipping trickle tick — system load too high`,{load:t.toFixed(2),cpuCount:e,threshold:G});return}let n=await this.pickFiles();if(n.length===0){await this.maybeRefreshChangedFiles();return}W.info(`Trickle indexing tick started`,{count:n.length,files:n});let r=await this.indexer.indexFiles(this.config,n);if(this.store)try{await this.store.createFtsIndex()}catch(e){W.warn(`FTS index rebuild failed after trickle tick`,{error:String(e)})}this.changedFiles=this.changedFiles.filter(e=>!n.includes(e)),W.info(`Trickle indexing tick complete`,{filesProcessed:r.filesProcessed,filesSkipped:r.filesSkipped,chunksCreated:r.chunksCreated})}catch(e){let t=String(e);if(t.includes(`not initialized`)||t.includes(`has been closed`)){W.warn(`Store closed — stopping smart index scheduler`,{error:t}),this.stop();return}W.error(`Trickle indexing tick failed`,{error:t})}finally{this.stopped||this.scheduleTick()}}getCpuCount(){try{return typeof x==`function`?x():4}catch{return 4}}async pickFiles(){let e=[];for(;e.length<this.batchSize&&this.priorityQueue.length>0;){let t=this.priorityQueue.shift();t&&!e.includes(t)&&e.push(t)}if(e.length<this.batchSize)for(await this.maybeRefreshChangedFiles();e.length<this.batchSize&&this.changedFiles.length>0;){let t=this.changedFiles.shift();t&&!e.includes(t)&&e.push(t)}return e}async maybeRefreshChangedFiles(){let e=Date.now();if(!(this.refreshing||this.changedFiles.length>0&&e-this.lastRefreshTime<6e5)){this.refreshing=!0;try{this.changedFiles=await this.indexer.getChangedFiles(this.config),this.lastRefreshTime=e,this.changedFiles.length>0&&W.info(`Refreshed changed files for trickle indexing`,{count:this.changedFiles.length})}catch(e){let t=String(e);if(t.includes(`not initialized`)||t.includes(`has been closed`)){W.warn(`Store closed — stopping smart index scheduler`,{error:t}),this.stop();return}W.error(`Failed to refresh changed files for trickle indexing`,{error:t})}finally{this.refreshing=!1}}}};export{L as FileHashCache,D as FilesystemCrawler,U as IncrementalIndexer,K as SmartIndexScheduler,F as extractGraph,T as generateRecordId,w as hashContent};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./curated-manager-CXSPygmJ.js";import{readFileSync as t}from"node:fs";import{dirname as n,resolve as r}from"node:path";import{fileURLToPath as i,pathToFileURL as a}from"node:url";import{parseArgs as o}from"node:util";import{createLogger as s,serializeError as c}from"../../core/dist/index.js";const l=n(i(import.meta.url)),u=(()=>{try{let e=r(l,`..`,`..`,`..`,`package.json`);return JSON.parse(t(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}})(),d=s(`server`);function f(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}const{values:p}=(()=>{let e=process.argv[1];if(!e)return!1;try{return import.meta.url===a(e).href}catch{return!1}})()?o({allowPositionals:!0,options:{transport:{type:`string`,default:f()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}):{values:{transport:f(),port:process.env.AIKIT_PORT??`3210`}};async function m(){if(process.on(`unhandledRejection`,e=>{d.error(`Unhandled rejection`,c(e))}),d.info(`Starting MCP AI Kit server`,{version:u}),p.transport===`http`){let[{default:e},{loadConfig:t,resolveIndexMode:n},{registerDashboardRoutes:r,resolveDashboardDir:i},{registerSettingsRoutes:a,resolveSettingsDir:o},{createSettingsRouter:s}]=await Promise.all([import(`express`),import(`./config-BL-I_FFY.js`),import(`./dashboard-static-BfIe0Si1.js`),import(`./settings-static-BosGZSPf.js`),import(`./routes-OaSHcA6x.js`)]),l=t();d.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path});let u=e();u.use(e.json());let f=Number(p.port);u.use((e,t,n)=>{if(t.setHeader(`Access-Control-Allow-Origin`,process.env.AIKIT_CORS_ORIGIN??`http://localhost:${f}`),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization`),e.method===`OPTIONS`){t.status(204).end();return}n()}),r(u,i(),d);let m=new Date().toISOString();u.use(`/settings/api`,s({log:d,mcpInfo:()=>({transport:`http`,port:f,pid:process.pid,startedAt:m})})),a(u,o(),d),u.get(`/health`,(e,t)=>{t.json({status:`ok`})});let h=!1,g=null,_=null,v=null,y=Promise.resolve();u.post(`/mcp`,async(e,t)=>{if(!h||!_||!v){t.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let n=y,r;y=new Promise(e=>{r=e}),await n;try{let n=new v({sessionIdGenerator:void 0});await _.connect(n),await n.handleRequest(e,t,e.body),n.close()}catch(e){if(d.error(`MCP handler error`,c(e)),!t.headersSent){let n=e instanceof Error?e.message:String(e),r=n.includes(`Not Acceptable`);t.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?n:`Internal server error`},id:null})}}finally{r()}}),u.get(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))}),u.delete(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))});let b=u.listen(f,`127.0.0.1`,()=>{d.info(`MCP server listening`,{url:`http://127.0.0.1:${f}/mcp`,port:f}),setTimeout(async()=>{try{let[{createLazyServer:e,ALL_TOOL_NAMES:t},{StreamableHTTPServerTransport:r},{checkForUpdates:i,autoUpgradeScaffold:a}]=await Promise.all([import(`./server-
|
|
1
|
+
import{t as e}from"./curated-manager-CXSPygmJ.js";import{readFileSync as t}from"node:fs";import{dirname as n,resolve as r}from"node:path";import{fileURLToPath as i,pathToFileURL as a}from"node:url";import{parseArgs as o}from"node:util";import{createLogger as s,serializeError as c}from"../../core/dist/index.js";const l=n(i(import.meta.url)),u=(()=>{try{let e=r(l,`..`,`..`,`..`,`package.json`);return JSON.parse(t(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}})(),d=s(`server`);function f(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}const{values:p}=(()=>{let e=process.argv[1];if(!e)return!1;try{return import.meta.url===a(e).href}catch{return!1}})()?o({allowPositionals:!0,options:{transport:{type:`string`,default:f()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}):{values:{transport:f(),port:process.env.AIKIT_PORT??`3210`}};async function m(){if(process.on(`unhandledRejection`,e=>{d.error(`Unhandled rejection`,c(e))}),d.info(`Starting MCP AI Kit server`,{version:u}),p.transport===`http`){let[{default:e},{loadConfig:t,resolveIndexMode:n},{registerDashboardRoutes:r,resolveDashboardDir:i},{registerSettingsRoutes:a,resolveSettingsDir:o},{createSettingsRouter:s}]=await Promise.all([import(`express`),import(`./config-BL-I_FFY.js`),import(`./dashboard-static-BfIe0Si1.js`),import(`./settings-static-BosGZSPf.js`),import(`./routes-OaSHcA6x.js`)]),l=t();d.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path});let u=e();u.use(e.json());let f=Number(p.port);u.use((e,t,n)=>{if(t.setHeader(`Access-Control-Allow-Origin`,process.env.AIKIT_CORS_ORIGIN??`http://localhost:${f}`),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization`),e.method===`OPTIONS`){t.status(204).end();return}n()}),r(u,i(),d);let m=new Date().toISOString();u.use(`/settings/api`,s({log:d,mcpInfo:()=>({transport:`http`,port:f,pid:process.pid,startedAt:m})})),a(u,o(),d),u.get(`/health`,(e,t)=>{t.json({status:`ok`})});let h=!1,g=null,_=null,v=null,y=Promise.resolve();u.post(`/mcp`,async(e,t)=>{if(!h||!_||!v){t.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let n=y,r;y=new Promise(e=>{r=e}),await n;try{let n=new v({sessionIdGenerator:void 0});await _.connect(n),await n.handleRequest(e,t,e.body),n.close()}catch(e){if(d.error(`MCP handler error`,c(e)),!t.headersSent){let n=e instanceof Error?e.message:String(e),r=n.includes(`Not Acceptable`);t.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?n:`Internal server error`},id:null})}}finally{r()}}),u.get(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))}),u.delete(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))});let b=u.listen(f,`127.0.0.1`,()=>{d.info(`MCP server listening`,{url:`http://127.0.0.1:${f}/mcp`,port:f}),setTimeout(async()=>{try{let[{createLazyServer:e,ALL_TOOL_NAMES:t},{StreamableHTTPServerTransport:r},{checkForUpdates:i,autoUpgradeScaffold:a}]=await Promise.all([import(`./server-qD-mw6RP.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-Bj07vc5x.js`)]);i(),a();let o=n(l),s=e(l,o);_=s.server,v=r,h=!0,d.info(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:t.length,resourceCount:2}),s.startInit(),o===`auto`?s.ready.then(async()=>{try{let e=l.sources.map(e=>e.path).join(`, `);d.info(`Running initial index`,{sourcePaths:e}),await s.runInitialIndex(),d.info(`Initial index complete`)}catch(e){d.error(`Initial index failed; will retry on aikit_reindex`,c(e))}}).catch(e=>d.error(`AI Kit init or indexing failed`,c(e))):o===`smart`?s.ready.then(async()=>{try{if(!s.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(s.aikit.indexer,l,s.aikit.store),n=s.aikit.store;g=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),s.setSmartScheduler(t),d.info(`Smart index scheduler started (HTTP mode)`)}catch(e){d.error(`Failed to start smart index scheduler`,c(e))}}).catch(e=>d.error(`AI Kit initialization failed`,c(e))):(s.ready.catch(e=>d.error(`AI Kit initialization failed`,c(e))),d.info(`Initial full indexing skipped in HTTP mode`,{indexMode:o}))}catch(e){d.error(`Failed to load server modules`,c(e))}},100)}),x=async e=>{d.info(`Shutdown signal received`,{signal:e}),g?.stop(),b.close(),_&&await _.close(),process.exit(0)};process.on(`SIGINT`,()=>x(`SIGINT`)),process.on(`SIGTERM`,()=>x(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:n},{createLazyServer:r},{checkForUpdates:a,autoUpgradeScaffold:o},{RootsListChangedNotificationSchema:s}]=await Promise.all([import(`./config-BL-I_FFY.js`),import(`./server-qD-mw6RP.js`),import(`./version-check-Bj07vc5x.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=e();d.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),a(),o();let u=n(l),f=r(l,u),{server:p,startInit:m,ready:h,runInitialIndex:g}=f,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await p.connect(v),d.info(`MCP server started`,{transport:`stdio`});let y=e=>{if(e.length===0)return!1;let n=e[0].uri,r=n.startsWith(`file://`)?i(n):n;return d.info(`MCP roots resolved`,{rootUri:n,rootPath:r,rootCount:e.length}),t(l,r),l.allRoots=e.map(e=>{let t=e.uri;return t.startsWith(`file://`)?i(t):t}),!0},b=!1;try{b=y((await p.server.listRoots()).roots),b||d.info(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(e){d.warn(`MCP roots/list not supported by client; using cwd fallback`,{cwd:process.cwd(),...c(e)}),b=!0}b||=await new Promise(e=>{let t=setTimeout(()=>{d.warn(`Timed out waiting for MCP roots/list_changed; using cwd fallback`,{cwd:process.cwd()}),e(!1)},5e3);p.server.setNotificationHandler(s,async()=>{clearTimeout(t);try{e(y((await p.server.listRoots()).roots))}catch(t){d.warn(`roots/list retry failed after notification`,c(t)),e(!1)}})}),m();let x=null,S=()=>{x&&clearTimeout(x),x=setTimeout(()=>{d.info(`Auto-shutdown: no activity for 30 minutes — exiting`),process.exit(0)},18e5),x.unref&&x.unref()};S(),process.stdin.on(`data`,()=>S()),h.catch(e=>{d.error(`Initialization failed — server will continue with limited tools`,c(e))}),u===`auto`?g().catch(e=>d.error(`Initial index failed`,c(e))):u===`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),d.info(`Smart index scheduler started (stdio mode)`)}catch(e){d.error(`Failed to start smart index scheduler`,c(e))}}).catch(e=>d.error(`AI Kit init failed for smart scheduler`,c(e))):d.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:u})}}m().catch(e=>{d.error(`Fatal error`,c(e)),process.exit(1)});export{e as CuratedKnowledgeManager};
|
|
@@ -1274,4 +1274,4 @@ Data matches the schema.`}]};let r=[`## Validation: FAILED`,``,`**${n.errors.len
|
|
|
1274
1274
|
│ To enable: install/rebuild better-sqlite3 (native module). │
|
|
1275
1275
|
└──────────────────────────────────────────────────────────────────┘`);let t=g(i,`lance`);a(t)&&Z.info(`Old LanceDB data found at ${t} — ignored. Safe to delete after verifying sqlite-vec works.`)}let[s,c,l,u]=await Promise.all([(async()=>{let e=new Dn({model:n.embedding.model,dimensions:n.embedding.dimensions});return await e.initialize(),Z.info(`Embedder loaded`,{modelId:e.modelId,dimensions:e.dimensions}),e})(),(async()=>{let e=await bn({backend:r,path:i,adapter:o??void 0,embeddingDim:n.embedding.dimensions});return await e.initialize(),Z.info(`Store initialized`,{backend:r}),e})(),(async()=>{let e=o?new vn({adapter:o}):new vn({path:i});return await e.initialize(),Z.info(`Graph store initialized`,{shared:!!o}),e})(),(async()=>{let e=await cn();return e?Z.info(`WASM tree-sitter enabled for AST analysis`):Z.warn(`WASM tree-sitter not available; analyzers will use regex fallback`),e})()]),f=new kn(s,c),p=new On(n.store.path);p.load(),f.setHashCache(p);let m=n.curated.path,h=new e(m);await h.initialize();let v=new t(m,c,s,h);f.setGraphStore(l);let b=Ea(n.er),x=b?new fn(n.curated.path):void 0;x&&Z.info(`Policy store initialized`,{ruleCount:x.getRules().length});let S=b?new dn:void 0,C=_(n.sources[0]?.path??process.cwd(),y.aiContext),w=a(C),T=n.onboardDir?a(n.onboardDir):!1,E=w||T,D,O=w?C:n.onboardDir;if(E&&O)try{D=d(O).mtime.toISOString()}catch{}return Z.info(`Onboard state detected`,{onboardComplete:E,onboardTimestamp:D,aiKbExists:w,onboardDirExists:T}),{embedder:s,store:c,indexer:f,curated:v,graphStore:l,fileCache:new N,bridge:b,policyStore:x,evolutionCollector:S,onboardComplete:E,onboardTimestamp:D}}function Xu(e,t,n){if(e.serverInstructions)return e.serverInstructions;let r=new Set;for(let e of t){let t=n[e];if(t?.category)for(let e of t.category)r.add(e)}let i=[`This server provides ${t.size} tools across ${r.size} categories: ${[...r].sort().join(`, `)}.`];return e.readOnly&&i.push(`Server is in read-only mode. Mutating operations are disabled.`),e.features?.length&&i.push(`Active feature groups: ${e.features.join(`, `)}.`),i.join(` `)}const Zu=D(`background-task`);var Qu=class{queue=[];running=null;get isRunning(){return this.running!==null}get currentTask(){return this.running}get pendingCount(){return this.queue.length}schedule(e){return new Promise((t,n)=>{this.queue.push({...e,resolve:t,reject:n}),this.running||this.processQueue()})}async processQueue(){for(;this.queue.length>0;){let e=this.queue.shift();if(!e)break;this.running=e.name,Zu.info(`Background task started`,{task:e.name,pending:this.queue.length});let t=Date.now();try{await e.fn();let n=Date.now()-t;Zu.info(`Background task completed`,{task:e.name,durationMs:n}),e.resolve()}catch(n){let r=Date.now()-t;Zu.error(`Background task failed`,{task:e.name,durationMs:r,err:n}),e.reject(n instanceof Error?n:Error(String(n)))}}this.running=null}};const $u=D(`idle-timer`);var ed=class{timer=null;cleanupFns=[];idleMs;disposed=!1;_busy=!1;constructor(e){this.idleMs=e?.idleMs??3e5}setBusy(e){this._busy=e,e?this.cancel():this.touch()}onIdle(e){this.cleanupFns.push(e)}touch(){this.disposed||this._busy||(this.cancel(),this.timer=setTimeout(()=>{this.runCleanup()},this.idleMs),this.timer.unref&&this.timer.unref())}cancel(){this.timer&&=(clearTimeout(this.timer),null)}dispose(){this.cancel(),this.cleanupFns.length=0,this.disposed=!0}async runCleanup(){if(this._busy){$u.info(`Skipping idle cleanup — background work in progress`);return}$u.info(`Idle for ${this.idleMs/1e3}s — running cleanup`);let e=await Promise.allSettled(this.cleanupFns.map(e=>e()));for(let t of e)t.status===`rejected`&&$u.warn(`Idle cleanup callback failed`,{error:String(t.reason)})}};const td=D(`memory-monitor`);var nd=class{timer=null;warningBytes;criticalBytes;intervalMs;pressureFns=[];lastLevel=`normal`;constructor(e){this.warningBytes=e?.warningBytes??4294967296,this.criticalBytes=e?.criticalBytes??8589934592,this.intervalMs=e?.intervalMs??6e4}onPressure(e){this.pressureFns.push(e)}start(){this.timer||(this.timer=setInterval(()=>this.check(),this.intervalMs),this.timer.unref&&this.timer.unref(),td.info(`Memory monitor started`,{warningMB:Math.round(this.warningBytes/1024/1024),criticalMB:Math.round(this.criticalBytes/1024/1024),intervalSec:Math.round(this.intervalMs/1e3)}))}stop(){this.timer&&=(clearInterval(this.timer),null)}getRssBytes(){return process.memoryUsage.rss()}check(){let e=this.getRssBytes(),t=`normal`;if(e>=this.criticalBytes?t=`critical`:e>=this.warningBytes&&(t=`warning`),t!==this.lastLevel||t===`critical`){let n=Math.round(e/1024/1024);t===`critical`?td.warn(`Memory CRITICAL: ${n}MB RSS — consider restarting the server`):t===`warning`?td.warn(`Memory WARNING: ${n}MB RSS`):this.lastLevel!==`normal`&&td.info(`Memory returned to normal: ${n}MB RSS`),this.lastLevel=t}if(t!==`normal`)for(let n of this.pressureFns)try{n(t,e)}catch{}return t===`critical`&&typeof globalThis.gc==`function`&&globalThis.gc(),t}};const rd=D(`tool-timeout`),id=new Set([`onboard`,`reindex`,`produce_knowledge`,`analyze`,`codemod`,`audit`]);var ad=class extends Error{constructor(e,t){super(`Tool "${e}" timed out after ${t}ms`),this.toolName=e,this.timeoutMs=t,this.name=`ToolTimeoutError`}};function od(e){return id.has(e)?6e5:12e4}function sd(e,t,n){return new Promise((r,i)=>{let a=!1,o=setTimeout(()=>{if(!a){a=!0;let e=new ad(n,t);rd.warn(e.message),i(e)}},t);o.unref&&o.unref(),e().then(e=>{a||(a=!0,clearTimeout(o),r(e))},e=>{a||(a=!0,clearTimeout(o),i(e))})})}const Q=D(`server`);function cd(e){let t=e.toLowerCase();return[`protobuf`,`invalid model`,`invalid onnx`,`unexpected end`,`unexpected token`,`failed to load`,`failed to initialize embedding`,`checksum`,`corrupt`,`malformed`,`could not load`,`onnx`,`database disk image is malformed`,`file is not a database`,`lance`].some(e=>t.includes(e))}async function ld(e,t){let n=t.toLowerCase(),r;try{({rm:r}=await import(`node:fs/promises`))}catch{return}if(n.includes(`embedding`)||n.includes(`onnx`)||n.includes(`protobuf`)||n.includes(`model`)){let t=e.embedding?.model??x.model,n=g(Cn(),`.cache`,`huggingface`,`transformers-js`,t);try{await r(n,{recursive:!0,force:!0}),Q.info(`Auto-heal: cleared embedding model cache`,{path:n})}catch{}}if(n.includes(`lance`)||n.includes(`database`)||n.includes(`store`)){let t=g(e.store.path,`lance`);try{await r(t,{recursive:!0,force:!0}),Q.info(`Auto-heal: cleared LanceDB store`,{path:t})}catch{}}if(n.includes(`sqlite`)||n.includes(`database disk image`)||n.includes(`graph`)){let t=g(e.store.path,`graph.db`);try{await r(t,{force:!0}),Q.info(`Auto-heal: cleared graph database`,{path:t})}catch{}}}function ud(e,t){let n=di(e,R,z,Hr(e)),i=Xu(e,n,z),a=new qt({name:e.serverName??`aikit`,version:r()},{capabilities:{logging:{},completions:{},prompts:{}},instructions:i}),o=`initializing`,s=``,c=!1,l=null,u=null,d=null;function f(e){if(!e||typeof e!=`object`)return[];let t=e,n=[];for(let e of[`path`,`file`,`source_path`,`sourcePath`,`filePath`]){let r=t[e];typeof r==`string`&&r&&n.push(r)}for(let e of[`changed_files`,`paths`,`files`]){let r=t[e];if(Array.isArray(r))for(let e of r){if(typeof e==`string`){n.push(e);continue}e&&typeof e==`object`&&typeof e.path==`string`&&n.push(e.path)}}if(Array.isArray(t.sources))for(let e of t.sources)e&&typeof e==`object`&&typeof e.path==`string`&&n.push(e.path);return n}let p=()=>o===`failed`?[`❌ AI Kit initialization failed — this tool is unavailable.`,``,s?`Error: ${s}`:``,``,`**${Gr.size} tools are still available** and fully functional:`,`check, eval, test_run, git_context, health, measure, web_fetch, web_search,`,`flow, regex_test, encode,`,`stash, checkpoint, lane, process, time, env, and more.`,``,`To fix embedding errors, try deleting the cached model:`,` rm -rf ~/.cache/huggingface/transformers-js/mixedbread-ai/`,`Then restart the server to re-download a fresh copy.`,``,`Try restarting the MCP server to retry initialization.`].filter(Boolean).join(`
|
|
1276
1276
|
`):[`AI Kit is still initializing (loading embeddings model & store).`,``,`**${Gr.size} tools are already available** while initialization completes — including:`,`check, eval, test_run, git_context, health, measure, web_fetch, web_search,`,`flow, regex_test, encode,`,`stash, checkpoint, lane, process, time, env, and more.`,``,`This tool requires the AI Kit index. Please retry in a few seconds,`,`or use one of the available tools above in the meantime.`].join(`
|
|
1277
|
-
`);Mn(a),Zr(a,new br,e.toolPrefix??``);let m=a.sendToolListChanged.bind(a);a.sendToolListChanged=()=>{};let h=[];for(let e of R){if(!n.has(e))continue;let t=B(e),r=a.registerTool(e,{title:t.title,description:`${t.title} — initializing, available shortly`,inputSchema:{},annotations:t.annotations},async()=>({content:[{type:`text`,text:p()}]}));Gr.has(e)?r.remove():h.push(r)}Ku(a,e,n),a.sendToolListChanged=m;let g=a.registerResource(`aikit-status`,`aikit://status`,{description:`AI Kit status (initializing...)`,mimeType:`text/plain`},async()=>({contents:[{uri:`aikit://status`,text:`AI Kit is initializing...`,mimeType:`text/plain`}]})),_=a.registerPrompt(`_init`,{description:`Initializing AI Kit…`,argsSchema:{_dummy:F(I.string(),()=>[])}},async()=>({messages:[]})),v,y,b=new Promise((e,t)=>{v=e,y=t}),x,S=new Promise(e=>{x=e}),C=()=>x?.(),w=(async()=>{await S;let n;try{n=await Yu(e)}catch(t){let r=t instanceof Error?t.message:String(t);if(cd(r)){Q.warn(`AI Kit initialization failed with recoverable error — attempting auto-heal retry`,{error:r}),await ld(e,r);try{n=await Yu(e),Q.info(`AI Kit auto-heal successful — initialization recovered after retry`)}catch(e){o=`failed`,s=e instanceof Error?e.message:String(e),Q.error(`AI Kit initialization failed after auto-heal attempt — server continuing with zero-dep tools only`,{error:s,originalError:r}),y?.(e instanceof Error?e:Error(s));return}}else{o=`failed`,s=r,Q.error(`AI Kit initialization failed — server continuing with zero-dep tools only`,{error:s}),y?.(t instanceof Error?t:Error(s));return}}let r=a.sendToolListChanged.bind(a);a.sendToolListChanged=()=>{};let i=a.sendPromptListChanged.bind(a);a.sendPromptListChanged=()=>{};let p=a.sendResourceListChanged.bind(a);a.sendResourceListChanged=()=>{};for(let e of h)e.remove();g.remove(),_.remove();let m=a._registeredTools??{};for(let e of Gr)m[e]?.remove();let b=new Ju(a),x=Po(a);Gu(a,n,e,An(a),b,x,t,t===`smart`?(()=>{let e=d;return e?.getState?e.getState():null}):null),Un(a,{curated:n.curated,store:n.store,graphStore:n.graphStore},t),a.sendToolListChanged=r,a.sendPromptListChanged=i,a.sendResourceListChanged=p,Promise.resolve(a.sendToolListChanged()).catch(()=>{}),Promise.resolve(a.sendPromptListChanged()).catch(()=>{}),Promise.resolve(a.sendResourceListChanged()).catch(()=>{});let C=a._registeredTools??{};for(let[e,t]of Object.entries(C)){if(Ur.has(e))continue;let r=t.handler;t.handler=async(...t)=>{if(!n.indexer.isIndexing)return r(...t);let i=c?`re-indexing`:`running initial index`,a=new Promise(t=>setTimeout(()=>t({content:[{type:`text`,text:`⏳ AI Kit is ${i}. The tool "${e}" timed out waiting for index data (${Wr/1e3}s).\n\nThe existing index may be temporarily locked. Please retry shortly — indexing will complete automatically.`}]}),Wr));return Promise.race([r(...t),a])}}for(let[e,t]of Object.entries(C)){let n=t.handler,r=od(e);t.handler=async(...t)=>{try{return await sd(()=>n(...t),r,e)}catch(t){if(t instanceof ad)return{content:[{type:`text`,text:`⏳ Tool "${e}" timed out after ${r/1e3}s. This may indicate a long-running operation. Please retry or break the task into smaller steps.`}]};throw t}}}let w=Object.keys(C).length;w<R.length&&Q.warn(`ALL_TOOL_NAMES count mismatch`,{expectedToolCount:R.length,registeredToolCount:w}),Q.info(`MCP server configured`,{toolCount:R.length,resourceCount:4});let T=new nd;T.onPressure((e,t)=>{e===`warning`&&In(),e===`critical`&&(Q.warn(`Memory pressure critical — consider restarting`,{rssMB:Math.round(t/1024/1024)}),In())}),T.start();let D=new ed;u=D,D.onIdle(async()=>{if(E.isRunning||n.indexer.isIndexing){Q.info(`Idle cleanup deferred — background tasks still running`),D.touch();return}Q.info(`Idle cleanup:
|
|
1277
|
+
`);Mn(a),Zr(a,new br,e.toolPrefix??``);let m=a.sendToolListChanged.bind(a);a.sendToolListChanged=()=>{};let h=[];for(let e of R){if(!n.has(e))continue;let t=B(e),r=a.registerTool(e,{title:t.title,description:`${t.title} — initializing, available shortly`,inputSchema:{},annotations:t.annotations},async()=>({content:[{type:`text`,text:p()}]}));Gr.has(e)?r.remove():h.push(r)}Ku(a,e,n),a.sendToolListChanged=m;let g=a.registerResource(`aikit-status`,`aikit://status`,{description:`AI Kit status (initializing...)`,mimeType:`text/plain`},async()=>({contents:[{uri:`aikit://status`,text:`AI Kit is initializing...`,mimeType:`text/plain`}]})),_=a.registerPrompt(`_init`,{description:`Initializing AI Kit…`,argsSchema:{_dummy:F(I.string(),()=>[])}},async()=>({messages:[]})),v,y,b=new Promise((e,t)=>{v=e,y=t}),x,S=new Promise(e=>{x=e}),C=()=>x?.(),w=(async()=>{await S;let n;try{n=await Yu(e)}catch(t){let r=t instanceof Error?t.message:String(t);if(cd(r)){Q.warn(`AI Kit initialization failed with recoverable error — attempting auto-heal retry`,{error:r}),await ld(e,r);try{n=await Yu(e),Q.info(`AI Kit auto-heal successful — initialization recovered after retry`)}catch(e){o=`failed`,s=e instanceof Error?e.message:String(e),Q.error(`AI Kit initialization failed after auto-heal attempt — server continuing with zero-dep tools only`,{error:s,originalError:r}),y?.(e instanceof Error?e:Error(s));return}}else{o=`failed`,s=r,Q.error(`AI Kit initialization failed — server continuing with zero-dep tools only`,{error:s}),y?.(t instanceof Error?t:Error(s));return}}let r=a.sendToolListChanged.bind(a);a.sendToolListChanged=()=>{};let i=a.sendPromptListChanged.bind(a);a.sendPromptListChanged=()=>{};let p=a.sendResourceListChanged.bind(a);a.sendResourceListChanged=()=>{};for(let e of h)e.remove();g.remove(),_.remove();let m=a._registeredTools??{};for(let e of Gr)m[e]?.remove();let b=new Ju(a),x=Po(a);Gu(a,n,e,An(a),b,x,t,t===`smart`?(()=>{let e=d;return e?.getState?e.getState():null}):null),Un(a,{curated:n.curated,store:n.store,graphStore:n.graphStore},t),a.sendToolListChanged=r,a.sendPromptListChanged=i,a.sendResourceListChanged=p,Promise.resolve(a.sendToolListChanged()).catch(()=>{}),Promise.resolve(a.sendPromptListChanged()).catch(()=>{}),Promise.resolve(a.sendResourceListChanged()).catch(()=>{});let C=a._registeredTools??{};for(let[e,t]of Object.entries(C)){if(Ur.has(e))continue;let r=t.handler;t.handler=async(...t)=>{if(!n.indexer.isIndexing)return r(...t);let i=c?`re-indexing`:`running initial index`,a=new Promise(t=>setTimeout(()=>t({content:[{type:`text`,text:`⏳ AI Kit is ${i}. The tool "${e}" timed out waiting for index data (${Wr/1e3}s).\n\nThe existing index may be temporarily locked. Please retry shortly — indexing will complete automatically.`}]}),Wr));return Promise.race([r(...t),a])}}for(let[e,t]of Object.entries(C)){let n=t.handler,r=od(e);t.handler=async(...t)=>{try{return await sd(()=>n(...t),r,e)}catch(t){if(t instanceof ad)return{content:[{type:`text`,text:`⏳ Tool "${e}" timed out after ${r/1e3}s. This may indicate a long-running operation. Please retry or break the task into smaller steps.`}]};throw t}}}let w=Object.keys(C).length;w<R.length&&Q.warn(`ALL_TOOL_NAMES count mismatch`,{expectedToolCount:R.length,registeredToolCount:w}),Q.info(`MCP server configured`,{toolCount:R.length,resourceCount:4});let T=new nd;T.onPressure((e,t)=>{e===`warning`&&In(),e===`critical`&&(Q.warn(`Memory pressure critical — consider restarting`,{rssMB:Math.round(t/1024/1024)}),In())}),T.start();let D=new ed;u=D,D.onIdle(async()=>{if(E.isRunning||n.indexer.isIndexing){Q.info(`Idle cleanup deferred — background tasks still running`),D.touch();return}Q.info(`Idle cleanup: releasing cached memory (connections stay open)`);try{n.store.releaseMemory?.(),n.graphStore.releaseMemory?.()}catch{}}),D.touch();for(let e of Object.values(C)){let t=e.handler;e.handler=async(...e)=>{if(D.touch(),d){let t=f(e[0]);t.length>0&&d.prioritize(...t)}return t(...e)}}l=n,v?.(n)})(),T=async()=>{let t;try{t=await b}catch{Q.warn(`Skipping initial index — AI Kit initialization failed`);return}u?.setBusy(!0);try{let n=e.sources.map(e=>e.path).join(`, `);Q.info(`Running initial index`,{sourcePaths:n});let r=await t.indexer.index(e,e=>{e.phase===`crawling`||e.phase===`done`||(e.phase===`chunking`&&e.currentFile&&Q.debug(`Indexing file`,{current:e.filesProcessed+1,total:e.filesTotal,file:e.currentFile}),e.phase===`cleanup`&&Q.debug(`Index cleanup`,{staleEntries:e.filesTotal-e.filesProcessed}))});c=!0,Q.info(`Initial index complete`,{filesProcessed:r.filesProcessed,filesSkipped:r.filesSkipped,chunksCreated:r.chunksCreated,durationMs:r.durationMs});try{await t.store.createFtsIndex()}catch(e){Q.warn(`FTS index creation failed`,j(e))}try{let e=await t.curated.reindexAll();Q.info(`Curated re-index complete`,{indexed:e.indexed})}catch(e){Q.error(`Curated re-index failed`,j(e))}}catch(e){Q.error(`Initial index failed; will retry on aikit_reindex`,j(e))}finally{u?.setBusy(!1)}},E=new Qu,D=()=>E.schedule({name:`initial-index`,fn:T}),O=process.ppid,k=setInterval(()=>{try{process.kill(O,0)}catch{Q.info(`Parent process died; shutting down`,{parentPid:O}),clearInterval(k),d?.stop&&d.stop(),b.then(async e=>{await Promise.all([e.embedder.shutdown().catch(()=>{}),e.graphStore.close().catch(()=>{}),e.store.close().catch(()=>{})])}).catch(()=>{}).finally(()=>process.exit(0))}},5e3);return k.unref(),{server:a,startInit:C,ready:w,runInitialIndex:D,get aikit(){return l},scheduler:E,setSmartScheduler(e){d=e}}}const $=D(`server`);function dd(e,t){let n=di(t,[...R,...Br],z,Hr(t)),i=Xu(t,n,z),a=new qt({name:t.serverName??`aikit`,version:r()},{capabilities:{logging:{},completions:{},prompts:{}},instructions:i});return Mn(a),Gu(a,e,t,An(a),new Ju(a),Po(a),void 0,null,n),Un(a,{curated:e.curated,store:e.store,graphStore:e.graphStore},t.indexMode),a}async function fd(e){let t=await Yu(e),n=dd(t,e);$.info(`MCP server configured`,{toolCount:R.length,resourceCount:2});let r=async()=>{try{let n=e.sources.map(e=>e.path).join(`, `);$.info(`Running initial index`,{sourcePaths:n});let r=await t.indexer.index(e,e=>{e.phase===`crawling`||e.phase===`done`||(e.phase===`chunking`&&e.currentFile&&$.debug(`Indexing file`,{current:e.filesProcessed+1,total:e.filesTotal,file:e.currentFile}),e.phase===`cleanup`&&$.debug(`Index cleanup`,{staleEntries:e.filesTotal-e.filesProcessed}))});$.info(`Initial index complete`,{filesProcessed:r.filesProcessed,filesSkipped:r.filesSkipped,chunksCreated:r.chunksCreated,durationMs:r.durationMs});try{await t.store.createFtsIndex()}catch(e){$.warn(`FTS index creation failed`,j(e))}try{let e=await t.curated.reindexAll();$.info(`Curated re-index complete`,{indexed:e.indexed})}catch(e){$.error(`Curated re-index failed`,j(e))}}catch(e){$.error(`Initial index failed; will retry on aikit_reindex`,j(e))}},i=async()=>{$.info(`Shutting down`),await Promise.all([t.embedder.shutdown().catch(()=>{}),t.graphStore.close().catch(()=>{}),t.store.close().catch(()=>{})]),process.exit(0)};process.on(`SIGINT`,i),process.on(`SIGTERM`,i);let a=process.ppid,o=setInterval(()=>{try{process.kill(a,0)}catch{$.info(`Parent process died; shutting down`,{parentPid:a}),clearInterval(o),i()}},5e3);return o.unref(),{server:n,runInitialIndex:r,shutdown:i}}export{R as ALL_TOOL_NAMES,ud as createLazyServer,dd as createMcpServer,fd as createServer,Yu as initializeAikit,Gu as registerMcpTools};
|
|
@@ -154,6 +154,8 @@ interface IGraphStore {
|
|
|
154
154
|
getCohesionScore(community: string): Promise<number>;
|
|
155
155
|
/** 360-degree view of a node: incoming, outgoing, community, processes */
|
|
156
156
|
getSymbol360(nodeId: string): Promise<Symbol360>;
|
|
157
|
+
/** Release cached memory without closing the connection (lightweight idle cleanup). */
|
|
158
|
+
releaseMemory?(): void;
|
|
157
159
|
/** Close the store */
|
|
158
160
|
close(): Promise<void>;
|
|
159
161
|
}
|
|
@@ -209,6 +211,10 @@ interface IKnowledgeStore {
|
|
|
209
211
|
ftsSearch(query: string, options?: SearchOptions): Promise<SearchResult[]>;
|
|
210
212
|
/** Drop the backing table entirely — used for hard resets (e.g. dimension changes) */
|
|
211
213
|
dropTable(): Promise<void>;
|
|
214
|
+
/** Release cached memory without closing the connection (lightweight idle cleanup). */
|
|
215
|
+
releaseMemory?(): void;
|
|
216
|
+
/** Register a callback invoked synchronously before the store closes. */
|
|
217
|
+
onBeforeClose?(fn: () => void): void;
|
|
212
218
|
/** Close the store connection */
|
|
213
219
|
close(): Promise<void>;
|
|
214
220
|
}
|
|
@@ -373,6 +379,11 @@ declare class SqliteGraphStore implements IGraphStore {
|
|
|
373
379
|
depthGroupedTraversal(startId: string, maxDepth?: number, options?: GraphTraversalOptions): Promise<DepthGroupedResult>;
|
|
374
380
|
getCohesionScore(community: string): Promise<number>;
|
|
375
381
|
getSymbol360(nodeId: string): Promise<Symbol360>;
|
|
382
|
+
/**
|
|
383
|
+
* Release cached memory without closing the connection.
|
|
384
|
+
* Called during idle periods to reduce memory footprint while keeping the store usable.
|
|
385
|
+
*/
|
|
386
|
+
releaseMemory(): void;
|
|
376
387
|
close(): Promise<void>;
|
|
377
388
|
}
|
|
378
389
|
//#endregion
|
|
@@ -397,6 +408,7 @@ declare class SqliteVecStore implements IKnowledgeStore {
|
|
|
397
408
|
private _draining;
|
|
398
409
|
private _priorityQueue;
|
|
399
410
|
private _normalQueue;
|
|
411
|
+
private _onCloseHooks;
|
|
400
412
|
constructor(options?: SqliteVecStoreOptions);
|
|
401
413
|
initialize(): Promise<void>;
|
|
402
414
|
/**
|
|
@@ -441,6 +453,13 @@ declare class SqliteVecStore implements IKnowledgeStore {
|
|
|
441
453
|
createFtsIndex(): Promise<void>;
|
|
442
454
|
dropTable(): Promise<void>;
|
|
443
455
|
private _dropTableImpl;
|
|
456
|
+
/**
|
|
457
|
+
* Release cached memory without closing the connection.
|
|
458
|
+
* Called during idle periods to reduce memory footprint while keeping the store usable.
|
|
459
|
+
*/
|
|
460
|
+
releaseMemory(): void;
|
|
461
|
+
/** Register a callback invoked synchronously before the store closes. */
|
|
462
|
+
onBeforeClose(fn: () => void): void;
|
|
444
463
|
close(): Promise<void>;
|
|
445
464
|
private getAdapter;
|
|
446
465
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{t as e}from"./lance-store-BRoi-4qY.js";import{i as t,r as n,t as r}from"./sqlite-vec-store-
|
|
1
|
+
import{t as e}from"./lance-store-BRoi-4qY.js";import{i as t,r as n,t as r}from"./sqlite-vec-store-DuGaWATy.js";import{AIKIT_PATHS as i}from"../../core/dist/index.js";import{existsSync as a,mkdirSync as o}from"node:fs";import{dirname as s,join as c}from"node:path";var l=class{adapter=null;reopenPromise=null;dbPath;externalAdapter;constructor(e={}){if(e.adapter)this.adapter=e.adapter,this.externalAdapter=!0,this.dbPath=``;else{let t=e.path??i.data;this.dbPath=c(t,`graph.db`),this.externalAdapter=!1}}async initialize(){if(this.externalAdapter){let e=this.getAdapter();this.createTables(e),this.migrateSchema(e),e.flush();return}let e=s(this.dbPath);a(e)||o(e,{recursive:!0}),this.adapter=await t(this.dbPath),this.configureAdapter(this.adapter),this.createTables(this.adapter),this.migrateSchema(this.adapter),this.adapter.flush()}configureAdapter(e){e.pragma(`journal_mode = WAL`),e.pragma(`foreign_keys = ON`)}createTables(e){e.exec(`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS nodes (
|
|
3
3
|
id TEXT PRIMARY KEY,
|
|
4
4
|
type TEXT NOT NULL,
|
|
@@ -87,4 +87,4 @@ import{t as e}from"./lance-store-BRoi-4qY.js";import{i as t,r as n,t as r}from".
|
|
|
87
87
|
VALUES (?, ?, ?, '{}', ?)`,[a,e,t,o]);for(let e=0;e<n.length;e++)this.run(`INSERT INTO process_steps (process_id, node_id, step_order) VALUES (?, ?, ?)`,[a,n[e],e]);s.exec(`COMMIT`),s.flush()}catch(e){throw s.exec(`ROLLBACK`),e}return{id:a,entryNodeId:e,label:t,properties:{},steps:n,createdAt:o}}async getProcesses(e){await this.ensureOpen();let t;t=e?this.query(`SELECT DISTINCT p.id, p.entry_node_id, p.label, p.properties, p.created_at
|
|
88
88
|
FROM processes p
|
|
89
89
|
JOIN process_steps ps ON p.id = ps.process_id
|
|
90
|
-
WHERE ps.node_id = ?`,[e]):this.query(`SELECT * FROM processes`);let n=[];for(let e of t){let t=this.query(`SELECT node_id FROM process_steps WHERE process_id = ? ORDER BY step_order`,[e.id]);n.push({id:e.id,entryNodeId:e.entry_node_id,label:e.label,properties:u(e.properties),steps:t.map(e=>e.node_id),createdAt:e.created_at})}return n}async deleteProcess(e){await this.ensureOpen();let t=this.getAdapter();t.exec(`BEGIN TRANSACTION`);try{this.run(`DELETE FROM process_steps WHERE process_id = ?`,[e]),this.run(`DELETE FROM processes WHERE id = ?`,[e]),t.exec(`COMMIT`),t.flush()}catch(e){throw t.exec(`ROLLBACK`),e}}async depthGroupedTraversal(e,t=3,n){await this.ensureOpen();let r=n?.direction??`both`,i=n?.edgeType,a=n?.limit??100,o={},s=new Set;s.add(e);let c=[e];for(let e=1;e<=t;e++){let t=[],n=[];for(let e of c){let o=await this.getNeighbors(e,{direction:r,edgeType:i,limit:a});for(let e of o.nodes)s.has(e.id)||(s.add(e.id),t.push(e.id),n.push(e))}if(n.length>0&&(o[e]=n),c=t,c.length===0||s.size>=a)break}return o}async getCohesionScore(e){await this.ensureOpen();let t=this.query(`SELECT id FROM nodes WHERE community = ?`,[e]);if(t.length===0)return 0;let n=new Set(t.map(e=>e.id)),r=t.map(()=>`?`).join(`,`),i=t.map(e=>e.id),a=this.query(`SELECT from_id, to_id FROM edges WHERE from_id IN (${r}) OR to_id IN (${r})`,[...i,...i]);if(a.length===0)return 0;let o=0;for(let e of a)n.has(e.from_id)&&n.has(e.to_id)&&o++;return o/a.length}async getSymbol360(e){let t=await this.getNode(e);if(!t)throw Error(`Node '${e}' not found`);let n=await this.findEdges({toId:e}),r=await this.findEdges({fromId:e}),i=await this.getProcesses(e);return{node:t,incoming:n,outgoing:r,community:t.community??null,processes:i}}async close(){this.adapter&&=(this.externalAdapter||this.adapter.close(),null)}};function u(e){if(!e)return{};try{return JSON.parse(e)}catch{return{}}}function d(e){return{id:e.id,type:e.type,name:e.name,properties:u(e.properties),sourceRecordId:e.source_record_id??void 0,sourcePath:e.source_path??void 0,createdAt:e.created_at,community:e.community??void 0}}function f(e){return{id:e.id,fromId:e.from_id,toId:e.to_id,type:e.type,weight:e.weight??1,confidence:e.confidence??1,properties:u(e.properties)}}function p(e){return{id:e.edge_id,fromId:e.from_id,toId:e.to_id,type:e.edge_type,weight:e.weight??1,confidence:e.edge_confidence??1,properties:u(e.edge_props??`{}`)}}function m(e){return{id:e.node_id,type:e.node_type,name:e.node_name,properties:u(e.node_props??`{}`),sourceRecordId:e.node_src_rec??void 0,sourcePath:e.node_src_path??void 0,createdAt:e.node_created,community:e.node_community??void 0}}async function h(e){switch(e.backend){case`lancedb`:{let{LanceStore:t}=await import(`./lance-store-BRoi-4qY.js`).then(e=>e.n);return new t({path:e.path})}case`sqlite-vec`:{let{SqliteVecStore:t}=await import(`./sqlite-vec-store-
|
|
90
|
+
WHERE ps.node_id = ?`,[e]):this.query(`SELECT * FROM processes`);let n=[];for(let e of t){let t=this.query(`SELECT node_id FROM process_steps WHERE process_id = ? ORDER BY step_order`,[e.id]);n.push({id:e.id,entryNodeId:e.entry_node_id,label:e.label,properties:u(e.properties),steps:t.map(e=>e.node_id),createdAt:e.created_at})}return n}async deleteProcess(e){await this.ensureOpen();let t=this.getAdapter();t.exec(`BEGIN TRANSACTION`);try{this.run(`DELETE FROM process_steps WHERE process_id = ?`,[e]),this.run(`DELETE FROM processes WHERE id = ?`,[e]),t.exec(`COMMIT`),t.flush()}catch(e){throw t.exec(`ROLLBACK`),e}}async depthGroupedTraversal(e,t=3,n){await this.ensureOpen();let r=n?.direction??`both`,i=n?.edgeType,a=n?.limit??100,o={},s=new Set;s.add(e);let c=[e];for(let e=1;e<=t;e++){let t=[],n=[];for(let e of c){let o=await this.getNeighbors(e,{direction:r,edgeType:i,limit:a});for(let e of o.nodes)s.has(e.id)||(s.add(e.id),t.push(e.id),n.push(e))}if(n.length>0&&(o[e]=n),c=t,c.length===0||s.size>=a)break}return o}async getCohesionScore(e){await this.ensureOpen();let t=this.query(`SELECT id FROM nodes WHERE community = ?`,[e]);if(t.length===0)return 0;let n=new Set(t.map(e=>e.id)),r=t.map(()=>`?`).join(`,`),i=t.map(e=>e.id),a=this.query(`SELECT from_id, to_id FROM edges WHERE from_id IN (${r}) OR to_id IN (${r})`,[...i,...i]);if(a.length===0)return 0;let o=0;for(let e of a)n.has(e.from_id)&&n.has(e.to_id)&&o++;return o/a.length}async getSymbol360(e){let t=await this.getNode(e);if(!t)throw Error(`Node '${e}' not found`);let n=await this.findEdges({toId:e}),r=await this.findEdges({fromId:e}),i=await this.getProcesses(e);return{node:t,incoming:n,outgoing:r,community:t.community??null,processes:i}}releaseMemory(){if(this.adapter)try{this.adapter.exec(`PRAGMA shrink_memory`),this.adapter.exec(`PRAGMA wal_checkpoint(TRUNCATE)`)}catch{}}async close(){this.adapter&&=(this.externalAdapter||this.adapter.close(),null)}};function u(e){if(!e)return{};try{return JSON.parse(e)}catch{return{}}}function d(e){return{id:e.id,type:e.type,name:e.name,properties:u(e.properties),sourceRecordId:e.source_record_id??void 0,sourcePath:e.source_path??void 0,createdAt:e.created_at,community:e.community??void 0}}function f(e){return{id:e.id,fromId:e.from_id,toId:e.to_id,type:e.type,weight:e.weight??1,confidence:e.confidence??1,properties:u(e.properties)}}function p(e){return{id:e.edge_id,fromId:e.from_id,toId:e.to_id,type:e.edge_type,weight:e.weight??1,confidence:e.edge_confidence??1,properties:u(e.edge_props??`{}`)}}function m(e){return{id:e.node_id,type:e.node_type,name:e.node_name,properties:u(e.node_props??`{}`),sourceRecordId:e.node_src_rec??void 0,sourcePath:e.node_src_path??void 0,createdAt:e.node_created,community:e.node_community??void 0}}async function h(e){switch(e.backend){case`lancedb`:{let{LanceStore:t}=await import(`./lance-store-BRoi-4qY.js`).then(e=>e.n);return new t({path:e.path})}case`sqlite-vec`:{let{SqliteVecStore:t}=await import(`./sqlite-vec-store-DuGaWATy.js`).then(e=>e.n);return new t({path:e.path,adapter:e.adapter,embeddingDim:e.embeddingDim})}default:{let t=e.backend;throw Error(`Unknown store backend: "${t}". Supported: lancedb, sqlite-vec`)}}}export{e as LanceStore,l as SqliteGraphStore,r as SqliteVecStore,n as createSqlJsAdapter,t as createSqliteAdapter,h as createStore};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as e,t}from"./rolldown-runtime-BynbHzcv.js";import{createRequire as n}from"node:module";import{EMBEDDING_DEFAULTS as r,SEARCH_DEFAULTS as i,STORE_DEFAULTS as a,createLogger as o,serializeError as s,sourceTypeContentTypes as c}from"../../core/dist/index.js";import{existsSync as l,mkdirSync as u,readFileSync as d,renameSync as f,unlinkSync as p,writeFileSync as m}from"node:fs";import{dirname as h}from"node:path";const g=o(`sqlite-adapter`),_=n(import.meta.url);var v=class{type=`better-sqlite3`;vectorCapable=!1;db=null;stmtCache=new Map;async open(e){let t;try{t=_(`better-sqlite3`)}catch(e){throw Error(`better-sqlite3 native binding unavailable: ${e instanceof Error?e.message:String(e)}`)}this.db=new t(e),this.db.pragma(`journal_mode = WAL`),this.db.pragma(`foreign_keys = ON`),this.db.pragma(`synchronous = NORMAL`);try{_(`sqlite-vec`).load(this.db),this.vectorCapable=!0,g.info(`sqlite-vec extension loaded`)}catch(e){this.vectorCapable=!1,g.warn(`sqlite-vec extension failed to load; vector search disabled`,s(e))}}exec(e){this.getDb().exec(e)}pragma(e){this.getDb().pragma(e)}queryAll(e,t=[]){let n=this.prepareCached(e);return t.length>0?n.all(...t):n.all()}run(e,t=[]){let n=this.prepareCached(e);t.length>0?n.run(...t):n.run()}flush(){}close(){this.db&&=(this.stmtCache.clear(),this.db.close(),null)}getDb(){if(!this.db)throw Error(`BetterSqlite3Adapter: database not opened`);return this.db}prepareCached(e){let t=this.stmtCache.get(e);if(t)return t;let n=this.getDb().prepare(e);return this.stmtCache.set(e,n),n}};function y(e){return _.resolve(`sql.js/dist/${e}`)}var b=class{type=`sql.js`;vectorCapable=!1;db=null;dbPath=``;dirty=!1;inTransaction=!1;async open(e){this.dbPath=e;let t=(await import(`sql.js`)).default,n=await t({locateFile:e=>y(e)});if(l(e)){let t=d(e);this.db=new n.Database(t)}else this.db=new n.Database}exec(e){let t=e.trimStart().toUpperCase();this.getDb().run(e),t.startsWith(`BEGIN`)?this.inTransaction=!0:(t.startsWith(`COMMIT`)||t.startsWith(`ROLLBACK`))&&(this.inTransaction=!1),this.dirty=!0}pragma(e){this.getDb().exec(`PRAGMA ${e}`)}queryAll(e,t=[]){let n=this.getDb().prepare(e);try{t.length>0&&n.bind(t);let e=[];for(;n.step();)e.push(n.getAsObject());return e}finally{n.free()}}run(e,t=[]){let n=this.getDb(),r=e.trimStart().toUpperCase(),i=!this.inTransaction&&(r.startsWith(`INSERT`)||r.startsWith(`UPDATE`));i&&n.run(`SAVEPOINT fk_check`);try{if(t.length>0){let r=n.prepare(e);try{r.bind(t),r.step()}finally{r.free()}}else n.run(e);if(i){if(n.exec(`PRAGMA foreign_key_check`).length>0)throw n.run(`ROLLBACK TO fk_check`),n.run(`RELEASE fk_check`),Error(`FOREIGN KEY constraint failed`);n.run(`RELEASE fk_check`)}}catch(e){if(i)try{n.run(`ROLLBACK TO fk_check`),n.run(`RELEASE fk_check`)}catch{}throw e}this.dirty=!0}flush(){if(!this.dirty||!this.db)return;let e=this.db.export(),t=`${this.dbPath}.tmp`;m(t,Buffer.from(e)),f(t,this.dbPath),this.dirty=!1}close(){if(this.db){let e=this.db,t;try{this.flush()}catch(e){t=e;try{p(`${this.dbPath}.tmp`)}catch{}}try{e.close()}finally{this.db=null}if(t)throw t}}getDb(){if(!this.db)throw Error(`SqlJsAdapter: database not opened`);return this.db}};let x=!1;async function S(e){let t=new v;try{return await t.open(e),t}catch(e){x||(x=!0,g.warn(`[aikit] better-sqlite3 unavailable — falling back to sql.js (vector search disabled). Reinstall with prebuild support or rebuild from source to enable vector search.`,s(e)))}let n=new b;try{return await n.open(e),n}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`[aikit] SQLite adapter "sql.js" failed to load: ${t}`)}}async function C(e){let t=new b;return await t.open(e),t}var w=t({SqliteVecStore:()=>A});function T(e){let t=0;for(let n=0;n<e.length;n++){let r=e[n]<0?-e[n]:e[n];r>t&&(t=r)}let n=new Int8Array(e.length);if(t===0)return Buffer.from(n.buffer,n.byteOffset,n.byteLength);let r=127/t;for(let t=0;t<e.length;t++){let i=Math.round(e[t]*r);n[t]=i<-127?-127:i>127?127:i}return Buffer.from(n.buffer,n.byteOffset,n.byteLength)}const E=/^[\w.\-/ ]+$/,D=o(`sqlite-vec-store`);function O(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function k(e,t){if(!E.test(e))throw Error(`Invalid ${t} filter value: contains disallowed characters`);return e}var A=class{adapter=null;externalAdapter;dbPath;embeddingDim;coarseDim;vectorEnabled=!1;warnedVectorDisabled=!1;_draining=!1;_priorityQueue=[];_normalQueue=[];constructor(e={}){this.embeddingDim=e.embeddingDim??r.dimensions,this.coarseDim=Math.min(128,this.embeddingDim),e.adapter?(this.adapter=e.adapter,this.externalAdapter=!0,this.dbPath=``):(this.dbPath=e.path??`${a.path}/aikit.db`,this.externalAdapter=!1)}async initialize(){if(!this.adapter){let e=h(this.dbPath);l(e)||u(e,{recursive:!0}),this.adapter=await S(this.dbPath)}this.vectorEnabled=this.adapter.vectorCapable,this.createKnowledgeTable(),this.createFtsTable(),this.vectorEnabled?this.ensureVecTable():this.warnedVectorDisabled||(this.warnedVectorDisabled=!0,D.warn(`SqliteVecStore: vector search disabled (sqlite-vec extension not loaded). Hybrid search will return FTS-only results.`))}getDiagnostics(){let t=this.adapter,n=t?t.constructor.name:`unknown`,r=null,i=this.externalAdapter?``:this.dbPath;if(i)try{let{statSync:t}=e(`node:fs`);r=t(i).size}catch{r=null}return{adapterType:n,vectorSearchEnabled:this.vectorEnabled,degradedMode:!this.vectorEnabled,dbPath:i,dbSizeBytes:r,embeddingDim:this.embeddingDim,vectorDtype:`int8`}}createKnowledgeTable(){let e=this.getAdapter();e.exec(`
|
|
1
|
+
import{n as e,t}from"./rolldown-runtime-BynbHzcv.js";import{createRequire as n}from"node:module";import{EMBEDDING_DEFAULTS as r,SEARCH_DEFAULTS as i,STORE_DEFAULTS as a,createLogger as o,serializeError as s,sourceTypeContentTypes as c}from"../../core/dist/index.js";import{existsSync as l,mkdirSync as u,readFileSync as d,renameSync as f,unlinkSync as p,writeFileSync as m}from"node:fs";import{dirname as h}from"node:path";const g=o(`sqlite-adapter`),_=n(import.meta.url);var v=class{type=`better-sqlite3`;vectorCapable=!1;db=null;stmtCache=new Map;async open(e){let t;try{t=_(`better-sqlite3`)}catch(e){throw Error(`better-sqlite3 native binding unavailable: ${e instanceof Error?e.message:String(e)}`)}this.db=new t(e),this.db.pragma(`journal_mode = WAL`),this.db.pragma(`foreign_keys = ON`),this.db.pragma(`synchronous = NORMAL`);try{_(`sqlite-vec`).load(this.db),this.vectorCapable=!0,g.info(`sqlite-vec extension loaded`)}catch(e){this.vectorCapable=!1,g.warn(`sqlite-vec extension failed to load; vector search disabled`,s(e))}}exec(e){this.getDb().exec(e)}pragma(e){this.getDb().pragma(e)}queryAll(e,t=[]){let n=this.prepareCached(e);return t.length>0?n.all(...t):n.all()}run(e,t=[]){let n=this.prepareCached(e);t.length>0?n.run(...t):n.run()}flush(){}close(){this.db&&=(this.stmtCache.clear(),this.db.close(),null)}getDb(){if(!this.db)throw Error(`BetterSqlite3Adapter: database not opened`);return this.db}prepareCached(e){let t=this.stmtCache.get(e);if(t)return t;let n=this.getDb().prepare(e);return this.stmtCache.set(e,n),n}};function y(e){return _.resolve(`sql.js/dist/${e}`)}var b=class{type=`sql.js`;vectorCapable=!1;db=null;dbPath=``;dirty=!1;inTransaction=!1;async open(e){this.dbPath=e;let t=(await import(`sql.js`)).default,n=await t({locateFile:e=>y(e)});if(l(e)){let t=d(e);this.db=new n.Database(t)}else this.db=new n.Database}exec(e){let t=e.trimStart().toUpperCase();this.getDb().run(e),t.startsWith(`BEGIN`)?this.inTransaction=!0:(t.startsWith(`COMMIT`)||t.startsWith(`ROLLBACK`))&&(this.inTransaction=!1),this.dirty=!0}pragma(e){this.getDb().exec(`PRAGMA ${e}`)}queryAll(e,t=[]){let n=this.getDb().prepare(e);try{t.length>0&&n.bind(t);let e=[];for(;n.step();)e.push(n.getAsObject());return e}finally{n.free()}}run(e,t=[]){let n=this.getDb(),r=e.trimStart().toUpperCase(),i=!this.inTransaction&&(r.startsWith(`INSERT`)||r.startsWith(`UPDATE`));i&&n.run(`SAVEPOINT fk_check`);try{if(t.length>0){let r=n.prepare(e);try{r.bind(t),r.step()}finally{r.free()}}else n.run(e);if(i){if(n.exec(`PRAGMA foreign_key_check`).length>0)throw n.run(`ROLLBACK TO fk_check`),n.run(`RELEASE fk_check`),Error(`FOREIGN KEY constraint failed`);n.run(`RELEASE fk_check`)}}catch(e){if(i)try{n.run(`ROLLBACK TO fk_check`),n.run(`RELEASE fk_check`)}catch{}throw e}this.dirty=!0}flush(){if(!this.dirty||!this.db)return;let e=this.db.export(),t=`${this.dbPath}.tmp`;m(t,Buffer.from(e)),f(t,this.dbPath),this.dirty=!1}close(){if(this.db){let e=this.db,t;try{this.flush()}catch(e){t=e;try{p(`${this.dbPath}.tmp`)}catch{}}try{e.close()}finally{this.db=null}if(t)throw t}}getDb(){if(!this.db)throw Error(`SqlJsAdapter: database not opened`);return this.db}};let x=!1;async function S(e){let t=new v;try{return await t.open(e),t}catch(e){x||(x=!0,g.warn(`[aikit] better-sqlite3 unavailable — falling back to sql.js (vector search disabled). Reinstall with prebuild support or rebuild from source to enable vector search.`,s(e)))}let n=new b;try{return await n.open(e),n}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`[aikit] SQLite adapter "sql.js" failed to load: ${t}`)}}async function C(e){let t=new b;return await t.open(e),t}var w=t({SqliteVecStore:()=>A});function T(e){let t=0;for(let n=0;n<e.length;n++){let r=e[n]<0?-e[n]:e[n];r>t&&(t=r)}let n=new Int8Array(e.length);if(t===0)return Buffer.from(n.buffer,n.byteOffset,n.byteLength);let r=127/t;for(let t=0;t<e.length;t++){let i=Math.round(e[t]*r);n[t]=i<-127?-127:i>127?127:i}return Buffer.from(n.buffer,n.byteOffset,n.byteLength)}const E=/^[\w.\-/ ]+$/,D=o(`sqlite-vec-store`);function O(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function k(e,t){if(!E.test(e))throw Error(`Invalid ${t} filter value: contains disallowed characters`);return e}var A=class{adapter=null;externalAdapter;dbPath;embeddingDim;coarseDim;vectorEnabled=!1;warnedVectorDisabled=!1;_draining=!1;_priorityQueue=[];_normalQueue=[];_onCloseHooks=[];constructor(e={}){this.embeddingDim=e.embeddingDim??r.dimensions,this.coarseDim=Math.min(128,this.embeddingDim),e.adapter?(this.adapter=e.adapter,this.externalAdapter=!0,this.dbPath=``):(this.dbPath=e.path??`${a.path}/aikit.db`,this.externalAdapter=!1)}async initialize(){if(!this.adapter){let e=h(this.dbPath);l(e)||u(e,{recursive:!0}),this.adapter=await S(this.dbPath)}this.vectorEnabled=this.adapter.vectorCapable,this.createKnowledgeTable(),this.createFtsTable(),this.vectorEnabled?this.ensureVecTable():this.warnedVectorDisabled||(this.warnedVectorDisabled=!0,D.warn(`SqliteVecStore: vector search disabled (sqlite-vec extension not loaded). Hybrid search will return FTS-only results.`))}getDiagnostics(){let t=this.adapter,n=t?t.constructor.name:`unknown`,r=null,i=this.externalAdapter?``:this.dbPath;if(i)try{let{statSync:t}=e(`node:fs`);r=t(i).size}catch{r=null}return{adapterType:n,vectorSearchEnabled:this.vectorEnabled,degradedMode:!this.vectorEnabled,dbPath:i,dbSizeBytes:r,embeddingDim:this.embeddingDim,vectorDtype:`int8`}}createKnowledgeTable(){let e=this.getAdapter();e.exec(`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS knowledge (
|
|
3
3
|
id TEXT PRIMARY KEY,
|
|
4
4
|
content TEXT NOT NULL,
|
|
@@ -85,4 +85,4 @@ import{n as e,t}from"./rolldown-runtime-BynbHzcv.js";import{createRequire as n}f
|
|
|
85
85
|
${this.buildFilterSqlSuffix(t,!0)}
|
|
86
86
|
ORDER BY _bm25 ASC
|
|
87
87
|
LIMIT ?
|
|
88
|
-
`,o;try{let t=j(e);o=n.queryAll(a,[t,r])}catch(e){return D.warn(`fts search failed`,s(e)),[]}return o.map(e=>({record:this.fromRow(e),score:M(e._bm25)}))}async getById(e){let t=this.getAdapter().queryAll(`SELECT * FROM knowledge WHERE id = ? LIMIT 1`,[e]);return t.length===0?null:this.fromRow(t[0])}async deleteBySourcePath(e){return this.enqueueWrite(()=>this._deleteBySourcePathImpl(e))}async _deleteBySourcePathImpl(e){let t=this.getAdapter(),n=t.queryAll(`SELECT id FROM knowledge WHERE sourcePath = ?`,[e]);if(n.length===0)return 0;t.exec(`BEGIN`);try{for(let{id:e}of n)this.vectorEnabled&&(t.run(`DELETE FROM vec_knowledge WHERE knowledge_id = ?`,[e]),this.coarseDim<this.embeddingDim&&t.run(`DELETE FROM vec_knowledge_coarse WHERE knowledge_id = ?`,[e])),t.run(`DELETE FROM knowledge_fts WHERE id = ?`,[e]);t.run(`DELETE FROM knowledge WHERE sourcePath = ?`,[e]),t.exec(`COMMIT`)}catch(e){try{t.exec(`ROLLBACK`)}catch{}throw e}return t.flush(),n.length}async deleteById(e){return this.enqueueWrite(()=>this._deleteByIdImpl(e))}async deleteByIdInteractive(e){return this.enqueueWrite(()=>this._deleteByIdImpl(e),!0)}async _deleteByIdImpl(e){let t=this.getAdapter();if(t.queryAll(`SELECT id FROM knowledge WHERE id = ? LIMIT 1`,[e]).length===0)return!1;t.exec(`BEGIN`);try{this.vectorEnabled&&(t.run(`DELETE FROM vec_knowledge WHERE knowledge_id = ?`,[e]),this.coarseDim<this.embeddingDim&&t.run(`DELETE FROM vec_knowledge_coarse WHERE knowledge_id = ?`,[e])),t.run(`DELETE FROM knowledge_fts WHERE id = ?`,[e]),t.run(`DELETE FROM knowledge WHERE id = ?`,[e]),t.exec(`COMMIT`)}catch(e){try{t.exec(`ROLLBACK`)}catch{}throw e}return t.flush(),!0}async getBySourcePath(e){return this.getAdapter().queryAll(`SELECT * FROM knowledge WHERE sourcePath = ? ORDER BY chunkIndex ASC`,[e]).map(e=>this.fromRow(e))}async getStats(){let e=this.getAdapter(),t=e.queryAll(`SELECT COUNT(*) AS n FROM knowledge`)[0]?.n??0;if(t===0)return{totalRecords:0,totalFiles:0,contentTypeBreakdown:{},lastIndexedAt:null,storeBackend:`sqlite-vec`,embeddingModel:r.model};let n=e.queryAll(`SELECT COUNT(DISTINCT sourcePath) AS n FROM knowledge`),i=e.queryAll(`SELECT contentType, COUNT(*) AS n FROM knowledge GROUP BY contentType`),a=e.queryAll(`SELECT MAX(indexedAt) AS ts FROM knowledge`),o={};for(let e of i)o[e.contentType]=e.n;return{totalRecords:t,totalFiles:n[0]?.n??0,contentTypeBreakdown:o,lastIndexedAt:a[0]?.ts??null,storeBackend:`sqlite-vec`,embeddingModel:r.model}}async listSourcePaths(){return this.getAdapter().queryAll(`SELECT DISTINCT sourcePath FROM knowledge ORDER BY sourcePath`).map(e=>e.sourcePath)}async createFtsIndex(){this.createFtsTable()}async dropTable(){return this.enqueueWrite(()=>this._dropTableImpl())}async _dropTableImpl(){let e=this.getAdapter();e.exec(`DROP TABLE IF EXISTS knowledge_fts`),this.vectorEnabled&&(this.coarseDim<this.embeddingDim&&e.exec(`DROP TABLE IF EXISTS vec_knowledge_coarse`),e.exec(`DROP TABLE IF EXISTS vec_knowledge`)),e.exec(`DROP TABLE IF EXISTS knowledge`),e.flush(),this.createKnowledgeTable(),this.createFtsTable(),this.vectorEnabled&&this.ensureVecTable()}async close(){for(;this._priorityQueue.length>0||this._normalQueue.length>0||this._draining;)await new Promise(e=>setTimeout(e,5));this.adapter&&!this.externalAdapter&&this.adapter.close(),this.adapter=null}getAdapter(){if(!this.adapter)throw Error(`SqliteVecStore: not initialized — call initialize() first`);return this.adapter}buildFilterSqlSuffix(e,t=!1){if(!e)return``;let n=[];if(e.contentType&&n.push(`k.contentType = '${k(e.contentType,`contentType`)}'`),e.sourceType){let t=c(e.sourceType);if(t.length>0){let e=t.map(e=>`'${k(e,`sourceType`)}'`).join(`, `);n.push(`k.contentType IN (${e})`)}}if(e.origin&&n.push(`k.origin = '${k(e.origin,`origin`)}'`),e.category&&n.push(`k.category = '${k(e.category,`category`)}'`),e.tags&&e.tags.length>0){let t=e.tags.map(e=>`k.tags LIKE '%' || '${k(e,`tag`)}' || '%'`);n.push(`(${t.join(` OR `)})`)}if(n.length===0)return``;let r=n.join(` AND `);return t?`AND ${r}`:`WHERE ${r}`}fromRow(e){return{id:e.id,content:e.content,sourcePath:e.sourcePath,contentType:e.contentType,headingPath:e.headingPath||void 0,chunkIndex:e.chunkIndex,totalChunks:e.totalChunks,startLine:e.startLine,endLine:e.endLine,fileHash:e.fileHash,contentHash:e.content_hash||void 0,indexedAt:e.indexedAt,origin:e.origin,tags:O(e.tags),category:e.category||void 0,version:e.version}}};function j(e){let t=e.replace(/["'()*:^-]/g,` `).trim();return t?t.split(/\s+/).filter(e=>e.length>0).map(e=>`"${e}"`).join(` OR `):`""`}function M(e){return e==null||Number.isNaN(e)?0:1-Math.exp(-Math.abs(e)/5)}export{S as i,w as n,C as r,A as t};
|
|
88
|
+
`,o;try{let t=j(e);o=n.queryAll(a,[t,r])}catch(e){return D.warn(`fts search failed`,s(e)),[]}return o.map(e=>({record:this.fromRow(e),score:M(e._bm25)}))}async getById(e){let t=this.getAdapter().queryAll(`SELECT * FROM knowledge WHERE id = ? LIMIT 1`,[e]);return t.length===0?null:this.fromRow(t[0])}async deleteBySourcePath(e){return this.enqueueWrite(()=>this._deleteBySourcePathImpl(e))}async _deleteBySourcePathImpl(e){let t=this.getAdapter(),n=t.queryAll(`SELECT id FROM knowledge WHERE sourcePath = ?`,[e]);if(n.length===0)return 0;t.exec(`BEGIN`);try{for(let{id:e}of n)this.vectorEnabled&&(t.run(`DELETE FROM vec_knowledge WHERE knowledge_id = ?`,[e]),this.coarseDim<this.embeddingDim&&t.run(`DELETE FROM vec_knowledge_coarse WHERE knowledge_id = ?`,[e])),t.run(`DELETE FROM knowledge_fts WHERE id = ?`,[e]);t.run(`DELETE FROM knowledge WHERE sourcePath = ?`,[e]),t.exec(`COMMIT`)}catch(e){try{t.exec(`ROLLBACK`)}catch{}throw e}return t.flush(),n.length}async deleteById(e){return this.enqueueWrite(()=>this._deleteByIdImpl(e))}async deleteByIdInteractive(e){return this.enqueueWrite(()=>this._deleteByIdImpl(e),!0)}async _deleteByIdImpl(e){let t=this.getAdapter();if(t.queryAll(`SELECT id FROM knowledge WHERE id = ? LIMIT 1`,[e]).length===0)return!1;t.exec(`BEGIN`);try{this.vectorEnabled&&(t.run(`DELETE FROM vec_knowledge WHERE knowledge_id = ?`,[e]),this.coarseDim<this.embeddingDim&&t.run(`DELETE FROM vec_knowledge_coarse WHERE knowledge_id = ?`,[e])),t.run(`DELETE FROM knowledge_fts WHERE id = ?`,[e]),t.run(`DELETE FROM knowledge WHERE id = ?`,[e]),t.exec(`COMMIT`)}catch(e){try{t.exec(`ROLLBACK`)}catch{}throw e}return t.flush(),!0}async getBySourcePath(e){return this.getAdapter().queryAll(`SELECT * FROM knowledge WHERE sourcePath = ? ORDER BY chunkIndex ASC`,[e]).map(e=>this.fromRow(e))}async getStats(){let e=this.getAdapter(),t=e.queryAll(`SELECT COUNT(*) AS n FROM knowledge`)[0]?.n??0;if(t===0)return{totalRecords:0,totalFiles:0,contentTypeBreakdown:{},lastIndexedAt:null,storeBackend:`sqlite-vec`,embeddingModel:r.model};let n=e.queryAll(`SELECT COUNT(DISTINCT sourcePath) AS n FROM knowledge`),i=e.queryAll(`SELECT contentType, COUNT(*) AS n FROM knowledge GROUP BY contentType`),a=e.queryAll(`SELECT MAX(indexedAt) AS ts FROM knowledge`),o={};for(let e of i)o[e.contentType]=e.n;return{totalRecords:t,totalFiles:n[0]?.n??0,contentTypeBreakdown:o,lastIndexedAt:a[0]?.ts??null,storeBackend:`sqlite-vec`,embeddingModel:r.model}}async listSourcePaths(){return this.getAdapter().queryAll(`SELECT DISTINCT sourcePath FROM knowledge ORDER BY sourcePath`).map(e=>e.sourcePath)}async createFtsIndex(){this.createFtsTable()}async dropTable(){return this.enqueueWrite(()=>this._dropTableImpl())}async _dropTableImpl(){let e=this.getAdapter();e.exec(`DROP TABLE IF EXISTS knowledge_fts`),this.vectorEnabled&&(this.coarseDim<this.embeddingDim&&e.exec(`DROP TABLE IF EXISTS vec_knowledge_coarse`),e.exec(`DROP TABLE IF EXISTS vec_knowledge`)),e.exec(`DROP TABLE IF EXISTS knowledge`),e.flush(),this.createKnowledgeTable(),this.createFtsTable(),this.vectorEnabled&&this.ensureVecTable()}releaseMemory(){if(this.adapter)try{this.adapter.exec(`PRAGMA shrink_memory`),this.adapter.exec(`PRAGMA wal_checkpoint(TRUNCATE)`)}catch{}}onBeforeClose(e){this._onCloseHooks.push(e)}async close(){for(let e of this._onCloseHooks)try{e()}catch{}for(this._onCloseHooks.length=0;this._priorityQueue.length>0||this._normalQueue.length>0||this._draining;)await new Promise(e=>setTimeout(e,5));this.adapter&&!this.externalAdapter&&this.adapter.close(),this.adapter=null}getAdapter(){if(!this.adapter)throw Error(`SqliteVecStore: not initialized — call initialize() first`);return this.adapter}buildFilterSqlSuffix(e,t=!1){if(!e)return``;let n=[];if(e.contentType&&n.push(`k.contentType = '${k(e.contentType,`contentType`)}'`),e.sourceType){let t=c(e.sourceType);if(t.length>0){let e=t.map(e=>`'${k(e,`sourceType`)}'`).join(`, `);n.push(`k.contentType IN (${e})`)}}if(e.origin&&n.push(`k.origin = '${k(e.origin,`origin`)}'`),e.category&&n.push(`k.category = '${k(e.category,`category`)}'`),e.tags&&e.tags.length>0){let t=e.tags.map(e=>`k.tags LIKE '%' || '${k(e,`tag`)}' || '%'`);n.push(`(${t.join(` OR `)})`)}if(n.length===0)return``;let r=n.join(` AND `);return t?`AND ${r}`:`WHERE ${r}`}fromRow(e){return{id:e.id,content:e.content,sourcePath:e.sourcePath,contentType:e.contentType,headingPath:e.headingPath||void 0,chunkIndex:e.chunkIndex,totalChunks:e.totalChunks,startLine:e.startLine,endLine:e.endLine,fileHash:e.fileHash,contentHash:e.content_hash||void 0,indexedAt:e.indexedAt,origin:e.origin,tags:O(e.tags),category:e.category||void 0,version:e.version}}};function j(e){let t=e.replace(/["'()*:^-]/g,` `).trim();return t?t.split(/\s+/).filter(e=>e.length>0).map(e=>`"${e}"`).join(` OR `):`""`}function M(e){return e==null||Number.isNaN(e)?0:1-Math.exp(-Math.abs(e)/5)}export{S as i,w as n,C as r,A as t};
|