@vpxa/aikit 0.1.304 → 0.1.306
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/analyzers/dist/index.js +7 -7
- package/packages/blocks-core/dist/index.mjs +3 -2
- package/packages/cli/dist/index.js +19 -19
- package/packages/indexer/dist/index.js +1 -1
- package/packages/present/dist/index.html +3 -2
- package/packages/server/dist/auth-7LFAZQBu.js +1 -0
- package/packages/server/dist/auth-bEP-6uqy.js +2 -0
- package/packages/server/dist/bin.js +6 -6
- package/packages/server/dist/config-B-wvmMyo.js +1 -0
- package/packages/server/dist/config-Bx85fwRX.js +2 -0
- package/packages/server/dist/{curated-manager-i5QA4c79.js → curated-manager-BrgM_znO.js} +4 -4
- package/packages/server/dist/dashboard-static-Dw7Nsq4f.js +1 -0
- package/packages/server/dist/dashboard-static-dPnij4uF.js +2 -0
- package/packages/server/dist/index.d.ts +97 -88
- package/packages/server/dist/index.js +1 -1
- package/packages/server/dist/{promotion-DmwIVl0c.js → promotion-BGWhzk_I.js} +2 -2
- package/packages/server/dist/{promotion-bQutAIz-.js → promotion-RbjKfC88.js} +2 -2
- package/packages/server/dist/proxy.js +1 -1
- package/packages/server/dist/resolve-sibling-BmZ7AxaA.js +1 -0
- package/packages/server/dist/resolve-sibling-DrGKPpb0.js +2 -0
- package/packages/server/dist/{routes-1wkXLxXe.js → routes-C7bDyCOW.js} +2 -2
- package/packages/server/dist/{routes-KC-D2U8n.js → routes-CfG5gdSR.js} +2 -2
- package/packages/server/dist/{server-B02eYZOD.js → server-B_KbLM43.js} +177 -175
- package/packages/server/dist/server-http-B-TDT3t-.js +2 -0
- package/packages/server/dist/server-http-BbuuthEP.js +1 -0
- package/packages/server/dist/server-stdio-BUb39kqq.js +2 -0
- package/packages/server/dist/server-stdio-Ch7yAxNk.js +1 -0
- package/packages/server/dist/{server-Cs9O29n1.js → server-utMi-Qu3.js} +177 -175
- package/packages/server/dist/server-utils-De-aZNQa.js +1 -0
- package/packages/server/dist/settings-static-BpQgaMRs.js +1 -0
- package/packages/server/dist/settings-static-MepJZjer.js +2 -0
- package/packages/server/dist/startup-maintenance-D0Uhpi3k.js +1 -0
- package/packages/server/dist/startup-maintenance-L9NUOBVy.js +2 -0
- package/packages/server/dist/version-check-6qDKknz4.js +1 -0
- package/packages/server/dist/version-check-DSWaugPC.js +2 -0
- package/packages/server/dist/workspace-bootstrap-BPWA6BVf.js +1 -0
- package/packages/server/viewers/canvas.html +3 -2
- package/packages/server/viewers/report-template.html +3 -2
- package/packages/server/viewers/tour-viewer.html +3 -2
- package/packages/store/dist/index.d.ts +3 -1
- package/packages/store/dist/index.js +24 -24
- package/scaffold/dist/adapters/hermes-agent.mjs +56 -0
- package/scaffold/dist/definitions/models.mjs +1 -1
- package/scaffold/dist/definitions/skills/c4-architecture.mjs +1 -1
- package/scaffold/dist/definitions/skills/docs.mjs +1 -1
- package/scaffold/dist/definitions/skills/present.mjs +1 -1
- package/scaffold/dist/generated/block-docs.mjs +13 -2
- package/packages/server/dist/auth-Bz5dmZgR.js +0 -1
- package/packages/server/dist/auth-lzZKfxlV.js +0 -2
- package/packages/server/dist/config-CaJwUDXI.js +0 -2
- package/packages/server/dist/config-_gMeJYrz.js +0 -1
- package/packages/server/dist/dashboard-static-CRfR1yKU.js +0 -2
- package/packages/server/dist/dashboard-static-FmfoS46e.js +0 -1
- package/packages/server/dist/resolve-sibling-1oDoO-Re.js +0 -1
- package/packages/server/dist/resolve-sibling-ByoHo7Tp.js +0 -2
- package/packages/server/dist/settings-static-B3lnYvcb.js +0 -2
- package/packages/server/dist/settings-static-BtvyIrza.js +0 -1
- package/packages/server/dist/version-check-CJK1Fwmy.js +0 -2
- package/packages/server/dist/version-check-yzdUDXHC.js +0 -1
|
@@ -1,3 +1,3 @@
|
|
|
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,open as s,readFile as c,readdir as l,stat as u}from"node:fs/promises";import{dirname as d,extname as f,join as p,relative as m,resolve as h}from"node:path";import{AIKIT_PATHS as g,FILE_LIMITS as _,createLogger as v,detectContentType as y,serializeError as b}from"../../core/dist/index.js";import{minimatch as x}from"minimatch";import{availableParallelism as S,loadavg as C}from"node:os";import{createChunkerSync as w}from"../../chunker/dist/index.js";function T(t){return e(`sha256`).update(t).digest(`hex`).slice(0,16)}function E(t,n){let r=`${t}:${n}`;return e(`sha256`).update(r).digest(`hex`).slice(0,16)}const D=v(`indexer`);var O=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(`,`));static GENERATED_PATH_PATTERN=/(?:lcov\.info|\.min\.(?:js|css)|\.css\.map|\.js\.map|\.map)$/i;static GENERATED_SAMPLE_LIMIT=5e4;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,s){let d;try{d=await l(t,{withFileTypes:!0})}catch(e){let n=e.code;(n===`EACCES`||n===`EPERM`)&&D.warn(`Permission denied, skipping directory`,{dir:t});return}for(let l of d){let d=p(t,l.name),h=m(n,d).replace(/\\/g,`/`);if(!this.isExcluded(h,i)){if(l.isDirectory()){if(l.name.startsWith(`.`)&&!(l.name===g.ai.slice(1)&&h.startsWith(g.ai)))continue;try{if((await o(d)).isSymbolicLink())continue}catch{continue}let e;try{e=r(d)}catch{continue}if(s.has(e))continue;s.add(e),await this.walkDir(d,n,i,a,s)}else if(l.isFile()){let t=f(l.name).toLowerCase();if(e.BINARY_EXTENSIONS.has(t))continue;try{let n=await u(d);if(n.size>_.maxFileSizeBytes)continue;if(e.isLikelyGeneratedPath(h)){D.debug(`Skipping likely generated file`,{path:h});continue}if(t===`.snap`&&n.size>e.GENERATED_SAMPLE_LIMIT){D.debug(`Skipping likely generated snapshot`,{path:h});continue}let r;try{r=await e.readTextPreview(d)}catch{continue}if(r.includes(`\0`))continue;if(e.isLikelyGeneratedContent(r,h,n.size)){D.debug(`Skipping likely generated file`,{path:h});continue}let i,o,s={relativePath:h,absolutePath:d,extension:t,size:n.size,mtimeMs:n.mtimeMs,content:i,readContent:async()=>i===void 0?(o??=c(d,`utf-8`).then(e=>(i=e,s.content=e,e)),o):i};a.push(s)}catch{}}}}}isExcluded(e,t){return t.some(t=>x(e,t,{dot:!0}))}static isLikelyGeneratedPath(t){return e.GENERATED_PATH_PATTERN.test(t)}static isLikelyGeneratedContent(e,t,n){let r=f(t).toLowerCase();if(t.split(`/`).includes(`coverage`)&&r===``)return!0;let i=e.slice(0,5e4).split(`
|
|
2
2
|
`),a=i.slice(0,100);if(a.length>0&&a.reduce((e,t)=>e+t.length,0)/a.length>500)return!0;let o=i.slice(1,201);if(o.length>=20){let e=new Map,t=0;for(let n of o){let r=n.replace(/\d/g,`#`).slice(0,40),i=(e.get(r)??0)+1;e.set(r,i),i>t&&(t=i)}if(t/o.length>.8)return!0}if(e.length>1e5){let t=0;for(let n of e)if(n===`
|
|
3
|
-
`&&(t+=1,t>=10))break;if(t<10)return!0}return!1}static async readTextPreview(t){let n=await s(t,`r`);try{let t=Buffer.alloc(e.GENERATED_SAMPLE_LIMIT),{bytesRead:r}=await n.read(t,0,t.length,0);return t.toString(`utf8`,0,r)}finally{await n.close()}}};const k=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.mjs`,`.cjs`]),A=[{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}],j=[/import\s+(?:(?:type\s+)?(?:(?:\{[^}]*\}|[\w*]+)\s+from\s+)?)['"]([^'"]+)['"]/g,/import\(\s*['"]([^'"]+)['"]\s*\)/g,/require\(\s*['"]([^'"]+)['"]\s*\)/g];function M(t,n,r){return e(`sha256`).update(`${t}:${n}:${r}`).digest(`hex`).slice(0,16)}function N(t,n,r){return e(`sha256`).update(`${t}-${r}-${n}`).digest(`hex`).slice(0,16)}function P(e,t){return p(d(t),e).replace(/\\/g,`/`).replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,``)}function F(e){return e.replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,``)}function I(e,t,n){let r=f(t).toLowerCase();if(!k.has(r))return{nodes:[],edges:[]};let i=[],a=[],o=new Date().toISOString(),s=new Set,c=F(t),l=M(`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 A){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=M(r,e,t);i.push({id:u,type:r,name:e,properties:{exported:c},sourcePath:t,createdAt:o}),a.push({id:N(l,u,`defines`),fromId:l,toId:u,type:`defines`,weight:c?1:.5})}}let u=n?.workspacePackages,d=new Set;for(let n of j){let r=new RegExp(n.source,n.flags),i;for(;(i=r.exec(e))!==null;){let e=i[1];if(d.has(e))continue;let n;if(e.startsWith(`.`))n=P(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;d.add(e);let r=F(n),o=M(`module`,r,r);a.push({id:N(l,o,`imports`),fromId:l,toId:o,type:`imports`,properties:{source:e}})}}return{nodes:i,edges:a}}const L=v(`hash-cache`);var R=class{cache;filePath;dirty=!1;constructor(e){this.filePath=h(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).map(([e,t])=>[e,typeof t==`string`?{hash:t}:t])),L.debug(`Hash cache loaded`,{entries:this.cache.size})}catch(e){L.warn(`Hash cache load failed, starting fresh`,{err:e}),this.cache=new Map}}get(e){return this.cache.get(e)?.hash}getEntry(e){return this.cache.get(e)}set(e,t,n){this.cache.set(e,{hash:t,...n?{size:n.size,mtimeMs:n.mtimeMs}:{}}),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){L.warn(`Hash cache flush failed`,{err:e})}}clear(){this.cache.clear(),this.dirty=!0,this.flush()}get size(){return this.cache.size}};const z=v(`indexer`),B=()=>new Promise(e=>setImmediate(e));async function V(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 B()}}await Promise.all(Array.from({length:Math.min(n,e.length)},()=>a()))}function H(e){let t=S(),n=C()[0]/t;return n>1.5?2:n>1?Math.max(2,Math.floor(e/2)):e}const U=Math.max(2,Math.min(4,Math.floor(S()*.5)));var W=class{embedder;store;crawler;indexing=!1;graphStore;hashCache;get isIndexing(){return this.indexing}constructor(e,t){this.embedder=e,this.store=t,this.crawler=new O}normalizeChunkText(e){return e.replace(/^\/\/ File: [^\n]*\n?/,``).toLowerCase().replace(/\s+/g,` `).trim()}async loadFileContent(e){if(e.content!==void 0)return e.content;let t=await e.readContent();return e.content=t,t}isMetadataUnchanged(e,t){return t?.size!==void 0&&t?.mtimeMs!==void 0&&t.size===e.size&&t.mtimeMs===e.mtimeMs}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??U,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??U;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??U,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;if(r){let t=e=>e.replace(/\\/g,`/`).toLowerCase(),n=new Set([...r].map(t));i=e.filter(e=>n.has(t(e.relativePath))||n.has(t(e.absolutePath)))}else i=e;if(n.skipHashCheck)return{filesToProcess:i,filesSkipped:0,pathsToRemove:[]};let a=r?[]:await this.getPathsToRemove(e),o=0,s=[];return await V(i,async e=>{let t=this.hashCache?.getEntry(e.relativePath);if(this.isMetadataUnchanged(e,t)){o++;return}let n=await this.loadFileContent(e);if(n.includes(`\0`)){o++;return}if(O.isLikelyGeneratedContent(n,e.relativePath,e.size)){o++;return}let r=T(n);if(this.hashCache){if((t?.hash??this.hashCache.get(e.relativePath))===r){o++;return}}else{let t=await this.store.getBySourcePath(e.relativePath);if(t.length>0&&t[0].fileHash===r){o++;return}}s.push(e)},H(t),(e,t)=>z.error(`Hash check failed`,{sourcePath:e.relativePath,...b(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(`${g.aiCurated}/`))}async buildWorkspacePackageMap(e){let t=new Map;for(let n of e)if(n.relativePath.endsWith(`package.json`))try{let e=JSON.parse(await this.loadFileContent(n));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,v=0,x=async()=>{if(h.length===0)return;let e=h,t=g,n=_;h=[],g=[],_=new Map,v=0;try{await this.store.upsert(e,t);for(let[e,t]of n)this.hashCache?.set(e,t.hash,{size:t.size,mtimeMs:t.mtimeMs})}catch(r){h.push(...e),g.push(...t);for(let[e,t]of n)_.set(e,t);throw r}},S=async()=>{if(this.graphStore){try{f.length>0&&await this.graphStore.upsertNodes(f),p.length>0&&await this.graphStore.upsertEdges(p)}catch(e){z.warn(`Graph batch flush failed`,b(e))}f=[],p=[],m=0}};return await V(n,async t=>{i?.({phase:`chunking`,filesTotal:l,filesProcessed:o,chunksTotal:s,chunksProcessed:s,currentFile:t.relativePath});let n=await this.loadFileContent(t),r=y(t.relativePath),C=w(t.extension).chunk(n,{sourcePath:t.relativePath,contentType:r});if(C.length===0)return;let D=T(n),O=new Date().toISOString(),k=(e,n,r)=>({id:E(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:D,contentHash:r,indexedAt:O,origin:`indexed`,tags:[],version:1}),A=[],j=[];for(let t=0;t<C.length;t++){let n=C[t],r=e(`sha256`).update(this.normalizeChunkText(n.text)).digest(`hex`),i=k(n,t,r),a=d.get(r);if(a&&this.store.upsertWithoutVector){j.push({record:i,sourceRecordId:a}),c++;continue}d.set(r,i.id),A.push({chunk:n,record:i})}i?.({phase:`embedding`,filesTotal:l,filesProcessed:o,chunksTotal:s+C.length,chunksProcessed:s,currentFile:t.relativePath});let M=A.length>0?await this.embedder.embedBatch(A.map(({chunk:e})=>e.text)):[],N=A.map(({record:e})=>e);if(i?.({phase:`storing`,filesTotal:l,filesProcessed:o,chunksTotal:s+C.length,chunksProcessed:s,currentFile:t.relativePath}),N.length>0&&(h.push(...N),g.push(...M),_.set(t.relativePath,{hash:D,size:t.size,mtimeMs:t.mtimeMs}),v++,v>=20&&await x()),j.length>0&&h.length>0&&await x(),this.store.upsertWithoutVector)for(let{record:e,sourceRecordId:t}of j)await this.store.upsertWithoutVector(e,t);if(N.length===0&&j.length>0&&this.hashCache?.set(t.relativePath,D,{size:t.size,mtimeMs:t.mtimeMs}),this.graphStore)try{a.graphCleared||await this.graphStore.deleteBySourcePath(t.relativePath);let e=I(n,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){z.warn(`Graph extraction failed`,{sourcePath:t.relativePath,...b(e)})}o++,s+=C.length},H(r),(e,t)=>z.error(`Processing failed`,{sourcePath:e.relativePath,...b(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 V(e,async e=>{await this.store.deleteBySourcePath(e),this.hashCache?.delete(e),this.graphStore&&await this.graphStore.deleteBySourcePath(e).catch(t=>z.warn(`Graph cleanup failed`,{sourcePath:e,...b(t)})),o++},H(t),(e,t)=>z.error(`Cleanup failed`,{sourcePath:e,...b(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(),z.info(`Graph store cleared`,{nodeCount:e.nodeCount,edgeCount:e.edgeCount}))}catch(e){z.warn(`Graph store clear failed`,b(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 G=v(`smart-index`),K=1.5;var q=class{indexer;config;store;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,G.debug(`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 G.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&&G.debug(`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){G.info(`Skipping trickle tick — indexing already in progress`);return}let e=this.getCpuCount(),t=C()[0];if(e>0&&t/e>K){G.info(`Skipping trickle tick — system load too high`,{load:t.toFixed(2),cpuCount:e,threshold:K});return}let n=await this.pickFiles();if(n.length===0){await this.maybeRefreshChangedFiles();return}G.debug(`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){G.warn(`FTS index rebuild failed after trickle tick`,{error:String(e)})}this.changedFiles=this.changedFiles.filter(e=>!n.includes(e)),G.debug(`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`)){G.warn(`Store closed — stopping smart index scheduler`,{error:t}),this.stop();return}G.error(`Trickle indexing tick failed`,{error:t})}finally{this.stopped||this.scheduleTick()}}getCpuCount(){try{return typeof S==`function`?S():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&&G.debug(`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`)){G.warn(`Store closed — stopping smart index scheduler`,{error:t}),this.stop();return}G.error(`Failed to refresh changed files for trickle indexing`,{error:t})}finally{this.refreshing=!1}}}};export{R as FileHashCache,O as FilesystemCrawler,W as IncrementalIndexer,q as SmartIndexScheduler,I as extractGraph,E as generateRecordId,T as hashContent};
|
|
3
|
+
`&&(t+=1,t>=10))break;if(t<10)return!0}return!1}static async readTextPreview(t){let n=await s(t,`r`);try{let t=Buffer.alloc(e.GENERATED_SAMPLE_LIMIT),{bytesRead:r}=await n.read(t,0,t.length,0);return t.toString(`utf8`,0,r)}finally{await n.close()}}};const k=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.mjs`,`.cjs`]),A=[{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}],j=[/import\s+(?:(?:type\s+)?(?:(?:\{[^}]*\}|[\w*]+)\s+from\s+)?)['"]([^'"]+)['"]/g,/import\(\s*['"]([^'"]+)['"]\s*\)/g,/require\(\s*['"]([^'"]+)['"]\s*\)/g];function M(t,n,r){return e(`sha256`).update(`${t}:${n}:${r}`).digest(`hex`).slice(0,16)}function N(t,n,r){return e(`sha256`).update(`${t}-${r}-${n}`).digest(`hex`).slice(0,16)}function P(e,t){return p(d(t),e).replace(/\\/g,`/`).replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,``)}function F(e){return e.replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,``)}function I(e,t,n){let r=f(t).toLowerCase();if(!k.has(r))return{nodes:[],edges:[]};let i=[],a=[],o=new Date().toISOString(),s=new Set,c=F(t),l=M(`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 A){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=M(r,e,t);i.push({id:u,type:r,name:e,properties:{exported:c},sourcePath:t,createdAt:o}),a.push({id:N(l,u,`defines`),fromId:l,toId:u,type:`defines`,weight:c?1:.5})}}let u=n?.workspacePackages,d=new Set;for(let n of j){let r=new RegExp(n.source,n.flags),i;for(;(i=r.exec(e))!==null;){let e=i[1];if(d.has(e))continue;let n;if(e.startsWith(`.`))n=P(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;d.add(e);let r=F(n),o=M(`module`,r,r);a.push({id:N(l,o,`imports`),fromId:l,toId:o,type:`imports`,properties:{source:e}})}}return{nodes:i,edges:a}}const L=v(`hash-cache`);var R=class{cache;filePath;dirty=!1;constructor(e){this.filePath=h(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).map(([e,t])=>[e,typeof t==`string`?{hash:t}:t])),L.debug(`Hash cache loaded`,{entries:this.cache.size})}catch(e){L.warn(`Hash cache load failed, starting fresh`,{err:e}),this.cache=new Map}}get(e){return this.cache.get(e)?.hash}getEntry(e){return this.cache.get(e)}set(e,t,n){this.cache.set(e,{hash:t,...n?{size:n.size,mtimeMs:n.mtimeMs}:{}}),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){L.warn(`Hash cache flush failed`,{err:e})}}clear(){this.cache.clear(),this.dirty=!0,this.flush()}get size(){return this.cache.size}};const z=v(`indexer`),B=()=>new Promise(e=>setImmediate(e));async function V(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 B()}}await Promise.all(Array.from({length:Math.min(n,e.length)},()=>a()))}function H(e){let t=S(),n=C()[0]/t;return n>1.5?2:n>1?Math.max(2,Math.floor(e/2)):e}const U=Math.max(2,Math.min(4,Math.floor(S()*.5)));var W=class{embedder;store;crawler;indexing=!1;graphStore;hashCache;get isIndexing(){return this.indexing}constructor(e,t){this.embedder=e,this.store=t,this.crawler=new O}normalizeChunkText(e){return e.replace(/^\/\/ File: [^\n]*\n?/,``).toLowerCase().replace(/\s+/g,` `).trim()}async loadFileContent(e){if(e.content!==void 0)return e.content;let t=await e.readContent();return e.content=t,t}isMetadataUnchanged(e,t){return t?.size!==void 0&&t?.mtimeMs!==void 0&&t.size===e.size&&t.mtimeMs===e.mtimeMs}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??U,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??U;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??U,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;if(r){let t=e=>e.replace(/\\/g,`/`).toLowerCase(),n=new Set([...r].map(t));i=e.filter(e=>n.has(t(e.relativePath))||n.has(t(e.absolutePath)))}else i=e;if(n.skipHashCheck)return{filesToProcess:i,filesSkipped:0,pathsToRemove:[]};let a=r?[]:await this.getPathsToRemove(e),o=0,s=[];return await V(i,async e=>{let t=this.hashCache?.getEntry(e.relativePath);if(this.isMetadataUnchanged(e,t)){o++;return}let n=await this.loadFileContent(e);if(n.includes(`\0`)){o++;return}if(O.isLikelyGeneratedContent(n,e.relativePath,e.size)){o++;return}let r=T(n);if(this.hashCache){if((t?.hash??this.hashCache.get(e.relativePath))===r){o++;return}}else{let t=await this.store.getBySourcePath(e.relativePath);if(t.length>0&&t[0].fileHash===r){o++;return}}s.push(e)},H(t),(e,t)=>z.error(`Hash check failed`,{sourcePath:e.relativePath,...b(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(`${g.aiCurated}/`))}async buildWorkspacePackageMap(e){let t=new Map;for(let n of e)if(n.relativePath.endsWith(`package.json`))try{let e=JSON.parse(await this.loadFileContent(n));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,v=0,x=async()=>{if(h.length===0)return;let e=h,t=g,n=_;h=[],g=[],_=new Map,v=0;try{await this.store.upsert(e,t);for(let[e,t]of n)this.hashCache?.set(e,t.hash,{size:t.size,mtimeMs:t.mtimeMs})}catch(r){h.push(...e),g.push(...t);for(let[e,t]of n)_.set(e,t);throw r}},S=async()=>{if(this.graphStore){try{f.length>0&&await this.graphStore.upsertNodes(f),p.length>0&&await this.graphStore.upsertEdges(p)}catch(e){z.warn(`Graph batch flush failed`,b(e))}f=[],p=[],m=0}};return await V(n,async t=>{i?.({phase:`chunking`,filesTotal:l,filesProcessed:o,chunksTotal:s,chunksProcessed:s,currentFile:t.relativePath});let n=await this.loadFileContent(t),r=y(t.relativePath),C=w(t.extension).chunk(n,{sourcePath:t.relativePath,contentType:r});if(C.length===0)return;let D=T(n),O=new Date().toISOString(),k=(e,n,r)=>({id:E(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:D,contentHash:r,indexedAt:O,origin:`indexed`,tags:[],version:1}),A=[],j=[];for(let t=0;t<C.length;t++){let n=C[t],r=e(`sha256`).update(this.normalizeChunkText(n.text)).digest(`hex`),i=k(n,t,r),a=d.get(r);if(a&&this.store.upsertWithoutVector){j.push({record:i,sourceRecordId:a}),c++;continue}d.set(r,i.id),A.push({chunk:n,record:i})}i?.({phase:`embedding`,filesTotal:l,filesProcessed:o,chunksTotal:s+C.length,chunksProcessed:s,currentFile:t.relativePath});let M=A.length>0?await this.embedder.embedBatch(A.map(({chunk:e})=>e.text)):[],N=A.map(({record:e})=>e);if(i?.({phase:`storing`,filesTotal:l,filesProcessed:o,chunksTotal:s+C.length,chunksProcessed:s,currentFile:t.relativePath}),N.length>0&&(h.push(...N),g.push(...M),_.set(t.relativePath,{hash:D,size:t.size,mtimeMs:t.mtimeMs}),v++,v>=20&&await x()),j.length>0&&h.length>0&&await x(),this.store.upsertWithoutVector)for(let{record:e,sourceRecordId:t}of j)try{await this.store.upsertWithoutVector(e,t)}catch(t){if(t instanceof Error&&t.message.includes(`source vector not found`)){if(h.push(e),this.embedder){let[t]=await this.embedder.embedBatch([e.content]);g.push(t)}}else throw z.warn(`upsertWithoutVector failed unexpectedly`,b(t)),t}if(N.length===0&&j.length>0&&this.hashCache?.set(t.relativePath,D,{size:t.size,mtimeMs:t.mtimeMs}),this.graphStore)try{a.graphCleared||await this.graphStore.deleteBySourcePath(t.relativePath);let e=I(n,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){z.warn(`Graph extraction failed`,{sourcePath:t.relativePath,...b(e)})}o++,s+=C.length},H(r),(e,t)=>z.error(`Processing failed`,{sourcePath:e.relativePath,...b(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 V(e,async e=>{await this.store.deleteBySourcePath(e),this.hashCache?.delete(e),this.graphStore&&await this.graphStore.deleteBySourcePath(e).catch(t=>z.warn(`Graph cleanup failed`,{sourcePath:e,...b(t)})),o++},H(t),(e,t)=>z.error(`Cleanup failed`,{sourcePath:e,...b(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(),z.info(`Graph store cleared`,{nodeCount:e.nodeCount,edgeCount:e.edgeCount}))}catch(e){z.warn(`Graph store clear failed`,b(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 G=v(`smart-index`),K=1.5;var q=class{indexer;config;store;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,G.debug(`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 G.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&&G.debug(`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){G.info(`Skipping trickle tick — indexing already in progress`);return}let e=this.getCpuCount(),t=C()[0];if(e>0&&t/e>K){G.info(`Skipping trickle tick — system load too high`,{load:t.toFixed(2),cpuCount:e,threshold:K});return}let n=await this.pickFiles();if(n.length===0){await this.maybeRefreshChangedFiles();return}G.debug(`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){G.warn(`FTS index rebuild failed after trickle tick`,{error:String(e)})}this.changedFiles=this.changedFiles.filter(e=>!n.includes(e)),G.debug(`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`)){G.warn(`Store closed — stopping smart index scheduler`,{error:t}),this.stop();return}G.error(`Trickle indexing tick failed`,{error:t})}finally{this.stopped||this.scheduleTick()}}getCpuCount(){try{return typeof S==`function`?S():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&&G.debug(`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`)){G.warn(`Store closed — stopping smart index scheduler`,{error:t}),this.stop();return}G.error(`Failed to refresh changed files for trickle indexing`,{error:t})}finally{this.refreshing=!1}}}};export{R as FileHashCache,O as FilesystemCrawler,W as IncrementalIndexer,q as SmartIndexScheduler,I as extractGraph,E as generateRecordId,T as hashContent};
|
|
@@ -456,8 +456,9 @@
|
|
|
456
456
|
.bk-form fieldset { border: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: var(--dt-space-3); }
|
|
457
457
|
.bk-form-field { display: flex; flex-direction: column; gap: var(--dt-space-1); }
|
|
458
458
|
.bk-form-label { font-size: 0.875rem; font-weight: 500; color: var(--dt-text-secondary); }
|
|
459
|
-
|
|
460
|
-
|
|
459
|
+
.bk-action-feedback { font-size: 0.875rem; color: var(--dt-text-secondary); padding: var(--dt-space-2) 0; }
|
|
460
|
+
.bk-action-feedback[data-feedback-state="sent"] { color: var(--dt-success-fg, #16a34a); }
|
|
461
|
+
`;function ne(e,t){return`<div class="bk-actions">${ee(e.value).map(e=>{let t=o(e.id);if(e.type===`select`){let n=(e.options??[]).map(e=>{let t=typeof e==`string`?e:e.value,n=typeof e==`string`?e:e.label;return`<option value="${i(t)}">${i(n)}</option>`}).join(``);return`<label class="bk-select-wrap"><span class="bk-visually-hidden">${i(e.label)}</span><select class="bk-select" data-action-id="${t}"><option value="" selected disabled>${i(e.label)}</option>${n}</select></label>`}if(e.type===`text-submit`)return`<div class="bk-text-submit" data-action-id="${t}"><input type="text" class="bk-input" placeholder="${i(e.label)}" data-action-id="${t}" /><button type="button" class="bk-action bk-action--primary" data-action-id="${t}">Send</button></div>`;if(e.type===`form-submit`&&e.schema){let n=e.schema;return`<form class="bk-form" data-action-id="${t}"><fieldset>${Object.entries(n).map(([e,t])=>{let n=t.description??e,r=t.type===`number`?`number`:`text`;return`<label class="bk-form-field"><span class="bk-form-label">${i(n)}</span><input type="${r}" class="bk-input" name="${i(e)}" placeholder="${i(n)}" /></label>`}).join(``)}<button type="submit" class="bk-action bk-action--primary">${i(e.label)}</button></fieldset></form>`}return`<button type="button" class="bk-action bk-action--${i(e.variant??`default`)}" data-action-id="${t}">${i(e.label)}</button>`}).join(``)}<div class="bk-action-feedback" style="display:none;font-size:0.875rem;color:var(--dt-text-secondary);padding:var(--dt-space-2) 0;" data-feedback-state="pending">💬 Feedback sent</div></div>`}var re=`
|
|
461
462
|
.bk-cards {
|
|
462
463
|
display: grid;
|
|
463
464
|
grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as e}from"./rolldown-runtime-DT7IzrpZ.js";import*as t from"node:fs";import{join as n}from"node:path";import{randomBytes as r,timingSafeEqual as i}from"node:crypto";import{homedir as a}from"node:os";var o=e({authMiddleware:()=>d,getOrCreateToken:()=>u,readToken:()=>f});const s=n(a(),`.aikit`);function c(e){let t=e?.tokenDir??s;return{tokenDir:t,tokenFile:n(t,`token`)}}function l(e,t){let n=Buffer.from(e),r=Buffer.from(t);return n.length===r.length?i(n,r):!1}function u(e){let{tokenDir:n,tokenFile:i}=c(e);if(t.existsSync(i)){let e=t.readFileSync(i,`utf-8`).trim();if(e.length>0)return e}t.existsSync(n)||t.mkdirSync(n,{recursive:!0,mode:448});let a=r(32).toString(`hex`);return t.writeFileSync(i,a,{mode:384}),a}function d(e){return(t,n,r)=>{if(t.path===`/health`||t.path===`/healthz`){r();return}let i=t.headers.authorization;if(!i?.startsWith(`Bearer `)){n.status(401).json({error:`Unauthorized: Bearer token required`});return}if(!l(i.slice(7).trim(),e)){n.status(401).json({error:`Unauthorized: Invalid token`});return}r()}}function f(e){try{let{tokenFile:n}=c(e);return t.readFileSync(n,`utf-8`).trim()}catch{return}}export{f as n,o as t};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import*as e from"node:fs";import{join as t}from"node:path";import{randomBytes as n,timingSafeEqual as r}from"node:crypto";import{homedir as i}from"node:os";const a=t(i(),`.aikit`);function o(e){let n=e?.tokenDir??a;return{tokenDir:n,tokenFile:t(n,`token`)}}function s(e,t){let n=Buffer.from(e),i=Buffer.from(t);return n.length===i.length?r(n,i):!1}function c(t){let{tokenDir:r,tokenFile:i}=o(t);if(e.existsSync(i)){let t=e.readFileSync(i,`utf-8`).trim();if(t.length>0)return t}e.existsSync(r)||e.mkdirSync(r,{recursive:!0,mode:448});let a=n(32).toString(`hex`);return e.writeFileSync(i,a,{mode:384}),a}function l(e){return(t,n,r)=>{if(t.path===`/health`||t.path===`/healthz`){r();return}let i=t.headers.authorization;if(!i?.startsWith(`Bearer `)){n.status(401).json({error:`Unauthorized: Bearer token required`});return}if(!s(i.slice(7).trim(),e)){n.status(401).json({error:`Unauthorized: Invalid token`});return}r()}}function u(t){try{let{tokenFile:n}=o(t);return e.readFileSync(n,`utf-8`).trim()}catch{return}}export{l as authMiddleware,c as getOrCreateToken,u as readToken};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{
|
|
3
|
-
`).filter(Boolean).map(e=>{let[t,n,...r]=e.split(`|`);return{sha:t,date:n,message:r.join(`|`)}}):[]}async diff(e,t,n){if(e=this.guardPath(e),!
|
|
4
|
-
`).filter(Boolean)){let[e,...r]=n.split(`|`),i=r.join(`|`),a=`${e.replace(`${
|
|
5
|
-
`).length,fileHash:this.hash(e.content),indexedAt:t,origin:`curated`,tags:e.frontmatter.tags,category:e.frontmatter.category,version:e.frontmatter.version}});try{return await this.store.upsert(i,r),e.length}catch(t){
|
|
6
|
-
`).length,fileHash:this.hash(t),indexedAt:a,origin:`curated`,tags:n.tags,category:n.category,version:n.version};await this.store.upsert([o],[r])}async indexCuratedFileBestEffort(e,t,n,
|
|
2
|
+
import{fileURLToPath as e,pathToFileURL as t}from"node:url";import{parseArgs as n}from"node:util";import{HealthBus as r,createLogger as i,serializeError as a}from"../../core/dist/index.js";import{readFileSync as o}from"node:fs";import{dirname as s,isAbsolute as c,join as l,resolve as u}from"node:path";import{createHash as d}from"node:crypto";import{GIT_REF_SLUG_PATTERN as f,gitAvailable as p,gitCommitToRef as m,gitExec as h,slugForRef as g}from"../../tools/dist/index.js";import{mkdir as _,readFile as v,readdir as y,stat as b,unlink as x,writeFile as S}from"node:fs/promises";function C(){try{let t=u(s(e(import.meta.url)),`..`,`..`,`..`,`package.json`);return JSON.parse(o(t,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}function w(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function T(e,t){let n=process.env[e];if(!n)return t;let r=Number.parseInt(n,10);return Number.isFinite(r)&&r>0?r:t}const E=/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;function D({requestOrigin:e,configuredOrigin:t,allowAnyOrigin:n,fallbackOrigin:r}){let i=t??r;return i===`*`?n?{allowOrigin:`*`,warn:!1}:e?E.test(e)?{allowOrigin:e,warn:!1}:{allowOrigin:null,warn:!0}:{allowOrigin:r,warn:!1}:{allowOrigin:i,warn:!1}}function O({limit:e,windowMs:t}){let n=new Map,r=(e,r)=>{let i=r-t,a=n.get(e)?.filter(e=>e>i)??[];return a.length===0?(n.delete(e),[]):(n.set(e,a),a)};return{allow(t,i=Date.now()){let a=r(t,i);return a.length>=e?!1:(a.push(i),n.set(t,a),!0)},getRetryAfterMs(n,i=Date.now()){let a=r(n,i);return a.length<e?0:Math.max(0,a[0]+t-i)}}}function k(t){return t.startsWith(`file://`)?e(t):t}function A(e){let t=u(e);return process.platform===`win32`?t.toLowerCase():t}function j(e){let t=new Map;for(let n of e){let e=k(n.uri);t.set(A(e),e)}return[...t.values()].sort((e,t)=>A(e).localeCompare(A(t)))}function M({config:e,roots:t}){let n=j(t);if(n.length===0)return null;let r=e.sources?.[0]?.path;if(r){let e=A(r),t=n.find(t=>A(t)===e);if(t)return t}return n[0]}function N({config:e,log:t,reconfigureForWorkspace:n,roots:r}){let i=j(r);if(i.length===0)return!1;let a=M({config:e,roots:i.map(e=>({uri:e}))});if(!a)return!1;let o=e.sources?.[0]?.path;return t.debug(`MCP roots resolved`,{rootPath:a,rootCount:i.length,selectedBy:o&&A(o)===A(a)?`configured-source`:`stable-sorted-root`}),n(e,a),e.allRoots=i,!0}async function P({config:e,indexMode:t,log:n,rootsChangedNotificationSchema:r,reconfigureForWorkspace:i,runInitialIndex:o,server:s,startInit:c,timeoutMs:l=5e3,getCwd:u=()=>process.cwd(),version:d=`0.0.0`}){let f=!1,p=!1,m,h=s.server,g=e=>{let t=a(e),n=`${String(e)} ${String(t.message??``)}`.toLowerCase();return n.includes(`method not found`)||n.includes(`not supported`)||n.includes(`unsupported`)||n.includes(`unknown method`)||n.includes(`roots/list`)||n.includes(`timed out`)},_=()=>{f||(f=!0,c())},v=()=>{p||t!==`auto`||(p=!0,(async()=>{try{await o()}catch(e){n.error(`Initial index failed`,{version:d,...a(e)})}})())},y=t=>t.length===0||(m&&=(clearTimeout(m),void 0),!N({config:e,log:n,reconfigureForWorkspace:i,roots:t}))?!1:(_(),v(),!0);try{if(y((await h.listRoots()).roots))return;n.debug(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(t){if(g(t)){n.warn(`MCP roots/list not supported by client; using cwd fallback`,{version:d,cwd:u(),...a(t)}),N({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:u()}]})&&(_(),v());return}n.warn(`MCP roots/list failed; waiting for roots/list_changed notification`,{version:d,cwd:u(),...a(t)})}h.setNotificationHandler(r,async()=>{try{y((await h.listRoots()).roots)}catch(e){n.warn(`roots/list retry failed after notification`,{version:d,...a(e)})}}),m=setTimeout(()=>{let t=u();n.debug(`Timed out waiting for roots/list_changed; falling back to cwd workspace`,{cwd:t}),N({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:t}]})&&(_(),v())},l)}var F=class{baseDir;constructor(e){this.baseDir=e}async initialize(){await _(this.baseDir,{recursive:!0})}async read(e){let t=l(this.baseDir,e);try{return await v(t,`utf-8`)}catch(e){if(e.code===`ENOENT`)return null;throw e}}async write(e,t,n){let r=l(this.baseDir,e);await _(s(r),{recursive:!0}),await S(r,t,{encoding:`utf-8`,flag:n?.exclusive?`wx`:`w`})}async delete(e){let t=l(this.baseDir,e);try{return await x(t),!0}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async list(e){let t=[],n=e?[e]:await this.listDirectories();for(let e of n){let n=l(this.baseDir,e),r;try{r=await y(n)}catch{continue}for(let n of r){if(!n.endsWith(`.md`))continue;let r=`${e}/${n}`,i=l(this.baseDir,r);try{let e=await b(i);t.push({path:r,size:e.size,mtimeMs:e.mtimeMs})}catch{}}}return t}async exists(e){let t=l(this.baseDir,e);try{return await b(t),!0}catch{return!1}}async listDirectories(){try{return(await y(this.baseDir,{withFileTypes:!0})).filter(e=>e.isDirectory()&&/^[a-z][a-z0-9-]*$/.test(e.name)).map(e=>e.name)}catch{return[]}}async close(){}};const I=50*1024,L=`refs/aikit/knowledge`,R=i(`server`);var z=class{curatedDir;store;embedder;adapter;constructor(e,t,n,r=new F(e)){this.curatedDir=e,this.store=t,this.embedder=n,this.adapter=r}async remember(e,t,n,r=[]){this.validateCategoryName(n),this.validateContentSize(t);let i=this.normalizeTags(r),a=this.slugify(e),o=await this.uniqueRelativePath(n,a),s=new Date().toISOString(),c={title:e,category:n,tags:i,created:s,updated:s,version:1,origin:`curated`,changelog:[{version:1,date:s,reason:`Initial creation`}]},l=this.serializeFile(t,c);try{await this.adapter.write(o,l,{exclusive:!0})}catch(e){throw e.code===`EEXIST`?Error(`Concurrent write collision for "${o}" — retry the operation`):e}return this.gitCommitKnowledge(o,l,`remember: ${e}\n\nCategory: ${n}\nTags: ${i.join(`, `)}`),await this.indexCuratedFileBestEffort(o,t,c,`remember`),{path:o}}async upsertAutoKnowledge(e,t,n,r,i=[],a=`Auto-knowledge refresh`){e=this.guardPath(e),this.validateCategoryName(r),this.validateContentSize(n),this.ensureCategoryPath(e,r);let o=this.normalizeTags(i),s=await this.adapter.read(e);if(s==null){let i=new Date().toISOString(),a={title:t,category:r,tags:o,created:i,updated:i,version:1,origin:`curated`,changelog:[{version:1,date:i,reason:`Initial creation`}]},s=this.serializeFile(n,a);try{await this.adapter.write(e,s,{exclusive:!0})}catch(t){throw t.code===`EEXIST`?Error(`Concurrent write collision for "${e}" — retry the operation`):t}return this.gitCommitKnowledge(e,s,`remember: ${t}\n\nCategory: ${r}\nTags: ${o.join(`, `)}`),await this.indexCuratedFileBestEffort(e,n,a,`remember`),{path:e,status:`created`,version:1}}let{frontmatter:c,content:l}=this.parseFile(s),u=this.normalizeTags(c.tags??[]),d=t.trim()||c.title;if(l===n&&c.category===r&&c.title===d&&this.sameTags(u,o))return{path:e,status:`unchanged`,version:c.version??1};let f=(c.version??1)+1,p=new Date().toISOString();c.title=d,c.category=r,c.tags=o,c.version=f,c.updated=p,c.changelog=[...c.changelog??[],{version:f,date:p,reason:a}];let m=this.serializeFile(n,c);return await this.adapter.write(e,m),this.gitCommitKnowledge(e,m,`update(v${f}): ${c.title}\n\nReason: ${a}\nVersion: ${f}`),await this.indexCuratedFileBestEffort(e,n,c,`update`),{path:e,status:`updated`,version:f}}async update(e,t,n){e=this.guardPath(e),this.validateContentSize(t);let r=await this.adapter.read(e);if(r==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:i}=this.parseFile(r),a=(i.version??1)+1,o=new Date().toISOString();i.version=a,i.updated=o,i.changelog=[...i.changelog??[],{version:a,date:o,reason:n}];let s=this.serializeFile(t,i);return await this.adapter.write(e,s),this.gitCommitKnowledge(e,s,`update(v${a}): ${i.title}\n\nReason: ${n}\nVersion: ${a}`),await this.indexCuratedFileBestEffort(e,t,i,`update`),{path:e,version:a}}async forget(e,t){if(e=this.guardPath(e),!await this.adapter.delete(e))throw Error(`Curated entry not found: ${e}`);let n=`.ai/curated/${e}`;return await this.store.deleteBySourcePath(n).catch(e=>{R.warn(`File deleted but vector cleanup failed`,{sourcePath:n,...a(e)})}),this.gitDeleteKnowledgeRef(e),{path:e}}async history(e,t=20){if(e=this.guardPath(e),!p(this.curatedDir))return[];let n=this.knowledgeRefForPath(e);if(!n)return[];let r=h([`log`,`--format=%H|%aI|%s`,n,`-n`,String(t)],this.curatedDir);return r?r.split(`
|
|
3
|
+
`).filter(Boolean).map(e=>{let[t,n,...r]=e.split(`|`);return{sha:t,date:n,message:r.join(`|`)}}):[]}async diff(e,t,n){if(e=this.guardPath(e),!p(this.curatedDir))return``;if(!n){let r=await this.history(e,2);if(r.length===0)return``;n=r[0].sha,r.length>1&&!t&&(t=r[1].sha)}return t&&n?h([`diff`,`${t}:entry.md`,`${n}:entry.md`],this.curatedDir)??``:n?h([`show`,`${n}:entry.md`],this.curatedDir)??``:``}async recover(e){if(e=this.guardPath(e),await this.adapter.exists(e))throw Error(`Entry already exists on filesystem: ${e}. Use update() instead.`);if(!p(this.curatedDir))return null;let t=this.knowledgeRefForPath(e);if(!t)return null;let n=h([`show`,`${t}:entry.md`],this.curatedDir);if(!n)return null;await this.adapter.write(e,n);let{frontmatter:r,content:i}=this.parseFile(n);return await this.indexCuratedFile(e,i,r),{path:e,version:r.version??1}}async listOrphaned(){if(!p(this.curatedDir))return[];let e=h([`for-each-ref`,`--format=%(refname)|%(subject)`,`${L}/`],this.curatedDir);if(!e)return[];let t=[];for(let n of e.split(`
|
|
4
|
+
`).filter(Boolean)){let[e,...r]=n.split(`|`),i=r.join(`|`),a=`${e.replace(`${L}/`,``)}.md`;await this.adapter.exists(a)||t.push({ref:e,path:a,lastMessage:i})}return t}async read(e){e=this.guardPath(e);let t=await this.adapter.read(e);if(t==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:n,content:r}=this.parseFile(t),i=e.split(`/`)[0];return{path:e,title:n.title??e,category:i,tags:n.tags??[],version:n.version??1,created:n.created??``,updated:n.updated??``,contentPreview:r.slice(0,200),content:r}}async list(e){return(await this.listPage(e)).entries}async listPage(e){let t=e?.category?[e.category]:await this.discoverCategories(),n=[];for(let e of t){let t=await this.adapter.list(e);for(let r of t)n.push({path:r.path,category:e,mtimeMs:r.mtimeMs??0})}let r=Math.max(0,e?.offset??0),i=e?.limit==null?null:Math.max(1,e.limit),a=(e?.order??`asc`)===`desc`?-1:1,o=e?.orderBy??`path`;if(o===`path`||o===`updated`){let t=this.sortCandidateMetadata(n,o,a);if(e?.tag){let n=i==null?void 0:r+i+1,{entries:a,scannedAll:o}=await this.readCandidateEntries(t,{tag:e.tag,maxMatches:n}),s=i==null?a.slice(r):a.slice(r,r+i),c=i!=null&&(a.length>r+s.length||!o);return{entries:s,totalCount:o?a.length:r+s.length+ +!!c,totalCountIsExact:o,limit:i,offset:r,hasMore:c}}let s=i==null?t.slice(r):t.slice(r,r+i),{entries:c}=await this.readCandidateEntries(s);return{entries:c,totalCount:t.length,totalCountIsExact:!0,limit:i,offset:r,hasMore:i!=null&&r+c.length<t.length}}let{entries:s}=await this.readCandidateEntries(n,{tag:e?.tag}),c=s.sort((e,t)=>{switch(o){case`created`:return(Date.parse(e.created)-Date.parse(t.created))*a;case`updated`:return(Date.parse(e.updated)-Date.parse(t.updated))*a;case`path`:return e.path.localeCompare(t.path)*a;default:return 0}}),l=i==null?c.slice(r):c.slice(r,r+i);return{entries:l,totalCount:c.length,totalCountIsExact:!0,limit:i,offset:r,hasMore:i!=null&&r+l.length<c.length}}async count(e){if(e?.tag)return(await this.listPage({...e,limit:void 0})).totalCount;let t=e?.category?[e.category]:await this.discoverCategories(),n=0;for(let e of t)n+=(await this.adapter.list(e)).length;return n}async listPaths(e){let t=e?.category?[e.category]:await this.discoverCategories(),n=[];for(let e of t){let t=await this.adapter.list(e);n.push(...t.map(e=>e.path))}n.sort((e,t)=>e.localeCompare(t));let r=Math.max(0,e?.offset??0),i=e?.limit==null?null:Math.max(1,e.limit);return i==null?n.slice(r):n.slice(r,r+i)}sortCandidateMetadata(e,t,n){return[...e].sort((e,r)=>t===`updated`?(e.mtimeMs-r.mtimeMs)*n:e.path.localeCompare(r.path)*n)}async readCandidateEntries(e,t){let n=[];for(let r of e){let e=await this.adapter.read(r.path);if(e==null)continue;let{frontmatter:i,content:a}=this.parseFile(e),o=i.tags??[];if(!(t?.tag&&!o.includes(t.tag))&&(n.push({path:r.path,title:i.title??r.path,category:r.category,tags:o,version:i.version??1,created:i.created??``,updated:i.updated??``,contentPreview:a.slice(0,200)}),t?.maxMatches!=null&&n.length>=t.maxMatches))return{entries:n,scannedAll:!1}}return{entries:n,scannedAll:!0}}async reindexAll(){let e=await this.discoverCategories(),t=[],n=[];for(let r of e){let e=await this.adapter.list(r);for(let r of e){let e=r.path;try{let r=await this.adapter.read(e);if(r==null){t.push(`${e}: read failed`);continue}let{frontmatter:i,content:a}=this.parseFile(r);n.push({relativePath:e,content:a,frontmatter:i})}catch(n){R.error(`Failed to read curated file`,{relativePath:e,...a(n)}),t.push(`${e}: read failed`)}}}if(n.length===0)return{indexed:0,errors:t};let r=new Date().toISOString(),i=0;for(let e=0;e<n.length;e+=16){let a=n.slice(e,e+16);i+=await this.embedAndUpsertBatch(a,r,t)}return{indexed:i,errors:t}}async embedAndUpsertBatch(e,t,n){try{let r=await this.embedder.embedBatch(e.map(e=>e.content)),i=e.map(e=>{let n=`.ai/curated/${e.relativePath}`;return{id:this.hashId(n,0),content:e.content,sourcePath:n,contentType:`curated-knowledge`,headingPath:e.frontmatter.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:e.content.split(`
|
|
5
|
+
`).length,fileHash:this.hash(e.content),indexedAt:t,origin:`curated`,tags:e.frontmatter.tags,category:e.frontmatter.category,version:e.frontmatter.version}});try{return await this.store.upsert(i,r),e.length}catch(t){R.error(`Failed to upsert curated batch`,{batchSize:e.length,...a(t)});for(let t of e)n.push(`${t.relativePath}: upsert failed`);return 0}}catch(r){if(e.length===1)return R.error(`Failed to embed curated item`,{relativePath:e[0].relativePath,...a(r)}),n.push(`${e[0].relativePath}: reindex failed`),0;R.warn(`Curated embed batch failed, retrying with smaller chunks`,{batchSize:e.length,...a(r)});let i=Math.ceil(e.length/2),o=e.slice(0,i),s=e.slice(i);return await this.embedAndUpsertBatch(o,t,n)+await this.embedAndUpsertBatch(s,t,n)}}gitCommitKnowledge(e,t,n){try{if(!p(this.curatedDir))return;let r=this.knowledgeRefForPath(e);if(!r)return;m(r,`entry.md`,t,n,this.curatedDir)}catch{}}gitDeleteKnowledgeRef(e){try{if(!p(this.curatedDir))return;let t=this.knowledgeRefForPath(e);if(!t)return;h([`update-ref`,`-d`,t],this.curatedDir)}catch{}}knowledgeRefForPath(e){let t=e.replace(/\.md$/,``).split(`/`).map(e=>g(e)).join(`/`);return t.split(`/`).every(e=>f.test(e))?`${L}/${t}`:null}async indexCuratedFile(e,t,n){let r=await this.embedder.embed(t),i=`.ai/curated/${e}`,a=new Date().toISOString(),o={id:this.hashId(i,0),content:t,sourcePath:i,contentType:`curated-knowledge`,headingPath:n.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:t.split(`
|
|
6
|
+
`).length,fileHash:this.hash(t),indexedAt:a,origin:`curated`,tags:n.tags,category:n.category,version:n.version};await this.store.upsert([o],[r])}async indexCuratedFileBestEffort(e,t,n,i){if(r.instance().isDegraded(`embedder`)){R.debug(`Skipping vector indexing — embedder degraded`,{relativePath:e,operation:i,subsystem:`embedder`});return}try{await this.indexCuratedFile(e,t,n)}catch(t){R.warn(`Curated file persisted but vector indexing deferred`,{relativePath:e,operation:i,...a(t)})}}async discoverCategories(){return this.adapter.listDirectories()}guardPath(e){let t=e.replace(/^\.ai\/curated\//,``);if(t.endsWith(`.md`)||(t+=`.md`),t.includes(`..`)||c(t))throw Error(`Invalid path: ${t}. Must be relative within .ai/curated/ directory.`);let n=t.split(`/`)[0];return this.validateCategoryName(n),t}validateCategoryName(e){if(!/^[a-z][a-z0-9-]*$/.test(e))throw Error(`Invalid category name: "${e}". Must be lowercase kebab-case (e.g., "decisions", "api-contracts").`)}validateContentSize(e){if(Buffer.byteLength(e,`utf-8`)>I)throw Error(`Content exceeds maximum size of ${I/1024}KB`)}slugify(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-|-$/g,``).slice(0,80)}normalizeTags(e){return[...new Set(e.map(e=>e.trim()).filter(Boolean))]}sameTags(e,t){if(e.length!==t.length)return!1;let n=new Set(e);return t.every(e=>n.has(e))}ensureCategoryPath(e,t){if(!e.startsWith(`${t}/`))throw Error(`Curated path "${e}" must stay within category "${t}"`)}async uniqueRelativePath(e,t){let n=`${e}/${t}.md`;if(!await this.adapter.exists(n))return n;for(let n=2;n<=100;n++){let r=`${e}/${t}-${n}.md`;if(!await this.adapter.exists(r))return r}throw Error(`Too many entries with slug "${t}" in category "${e}"`)}hash(e){return d(`sha256`).update(e).digest(`hex`).slice(0,16)}hashId(e,t){return this.hash(`${e}::${t}`)}serializeFile(e,t){return`${[`---`,`title: "${t.title.replace(/"/g,`\\"`)}"`,`category: ${t.category}`,`tags: [${t.tags.map(e=>`"${e}"`).join(`, `)}]`,`created: ${t.created}`,`updated: ${t.updated}`,`version: ${t.version}`,`origin: ${t.origin}`,`changelog:`,...t.changelog.map(e=>` - version: ${e.version}\n date: ${e.date}\n reason: "${e.reason.replace(/"/g,`\\"`)}"`),`---`].join(`
|
|
7
7
|
`)}\n\n${e}\n`}parseFile(e){let t=e.match(/^---\n([\s\S]*?)\n---\n\n?([\s\S]*)$/);if(!t)return{frontmatter:{title:`Untitled`,category:`notes`,tags:[],created:``,updated:``,version:1,origin:`curated`,changelog:[]},content:e};let n=t[1],r=t[2].trim(),i={},a=[],o=n.split(`
|
|
8
|
-
`),s=!1,c={};for(let e of o){if(/^changelog:\s*$/.test(e)){s=!0;continue}if(s){let t=e.match(/^\s+-\s+version:\s*(\d+)$/);if(t){c.version!=null&&a.push(c),c={version:parseInt(t[1],10)};continue}let n=e.match(/^\s+date:\s*(.+)$/);if(n){c.date=n[1].trim();continue}let r=e.match(/^\s+reason:\s*"?(.*?)"?\s*$/);if(r){c.reason=r[1];continue}/^\w/.test(e)&&(s=!1,c.version!=null&&a.push(c),c={});continue}let t=e.match(/^(\w+):\s*(.*)$/);if(t){let e=t[1],n=t[2];typeof n==`string`&&n.startsWith(`[`)&&n.endsWith(`]`)?n=n.slice(1,-1).split(`,`).map(e=>e.trim().replace(/^"|"$/g,``)).filter(e=>e.length>0):typeof n==`string`&&/^\d+$/.test(n)?n=parseInt(n,10):typeof n==`string`&&n.startsWith(`"`)&&n.endsWith(`"`)&&(n=n.slice(1,-1)),i[e]=n}}return c.version!=null&&a.push(c),{frontmatter:{title:i.title??`Untitled`,category:i.category??`notes`,tags:i.tags??[],created:i.created??``,updated:i.updated??``,version:i.version??1,origin:`curated`,changelog:a},content:r}}};const A=`__pending__:`;function j(e){return e.startsWith(A)}function M(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function N(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var P=class{options;runtimes=new Map;maxSessions;sessionTimeoutMs;now;constructor(e){this.options=e,this.maxSessions=e.maxSessions??8,this.sessionTimeoutMs=(e.sessionTimeoutMinutes??30)*60*1e3,this.now=e.now??(()=>Date.now())}hasSession(e){return this.runtimes.has(e)}getSessionCount(){return this.runtimes.size}async handleRequest(e,t,n=e.body){let r=M(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){N(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){N(t,400,-32e3,`Session required`);return}if(i=await this.createRuntime(t),!i)return}await this.withRuntimeLock(i,async()=>{await i.transport.handleRequest(e,t,n),i.lastAccessAt=this.now();let r=i.transport.sessionId??i.id;e.method!==`DELETE`&&!j(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!j(r)&&await this.closeSession(r,{closeTransport:!1})})}async closeExpiredSessions(){let e=[...this.runtimes.values()].filter(e=>this.now()-e.lastAccessAt>=this.sessionTimeoutMs).map(e=>e.id);for(let t of e)await this.closeSession(t);return e.length}async closeSession(e,t={}){let n=this.runtimes.get(e);return n?(this.runtimes.delete(e),t.notifySessionEnd!==!1&&!j(e)&&this.options.onSessionEnd?.(e),t.closeTransport!==!1&&await n.transport.close().catch(()=>void 0),await n.server.close().catch(()=>void 0),!0):!1}async closeAll(){let e=[...this.runtimes.keys()];for(let t of e)await this.closeSession(t)}async createRuntime(e){if(await this.closeExpiredSessions(),this.runtimes.size>=this.maxSessions){N(e,503,-32003,`Session capacity reached`);return}let n=this.now(),r=await this.options.createServer(),i={id:`${A}${t()}`,transport:void 0,createdAt:n,lastAccessAt:n,server:r,requestChain:Promise.resolve()},a=this.options.createTransport({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{this.runtimes.delete(i.id),i.id=e,this.runtimes.set(e,i),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return i.transport=a,a.onclose=()=>{let e=i.transport.sessionId??i.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(i.id,i),await r.connect(a),i}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function F(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var I=class{stateStore;options;gcTimer=null;constructor(e,t={}){this.stateStore=e,this.options=t}onSessionStart(e,t){this.stateStore.sessionCreate(e,t)}onSessionActivity(e){this.stateStore.sessionTouch(e)}onSessionEnd(e){this.stateStore.sessionDelete(e),Promise.resolve(this.options.onSessionEndMaintenance?.(e)).catch(()=>{})}startGC(){if(this.gcTimer)return;let e=(this.options.gcIntervalMinutes??5)*60*1e3;this.gcTimer=setInterval(()=>{this.runGC()},e),this.gcTimer.unref()}runGC(){let e=this.getStaleSessionIds();for(let t of e)this.options.onBeforeSessionDelete?.(t),Promise.resolve(this.options.onSessionEndMaintenance?.(t)).catch(()=>{}),this.stateStore.sessionDelete(t);return e.length}stop(){this.gcTimer&&=(clearInterval(this.gcTimer),null)}getActiveSessions(){return this.stateStore.sessionList().length}listSessions(){return this.stateStore.sessionList()}getStaleSessionIds(e=Date.now()){let t=(this.options.staleTimeoutMinutes??30)*60*1e3;return this.stateStore.sessionList().filter(n=>{let r=F(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};function L(){try{let e=o(r(s(import.meta.url)),`..`,`..`,`..`,`package.json`);return JSON.parse(n(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}const R=d(`server`);function z(e,t){return t?{version:e,...f(t)}:{version:e}}const B=/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;function V({requestOrigin:e,configuredOrigin:t,allowAnyOrigin:n,fallbackOrigin:r}){let i=t??r;return i===`*`?n?{allowOrigin:`*`,warn:!1}:e?B.test(e)?{allowOrigin:e,warn:!1}:{allowOrigin:null,warn:!0}:{allowOrigin:r,warn:!1}:{allowOrigin:i,warn:!1}}function H({limit:e,windowMs:t}){let n=new Map,r=(e,r)=>{let i=r-t,a=n.get(e)?.filter(e=>e>i)??[];return a.length===0?(n.delete(e),[]):(n.set(e,a),a)};return{allow(t,i=Date.now()){let a=r(t,i);return a.length>=e?!1:(a.push(i),n.set(t,a),!0)},getRetryAfterMs(n,i=Date.now()){let a=r(n,i);return a.length<e?0:Math.max(0,a[0]+t-i)}}}function U(e){return e.startsWith(`file://`)?s(e):e}function W(e){let t=o(e);return process.platform===`win32`?t.toLowerCase():t}function G(e){let t=new Map;for(let n of e){let e=U(n.uri);t.set(W(e),e)}return[...t.values()].sort((e,t)=>W(e).localeCompare(W(t)))}function K({config:e,roots:t}){let n=G(t);if(n.length===0)return null;let r=e.sources?.[0]?.path;if(r){let e=W(r),t=n.find(t=>W(t)===e);if(t)return t}return n[0]}function q({config:e,log:t,reconfigureForWorkspace:n,roots:r}){let i=G(r);if(i.length===0)return!1;let a=K({config:e,roots:i.map(e=>({uri:e}))});if(!a)return!1;let o=e.sources?.[0]?.path,s=o&&W(o)===W(a)?`configured-source`:`stable-sorted-root`;return t.debug(`MCP roots resolved`,{rootPath:a,rootCount:i.length,selectedBy:s}),n(e,a),e.allRoots=i,!0}async function J({config:e,indexMode:t,log:n,rootsChangedNotificationSchema:r,reconfigureForWorkspace:i,runInitialIndex:a,server:o,startInit:s,timeoutMs:c=5e3,getCwd:l=()=>process.cwd()}){let u=L(),d=!1,p=!1,m,h=o.server,g=e=>{let t=f(e),n=`${String(e)} ${String(t.message??``)}`.toLowerCase();return n.includes(`method not found`)||n.includes(`not supported`)||n.includes(`unsupported`)||n.includes(`unknown method`)||n.includes(`roots/list`)||n.includes(`timed out`)},_=()=>{d||(d=!0,s())},v=()=>{p||t!==`auto`||(p=!0,(async()=>{try{await a()}catch(e){n.error(`Initial index failed`,z(u,e))}})())},y=t=>t.length===0||(m&&=(clearTimeout(m),void 0),!q({config:e,log:n,reconfigureForWorkspace:i,roots:t}))?!1:(_(),v(),!0);try{if(y((await h.listRoots()).roots))return;n.debug(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(t){if(g(t)){n.warn(`MCP roots/list not supported by client; using cwd fallback`,{version:u,cwd:l(),...f(t)}),q({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:l()}]})&&(_(),v());return}n.warn(`MCP roots/list failed during bootstrap; waiting for roots/list_changed notification`,{version:u,cwd:l(),...f(t)})}h.setNotificationHandler(r,async()=>{try{y((await h.listRoots()).roots)}catch(e){n.warn(`roots/list retry failed after notification`,z(u,e))}}),m=setTimeout(()=>{let t=l();n.debug(`Timed out waiting for MCP roots/list_changed; falling back to cwd workspace`,{cwd:t}),q({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:t}]})&&(_(),v())},c)}function Y(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function X(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===c(e).href}catch{return!1}}function Z(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function Q(e,t){let n=process.env[e];if(!n)return t;let r=Number.parseInt(n,10);return Number.isFinite(r)&&r>0?r:t}function $(){return X()?l({allowPositionals:!0,options:{transport:{type:`string`,default:Y()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:Y(),port:process.env.AIKIT_PORT??`3210`}}async function ee(){let e=L(),n=$();process.on(`unhandledRejection`,t=>{R.error(`Unhandled rejection`,z(e,t))}),process.on(`uncaughtException`,t=>{R.error(`Uncaught exception — exiting`,z(e,t)),process.exit(1)});let r=(t,n)=>{t.then(async()=>{try{let{markPromoteRun:e,markPruneRun:t,prune:r,shouldRunStartupPrune:i,shouldRunWeeklyPromote:a}=await import(`../../tools/dist/index.js`),o=n();if(!o)return;if(i()){let e=await r({});t(),e.totalBytesFreed>0&&R.info(`Storage maintenance complete`,{forgeOrphans:e.forgeGroundOrphans.count,legacyLance:e.legacyLance.count,bytesFreed:e.totalBytesFreed});let{groupLessons:n,pruneLessons:i}=await import(`./evolution-DWaEE6XW.js`).then(e=>e.t),a=await i(o.curated,o.stateStore,{dryRun:!1});a.pruned.length>0&&R.info(`Startup lesson prune complete`,{pruned:a.pruned.length});let s=await n(o.curated,o.stateStore,{dryRun:!1});(s.groupsCreated>0||s.lessonsGrouped>0)&&R.info(`Startup lesson grouping complete`,{groupsCreated:s.groupsCreated,lessonsGrouped:s.lessonsGrouped})}if(a()){let{DEFAULT_PROMOTE_CONFIG:t,collectWorkspaceLessons:n,getGlobalCuratedDir:r,promoteLessons:i,scanForDuplicates:a}=await import(`./promotion-bQutAIz-.js`).then(e=>e.o),s=o.curated,c=new k(r(),s.store,s.embedder),l=await n(),u={...t,dryRun:!1},d=await i(a(l,u),c,u);e(),d.promoted.length>0&&R.info(`Weekly lesson promotion complete`,{promoted:d.promoted.length,candidates:d.candidates.length})}}catch(t){R.warn(`Startup maintenance failed (non-critical)`,z(e,t))}}).catch(()=>{})};if(R.info(`Starting MCP AI Kit server`,{version:e}),n.transport===`http`){let[{default:i},{loadConfig:a,resolveIndexMode:o},{registerDashboardRoutes:s,resolveDashboardDir:c},{registerSettingsRoutes:l,resolveSettingsDir:u},{createSettingsRouter:d},{authMiddleware:m,getOrCreateToken:h}]=await Promise.all([import(`express`),import(`./config-CaJwUDXI.js`),import(`./dashboard-static-CRfR1yKU.js`),import(`./settings-static-B3lnYvcb.js`),import(`./routes-KC-D2U8n.js`),import(`./auth-lzZKfxlV.js`)]),g=a();p(g.logging?.errorDetails===!0),g.configError&&R.warn(`Config load failure`,{error:g.configError}),R.info(`Config loaded`,{sourceCount:g.sources.length,storePath:g.store.path});let _=i();_.use(i.json({limit:`1mb`}));let v=Number(n.port),y=`http://localhost:${v}`,b=process.env.AIKIT_CORS_ORIGIN??y,x=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,S=Q(`AIKIT_HTTP_MAX_SESSIONS`,8),C=Q(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),w=Q(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),T=H({limit:100,windowMs:6e4}),E=!1;_.use((e,t,n)=>{let r=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,i=V({requestOrigin:r,configuredOrigin:b,allowAnyOrigin:x,fallbackOrigin:y});if(i.warn&&!E&&(E=!0,R.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:r,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),r&&!i.allowOrigin){t.status(403).json({error:`Origin not allowed`});return}if(i.allowOrigin&&t.setHeader(`Access-Control-Allow-Origin`,i.allowOrigin),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID`),t.setHeader(`Access-Control-Expose-Headers`,`Mcp-Session-Id`),e.method===`OPTIONS`){t.status(204).end();return}n()});let D=h();_.use(m(D)),_.use(`/mcp`,(e,t,n)=>{let r=Z(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(T.allow(r)){n();return}let i=Math.max(1,Math.ceil(T.getRetryAfterMs(r)/1e3));t.setHeader(`Retry-After`,String(i)),t.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})});let O=!1;_.use(`/mcp`,(e,t,n)=>{if(!O){let t=e.headers[`x-workspace-root`];typeof t==`string`&&t.length>0&&(g.sources[0]={path:t,excludePatterns:g.sources[0]?.excludePatterns??[]},g.allRoots=[t],O=!0,R.debug(`Workspace root applied from proxy header`,{wsRoot:t}))}n()}),s(_,c(),R);let k=new Date().toISOString();_.use(`/settings/api`,d({log:R,mcpInfo:()=>({transport:`http`,port:v,pid:process.pid,startedAt:k})})),l(_,u(),R),_.get(`/health`,(e,t)=>{t.json({status:`ok`})});let A=!1,j=null,M=null,N=null,F=null,L=null,B=null,U=null,W=null,G=Promise.resolve(),K=async(e,n)=>{if(!A||!N||!F){n.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=G,i;G=new Promise(e=>{i=e}),await r;try{let r=Z(e);if(!B){if(r){n.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new F({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{U=e,M?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&M?.onSessionEnd(e),U=null}});e.onclose=()=>{B===e&&(B=null),U===e.sessionId&&(U=null)},B=e,await N.connect(e)}let i=B;await i.handleRequest(e,n,e.body),e.method!==`DELETE`&&(!r&&i.sessionId?(U=i.sessionId,M?.onSessionStart(i.sessionId,{transport:`http`}),M?.onSessionActivity(i.sessionId)):r&&M?.onSessionActivity(r))}catch(e){if(R.error(`MCP handler error`,f(e)),!n.headersSent){let t=e instanceof Error?e.message:String(e),r=t.includes(`Not Acceptable`);n.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?t:`Internal server error`},id:null})}}finally{i()}},q=async(e,t)=>{let n=Z(e);if(L&&(!B||n!==U)){await L.handleRequest(e,t,e.body);return}await K(e,t)};_.post(`/mcp`,q),_.get(`/mcp`,q),_.delete(`/mcp`,q);let J=_.listen(v,`127.0.0.1`,()=>{R.info(`MCP server listening`,{url:`http://127.0.0.1:${v}/mcp`,port:v}),setTimeout(async()=>{try{let[{createLazyServer:t,createMcpServer:n,ALL_TOOL_NAMES:i},{StreamableHTTPServerTransport:a},{checkForUpdates:s,autoUpgradeScaffold:c}]=await Promise.all([import(`./server-B02eYZOD.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-CJK1Fwmy.js`)]);s(),c(),setInterval(s,1440*60*1e3).unref();let l=o(g),u=t(g,l);W=async()=>{u.aikit&&await Promise.all([u.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),u.aikit.graphStore.close().catch(()=>{}),u.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),u.aikit.store.close().catch(()=>{})])},N=u.server,F=a,A=!0,R.debug(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:i.length,resourceCount:2}),u.startInit(),u.ready.then(()=>{if(!u.aikit)throw Error(`AI Kit components are not available after initialization`);M=new I(u.aikit.stateStore,{staleTimeoutMinutes:C,gcIntervalMinutes:w,onBeforeSessionDelete:e=>{if(U===e&&B){let e=B;B=null,U=null,e.close().catch(()=>void 0)}L?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!u.aikit?.curated||!u.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-DWaEE6XW.js`).then(e=>e.t),t=await e(u.aikit.curated,u.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&R.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),L=new P({createServer:()=>{if(!u.aikit)throw Error(`AI Kit components are not available after initialization`);return n(u.aikit,g)},createTransport:e=>new a(e),maxSessions:S,sessionTimeoutMinutes:C,onSessionStart:e=>M?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>M?.onSessionActivity(e),onSessionEnd:e=>M?.onSessionEnd(e)}),M.startGC(),U&&(M.onSessionStart(U,{transport:`http`}),M.onSessionActivity(U)),R.info(`HTTP session runtime ready`,{maxSessions:S,sessionTimeoutMinutes:C,gcIntervalMinutes:w})}).catch(e=>R.error(`Failed to start session manager`,f(e))),l===`auto`?u.ready.then(async()=>{try{let e=g.sources.map(e=>e.path).join(`, `);R.info(`Running initial index`,{sourcePaths:e}),await u.runInitialIndex(),R.info(`Initial index complete`)}catch(t){R.error(`Initial index failed; will retry on aikit_reindex`,z(e,t))}}).catch(t=>R.error(`AI Kit init or indexing failed`,z(e,t))):l===`smart`?u.ready.then(async()=>{try{if(!u.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(u.aikit.indexer,g,u.aikit.store),n=u.aikit.store;j=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),u.setSmartScheduler(t),R.debug(`Smart index scheduler started (HTTP mode)`)}catch(t){R.error(`Failed to start smart index scheduler`,z(e,t))}}).catch(t=>R.error(`AI Kit initialization failed`,z(e,t))):(u.ready.catch(t=>R.error(`AI Kit initialization failed`,z(e,t))),R.info(`Initial full indexing skipped in HTTP mode`,{indexMode:l})),r(u.ready,()=>u.aikit?{curated:u.aikit.curated,stateStore:u.aikit.stateStore}:null)}catch(t){R.error(`Failed to load server modules`,z(e,t))}},100)}),Y=!1,X=async e=>{Y||(Y=!0,R.info(`Shutdown signal received`,{signal:e}),j?.stop(),M?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await L?.closeAll().catch(()=>void 0),U&&M?.onSessionEnd(U),B&&(await B.close().catch(()=>void 0),B=null,U=null),J.close(),N&&await N.close(),await W?.().catch(()=>void 0),process.exit(0))};process.on(`SIGINT`,()=>X(`SIGINT`)),process.on(`SIGTERM`,()=>X(`SIGTERM`))}else{let[{loadConfig:t,reconfigureForWorkspace:n,resolveIndexMode:i},{createLazyServer:a},{checkForUpdates:o,autoUpgradeScaffold:s},{RootsListChangedNotificationSchema:c}]=await Promise.all([import(`./config-CaJwUDXI.js`),import(`./server-B02eYZOD.js`),import(`./version-check-CJK1Fwmy.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=t();p(l.logging?.errorDetails===!0),l.configError&&R.warn(`Config load failure`,{error:l.configError}),R.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),o(),s(),setInterval(o,1440*60*1e3).unref();let u=i(l),d=a(l,u),{server:f,startInit:m,ready:h,runInitialIndex:g}=d,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await f.connect(v),R.debug(`MCP server started`,{transport:`stdio`}),await J({config:l,indexMode:u,log:R,rootsChangedNotificationSchema:c,reconfigureForWorkspace:n,runInitialIndex:g,server:f,startInit:m});let y=null,b=null,x=!1,S=async e=>{x||(x=!0,R.info(`Shutdown signal received`,{signal:e}),y&&=(clearTimeout(y),null),b?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await v.close().catch(()=>void 0),await f.close().catch(()=>void 0),d.aikit&&await Promise.all([d.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),d.aikit.graphStore.close().catch(()=>{}),d.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),d.aikit.store.close().catch(()=>{})]),process.exit(0))},C=()=>{y&&clearTimeout(y),y=setTimeout(async()=>{R.info(`Auto-shutdown: no activity for 30 minutes — releasing resources`);try{let e=d.aikit;e&&(e.embedder.shutdown?.().catch(()=>{}),e.store.releaseMemory?.(),e.graphStore.releaseMemory?.())}catch{}},18e5),y.unref&&y.unref()};C(),process.stdin.on(`data`,()=>C()),process.stdin.on(`end`,()=>void S(`stdin-end`)),process.stdin.on(`close`,()=>void S(`stdin-close`)),process.stdin.on(`error`,()=>void S(`stdin-error`)),process.on(`SIGINT`,()=>void S(`SIGINT`)),process.on(`SIGTERM`,()=>void S(`SIGTERM`)),h.catch(t=>{R.error(`Initialization failed — server will continue with limited tools`,z(e,t))}),u===`smart`?h.then(async()=>{try{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(d.aikit.indexer,l,d.aikit.store);b=t;let n=d.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),d.setSmartScheduler(t),R.debug(`Smart index scheduler started (stdio mode)`)}catch(t){R.error(`Failed to start smart index scheduler`,z(e,t))}}).catch(t=>R.error(`AI Kit init failed for smart scheduler`,z(e,t))):R.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:u}),r(h,()=>d.aikit?{curated:d.aikit.curated,stateStore:d.aikit.stateStore}:null)}}ee();export{T as n,k as t};
|
|
8
|
+
`),s=!1,c={};for(let e of o){if(/^changelog:\s*$/.test(e)){s=!0;continue}if(s){let t=e.match(/^\s+-\s+version:\s*(\d+)$/);if(t){c.version!=null&&a.push(c),c={version:parseInt(t[1],10)};continue}let n=e.match(/^\s+date:\s*(.+)$/);if(n){c.date=n[1].trim();continue}let r=e.match(/^\s+reason:\s*"?(.*?)"?\s*$/);if(r){c.reason=r[1];continue}/^\w/.test(e)&&(s=!1,c.version!=null&&a.push(c),c={});continue}let t=e.match(/^(\w+):\s*(.*)$/);if(t){let e=t[1],n=t[2];typeof n==`string`&&n.startsWith(`[`)&&n.endsWith(`]`)?n=n.slice(1,-1).split(`,`).map(e=>e.trim().replace(/^"|"$/g,``)).filter(e=>e.length>0):typeof n==`string`&&/^\d+$/.test(n)?n=parseInt(n,10):typeof n==`string`&&n.startsWith(`"`)&&n.endsWith(`"`)&&(n=n.slice(1,-1)),i[e]=n}}return c.version!=null&&a.push(c),{frontmatter:{title:i.title??`Untitled`,category:i.category??`notes`,tags:i.tags??[],created:i.created??``,updated:i.updated??``,version:i.version??1,origin:`curated`,changelog:a},content:r}}};const B=i(`server`);function V(e,t){return t?{version:e,...a(t)}:{version:e}}function H(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function U(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===t(e).href}catch{return!1}}function W(){return U()?n({allowPositionals:!0,options:{transport:{type:`string`,default:H()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:H(),port:process.env.AIKIT_PORT??`3210`}}async function G(){let e=C(),t=W();if(process.on(`unhandledRejection`,t=>{B.error(`Unhandled rejection`,V(e,t))}),process.on(`uncaughtException`,t=>{B.error(`Uncaught exception — exiting`,V(e,t)),process.exit(1)}),B.info(`Starting MCP AI Kit server`,{version:e}),t.transport===`http`){let{startHttpMode:n}=await import(`./server-http-B-TDT3t-.js`);await n(e,t.port)}else{let{startStdioMode:t}=await import(`./server-stdio-BUb39kqq.js`);await t(e)}}G();export{w as a,O as i,F as n,T as o,P as r,D as s,z as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{o as e,t}from"./supersession-CWEne3av.js";import{fileURLToPath as n}from"node:url";import{AIKIT_RUNTIME_PATHS as r,EMBEDDING_DEFAULTS as i,computePartitionKey as a,createLogger as o,getPartitionDir as s,migrateLegacyWorkspaceLayout as c,serializeError as l}from"../../core/dist/index.js";import{existsSync as u,mkdirSync as d,readFileSync as f,writeFileSync as p}from"node:fs";import{dirname as m,isAbsolute as h,relative as g,resolve as _}from"node:path";const v={workingToEpisodicAccesses:2,episodicToSemanticReferences:3,semanticToProceduralVerifications:5},y={working:1,episodic:2,semantic:4,procedural:12};function b(e,t=v){switch(e.tier){case`working`:if(e.accessCount>=t.workingToEpisodicAccesses)return`episodic`;break;case`episodic`:if(e.accessCount>=t.workingToEpisodicAccesses+t.episodicToSemanticReferences)return`semantic`;break;case`semantic`:if(e.accessCount>=t.workingToEpisodicAccesses+t.episodicToSemanticReferences+t.semanticToProceduralVerifications)return`procedural`;break;case`procedural`:break;default:break}}function x(e,t,n){e.memoryMetaUpdateTier(t,n)}const S={stabilityHours:168,accessMultiplier:1.5,flagThreshold:.1,maxStabilityHours:8760};function C(e){return{...S,...e}}function w(e,t){if(!e)return t;let n=Date.parse(e);return Number.isNaN(n)?t:n}function T(e){return e&&e in y?e:`working`}function E(e,t,n,r=S,i){let a=typeof r==`string`?T(r):`working`,o=C(typeof r==`string`?i:r),s=w(e,w(n,Date.now())),c=Math.max(0,Date.now()-s)/(1e3*60*60),l=Math.min(o.stabilityHours*y[a]*o.accessMultiplier**Math.max(0,t),o.maxStabilityHours);return Math.exp(-c/l)}function D(e,t,n){let r=e.memoryMetaGet(t);if(!r)return;let i=E(r.lastAccessedAt,r.accessCount,r.createdAt,r.tier,n);return r.retentionScore!==i&&e.memoryMetaUpdateScore(t,i),e.memoryMetaGet(t)??{...r,retentionScore:i}}function O(e,t,n){e.memoryMetaGet(t)||e.memoryMetaCreate(t),e.memoryMetaTouch(t);let r=e.memoryMetaGet(t);if(!r)return 1;let i=E(r.lastAccessedAt,r.accessCount,r.createdAt,r.tier,n);return e.memoryMetaUpdateScore(t,i),i}function k(e,t){let n=C(t);return e.memoryMetaList().map(t=>D(e,t.entryId,n)??t).filter(e=>e.retentionScore<n.flagThreshold).sort((e,t)=>e.retentionScore-t.retentionScore)}const A=m(n(import.meta.url)),j=o(`server`),M=[`auto`,`manual`,`smart`],N={model:i.model,dimensions:i.dimensions,childProcess:!0,idleTimeoutMs:3e5};function P(e){return typeof e==`string`&&M.includes(e)}function F(e,t,n){let r=_(e),i=g(_(t),r);if(i.startsWith(`..`)||h(i))throw Error(`Config ${n} path escapes allowed root: ${e} is not under ${t}`);return r}function I(e,t){let n=_(e),r=g(_(t),n);return!(r.startsWith(`..`)||h(r))}function L(e){return s(a(e))}function R(e,t,n,r,i){let a=r?_(t,r):t;if(!n)return F(a,t,i);let o=_(e,n);return I(o,t)?r&&_(o)===_(t)?F(a,t,i):F(o,t,i):F(a,t,i)}function z(e){let t=[e.store?.path,e.curated?.path,e.onboardDir,e.stateDir];for(let e of t)e&&d(e,{recursive:!0})}function B(e,t){c(t);let n=L(t);e.store={...e.store,path:R(t,n,e.store?.path,r.data,`store`)},e.curated={...e.curated,path:R(t,n,e.curated?.path,r.curated,`curated`)},e.onboardDir=R(t,n,e.onboardDir,r.onboard,`onboard`),e.stateDir=R(t,n,e.stateDir,r.state,`state`)}function V(e){let t=process.env.AIKIT_INDEX_MODE;if(P(t))return t;if(e.indexMode)return e.indexMode;let n=process.env.AIKIT_AUTO_INDEX;return n===void 0?e.autoIndex===void 0?`smart`:e.autoIndex?`auto`:`manual`:n===`true`?`auto`:`manual`}function H(){let n=process.env.AIKIT_CONFIG_PATH??(u(_(process.cwd(),`aikit.config.json`))?_(process.cwd(),`aikit.config.json`):_(A,`..`,`..`,`..`,`aikit.config.json`));try{if(!u(n))return j.info(`No config file found, using defaults`,{configPath:n}),W();let r=f(n,`utf-8`),i=JSON.parse(r),a={...N,...i.embedding};if(i.embedding=a,i.memory={retention:{...S,...i.memory?.retention},lessons:{...e,...i.memory?.lessons},consolidation:{...v,...i.memory?.consolidation},supersession:{...t,...i.memory?.supersession}},i.logging?.errorDetails!==void 0&&typeof i.logging.errorDetails!=`boolean`)throw Error(`Config logging.errorDetails must be a boolean`);if(i.logging={errorDetails:i.logging?.errorDetails===!0},!i.sources||!Array.isArray(i.sources)||i.sources.length===0)throw Error(`Config must have at least one source`);if(!i.store?.path)throw Error(`Config must specify store.path`);if(i.autoIndex!==void 0&&typeof i.autoIndex!=`boolean`)throw Error(`Config autoIndex must be a boolean`);if(i.indexMode!==void 0&&!P(i.indexMode))throw Error(`Config indexMode must be one of: ${M.join(`, `)}`);if(typeof a.model!=`string`||a.model.trim()===``)throw Error(`Config embedding.model must be a non-empty string`);if(a.nativeDim!==void 0&&(!Number.isInteger(a.nativeDim)||a.nativeDim<=0))throw Error(`Config embedding.nativeDim must be a positive integer`);if(a.dimensions!==void 0&&(!Number.isInteger(a.dimensions)||a.dimensions<=0))throw Error(`Config embedding.dimensions must be a positive integer`);if(a.dimensions!==void 0&&a.nativeDim!==void 0&&a.dimensions>a.nativeDim)throw Error(`Config embedding.dimensions must not exceed embedding.nativeDim`);if(a.queryPrefix!==void 0&&typeof a.queryPrefix!=`string`)throw Error(`Config embedding.queryPrefix must be a string`);let o=m(n);return i.sources=i.sources.map(e=>({...e,path:F(_(o,e.path),o,`source`)})),G(i,n),B(i,o),i.indexMode=V(i),i}catch(e){let t=`Failed to load config from ${n}. ${e instanceof Error?e.message:String(e)}`;console.error(`\n ⚠ CONFIG ERROR — ${t}\n Check that the file exists, is valid JSON, and all required fields are present.\n`),j.error(`Failed to load config`,{configPath:n,...l(e)}),j.warn(`Falling back to default configuration`,{configPath:n});let r=W();return r.configError=t,r}}const U=[`.git/**`,`**/node_modules/**`,`*.lock`,`pnpm-lock.yaml`,`package-lock.json`,`**/dist/**`,`**/build/**`,`**/out/**`,`**/.output/**`,`**/cdk.out/**`,`**/.next/**`,`**/.nuxt/**`,`**/.vercel/**`,`**/.serverless/**`,`**/.turbo/**`,`**/.cache/**`,`**/.parcel-cache/**`,`**/coverage/**`,`**/.terraform/**`,`**/__pycache__/**`,`**/.venv/**`,`**/.docusaurus/**`,`**/.temp/**`,`**/tmp/**`];function W(){let n=process.env.AIKIT_WORKSPACE_ROOT??process.cwd(),i=L(n),a={sources:[{path:n,excludePatterns:[...U]}],serverName:`aikit`,indexing:{chunkSize:800,chunkOverlap:150,minChunkSize:100},embedding:{...N},store:{backend:`sqlite-vec`,path:_(i,r.data)},curated:{path:_(i,r.curated)},memory:{retention:{...S},lessons:{...e},consolidation:{...v},supersession:{...t}},logging:{errorDetails:!1},onboardDir:_(i,r.onboard),stateDir:_(i,r.state)};return a.indexMode=V(a),a}function G(e,t){let n=e.configVersion??0;if(n>=1)return e;if(n<1)for(let t of e.sources){t.excludePatterns=t.excludePatterns??[];let e=new Set(t.excludePatterns);for(let n of U)e.has(n)||t.excludePatterns.push(n)}e.configVersion=1;try{p(t,`${JSON.stringify(e,null,2)}\n`,`utf-8`),j.info(`Config auto-upgraded`,{from:n,to:1,configPath:t})}catch(e){j.warn(`Failed to write upgraded config`,{configPath:t,...l(e)})}return e}function K(e,t){if(!u(t))throw Error(`Workspace root does not exist: ${t}`);c(t),j.debug(`Reconfiguring for workspace root`,{workspaceRoot:t});try{process.chdir(t),j.debug(`Changed process cwd to workspace root`,{cwd:process.cwd()})}catch(e){j.warn(`Failed to chdir to workspace root`,{workspaceRoot:t,...l(e)})}e.sources=[{path:t,excludePatterns:e.sources[0]?.excludePatterns??[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],B(e,t),z(e)}export{U as DEFAULT_EXCLUDE_PATTERNS,b as a,v as i,H as loadConfig,D as n,x as o,O as r,K as reconfigureForWorkspace,V as resolveIndexMode,k as t};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{o as e,t}from"./supersession-DO_ZROFl.js";import{fileURLToPath as n}from"node:url";import{AIKIT_RUNTIME_PATHS as r,EMBEDDING_DEFAULTS as i,computePartitionKey as a,createLogger as o,getPartitionDir as s,migrateLegacyWorkspaceLayout as c,serializeError as l}from"../../core/dist/index.js";import{existsSync as u,mkdirSync as d,readFileSync as f,writeFileSync as p}from"node:fs";import{dirname as m,isAbsolute as h,relative as g,resolve as _}from"node:path";const v={workingToEpisodicAccesses:2,episodicToSemanticReferences:3,semanticToProceduralVerifications:5},y={working:1,episodic:2,semantic:4,procedural:12};function b(e,t=v){switch(e.tier){case`working`:if(e.accessCount>=t.workingToEpisodicAccesses)return`episodic`;break;case`episodic`:if(e.accessCount>=t.workingToEpisodicAccesses+t.episodicToSemanticReferences)return`semantic`;break;case`semantic`:if(e.accessCount>=t.workingToEpisodicAccesses+t.episodicToSemanticReferences+t.semanticToProceduralVerifications)return`procedural`;break;case`procedural`:break;default:break}}function x(e,t,n){e.memoryMetaUpdateTier(t,n)}const S={stabilityHours:168,accessMultiplier:1.5,flagThreshold:.1,maxStabilityHours:8760};function C(e){return{...S,...e}}function w(e,t){if(!e)return t;let n=Date.parse(e);return Number.isNaN(n)?t:n}function T(e){return e&&e in y?e:`working`}function E(e,t,n,r=S,i){let a=typeof r==`string`?T(r):`working`,o=C(typeof r==`string`?i:r),s=w(e,w(n,Date.now())),c=Math.max(0,Date.now()-s)/(1e3*60*60),l=Math.min(o.stabilityHours*y[a]*o.accessMultiplier**Math.max(0,t),o.maxStabilityHours);return Math.exp(-c/l)}function D(e,t,n){let r=e.memoryMetaGet(t);if(!r)return;let i=E(r.lastAccessedAt,r.accessCount,r.createdAt,r.tier,n);return r.retentionScore!==i&&e.memoryMetaUpdateScore(t,i),e.memoryMetaGet(t)??{...r,retentionScore:i}}function O(e,t,n){e.memoryMetaGet(t)||e.memoryMetaCreate(t),e.memoryMetaTouch(t);let r=e.memoryMetaGet(t);if(!r)return 1;let i=E(r.lastAccessedAt,r.accessCount,r.createdAt,r.tier,n);return e.memoryMetaUpdateScore(t,i),i}function k(e,t){let n=C(t);return e.memoryMetaList().map(t=>D(e,t.entryId,n)??t).filter(e=>e.retentionScore<n.flagThreshold).sort((e,t)=>e.retentionScore-t.retentionScore)}const A=m(n(import.meta.url)),j=o(`server`),M=[`auto`,`manual`,`smart`],N={model:i.model,dimensions:i.dimensions,childProcess:!0,idleTimeoutMs:3e5};function P(e){return typeof e==`string`&&M.includes(e)}function F(e,t,n){let r=_(e),i=g(_(t),r);if(i.startsWith(`..`)||h(i))throw Error(`Config ${n} path escapes allowed root: ${e} is not under ${t}`);return r}function I(e,t){let n=_(e),r=g(_(t),n);return!(r.startsWith(`..`)||h(r))}function L(e){return s(a(e))}function R(e,t,n,r,i){let a=r?_(t,r):t;if(!n)return F(a,t,i);let o=_(e,n);return I(o,t)?r&&_(o)===_(t)?F(a,t,i):F(o,t,i):F(a,t,i)}function z(e){let t=[e.store?.path,e.curated?.path,e.onboardDir,e.stateDir];for(let e of t)e&&d(e,{recursive:!0})}function B(e,t){c(t);let n=L(t);e.store={...e.store,path:R(t,n,e.store?.path,r.data,`store`)},e.curated={...e.curated,path:R(t,n,e.curated?.path,r.curated,`curated`)},e.onboardDir=R(t,n,e.onboardDir,r.onboard,`onboard`),e.stateDir=R(t,n,e.stateDir,r.state,`state`)}function V(e){let t=process.env.AIKIT_INDEX_MODE;if(P(t))return t;if(e.indexMode)return e.indexMode;let n=process.env.AIKIT_AUTO_INDEX;return n===void 0?e.autoIndex===void 0?`smart`:e.autoIndex?`auto`:`manual`:n===`true`?`auto`:`manual`}function H(){let n=process.env.AIKIT_CONFIG_PATH??(u(_(process.cwd(),`aikit.config.json`))?_(process.cwd(),`aikit.config.json`):_(A,`..`,`..`,`..`,`aikit.config.json`));try{if(!u(n))return j.info(`No config file found, using defaults`,{configPath:n}),W();let r=f(n,`utf-8`),i=JSON.parse(r),a={...N,...i.embedding};if(i.embedding=a,i.memory={retention:{...S,...i.memory?.retention},lessons:{...e,...i.memory?.lessons},consolidation:{...v,...i.memory?.consolidation},supersession:{...t,...i.memory?.supersession}},i.logging?.errorDetails!==void 0&&typeof i.logging.errorDetails!=`boolean`)throw Error(`Config logging.errorDetails must be a boolean`);if(i.logging={errorDetails:i.logging?.errorDetails===!0},!i.sources||!Array.isArray(i.sources)||i.sources.length===0)throw Error(`Config must have at least one source`);if(!i.store?.path)throw Error(`Config must specify store.path`);if(i.autoIndex!==void 0&&typeof i.autoIndex!=`boolean`)throw Error(`Config autoIndex must be a boolean`);if(i.indexMode!==void 0&&!P(i.indexMode))throw Error(`Config indexMode must be one of: ${M.join(`, `)}`);if(typeof a.model!=`string`||a.model.trim()===``)throw Error(`Config embedding.model must be a non-empty string`);if(a.nativeDim!==void 0&&(!Number.isInteger(a.nativeDim)||a.nativeDim<=0))throw Error(`Config embedding.nativeDim must be a positive integer`);if(a.dimensions!==void 0&&(!Number.isInteger(a.dimensions)||a.dimensions<=0))throw Error(`Config embedding.dimensions must be a positive integer`);if(a.dimensions!==void 0&&a.nativeDim!==void 0&&a.dimensions>a.nativeDim)throw Error(`Config embedding.dimensions must not exceed embedding.nativeDim`);if(a.queryPrefix!==void 0&&typeof a.queryPrefix!=`string`)throw Error(`Config embedding.queryPrefix must be a string`);let o=m(n);return i.sources=i.sources.map(e=>({...e,path:F(_(o,e.path),o,`source`)})),G(i,n),B(i,o),i.indexMode=V(i),i}catch(e){let t=`Failed to load config from ${n}. ${e instanceof Error?e.message:String(e)}`;console.error(`\n ⚠ CONFIG ERROR — ${t}\n Check that the file exists, is valid JSON, and all required fields are present.\n`),j.error(`Failed to load config`,{configPath:n,...l(e)}),j.warn(`Falling back to default configuration`,{configPath:n});let r=W();return r.configError=t,r}}const U=[`.git/**`,`**/node_modules/**`,`*.lock`,`pnpm-lock.yaml`,`package-lock.json`,`**/dist/**`,`**/build/**`,`**/out/**`,`**/.output/**`,`**/cdk.out/**`,`**/.next/**`,`**/.nuxt/**`,`**/.vercel/**`,`**/.serverless/**`,`**/.turbo/**`,`**/.cache/**`,`**/.parcel-cache/**`,`**/coverage/**`,`**/.terraform/**`,`**/__pycache__/**`,`**/.venv/**`,`**/.docusaurus/**`,`**/.temp/**`,`**/tmp/**`];function W(){let n=process.env.AIKIT_WORKSPACE_ROOT??process.cwd(),i=L(n),a={sources:[{path:n,excludePatterns:[...U]}],serverName:`aikit`,indexing:{chunkSize:800,chunkOverlap:150,minChunkSize:100},embedding:{...N},store:{backend:`sqlite-vec`,path:_(i,r.data)},curated:{path:_(i,r.curated)},memory:{retention:{...S},lessons:{...e},consolidation:{...v},supersession:{...t}},logging:{errorDetails:!1},onboardDir:_(i,r.onboard),stateDir:_(i,r.state)};return a.indexMode=V(a),a}function G(e,t){let n=e.configVersion??0;if(n>=1)return e;if(n<1)for(let t of e.sources){t.excludePatterns=t.excludePatterns??[];let e=new Set(t.excludePatterns);for(let n of U)e.has(n)||t.excludePatterns.push(n)}e.configVersion=1;try{p(t,`${JSON.stringify(e,null,2)}\n`,`utf-8`),j.info(`Config auto-upgraded`,{from:n,to:1,configPath:t})}catch(e){j.warn(`Failed to write upgraded config`,{configPath:t,...l(e)})}return e}function K(e,t){if(!u(t))throw Error(`Workspace root does not exist: ${t}`);c(t),j.debug(`Reconfiguring for workspace root`,{workspaceRoot:t});try{process.chdir(t),j.debug(`Changed process cwd to workspace root`,{cwd:process.cwd()})}catch(e){j.warn(`Failed to chdir to workspace root`,{workspaceRoot:t,...l(e)})}e.sources=[{path:t,excludePatterns:e.sources[0]?.excludePatterns??[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],B(e,t),z(e)}export{U as DEFAULT_EXCLUDE_PATTERNS,b as a,v as i,H as loadConfig,D as n,x as o,O as r,K as reconfigureForWorkspace,V as resolveIndexMode,k as t};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{HealthBus as e,createLogger as t,serializeError as n}from"../../core/dist/index.js";import{dirname as r,isAbsolute as i,join as a}from"node:path";import{createHash as o}from"node:crypto";import{GIT_REF_SLUG_PATTERN as s,gitAvailable as c,gitCommitToRef as l,gitExec as u,slugForRef as d}from"../../tools/dist/index.js";import{mkdir as f,readFile as p,readdir as m,stat as h,unlink as g,writeFile as _}from"node:fs/promises";var v=class{baseDir;constructor(e){this.baseDir=e}async initialize(){await f(this.baseDir,{recursive:!0})}async read(e){let t=a(this.baseDir,e);try{return await p(t,`utf-8`)}catch(e){if(e.code===`ENOENT`)return null;throw e}}async write(e,t,n){let i=a(this.baseDir,e);await f(r(i),{recursive:!0}),await _(i,t,{encoding:`utf-8`,flag:n?.exclusive?`wx`:`w`})}async delete(e){let t=a(this.baseDir,e);try{return await g(t),!0}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async list(e){let t=[],n=e?[e]:await this.listDirectories();for(let e of n){let n=a(this.baseDir,e),r;try{r=await m(n)}catch{continue}for(let n of r){if(!n.endsWith(`.md`))continue;let r=`${e}/${n}`,i=a(this.baseDir,r);try{let e=await h(i);t.push({path:r,size:e.size,mtimeMs:e.mtimeMs})}catch{}}}return t}async exists(e){let t=a(this.baseDir,e);try{return await h(t),!0}catch{return!1}}async listDirectories(){try{return(await m(this.baseDir,{withFileTypes:!0})).filter(e=>e.isDirectory()&&/^[a-z][a-z0-9-]*$/.test(e.name)).map(e=>e.name)}catch{return[]}}async close(){}};const y=50*1024,b=`refs/aikit/knowledge`,x=t(`server`);var S=class{curatedDir;store;embedder;adapter;constructor(e,t,n,r=new v(e)){this.curatedDir=e,this.store=t,this.embedder=n,this.adapter=r}async remember(e,t,n,r=[]){this.validateCategoryName(n),this.validateContentSize(t);let i=this.normalizeTags(r),a=this.slugify(e),o=await this.uniqueRelativePath(n,a),s=new Date().toISOString(),c={title:e,category:n,tags:i,created:s,updated:s,version:1,origin:`curated`,changelog:[{version:1,date:s,reason:`Initial creation`}]},l=this.serializeFile(t,c);try{await this.adapter.write(o,l,{exclusive:!0})}catch(e){throw e.code===`EEXIST`?Error(`Concurrent write collision for "${o}" — retry the operation`):e}return this.gitCommitKnowledge(o,l,`remember: ${e}\n\nCategory: ${n}\nTags: ${i.join(`, `)}`),await this.indexCuratedFileBestEffort(o,t,c,`remember`),{path:o}}async upsertAutoKnowledge(e,t,n,r,i=[],a=`Auto-knowledge refresh`){e=this.guardPath(e),this.validateCategoryName(r),this.validateContentSize(n),this.ensureCategoryPath(e,r);let o=this.normalizeTags(i),s=await this.adapter.read(e);if(s==null){let i=new Date().toISOString(),a={title:t,category:r,tags:o,created:i,updated:i,version:1,origin:`curated`,changelog:[{version:1,date:i,reason:`Initial creation`}]},s=this.serializeFile(n,a);try{await this.adapter.write(e,s,{exclusive:!0})}catch(t){throw t.code===`EEXIST`?Error(`Concurrent write collision for "${e}" — retry the operation`):t}return this.gitCommitKnowledge(e,s,`remember: ${t}\n\nCategory: ${r}\nTags: ${o.join(`, `)}`),await this.indexCuratedFileBestEffort(e,n,a,`remember`),{path:e,status:`created`,version:1}}let{frontmatter:c,content:l}=this.parseFile(s),u=this.normalizeTags(c.tags??[]),d=t.trim()||c.title;if(l===n&&c.category===r&&c.title===d&&this.sameTags(u,o))return{path:e,status:`unchanged`,version:c.version??1};let f=(c.version??1)+1,p=new Date().toISOString();c.title=d,c.category=r,c.tags=o,c.version=f,c.updated=p,c.changelog=[...c.changelog??[],{version:f,date:p,reason:a}];let m=this.serializeFile(n,c);return await this.adapter.write(e,m),this.gitCommitKnowledge(e,m,`update(v${f}): ${c.title}\n\nReason: ${a}\nVersion: ${f}`),await this.indexCuratedFileBestEffort(e,n,c,`update`),{path:e,status:`updated`,version:f}}async update(e,t,n){e=this.guardPath(e),this.validateContentSize(t);let r=await this.adapter.read(e);if(r==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:i}=this.parseFile(r),a=(i.version??1)+1,o=new Date().toISOString();i.version=a,i.updated=o,i.changelog=[...i.changelog??[],{version:a,date:o,reason:n}];let s=this.serializeFile(t,i);return await this.adapter.write(e,s),this.gitCommitKnowledge(e,s,`update(v${a}): ${i.title}\n\nReason: ${n}\nVersion: ${a}`),await this.indexCuratedFileBestEffort(e,t,i,`update`),{path:e,version:a}}async forget(e,t){if(e=this.guardPath(e),!await this.adapter.delete(e))throw Error(`Curated entry not found: ${e}`);let r=`.ai/curated/${e}`;return await this.store.deleteBySourcePath(r).catch(e=>{x.warn(`File deleted but vector cleanup failed`,{sourcePath:r,...n(e)})}),this.gitDeleteKnowledgeRef(e),{path:e}}async history(e,t=20){if(e=this.guardPath(e),!c(this.curatedDir))return[];let n=this.knowledgeRefForPath(e);if(!n)return[];let r=u([`log`,`--format=%H|%aI|%s`,n,`-n`,String(t)],this.curatedDir);return r?r.split(`
|
|
2
2
|
`).filter(Boolean).map(e=>{let[t,n,...r]=e.split(`|`);return{sha:t,date:n,message:r.join(`|`)}}):[]}async diff(e,t,n){if(e=this.guardPath(e),!c(this.curatedDir))return``;if(!n){let r=await this.history(e,2);if(r.length===0)return``;n=r[0].sha,r.length>1&&!t&&(t=r[1].sha)}return t&&n?u([`diff`,`${t}:entry.md`,`${n}:entry.md`],this.curatedDir)??``:n?u([`show`,`${n}:entry.md`],this.curatedDir)??``:``}async recover(e){if(e=this.guardPath(e),await this.adapter.exists(e))throw Error(`Entry already exists on filesystem: ${e}. Use update() instead.`);if(!c(this.curatedDir))return null;let t=this.knowledgeRefForPath(e);if(!t)return null;let n=u([`show`,`${t}:entry.md`],this.curatedDir);if(!n)return null;await this.adapter.write(e,n);let{frontmatter:r,content:i}=this.parseFile(n);return await this.indexCuratedFile(e,i,r),{path:e,version:r.version??1}}async listOrphaned(){if(!c(this.curatedDir))return[];let e=u([`for-each-ref`,`--format=%(refname)|%(subject)`,`${b}/`],this.curatedDir);if(!e)return[];let t=[];for(let n of e.split(`
|
|
3
|
-
`).filter(Boolean)){let[e,...r]=n.split(`|`),i=r.join(`|`),a=`${e.replace(`${b}/`,``)}.md`;await this.adapter.exists(a)||t.push({ref:e,path:a,lastMessage:i})}return t}async read(e){e=this.guardPath(e);let t=await this.adapter.read(e);if(t==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:n,content:r}=this.parseFile(t),i=e.split(`/`)[0];return{path:e,title:n.title??e,category:i,tags:n.tags??[],version:n.version??1,created:n.created??``,updated:n.updated??``,contentPreview:r.slice(0,200),content:r}}async list(e){return(await this.listPage(e)).entries}async listPage(e){let t=e?.category?[e.category]:await this.discoverCategories(),n=[];for(let e of t){let t=await this.adapter.list(e);for(let r of t)n.push({path:r.path,category:e,mtimeMs:r.mtimeMs??0})}let r=Math.max(0,e?.offset??0),i=e?.limit==null?null:Math.max(1,e.limit),a=(e?.order??`asc`)===`desc`?-1:1,o=e?.orderBy??`path`;if(o===`path`||o===`updated`){let t=this.sortCandidateMetadata(n,o,a);if(e?.tag){let n=i==null?void 0:r+i+1,{entries:a,scannedAll:o}=await this.readCandidateEntries(t,{tag:e.tag,maxMatches:n}),s=i==null?a.slice(r):a.slice(r,r+i),c=i!=null&&(a.length>r+s.length||!o);return{entries:s,totalCount:o?a.length:r+s.length+ +!!c,totalCountIsExact:o,limit:i,offset:r,hasMore:c}}let s=i==null?t.slice(r):t.slice(r,r+i),{entries:c}=await this.readCandidateEntries(s);return{entries:c,totalCount:t.length,totalCountIsExact:!0,limit:i,offset:r,hasMore:i!=null&&r+c.length<t.length}}let{entries:s}=await this.readCandidateEntries(n,{tag:e?.tag}),c=s.sort((e,t)=>{switch(o){case`created`:return(Date.parse(e.created)-Date.parse(t.created))*a;case`updated`:return(Date.parse(e.updated)-Date.parse(t.updated))*a;case`path`:return e.path.localeCompare(t.path)*a;default:return 0}}),l=i==null?c.slice(r):c.slice(r,r+i);return{entries:l,totalCount:c.length,totalCountIsExact:!0,limit:i,offset:r,hasMore:i!=null&&r+l.length<c.length}}async count(e){if(e?.tag)return(await this.listPage({...e,limit:void 0})).totalCount;let t=e?.category?[e.category]:await this.discoverCategories(),n=0;for(let e of t)n+=(await this.adapter.list(e)).length;return n}async listPaths(e){let t=e?.category?[e.category]:await this.discoverCategories(),n=[];for(let e of t){let t=await this.adapter.list(e);n.push(...t.map(e=>e.path))}n.sort((e,t)=>e.localeCompare(t));let r=Math.max(0,e?.offset??0),i=e?.limit==null?null:Math.max(1,e.limit);return i==null?n.slice(r):n.slice(r,r+i)}sortCandidateMetadata(e,t,n){return[...e].sort((e,r)=>t===`updated`?(e.mtimeMs-r.mtimeMs)*n:e.path.localeCompare(r.path)*n)}async readCandidateEntries(e,t){let n=[];for(let r of e){let e=await this.adapter.read(r.path);if(e==null)continue;let{frontmatter:i,content:a}=this.parseFile(e),o=i.tags??[];if(!(t?.tag&&!o.includes(t.tag))&&(n.push({path:r.path,title:i.title??r.path,category:r.category,tags:o,version:i.version??1,created:i.created??``,updated:i.updated??``,contentPreview:a.slice(0,200)}),t?.maxMatches!=null&&n.length>=t.maxMatches))return{entries:n,scannedAll:!1}}return{entries:n,scannedAll:!0}}async reindexAll(){let e=await this.discoverCategories(),t=[],
|
|
4
|
-
`).length,fileHash:this.hash(e.content),indexedAt:t,origin:`curated`,tags:e.frontmatter.tags,category:e.frontmatter.category,version:e.frontmatter.version}});try{return await this.store.upsert(i
|
|
5
|
-
`).length,fileHash:this.hash(t),indexedAt:a,origin:`curated`,tags:n.tags,category:n.category,version:n.version};await this.store.upsert([o],[r])}async indexCuratedFileBestEffort(
|
|
3
|
+
`).filter(Boolean)){let[e,...r]=n.split(`|`),i=r.join(`|`),a=`${e.replace(`${b}/`,``)}.md`;await this.adapter.exists(a)||t.push({ref:e,path:a,lastMessage:i})}return t}async read(e){e=this.guardPath(e);let t=await this.adapter.read(e);if(t==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:n,content:r}=this.parseFile(t),i=e.split(`/`)[0];return{path:e,title:n.title??e,category:i,tags:n.tags??[],version:n.version??1,created:n.created??``,updated:n.updated??``,contentPreview:r.slice(0,200),content:r}}async list(e){return(await this.listPage(e)).entries}async listPage(e){let t=e?.category?[e.category]:await this.discoverCategories(),n=[];for(let e of t){let t=await this.adapter.list(e);for(let r of t)n.push({path:r.path,category:e,mtimeMs:r.mtimeMs??0})}let r=Math.max(0,e?.offset??0),i=e?.limit==null?null:Math.max(1,e.limit),a=(e?.order??`asc`)===`desc`?-1:1,o=e?.orderBy??`path`;if(o===`path`||o===`updated`){let t=this.sortCandidateMetadata(n,o,a);if(e?.tag){let n=i==null?void 0:r+i+1,{entries:a,scannedAll:o}=await this.readCandidateEntries(t,{tag:e.tag,maxMatches:n}),s=i==null?a.slice(r):a.slice(r,r+i),c=i!=null&&(a.length>r+s.length||!o);return{entries:s,totalCount:o?a.length:r+s.length+ +!!c,totalCountIsExact:o,limit:i,offset:r,hasMore:c}}let s=i==null?t.slice(r):t.slice(r,r+i),{entries:c}=await this.readCandidateEntries(s);return{entries:c,totalCount:t.length,totalCountIsExact:!0,limit:i,offset:r,hasMore:i!=null&&r+c.length<t.length}}let{entries:s}=await this.readCandidateEntries(n,{tag:e?.tag}),c=s.sort((e,t)=>{switch(o){case`created`:return(Date.parse(e.created)-Date.parse(t.created))*a;case`updated`:return(Date.parse(e.updated)-Date.parse(t.updated))*a;case`path`:return e.path.localeCompare(t.path)*a;default:return 0}}),l=i==null?c.slice(r):c.slice(r,r+i);return{entries:l,totalCount:c.length,totalCountIsExact:!0,limit:i,offset:r,hasMore:i!=null&&r+l.length<c.length}}async count(e){if(e?.tag)return(await this.listPage({...e,limit:void 0})).totalCount;let t=e?.category?[e.category]:await this.discoverCategories(),n=0;for(let e of t)n+=(await this.adapter.list(e)).length;return n}async listPaths(e){let t=e?.category?[e.category]:await this.discoverCategories(),n=[];for(let e of t){let t=await this.adapter.list(e);n.push(...t.map(e=>e.path))}n.sort((e,t)=>e.localeCompare(t));let r=Math.max(0,e?.offset??0),i=e?.limit==null?null:Math.max(1,e.limit);return i==null?n.slice(r):n.slice(r,r+i)}sortCandidateMetadata(e,t,n){return[...e].sort((e,r)=>t===`updated`?(e.mtimeMs-r.mtimeMs)*n:e.path.localeCompare(r.path)*n)}async readCandidateEntries(e,t){let n=[];for(let r of e){let e=await this.adapter.read(r.path);if(e==null)continue;let{frontmatter:i,content:a}=this.parseFile(e),o=i.tags??[];if(!(t?.tag&&!o.includes(t.tag))&&(n.push({path:r.path,title:i.title??r.path,category:r.category,tags:o,version:i.version??1,created:i.created??``,updated:i.updated??``,contentPreview:a.slice(0,200)}),t?.maxMatches!=null&&n.length>=t.maxMatches))return{entries:n,scannedAll:!1}}return{entries:n,scannedAll:!0}}async reindexAll(){let e=await this.discoverCategories(),t=[],r=[];for(let i of e){let e=await this.adapter.list(i);for(let i of e){let e=i.path;try{let n=await this.adapter.read(e);if(n==null){t.push(`${e}: read failed`);continue}let{frontmatter:i,content:a}=this.parseFile(n);r.push({relativePath:e,content:a,frontmatter:i})}catch(r){x.error(`Failed to read curated file`,{relativePath:e,...n(r)}),t.push(`${e}: read failed`)}}}if(r.length===0)return{indexed:0,errors:t};let i=new Date().toISOString(),a=0;for(let e=0;e<r.length;e+=16){let n=r.slice(e,e+16);a+=await this.embedAndUpsertBatch(n,i,t)}return{indexed:a,errors:t}}async embedAndUpsertBatch(e,t,r){try{let i=await this.embedder.embedBatch(e.map(e=>e.content)),a=e.map(e=>{let n=`.ai/curated/${e.relativePath}`;return{id:this.hashId(n,0),content:e.content,sourcePath:n,contentType:`curated-knowledge`,headingPath:e.frontmatter.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:e.content.split(`
|
|
4
|
+
`).length,fileHash:this.hash(e.content),indexedAt:t,origin:`curated`,tags:e.frontmatter.tags,category:e.frontmatter.category,version:e.frontmatter.version}});try{return await this.store.upsert(a,i),e.length}catch(t){x.error(`Failed to upsert curated batch`,{batchSize:e.length,...n(t)});for(let t of e)r.push(`${t.relativePath}: upsert failed`);return 0}}catch(i){if(e.length===1)return x.error(`Failed to embed curated item`,{relativePath:e[0].relativePath,...n(i)}),r.push(`${e[0].relativePath}: reindex failed`),0;x.warn(`Curated embed batch failed, retrying with smaller chunks`,{batchSize:e.length,...n(i)});let a=Math.ceil(e.length/2),o=e.slice(0,a),s=e.slice(a);return await this.embedAndUpsertBatch(o,t,r)+await this.embedAndUpsertBatch(s,t,r)}}gitCommitKnowledge(e,t,n){try{if(!c(this.curatedDir))return;let r=this.knowledgeRefForPath(e);if(!r)return;l(r,`entry.md`,t,n,this.curatedDir)}catch{}}gitDeleteKnowledgeRef(e){try{if(!c(this.curatedDir))return;let t=this.knowledgeRefForPath(e);if(!t)return;u([`update-ref`,`-d`,t],this.curatedDir)}catch{}}knowledgeRefForPath(e){let t=e.replace(/\.md$/,``).split(`/`).map(e=>d(e)).join(`/`);return t.split(`/`).every(e=>s.test(e))?`${b}/${t}`:null}async indexCuratedFile(e,t,n){let r=await this.embedder.embed(t),i=`.ai/curated/${e}`,a=new Date().toISOString(),o={id:this.hashId(i,0),content:t,sourcePath:i,contentType:`curated-knowledge`,headingPath:n.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:t.split(`
|
|
5
|
+
`).length,fileHash:this.hash(t),indexedAt:a,origin:`curated`,tags:n.tags,category:n.category,version:n.version};await this.store.upsert([o],[r])}async indexCuratedFileBestEffort(t,r,i,a){if(e.instance().isDegraded(`embedder`)){x.debug(`Skipping vector indexing — embedder degraded`,{relativePath:t,operation:a,subsystem:`embedder`});return}try{await this.indexCuratedFile(t,r,i)}catch(e){x.warn(`Curated file persisted but vector indexing deferred`,{relativePath:t,operation:a,...n(e)})}}async discoverCategories(){return this.adapter.listDirectories()}guardPath(e){let t=e.replace(/^\.ai\/curated\//,``);if(t.endsWith(`.md`)||(t+=`.md`),t.includes(`..`)||i(t))throw Error(`Invalid path: ${t}. Must be relative within .ai/curated/ directory.`);let n=t.split(`/`)[0];return this.validateCategoryName(n),t}validateCategoryName(e){if(!/^[a-z][a-z0-9-]*$/.test(e))throw Error(`Invalid category name: "${e}". Must be lowercase kebab-case (e.g., "decisions", "api-contracts").`)}validateContentSize(e){if(Buffer.byteLength(e,`utf-8`)>y)throw Error(`Content exceeds maximum size of ${y/1024}KB`)}slugify(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-|-$/g,``).slice(0,80)}normalizeTags(e){return[...new Set(e.map(e=>e.trim()).filter(Boolean))]}sameTags(e,t){if(e.length!==t.length)return!1;let n=new Set(e);return t.every(e=>n.has(e))}ensureCategoryPath(e,t){if(!e.startsWith(`${t}/`))throw Error(`Curated path "${e}" must stay within category "${t}"`)}async uniqueRelativePath(e,t){let n=`${e}/${t}.md`;if(!await this.adapter.exists(n))return n;for(let n=2;n<=100;n++){let r=`${e}/${t}-${n}.md`;if(!await this.adapter.exists(r))return r}throw Error(`Too many entries with slug "${t}" in category "${e}"`)}hash(e){return o(`sha256`).update(e).digest(`hex`).slice(0,16)}hashId(e,t){return this.hash(`${e}::${t}`)}serializeFile(e,t){return`${[`---`,`title: "${t.title.replace(/"/g,`\\"`)}"`,`category: ${t.category}`,`tags: [${t.tags.map(e=>`"${e}"`).join(`, `)}]`,`created: ${t.created}`,`updated: ${t.updated}`,`version: ${t.version}`,`origin: ${t.origin}`,`changelog:`,...t.changelog.map(e=>` - version: ${e.version}\n date: ${e.date}\n reason: "${e.reason.replace(/"/g,`\\"`)}"`),`---`].join(`
|
|
6
6
|
`)}\n\n${e}\n`}parseFile(e){let t=e.match(/^---\n([\s\S]*?)\n---\n\n?([\s\S]*)$/);if(!t)return{frontmatter:{title:`Untitled`,category:`notes`,tags:[],created:``,updated:``,version:1,origin:`curated`,changelog:[]},content:e};let n=t[1],r=t[2].trim(),i={},a=[],o=n.split(`
|
|
7
7
|
`),s=!1,c={};for(let e of o){if(/^changelog:\s*$/.test(e)){s=!0;continue}if(s){let t=e.match(/^\s+-\s+version:\s*(\d+)$/);if(t){c.version!=null&&a.push(c),c={version:parseInt(t[1],10)};continue}let n=e.match(/^\s+date:\s*(.+)$/);if(n){c.date=n[1].trim();continue}let r=e.match(/^\s+reason:\s*"?(.*?)"?\s*$/);if(r){c.reason=r[1];continue}/^\w/.test(e)&&(s=!1,c.version!=null&&a.push(c),c={});continue}let t=e.match(/^(\w+):\s*(.*)$/);if(t){let e=t[1],n=t[2];typeof n==`string`&&n.startsWith(`[`)&&n.endsWith(`]`)?n=n.slice(1,-1).split(`,`).map(e=>e.trim().replace(/^"|"$/g,``)).filter(e=>e.length>0):typeof n==`string`&&/^\d+$/.test(n)?n=parseInt(n,10):typeof n==`string`&&n.startsWith(`"`)&&n.endsWith(`"`)&&(n=n.slice(1,-1)),i[e]=n}}return c.version!=null&&a.push(c),{frontmatter:{title:i.title??`Untitled`,category:i.category??`notes`,tags:i.tags??[],created:i.created??``,updated:i.updated??``,version:i.version??1,origin:`curated`,changelog:a},content:r}}};export{v as n,S as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as e}from"./resolve-sibling-BmZ7AxaA.js";import{fileURLToPath as t}from"node:url";import{createReadStream as n,existsSync as r,statSync as i}from"node:fs";import{dirname as a,extname as o,join as s,resolve as c,sep as l}from"node:path";const u=import.meta.dirname??a(t(import.meta.url)),d={".html":`text/html`,".js":`application/javascript`,".css":`text/css`,".json":`application/json`,".png":`image/png`,".svg":`image/svg+xml`,".ico":`image/x-icon`,".woff":`font/woff`,".woff2":`font/woff2`};function f(t){return t?s(t,`..`,`..`,`dashboard`,`dist`):e(`dashboard`)??s(u,`..`,`..`,`dashboard`,`dist`)}function p(e,t){let n=t.replace(/^\/_dashboard\/?/,``)||`index.html`;try{n=decodeURIComponent(n)}catch{}let a=c(e,n);if(!(a===e||a.startsWith(`${e}${l}`)))return{kind:`forbidden`};try{if(i(a).isFile())return{kind:`file`,path:a,contentType:d[o(a)]??`application/octet-stream`}}catch{}let u=s(e,`index.html`);return r(u)?{kind:`spa`,path:u,contentType:`text/html`}:{kind:`not-found`}}function m(e,t,i){return r(t)?(e.get(`/_dashboard{/*path}`,(e,r)=>{let i=p(t,e.path);if(i.kind===`forbidden`){r.status(403).end(`Forbidden`);return}if(i.kind===`not-found`){r.status(404).end(`Not found`);return}r.setHeader(`Content-Type`,i.contentType),i.kind===`file`&&/\.[a-f0-9]{8,}\.(js|css)$/i.test(i.path)?r.setHeader(`Cache-Control`,`public, max-age=31536000, immutable`):r.setHeader(`Cache-Control`,`no-cache`),n(i.path).pipe(r)}),i.info(`Dashboard available`,{url:`/_dashboard/`,dir:t}),!0):!1}export{m as registerDashboardRoutes,f as resolveDashboardDir,p as resolveDashboardRequest};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{t as e}from"./resolve-sibling-DrGKPpb0.js";import{fileURLToPath as t}from"node:url";import{createReadStream as n,existsSync as r,statSync as i}from"node:fs";import{dirname as a,extname as o,join as s,resolve as c,sep as l}from"node:path";const u=import.meta.dirname??a(t(import.meta.url)),d={".html":`text/html`,".js":`application/javascript`,".css":`text/css`,".json":`application/json`,".png":`image/png`,".svg":`image/svg+xml`,".ico":`image/x-icon`,".woff":`font/woff`,".woff2":`font/woff2`};function f(t){return t?s(t,`..`,`..`,`dashboard`,`dist`):e(`dashboard`)??s(u,`..`,`..`,`dashboard`,`dist`)}function p(e,t){let n=t.replace(/^\/_dashboard\/?/,``)||`index.html`;try{n=decodeURIComponent(n)}catch{}let a=c(e,n);if(!(a===e||a.startsWith(`${e}${l}`)))return{kind:`forbidden`};try{if(i(a).isFile())return{kind:`file`,path:a,contentType:d[o(a)]??`application/octet-stream`}}catch{}let u=s(e,`index.html`);return r(u)?{kind:`spa`,path:u,contentType:`text/html`}:{kind:`not-found`}}function m(e,t,i){return r(t)?(e.get(`/_dashboard{/*path}`,(e,r)=>{let i=p(t,e.path);if(i.kind===`forbidden`){r.status(403).end(`Forbidden`);return}if(i.kind===`not-found`){r.status(404).end(`Not found`);return}r.setHeader(`Content-Type`,i.contentType),i.kind===`file`&&/\.[a-f0-9]{8,}\.(js|css)$/i.test(i.path)?r.setHeader(`Cache-Control`,`public, max-age=31536000, immutable`):r.setHeader(`Cache-Control`,`no-cache`),n(i.path).pipe(r)}),i.info(`Dashboard available`,{url:`/_dashboard/`,dir:t}),!0):!1}export{m as registerDashboardRoutes,f as resolveDashboardDir,p as resolveDashboardRequest};
|
|
@@ -1,6 +1,102 @@
|
|
|
1
1
|
import { IKnowledgeStore } from "../../store/dist/index.js";
|
|
2
2
|
import { IEmbedder } from "../../embeddings/dist/index.js";
|
|
3
3
|
|
|
4
|
+
//#region packages/server/src/server-utils.d.ts
|
|
5
|
+
declare function readVersion(): string;
|
|
6
|
+
declare function getSessionIdHeader(req: import('express').Request): string | undefined;
|
|
7
|
+
declare function readPositiveIntEnv(name: string, fallback: number): number;
|
|
8
|
+
interface CorsOriginResolution {
|
|
9
|
+
allowOrigin: string | null;
|
|
10
|
+
warn: boolean;
|
|
11
|
+
}
|
|
12
|
+
interface ResolveCorsOriginOptions {
|
|
13
|
+
requestOrigin: string | undefined;
|
|
14
|
+
configuredOrigin: string | undefined;
|
|
15
|
+
allowAnyOrigin: boolean;
|
|
16
|
+
fallbackOrigin: string;
|
|
17
|
+
}
|
|
18
|
+
declare function resolveCorsOrigin({
|
|
19
|
+
requestOrigin,
|
|
20
|
+
configuredOrigin,
|
|
21
|
+
allowAnyOrigin,
|
|
22
|
+
fallbackOrigin
|
|
23
|
+
}: ResolveCorsOriginOptions): CorsOriginResolution;
|
|
24
|
+
interface SlidingWindowRateLimiter {
|
|
25
|
+
allow: (key: string, now?: number) => boolean;
|
|
26
|
+
getRetryAfterMs: (key: string, now?: number) => number;
|
|
27
|
+
}
|
|
28
|
+
declare function createSlidingWindowRateLimiter({
|
|
29
|
+
limit,
|
|
30
|
+
windowMs
|
|
31
|
+
}: {
|
|
32
|
+
limit: number;
|
|
33
|
+
windowMs: number;
|
|
34
|
+
}): SlidingWindowRateLimiter;
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region packages/server/src/workspace-bootstrap.d.ts
|
|
37
|
+
type WorkspaceLogger = {
|
|
38
|
+
debug: (msg: string, data?: Record<string, unknown>) => void;
|
|
39
|
+
info: (msg: string, data?: Record<string, unknown>) => void;
|
|
40
|
+
warn: (msg: string, data?: Record<string, unknown>) => void;
|
|
41
|
+
error: (msg: string, data?: Record<string, unknown>) => void;
|
|
42
|
+
};
|
|
43
|
+
type WorkspaceRootConfig = {
|
|
44
|
+
allRoots?: string[];
|
|
45
|
+
sources?: Array<{
|
|
46
|
+
path: string;
|
|
47
|
+
}>;
|
|
48
|
+
};
|
|
49
|
+
type WorkspaceRootApplyDeps<Config extends WorkspaceRootConfig> = {
|
|
50
|
+
config: Config;
|
|
51
|
+
log: WorkspaceLogger;
|
|
52
|
+
reconfigureForWorkspace: (config: Config, workspaceRoot: string) => void;
|
|
53
|
+
roots: Array<{
|
|
54
|
+
uri: string;
|
|
55
|
+
}>;
|
|
56
|
+
};
|
|
57
|
+
type WorkspaceRootBootstrapDeps<Config extends {
|
|
58
|
+
allRoots?: string[];
|
|
59
|
+
}> = {
|
|
60
|
+
config: Config;
|
|
61
|
+
indexMode: string;
|
|
62
|
+
log: WorkspaceLogger;
|
|
63
|
+
rootsChangedNotificationSchema: unknown;
|
|
64
|
+
reconfigureForWorkspace: (config: Config, workspaceRoot: string) => void;
|
|
65
|
+
runInitialIndex: () => Promise<unknown> | undefined;
|
|
66
|
+
server: {
|
|
67
|
+
server: unknown;
|
|
68
|
+
};
|
|
69
|
+
startInit: () => void;
|
|
70
|
+
timeoutMs?: number;
|
|
71
|
+
getCwd?: () => string;
|
|
72
|
+
version?: string;
|
|
73
|
+
};
|
|
74
|
+
declare function selectWorkspaceRoot<Config extends WorkspaceRootConfig>({
|
|
75
|
+
config,
|
|
76
|
+
roots
|
|
77
|
+
}: Pick<WorkspaceRootApplyDeps<Config>, 'config' | 'roots'>): string | null;
|
|
78
|
+
declare function applyWorkspaceRoots<Config extends WorkspaceRootConfig>({
|
|
79
|
+
config,
|
|
80
|
+
log,
|
|
81
|
+
reconfigureForWorkspace,
|
|
82
|
+
roots
|
|
83
|
+
}: WorkspaceRootApplyDeps<Config>): boolean;
|
|
84
|
+
declare function bootstrapWorkspaceRoots<Config extends {
|
|
85
|
+
allRoots?: string[];
|
|
86
|
+
}>({
|
|
87
|
+
config,
|
|
88
|
+
indexMode,
|
|
89
|
+
log,
|
|
90
|
+
rootsChangedNotificationSchema,
|
|
91
|
+
reconfigureForWorkspace,
|
|
92
|
+
runInitialIndex,
|
|
93
|
+
server,
|
|
94
|
+
startInit,
|
|
95
|
+
timeoutMs,
|
|
96
|
+
getCwd,
|
|
97
|
+
version
|
|
98
|
+
}: WorkspaceRootBootstrapDeps<Config>): Promise<void>;
|
|
99
|
+
//#endregion
|
|
4
100
|
//#region packages/server/src/curated-adapter.interface.d.ts
|
|
5
101
|
/**
|
|
6
102
|
* Abstraction for curated knowledge storage.
|
|
@@ -226,93 +322,6 @@ declare class CuratedKnowledgeManager {
|
|
|
226
322
|
}
|
|
227
323
|
//#endregion
|
|
228
324
|
//#region packages/server/src/index.d.ts
|
|
229
|
-
interface CorsOriginResolution {
|
|
230
|
-
allowOrigin: string | null;
|
|
231
|
-
warn: boolean;
|
|
232
|
-
}
|
|
233
|
-
interface ResolveCorsOriginOptions {
|
|
234
|
-
requestOrigin: string | undefined;
|
|
235
|
-
configuredOrigin: string | undefined;
|
|
236
|
-
allowAnyOrigin: boolean;
|
|
237
|
-
fallbackOrigin: string;
|
|
238
|
-
}
|
|
239
|
-
interface SlidingWindowRateLimiter {
|
|
240
|
-
allow: (key: string, now?: number) => boolean;
|
|
241
|
-
getRetryAfterMs: (key: string, now?: number) => number;
|
|
242
|
-
}
|
|
243
|
-
declare function resolveCorsOrigin({
|
|
244
|
-
requestOrigin,
|
|
245
|
-
configuredOrigin,
|
|
246
|
-
allowAnyOrigin,
|
|
247
|
-
fallbackOrigin
|
|
248
|
-
}: ResolveCorsOriginOptions): CorsOriginResolution;
|
|
249
|
-
declare function createSlidingWindowRateLimiter({
|
|
250
|
-
limit,
|
|
251
|
-
windowMs
|
|
252
|
-
}: {
|
|
253
|
-
limit: number;
|
|
254
|
-
windowMs: number;
|
|
255
|
-
}): SlidingWindowRateLimiter;
|
|
256
|
-
type WorkspaceLogger = {
|
|
257
|
-
debug: (msg: string, data?: Record<string, unknown>) => void;
|
|
258
|
-
error: (msg: string, data?: Record<string, unknown>) => void;
|
|
259
|
-
info: (msg: string, data?: Record<string, unknown>) => void;
|
|
260
|
-
warn: (msg: string, data?: Record<string, unknown>) => void;
|
|
261
|
-
};
|
|
262
|
-
type WorkspaceRootBootstrapDeps<Config extends {
|
|
263
|
-
allRoots?: string[];
|
|
264
|
-
}> = {
|
|
265
|
-
config: Config;
|
|
266
|
-
indexMode: string;
|
|
267
|
-
log: WorkspaceLogger;
|
|
268
|
-
rootsChangedNotificationSchema: unknown;
|
|
269
|
-
reconfigureForWorkspace: (config: Config, workspaceRoot: string) => void;
|
|
270
|
-
runInitialIndex: () => Promise<unknown> | undefined;
|
|
271
|
-
server: {
|
|
272
|
-
server: unknown;
|
|
273
|
-
};
|
|
274
|
-
startInit: () => void;
|
|
275
|
-
timeoutMs?: number;
|
|
276
|
-
getCwd?: () => string;
|
|
277
|
-
};
|
|
278
|
-
type WorkspaceRootConfig = {
|
|
279
|
-
allRoots?: string[];
|
|
280
|
-
sources?: Array<{
|
|
281
|
-
path: string;
|
|
282
|
-
}>;
|
|
283
|
-
};
|
|
284
|
-
type WorkspaceRootApplyDeps<Config extends WorkspaceRootConfig> = {
|
|
285
|
-
config: Config;
|
|
286
|
-
log: WorkspaceLogger;
|
|
287
|
-
reconfigureForWorkspace: (config: Config, workspaceRoot: string) => void;
|
|
288
|
-
roots: Array<{
|
|
289
|
-
uri: string;
|
|
290
|
-
}>;
|
|
291
|
-
};
|
|
292
|
-
declare function selectWorkspaceRoot<Config extends WorkspaceRootConfig>({
|
|
293
|
-
config,
|
|
294
|
-
roots
|
|
295
|
-
}: Pick<WorkspaceRootApplyDeps<Config>, 'config' | 'roots'>): string | null;
|
|
296
|
-
declare function applyWorkspaceRoots<Config extends WorkspaceRootConfig>({
|
|
297
|
-
config,
|
|
298
|
-
log,
|
|
299
|
-
reconfigureForWorkspace,
|
|
300
|
-
roots
|
|
301
|
-
}: WorkspaceRootApplyDeps<Config>): boolean;
|
|
302
|
-
declare function bootstrapWorkspaceRoots<Config extends {
|
|
303
|
-
allRoots?: string[];
|
|
304
|
-
}>({
|
|
305
|
-
config,
|
|
306
|
-
indexMode,
|
|
307
|
-
log,
|
|
308
|
-
rootsChangedNotificationSchema,
|
|
309
|
-
reconfigureForWorkspace,
|
|
310
|
-
runInitialIndex,
|
|
311
|
-
server,
|
|
312
|
-
startInit,
|
|
313
|
-
timeoutMs,
|
|
314
|
-
getCwd
|
|
315
|
-
}: WorkspaceRootBootstrapDeps<Config>): Promise<void>;
|
|
316
325
|
declare function main(): Promise<void>;
|
|
317
326
|
//#endregion
|
|
318
|
-
export { CuratedKnowledgeManager, applyWorkspaceRoots, bootstrapWorkspaceRoots, createSlidingWindowRateLimiter, main, resolveCorsOrigin, selectWorkspaceRoot };
|
|
327
|
+
export { CuratedKnowledgeManager, applyWorkspaceRoots, bootstrapWorkspaceRoots, createSlidingWindowRateLimiter, getSessionIdHeader, main, readPositiveIntEnv, readVersion, resolveCorsOrigin, selectWorkspaceRoot };
|