@vpxa/aikit 0.1.215 → 0.1.217
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/core/dist/index.d.ts +195 -1
- package/packages/core/dist/index.js +1 -1
- package/packages/embeddings/dist/embedder-worker.js +1 -1
- package/packages/embeddings/dist/index.d.ts +6 -5
- package/packages/embeddings/dist/index.js +1 -1
- package/packages/enterprise-bridge/dist/index.d.ts +3 -11
- package/packages/enterprise-bridge/dist/index.js +1 -1
- package/packages/server/dist/bin.js +11 -11
- package/packages/server/dist/curated-manager-BrtqcmVm.js +7 -0
- package/packages/server/dist/index.d.ts +1 -0
- package/packages/server/dist/index.js +1 -1
- package/packages/server/dist/{promotion-OY53YCsT.js → promotion-BppF9YlR.js} +1 -1
- package/packages/server/dist/{server-DGKTbYuR.js → server-CBbp-_E9.js} +153 -153
- package/packages/server/dist/{server-CL3Jeefd.js → server-jy-ICjJR.js} +153 -153
- package/scaffold/dist/definitions/bodies.mjs +12 -10
- package/scaffold/dist/definitions/models.mjs +1 -1
- package/scaffold/dist/definitions/protocols.mjs +13 -8
- package/packages/server/dist/curated-manager-D1u5qOwK.js +0 -7
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import"node:module";import{createHash as e,randomUUID as t}from"node:crypto";import{readFileSync as n}from"node:fs";import{dirname as r,isAbsolute as i,join as a,resolve as o}from"node:path";import{fileURLToPath as s,pathToFileURL as c}from"node:url";import{parseArgs as l}from"node:util";import{
|
|
3
|
-
`)})})}function
|
|
4
|
-
`)})})}function
|
|
5
|
-
`)})})}function
|
|
6
|
-
`).filter(Boolean).map(e=>{try{return JSON.parse(e)}catch{return null}}).filter(
|
|
2
|
+
import"node:module";import{createHash as e,randomUUID as t}from"node:crypto";import{readFileSync as n}from"node:fs";import{dirname as r,isAbsolute as i,join as a,resolve as o}from"node:path";import{fileURLToPath as s,pathToFileURL as c}from"node:url";import{parseArgs as l}from"node:util";import{HealthBus as u,createLogger as d,serializeError as f}from"../../core/dist/index.js";import{mkdir as p,readFile as m,readdir as h,stat as g,unlink as _,writeFile as v}from"node:fs/promises";import{tmpdir as y}from"node:os";import{GIT_REF_SLUG_PATTERN as b,gitAvailable as x,gitCommitToRef as S,gitExec as C,replayAppend as w,slugForRef as ee}from"../../tools/dist/index.js";var te=Object.defineProperty,T=(e,t)=>{let n={};for(var r in e)te(n,r,{get:e[r],enumerable:!0});return t||te(n,Symbol.toStringTag,{value:`Module`}),n};const E=`__pending__:`;function D(e){return e.startsWith(E)}function O(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function k(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var ne=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=O(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){k(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){k(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`&&!D(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!D(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&&!D(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){k(e,503,-32003,`Session capacity reached`);return}let n=this.now(),r=await this.options.createServer(),i={id:`${E}${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()}}};const A=d(`auto-gc`);let j=`warming`,M=null,N=0;function P(){let e=[...ke()];if(e.length<10)return 0;e.sort((e,t)=>e-t);let t=Math.floor(e.length*.95);return e[Math.min(t,e.length-1)]}function F(e){let t=P();if(t===0){j=`warming`;return}if(t>500){j=`degraded`;let n=Date.now();if(M&&n-M<36e5){A.debug(`GC cooldown active — skipping`,{lastGcAgoMs:n-M});return}M=n,N++,A.warn(`p95 latency exceeds threshold, triggering GC`,{p95:t,cycle:N}),e&&e().catch(e=>A.error(`GC callback failed`,{err:String(e)}))}else t<200&&(j=`healthy`)}function re(){return{state:j,p95:P(),lastGcAt:M,gcCount:N,bufferSize:ke().length}}var I=T({DEFAULT_SUPERSESSION_CONFIG:()=>L,findSupersessionCandidates:()=>ie,jaccardSimilarity:()=>B,performSupersession:()=>ae,resolveSupersessionConfig:()=>R,tokenize:()=>z});const L={threshold:.7,maxCompare:50,autoThreshold:.95};function R(e){let t=Math.min(1,Math.max(0,e?.threshold??L.threshold)),n=Math.min(1,Math.max(t,e?.autoThreshold??L.autoThreshold));return{threshold:t,maxCompare:Math.max(1,Math.trunc(e?.maxCompare??L.maxCompare)),autoThreshold:n}}function z(e){let t=e.toLowerCase().match(/[a-z0-9]{2,}/g)??[];return new Set(t)}function B(e,t){let n=z(e),r=z(t);if(n.size===0&&r.size===0)return 1;if(n.size===0||r.size===0)return 0;let i=new Set([...n].filter(e=>r.has(e))),a=new Set([...n,...r]);return i.size/a.size}function ie(e,t,n=L){let r=R(n);return t.slice(0,r.maxCompare).map(t=>({entryId:t.id,title:t.title,similarity:B(e,t.content),path:t.path})).filter(e=>e.similarity>=r.threshold).sort((e,t)=>t.similarity-e.similarity)}function ae(e,t,n){e.memoryMetaCreate(t),e.memoryMetaSetSuperseded(t,n)}const V={enabled:!0,batchThreshold:20,cooldownMs:3e5,maxCandidatesPerSession:5,initialConfidence:40,excludeTools:[`knowledge`,`replay`,`stash`,`checkpoint`,`session_digest`,`reindex`,`status`,`flow`,`evidence_map`,`present`]},oe=new Set([`search`,`find`,`symbol`,`grep_search`,`semantic_search`]),se=new Set([`replace_string_in_file`,`editfiles`,`create_file`,`apply_patch`]),ce=new Set([`check`,`test_run`]),le=new Set(`action.and.args.auto.buffer.category.content.create.cwd.false.file.files.find.grep.json.knowledge.list.path.query.read.replace.search.semantic.subaction.symbol.test.tool.true.update`.split(`.`));function H(e){return e.replace(/^mcp_[^_]+_/,``).toLowerCase()}function ue(e){return[...new Set(e.filter(e=>e.length>0))]}function U(e,t){return{...t,confidence:V.initialConfidence,tags:[`auto-observed`,`detector:${e}`],detector:e}}function de(e,t){let n=new Map;for(let t of e)for(let e of z(t))le.has(e)||n.set(e,(n.get(e)??0)+1);let r=[...n.entries()].filter(([,e])=>e>=t).sort((e,t)=>t[1]-e[1]||e[0].localeCompare(t[0])).map(([e])=>e);return r.length>0?r.slice(0,4):[...n.entries()].sort((e,t)=>t[1]-e[1]||e[0].localeCompare(t[0])).slice(0,4).map(([e])=>e)}function fe(e){return e.length>0?e.join(`, `):`similar tasks`}function pe(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.ts==`number`&&Number.isFinite(t.ts)&&typeof t.tool==`string`&&typeof t.input==`string`&&Array.isArray(t.files)&&t.files.every(e=>typeof e==`string`)}function me(e){let t=[];for(let n of e)t.some(e=>B(e.title,n.title)>.8)||t.push(n);return t}function he(e){let t=new Map;for(let n of e){let e=H(n.tool),r=t.get(e)??[];r.push(n),t.set(e,r)}return[...t.entries()].filter(([,e])=>e.length>=5).map(([e,t])=>{let n=fe(de(t.map(e=>e.input),Math.max(2,Math.ceil(t.length/2))));return U(`tool-preference`,{title:`Preferred tool: ${e} for ${n}`,context:`Observed ${t.length} ${e} calls with recurring inputs around ${n}.`,insight:`Use ${e} when working with ${n}.`,evidence:t.slice(0,5).map(e=>`${e.tool}: ${e.input}`).join(`
|
|
3
|
+
`)})})}function ge(e){let t=new Map;for(let n=0;n<e.length;n+=1){let r=e[n];if(oe.has(H(r.tool)))for(let i=n+1;i<e.length&&i<=n+5;i+=1){let n=e[i];if(!(!se.has(H(n.tool))||n.files.length===0))for(let e of ue(n.files)){let i=t.get(e)??{count:0,queries:[],evidence:[]};i.count+=1,i.queries.push(r.input),i.evidence.push(`${r.tool}: ${r.input} -> ${n.tool}: ${e}`),t.set(e,i)}}}return[...t.entries()].filter(([,e])=>e.count>=3).map(([e,t])=>{let n=fe(de(t.queries,Math.max(2,Math.ceil(t.count/2))));return U(`search-action`,{title:`Check ${e} when searching for ${n}`,context:`Searches related to ${n} were followed by edits to ${e} ${t.count} times within five tool calls.`,insight:`When working on ${n}, check ${e} early because searches repeatedly led there.`,evidence:t.evidence.slice(0,5).join(`
|
|
4
|
+
`)})})}function _e(e){let t=new Map;for(let n=0;n<e.length-2;n+=1){let r=e[n];if(!ce.has(H(r.tool)))continue;let i=new Set,a=!1;for(let o=n+1;o<e.length;o+=1){let n=e[o],s=H(n.tool);if(se.has(s)){a=!0;for(let e of n.files)i.add(e);continue}if(ce.has(s)){if(!a||i.size===0)break;let e=[...i].sort(),o=e.join(`|`),s=t.get(o)??{count:0,evidence:[]};s.count+=1,s.evidence.push(`${r.tool} -> edit(${e.join(`, `)}) -> ${n.tool}`),t.set(o,s);break}if(!a)break}}return[...t.entries()].filter(([,e])=>e.count>=2).map(([e,t])=>{let n=e.split(`|`);return U(`error-fix-cycle`,{title:`Repeated validation-edit loop in ${n.length===1?n[0]:`${n[0]} and related files`}`,context:`Observed ${t.count} validation cycles touching ${n.join(`, `)}.`,insight:`Common fix pattern in ${n.join(`, `)}: check -> edit -> recheck.`,evidence:t.evidence.slice(0,5).join(`
|
|
5
|
+
`)})})}function ve(e,t=V){if(!t.enabled||e.length===0)return[];let n=new Set(t.excludeTools.map(e=>e.toLowerCase())),r=e.filter(e=>!n.has(H(e.tool)));return me([...he(r),...ge(r),..._e(r)].map(e=>({...e,confidence:t.initialConfidence,tags:ue([`auto-observed`,`detector:${e.detector}`,...e.tags])}))).slice(0,t.maxCandidatesPerSession)}function ye(e){return e.split(`
|
|
6
|
+
`).filter(Boolean).map(e=>{try{return JSON.parse(e)}catch{return null}}).filter(pe)}const be=d(`replay-interceptor`),xe=/key|token|secret|auth|password|bearer/i,Se=new Set([`eval`,`env`]);function W(e){if(typeof e==`string`)return/^(Bearer |sk-|ghp_|glpat-|ghu_|ghs_|github_pat_)/i.test(e)?`[REDACTED]`:e;if(Array.isArray(e))return e.map(W);if(e&&typeof e==`object`){let t={};for(let[n,r]of Object.entries(e))/(?:token|secret|password|passphrase|key|auth|credential|api.?key)/i.test(n)?t[n]=`[REDACTED]`:t[n]=W(r);return t}return e}function G(e,t){if(Se.has(e))return JSON.stringify({_redacted:!0,tool:e});let n=W(t);if(e===`http`&&n.headers&&typeof n.headers==`object`){let e={};for(let[t,r]of Object.entries(n.headers))e[t]=xe.test(t)?`[REDACTED]`:r;return n.headers=e,JSON.stringify(n).slice(0,2e3)}return JSON.stringify(n).slice(0,2e3)}const K=new Map,q=[],J=[];let Ce=0,Y;function we(e,t){return G(e,t).slice(0,500)}function Te(e){let t=new Set,n=[e];for(;n.length>0&&t.size<20;){let e=n.pop();if(e!=null){if(Array.isArray(e)){for(let t of e)n.push(t);continue}if(typeof e==`object`)for(let[r,i]of Object.entries(e)){if(Array.isArray(i)){if(/^(?:files|paths)$/i.test(r))for(let e of i)typeof e==`string`&&e.length>0&&t.add(e);else n.push(i);continue}if(typeof i==`string`&&/^(?:file|filepath|path)$/i.test(r)&&i.length>0){t.add(i);continue}i&&typeof i==`object`&&n.push(i)}}}return[...t]}function Ee(e,t,n){if(Ce+=1,J.push(JSON.stringify({tool:e,input:we(e,t),output:n.slice(0,500),files:Te(t),ts:Date.now()})),J.length>100&&J.shift(),Ce%50!=0)return;let r=J.join(`
|
|
7
7
|
`);J.length=0,!(!Y||r.trim().split(`
|
|
8
|
-
`).filter(Boolean).length<20)&&Promise.resolve().then(async()=>{let e=
|
|
9
|
-
`).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),!
|
|
10
|
-
`).filter(Boolean)){let[e,...r]=n.split(`|`),i=r.join(`|`),a=`${e.replace(`${X}/`,``)}.md`;await this.adapter.exists(a)||t.push({ref:e,path:a,lastMessage:i})}return t}async read(e){e=this.guardPath(e);let t=await this.adapter.read(e);if(t==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:n,content:r}=this.parseFile(t),i=e.split(`/`)[0];return{path:e,title:n.title??e,category:i,tags:n.tags??[],version:n.version??1,created:n.created??``,updated:n.updated??``,contentPreview:r.slice(0,200),content:r}}async list(e){let t=[],n=e?.category?[e.category]:await this.discoverCategories();for(let r of n){let n=await this.adapter.list(r);for(let i of n){let n=await this.adapter.read(i.path);if(n==null)continue;let{frontmatter:a,content:o}=this.parseFile(n);e?.tag&&!(a.tags??[]).includes(e.tag)||t.push({path:i.path,title:a.title??i.path,category:r,tags:a.tags??[],version:a.version??1,created:a.created??``,updated:a.updated??``,contentPreview:o.slice(0,200)})}}return t}async reindexAll(){let e=await this.discoverCategories(),t=[],n=[];for(let r of e){let e=await this.adapter.list(r);for(let r of e){let e=r.path;try{let r=await this.adapter.read(e);if(r==null){t.push(`${e}: read failed`);continue}let{frontmatter:i,content:a}=this.parseFile(r);n.push({relativePath:e,content:a,frontmatter:i})}catch(n){
|
|
11
|
-
`).length,fileHash:this.hash(e.content),indexedAt:i,origin:`curated`,tags:e.frontmatter.tags,category:e.frontmatter.category,version:e.frontmatter.version}});return await this.store.upsert(a,r),{indexed:n.length,errors:t}}gitCommitKnowledge(e,t,n){try{if(!
|
|
12
|
-
`).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 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`)>
|
|
8
|
+
`).filter(Boolean).length<20)&&Promise.resolve().then(async()=>{let e=ve(ye(r),V);if(e.length!==0){try{let t=a(y(),`aikit-auto-observe-${process.pid}-${Date.now()}.json`);await v(t,JSON.stringify(e,null,2),`utf8`),be.info(`Auto-observe candidates detected`,{count:e.length,filePath:t})}catch(e){be.warn(`Failed to persist auto-observe candidates`,{error:String(e)})}Y?.(e)}}).catch(()=>{})}function De(e,t,n,r,i){let a=K.get(e);a||(a={callCount:0,totalDurationMs:0,totalInputChars:0,totalOutputChars:0,errorCount:0},K.set(e,a)),a.callCount++,a.totalDurationMs+=t,a.totalInputChars+=n,a.totalOutputChars+=r,i&&a.errorCount++,q.push(t),q.length>100&&q.shift(),q.length>=10&&q.length%20==0&&F()}function Oe(){return Array.from(K.entries()).map(([e,t])=>({tool:e,...t}))}function ke(){return q}function Ae(e){Y=e}function je(){return async(e,t)=>{let n=Date.now(),r=JSON.stringify(e.args??{}).length;try{let i=await t(),a=Date.now()-n,o=JSON.stringify(i);return w({ts:new Date().toISOString(),source:`mcp`,tool:e.toolName,input:G(e.toolName,e.args),durationMs:a,status:`ok`,output:o,traceId:e.requestId,outputChars:o.length}),Ee(e.toolName,e.args,o),De(e.toolName,a,r,o.length,!1),i}catch(t){let i=Date.now()-n,a=t instanceof Error?t.message:String(t);throw w({ts:new Date().toISOString(),source:`mcp`,tool:e.toolName,input:G(e.toolName,e.args),durationMs:i,status:`error`,output:a,traceId:e.requestId,outputChars:0}),Ee(e.toolName,e.args,a),De(e.toolName,i,r,0,!0),t}}}function Me(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var Ne=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=Me(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}},Pe=class{baseDir;constructor(e){this.baseDir=e}async initialize(){await p(this.baseDir,{recursive:!0})}async read(e){let t=a(this.baseDir,e);try{return await m(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 p(r(i),{recursive:!0}),await v(i,t,{encoding:`utf-8`,flag:n?.exclusive?`wx`:`w`})}async delete(e){let t=a(this.baseDir,e);try{return await _(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 h(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 g(i);t.push({path:r,size:e.size})}catch{}}}return t}async exists(e){let t=a(this.baseDir,e);try{return await g(t),!0}catch{return!1}}async listDirectories(){try{return(await h(this.baseDir,{withFileTypes:!0})).filter(e=>e.isDirectory()&&/^[a-z][a-z0-9-]*$/.test(e.name)).map(e=>e.name)}catch{return[]}}async close(){}},Fe=T({CuratedKnowledgeManager:()=>Le});const Ie=50*1024,X=`refs/aikit/knowledge`,Z=d(`server`);var Le=class{curatedDir;store;embedder;adapter;constructor(e,t,n,r=new Pe(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.slugify(e),a=await this.uniqueRelativePath(n,i),o=new Date().toISOString(),s={title:e,category:n,tags:r,created:o,updated:o,version:1,origin:`curated`,changelog:[{version:1,date:o,reason:`Initial creation`}]},c=this.serializeFile(t,s);try{await this.adapter.write(a,c,{exclusive:!0})}catch(e){throw e.code===`EEXIST`?Error(`Concurrent write collision for "${a}" — retry the operation`):e}return this.gitCommitKnowledge(a,c,`remember: ${e}\n\nCategory: ${n}\nTags: ${r.join(`, `)}`),await this.indexCuratedFileBestEffort(a,t,s,`remember`),{path:a}}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=>{Z.warn(`File deleted but vector cleanup failed`,{sourcePath:n,...f(e)})}),this.gitDeleteKnowledgeRef(e),{path:e}}async history(e,t=20){if(e=this.guardPath(e),!x(this.curatedDir))return[];let n=this.knowledgeRefForPath(e);if(!n)return[];let r=C([`log`,`--format=%H|%aI|%s`,n,`-n`,String(t)],this.curatedDir);return r?r.split(`
|
|
9
|
+
`).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),!x(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?C([`diff`,`${t}:entry.md`,`${n}:entry.md`],this.curatedDir)??``:n?C([`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(!x(this.curatedDir))return null;let t=this.knowledgeRefForPath(e);if(!t)return null;let n=C([`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(!x(this.curatedDir))return[];let e=C([`for-each-ref`,`--format=%(refname)|%(subject)`,`${X}/`],this.curatedDir);if(!e)return[];let t=[];for(let n of e.split(`
|
|
10
|
+
`).filter(Boolean)){let[e,...r]=n.split(`|`),i=r.join(`|`),a=`${e.replace(`${X}/`,``)}.md`;await this.adapter.exists(a)||t.push({ref:e,path:a,lastMessage:i})}return t}async read(e){e=this.guardPath(e);let t=await this.adapter.read(e);if(t==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:n,content:r}=this.parseFile(t),i=e.split(`/`)[0];return{path:e,title:n.title??e,category:i,tags:n.tags??[],version:n.version??1,created:n.created??``,updated:n.updated??``,contentPreview:r.slice(0,200),content:r}}async list(e){let t=[],n=e?.category?[e.category]:await this.discoverCategories();for(let r of n){let n=await this.adapter.list(r);for(let i of n){let n=await this.adapter.read(i.path);if(n==null)continue;let{frontmatter:a,content:o}=this.parseFile(n);e?.tag&&!(a.tags??[]).includes(e.tag)||t.push({path:i.path,title:a.title??i.path,category:r,tags:a.tags??[],version:a.version??1,created:a.created??``,updated:a.updated??``,contentPreview:o.slice(0,200)})}}return t}async reindexAll(){let e=await this.discoverCategories(),t=[],n=[];for(let r of e){let e=await this.adapter.list(r);for(let r of e){let e=r.path;try{let r=await this.adapter.read(e);if(r==null){t.push(`${e}: read failed`);continue}let{frontmatter:i,content:a}=this.parseFile(r);n.push({relativePath:e,content:a,frontmatter:i})}catch(n){Z.error(`Failed to read curated file`,{relativePath:e,...f(n)}),t.push(`${e}: read failed`)}}}if(n.length===0)return{indexed:0,errors:t};let r=await this.embedder.embedBatch(n.map(e=>e.content)),i=new Date().toISOString(),a=n.map(e=>{let t=`.ai/curated/${e.relativePath}`;return{id:this.hashId(t,0),content:e.content,sourcePath:t,contentType:`curated-knowledge`,headingPath:e.frontmatter.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:e.content.split(`
|
|
11
|
+
`).length,fileHash:this.hash(e.content),indexedAt:i,origin:`curated`,tags:e.frontmatter.tags,category:e.frontmatter.category,version:e.frontmatter.version}});return await this.store.upsert(a,r),{indexed:n.length,errors:t}}gitCommitKnowledge(e,t,n){try{if(!x(this.curatedDir))return;let r=this.knowledgeRefForPath(e);if(!r)return;S(r,`entry.md`,t,n,this.curatedDir)}catch{}}gitDeleteKnowledgeRef(e){try{if(!x(this.curatedDir))return;let t=this.knowledgeRefForPath(e);if(!t)return;C([`update-ref`,`-d`,t],this.curatedDir)}catch{}}knowledgeRefForPath(e){let t=e.replace(/\.md$/,``).split(`/`).map(e=>ee(e)).join(`/`);return t.split(`/`).every(e=>b.test(e))?`${X}/${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(`
|
|
12
|
+
`).length,fileHash:this.hash(t),indexedAt:a,origin:`curated`,tags:n.tags,category:n.category,version:n.version};await this.store.upsert([o],[r])}async indexCuratedFileBestEffort(e,t,n,r){if(u.instance().isDegraded(`embedder`)){Z.debug(`Skipping vector indexing — embedder degraded`,{relativePath:e,operation:r,subsystem:`embedder`});return}try{await this.indexCuratedFile(e,t,n)}catch(t){Z.warn(`Curated file persisted but vector indexing deferred`,{relativePath:e,operation:r,...f(t)})}}async discoverCategories(){return this.adapter.listDirectories()}guardPath(e){let t=e.replace(/^\.ai\/curated\//,``);if(t.endsWith(`.md`)||(t+=`.md`),t.includes(`..`)||i(t))throw Error(`Invalid path: ${t}. Must be relative within .ai/curated/ directory.`);let n=t.split(`/`)[0];return this.validateCategoryName(n),t}validateCategoryName(e){if(!/^[a-z][a-z0-9-]*$/.test(e))throw Error(`Invalid category name: "${e}". Must be lowercase kebab-case (e.g., "decisions", "api-contracts").`)}validateContentSize(e){if(Buffer.byteLength(e,`utf-8`)>Ie)throw Error(`Content exceeds maximum size of ${Ie/1024}KB`)}slugify(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-|-$/g,``).slice(0,80)}async uniqueRelativePath(e,t){let n=`${e}/${t}.md`;if(!await this.adapter.exists(n))return n;for(let n=2;n<=100;n++){let r=`${e}/${t}-${n}.md`;if(!await this.adapter.exists(r))return r}throw Error(`Too many entries with slug "${t}" in category "${e}"`)}hash(t){return e(`sha256`).update(t).digest(`hex`).slice(0,16)}hashId(e,t){return this.hash(`${e}::${t}`)}serializeFile(e,t){return`${[`---`,`title: "${t.title.replace(/"/g,`\\"`)}"`,`category: ${t.category}`,`tags: [${t.tags.map(e=>`"${e}"`).join(`, `)}]`,`created: ${t.created}`,`updated: ${t.updated}`,`version: ${t.version}`,`origin: ${t.origin}`,`changelog:`,...t.changelog.map(e=>` - version: ${e.version}\n date: ${e.date}\n reason: "${e.reason.replace(/"/g,`\\"`)}"`),`---`].join(`
|
|
13
13
|
`)}\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(`
|
|
14
|
-
`),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}}};function Re(){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 Z=u(`server`),ze=/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;function Be({requestOrigin:e,configuredOrigin:t,allowAnyOrigin:n,fallbackOrigin:r}){let i=t??r;return i===`*`?n?{allowOrigin:`*`,warn:!1}:e?ze.test(e)?{allowOrigin:e,warn:!1}:{allowOrigin:null,warn:!0}:{allowOrigin:r,warn:!1}:{allowOrigin:i,warn:!1}}function Ve({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 He(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function Ue(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===c(e).href}catch{return!1}}function Q(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function $(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 We(){return Ue()?l({allowPositionals:!0,options:{transport:{type:`string`,default:He()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:He(),port:process.env.AIKIT_PORT??`3210`}}function Ge(e){return`## Context\n${e.context}\n\n## Insight\n${e.insight}\n\n## Evidence\n${e.evidence}`}function Ke(e){ke(t=>{(async()=>{let n=e();if(!n)return;let{jaccardSimilarity:r}=await Promise.resolve().then(()=>ne),i=await n.curated.list({category:`lessons`});for(let e of t)i.some(t=>r(e.title,t.title)>.6)||(await n.curated.remember(e.title,Ge(e),`lessons`,[`lesson`,`auto-observed`,`detector:${e.detector}`]),i.push({path:`lessons/${e.title}`,title:e.title,category:`lessons`,tags:[`lesson`,`auto-observed`,`detector:${e.detector}`],version:1,created:new Date().toISOString(),updated:new Date().toISOString(),contentPreview:e.insight.slice(0,200)}))})().catch(()=>{})})}async function qe(){let e=Re(),n=We();process.on(`unhandledRejection`,e=>{Z.error(`Unhandled rejection`,d(e))}),process.on(`uncaughtException`,e=>{Z.error(`Uncaught exception — exiting`,d(e)),process.exit(1)});let r=(e,t)=>{e.then(async()=>{try{let{markPromoteRun:e,markPruneRun:n,prune:r,shouldRunStartupPrune:i,shouldRunWeeklyPromote:a}=await import(`../../tools/dist/index.js`),o=t();if(!o)return;if(i()){let e=await r({});n(),e.totalBytesFreed>0&&Z.info(`Storage maintenance complete`,{forgeOrphans:e.forgeGroundOrphans.count,legacyLance:e.legacyLance.count,bytesFreed:e.totalBytesFreed});let{groupLessons:t,pruneLessons:i}=await import(`./evolution-9hXRopDC.js`).then(e=>e.t),a=await i(o.curated,o.stateStore,{dryRun:!1});a.pruned.length>0&&Z.info(`Startup lesson prune complete`,{pruned:a.pruned.length});let s=await t(o.curated,o.stateStore,{dryRun:!1});(s.groupsCreated>0||s.lessonsGrouped>0)&&Z.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-Bd_YB7E1.js`).then(e=>e.o),{CuratedKnowledgeManager:s}=await Promise.resolve().then(()=>Pe),c=o.curated,l=new s(r(),c.store,c.embedder),u=await n(),d={...t,dryRun:!1},f=await i(a(u,d),l,d);e(),f.promoted.length>0&&Z.info(`Weekly lesson promotion complete`,{promoted:f.promoted.length,candidates:f.candidates.length})}}catch(e){Z.warn(`Startup maintenance failed (non-critical)`,d(e))}}).catch(()=>{})};if(Z.info(`Starting MCP AI Kit server`,{version:e}),n.transport===`http`){let[{default:e},{loadConfig:i,resolveIndexMode:a},{registerDashboardRoutes:o,resolveDashboardDir:s},{registerSettingsRoutes:c,resolveSettingsDir:l},{createSettingsRouter:u},{authMiddleware:f,getOrCreateToken:p}]=await Promise.all([import(`express`),import(`./config-C4mVyqAF.js`),import(`./dashboard-static-CRfR1yKU.js`),import(`./settings-static-B3lnYvcb.js`),import(`./routes-Afg7J7xK.js`),import(`./auth-lzZKfxlV.js`)]),m=i();Z.info(`Config loaded`,{sourceCount:m.sources.length,storePath:m.store.path});let h=e();h.use(e.json({limit:`1mb`}));let g=Number(n.port),_=`http://localhost:${g}`,v=process.env.AIKIT_CORS_ORIGIN??_,y=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,b=$(`AIKIT_HTTP_MAX_SESSIONS`,8),x=$(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),S=$(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),C=Ve({limit:100,windowMs:6e4}),w=!1;h.use((e,t,n)=>{let r=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,i=Be({requestOrigin:r,configuredOrigin:v,allowAnyOrigin:y,fallbackOrigin:_});if(i.warn&&!w&&(w=!0,Z.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 T=p();console.error(`[aikit] Auth token: ~/.aikit/token`),h.use(f(T)),h.use(`/mcp`,(e,t,n)=>{let r=Q(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(C.allow(r)){n();return}let i=Math.max(1,Math.ceil(C.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})}),o(h,s(),Z);let E=new Date().toISOString();h.use(`/settings/api`,u({log:Z,mcpInfo:()=>({transport:`http`,port:g,pid:process.pid,startedAt:E})})),c(h,l(),Z),h.get(`/health`,(e,t)=>{t.json({status:`ok`})});let D=!1,O=null,k=null,A=null,j=null,M=null,N=null,P=null,F=Promise.resolve(),te=async(e,n)=>{if(!D||!A||!j){n.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=F,i;F=new Promise(e=>{i=e}),await r;try{let r=Q(e);if(!N){if(r){n.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new j({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{P=e,k?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&k?.onSessionEnd(e),P=null}});e.onclose=()=>{N===e&&(N=null),P===e.sessionId&&(P=null)},N=e,await A.connect(e)}let i=N;await i.handleRequest(e,n,e.body),e.method!==`DELETE`&&(!r&&i.sessionId?(P=i.sessionId,k?.onSessionStart(i.sessionId,{transport:`http`}),k?.onSessionActivity(i.sessionId)):r&&k?.onSessionActivity(r))}catch(e){if(Z.error(`MCP handler error`,d(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()}},I=async(e,t)=>{let n=Q(e);if(M&&(!N||n!==P)){await M.handleRequest(e,t,e.body);return}await te(e,t)};h.post(`/mcp`,I),h.get(`/mcp`,I),h.delete(`/mcp`,I);let ne=h.listen(g,`127.0.0.1`,()=>{Z.info(`MCP server listening`,{url:`http://127.0.0.1:${g}/mcp`,port:g}),setTimeout(async()=>{try{let[{createLazyServer:e,createMcpServer:t,ALL_TOOL_NAMES:n},{StreamableHTTPServerTransport:i},{checkForUpdates:o,autoUpgradeScaffold:s}]=await Promise.all([import(`./server-CL3Jeefd.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-gazMo-D4.js`)]);o(),s();let c=a(m),l=e(m,c);A=l.server,j=i,D=!0,Z.info(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:n.length,resourceCount:2}),l.startInit(),l.ready.then(()=>{if(!l.aikit)throw Error(`AI Kit components are not available after initialization`);k=new Me(l.aikit.stateStore,{staleTimeoutMinutes:x,gcIntervalMinutes:S,onBeforeSessionDelete:e=>{if(P===e&&N){let e=N;N=null,P=null,e.close().catch(()=>void 0)}M?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!l.aikit?.curated||!l.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-9hXRopDC.js`).then(e=>e.t),t=await e(l.aikit.curated,l.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&Z.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),M=new ee({createServer:()=>{if(!l.aikit)throw Error(`AI Kit components are not available after initialization`);return t(l.aikit,m)},createTransport:e=>new i(e),maxSessions:b,sessionTimeoutMinutes:x,onSessionStart:e=>k?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>k?.onSessionActivity(e),onSessionEnd:e=>k?.onSessionEnd(e)}),k.startGC(),P&&(k.onSessionStart(P,{transport:`http`}),k.onSessionActivity(P)),Ke(()=>l.aikit?{curated:l.aikit.curated,stateStore:l.aikit.stateStore}:null),Z.info(`HTTP session runtime ready`,{maxSessions:b,sessionTimeoutMinutes:x,gcIntervalMinutes:S})}).catch(e=>Z.error(`Failed to start session manager`,d(e))),c===`auto`?l.ready.then(async()=>{try{let e=m.sources.map(e=>e.path).join(`, `);Z.info(`Running initial index`,{sourcePaths:e}),await l.runInitialIndex(),Z.info(`Initial index complete`)}catch(e){Z.error(`Initial index failed; will retry on aikit_reindex`,d(e))}}).catch(e=>Z.error(`AI Kit init or indexing failed`,d(e))):c===`smart`?l.ready.then(async()=>{try{if(!l.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(l.aikit.indexer,m,l.aikit.store),n=l.aikit.store;O=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),l.setSmartScheduler(t),Z.info(`Smart index scheduler started (HTTP mode)`)}catch(e){Z.error(`Failed to start smart index scheduler`,d(e))}}).catch(e=>Z.error(`AI Kit initialization failed`,d(e))):(l.ready.catch(e=>Z.error(`AI Kit initialization failed`,d(e))),Z.info(`Initial full indexing skipped in HTTP mode`,{indexMode:c})),r(l.ready,()=>l.aikit?{curated:l.aikit.curated,stateStore:l.aikit.stateStore}:null)}catch(e){Z.error(`Failed to load server modules`,d(e))}},100)}),L=async e=>{Z.info(`Shutdown signal received`,{signal:e}),O?.stop(),k?.stop(),await M?.closeAll().catch(()=>void 0),P&&k?.onSessionEnd(P),N&&(await N.close().catch(()=>void 0),N=null,P=null),ne.close(),A&&await A.close(),process.exit(0)};process.on(`SIGINT`,()=>L(`SIGINT`)),process.on(`SIGTERM`,()=>L(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:n},{createLazyServer:i},{checkForUpdates:a,autoUpgradeScaffold:o},{RootsListChangedNotificationSchema:c}]=await Promise.all([import(`./config-C4mVyqAF.js`),import(`./server-CL3Jeefd.js`),import(`./version-check-gazMo-D4.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=e();Z.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),a(),o();let u=n(l),f=i(l,u),{server:p,startInit:m,ready:h,runInitialIndex:g}=f,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await p.connect(v),Z.info(`MCP server started`,{transport:`stdio`});let y=e=>{if(e.length===0)return!1;let n=e[0].uri,r=n.startsWith(`file://`)?s(n):n;return Z.info(`MCP roots resolved`,{rootUri:n,rootPath:r,rootCount:e.length}),t(l,r),l.allRoots=e.map(e=>{let t=e.uri;return t.startsWith(`file://`)?s(t):t}),!0},b=!1;try{b=y((await p.server.listRoots()).roots),b||Z.info(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(e){Z.warn(`MCP roots/list not supported by client; using cwd fallback`,{cwd:process.cwd(),...d(e)}),b=!0}b||=await new Promise(e=>{let t=setTimeout(()=>{Z.warn(`Timed out waiting for MCP roots/list_changed; using cwd fallback`,{cwd:process.cwd()}),e(!1)},5e3);p.server.setNotificationHandler(c,async()=>{clearTimeout(t);try{e(y((await p.server.listRoots()).roots))}catch(t){Z.warn(`roots/list retry failed after notification`,d(t)),e(!1)}})}),m();let x=null,S=()=>{x&&clearTimeout(x),x=setTimeout(async()=>{Z.info(`Auto-shutdown: no activity for 30 minutes — shutting down gracefully`);try{let e=f.aikit;e&&await Promise.all([e.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),e.graphStore.close().catch(()=>{}),e.store.close().catch(()=>{})])}catch{}process.exit(0)},18e5),x.unref&&x.unref()};S(),process.stdin.on(`data`,()=>S()),h.catch(e=>{Z.error(`Initialization failed — server will continue with limited tools`,d(e))}),h.then(()=>{Ke(()=>f.aikit?{curated:f.aikit.curated,stateStore:f.aikit.stateStore}:null)}).catch(()=>{}),u===`auto`?g().catch(e=>Z.error(`Initial index failed`,d(e))):u===`smart`?h.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.aikit.indexer,l,f.aikit.store),n=f.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),f.setSmartScheduler(t),Z.info(`Smart index scheduler started (stdio mode)`)}catch(e){Z.error(`Failed to start smart index scheduler`,d(e))}}).catch(e=>Z.error(`AI Kit init failed for smart scheduler`,d(e))):Z.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:u}),r(h,()=>f.aikit?{curated:f.aikit.curated,stateStore:f.aikit.stateStore}:null)}}qe();export{V as a,L as c,ie as d,R as f,De as i,re as l,E as m,Ne as n,ve as o,I as p,Ae as r,_e as s,Le as t,B as u};
|
|
14
|
+
`),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}}};function Re(){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 Q=d(`server`),ze=/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;function Be({requestOrigin:e,configuredOrigin:t,allowAnyOrigin:n,fallbackOrigin:r}){let i=t??r;return i===`*`?n?{allowOrigin:`*`,warn:!1}:e?ze.test(e)?{allowOrigin:e,warn:!1}:{allowOrigin:null,warn:!0}:{allowOrigin:r,warn:!1}:{allowOrigin:i,warn:!1}}function Ve({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 He(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function Ue(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===c(e).href}catch{return!1}}function We(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function $(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 Ge(){return Ue()?l({allowPositionals:!0,options:{transport:{type:`string`,default:He()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:He(),port:process.env.AIKIT_PORT??`3210`}}function Ke(e){return`## Context\n${e.context}\n\n## Insight\n${e.insight}\n\n## Evidence\n${e.evidence}`}function qe(e){Ae(t=>{(async()=>{let n=e();if(!n)return;let{jaccardSimilarity:r}=await Promise.resolve().then(()=>I),i=await n.curated.list({category:`lessons`});for(let e of t)i.some(t=>r(e.title,t.title)>.6)||(await n.curated.remember(e.title,Ke(e),`lessons`,[`lesson`,`auto-observed`,`detector:${e.detector}`]),i.push({path:`lessons/${e.title}`,title:e.title,category:`lessons`,tags:[`lesson`,`auto-observed`,`detector:${e.detector}`],version:1,created:new Date().toISOString(),updated:new Date().toISOString(),contentPreview:e.insight.slice(0,200)}))})().catch(()=>{})})}async function Je(){let e=Re(),n=Ge();process.on(`unhandledRejection`,e=>{Q.error(`Unhandled rejection`,f(e))}),process.on(`uncaughtException`,e=>{Q.error(`Uncaught exception — exiting`,f(e)),process.exit(1)});let r=(e,t)=>{e.then(async()=>{try{let{markPromoteRun:e,markPruneRun:n,prune:r,shouldRunStartupPrune:i,shouldRunWeeklyPromote:a}=await import(`../../tools/dist/index.js`),o=t();if(!o)return;if(i()){let e=await r({});n(),e.totalBytesFreed>0&&Q.info(`Storage maintenance complete`,{forgeOrphans:e.forgeGroundOrphans.count,legacyLance:e.legacyLance.count,bytesFreed:e.totalBytesFreed});let{groupLessons:t,pruneLessons:i}=await import(`./evolution-9hXRopDC.js`).then(e=>e.t),a=await i(o.curated,o.stateStore,{dryRun:!1});a.pruned.length>0&&Q.info(`Startup lesson prune complete`,{pruned:a.pruned.length});let s=await t(o.curated,o.stateStore,{dryRun:!1});(s.groupsCreated>0||s.lessonsGrouped>0)&&Q.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-Bd_YB7E1.js`).then(e=>e.o),{CuratedKnowledgeManager:s}=await Promise.resolve().then(()=>Fe),c=o.curated,l=new s(r(),c.store,c.embedder),u=await n(),d={...t,dryRun:!1},f=await i(a(u,d),l,d);e(),f.promoted.length>0&&Q.info(`Weekly lesson promotion complete`,{promoted:f.promoted.length,candidates:f.candidates.length})}}catch(e){Q.warn(`Startup maintenance failed (non-critical)`,f(e))}}).catch(()=>{})};if(Q.info(`Starting MCP AI Kit server`,{version:e}),n.transport===`http`){let[{default:e},{loadConfig:i,resolveIndexMode:a},{registerDashboardRoutes:o,resolveDashboardDir:s},{registerSettingsRoutes:c,resolveSettingsDir:l},{createSettingsRouter:u},{authMiddleware:d,getOrCreateToken:p}]=await Promise.all([import(`express`),import(`./config-C4mVyqAF.js`),import(`./dashboard-static-CRfR1yKU.js`),import(`./settings-static-B3lnYvcb.js`),import(`./routes-Afg7J7xK.js`),import(`./auth-lzZKfxlV.js`)]),m=i();Q.info(`Config loaded`,{sourceCount:m.sources.length,storePath:m.store.path});let h=e();h.use(e.json({limit:`1mb`}));let g=Number(n.port),_=`http://localhost:${g}`,v=process.env.AIKIT_CORS_ORIGIN??_,y=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,b=$(`AIKIT_HTTP_MAX_SESSIONS`,8),x=$(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),S=$(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),C=Ve({limit:100,windowMs:6e4}),w=!1;h.use((e,t,n)=>{let r=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,i=Be({requestOrigin:r,configuredOrigin:v,allowAnyOrigin:y,fallbackOrigin:_});if(i.warn&&!w&&(w=!0,Q.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 ee=p();console.error(`[aikit] Auth token: ~/.aikit/token`),h.use(d(ee)),h.use(`/mcp`,(e,t,n)=>{let r=We(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(C.allow(r)){n();return}let i=Math.max(1,Math.ceil(C.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})}),o(h,s(),Q);let te=new Date().toISOString();h.use(`/settings/api`,u({log:Q,mcpInfo:()=>({transport:`http`,port:g,pid:process.pid,startedAt:te})})),c(h,l(),Q),h.get(`/health`,(e,t)=>{t.json({status:`ok`})});let T=!1,E=null,D=null,O=null,k=null,A=null,j=null,M=null,N=Promise.resolve(),P=async(e,n)=>{if(!T||!O||!k){n.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=N,i;N=new Promise(e=>{i=e}),await r;try{let r=We(e);if(!j){if(r){n.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new k({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{M=e,D?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&D?.onSessionEnd(e),M=null}});e.onclose=()=>{j===e&&(j=null),M===e.sessionId&&(M=null)},j=e,await O.connect(e)}let i=j;await i.handleRequest(e,n,e.body),e.method!==`DELETE`&&(!r&&i.sessionId?(M=i.sessionId,D?.onSessionStart(i.sessionId,{transport:`http`}),D?.onSessionActivity(i.sessionId)):r&&D?.onSessionActivity(r))}catch(e){if(Q.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()}},F=async(e,t)=>{let n=We(e);if(A&&(!j||n!==M)){await A.handleRequest(e,t,e.body);return}await P(e,t)};h.post(`/mcp`,F),h.get(`/mcp`,F),h.delete(`/mcp`,F);let re=h.listen(g,`127.0.0.1`,()=>{Q.info(`MCP server listening`,{url:`http://127.0.0.1:${g}/mcp`,port:g}),setTimeout(async()=>{try{let[{createLazyServer:e,createMcpServer:t,ALL_TOOL_NAMES:n},{StreamableHTTPServerTransport:i},{checkForUpdates:o,autoUpgradeScaffold:s}]=await Promise.all([import(`./server-jy-ICjJR.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-gazMo-D4.js`)]);o(),s();let c=a(m),l=e(m,c);O=l.server,k=i,T=!0,Q.info(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:n.length,resourceCount:2}),l.startInit(),l.ready.then(()=>{if(!l.aikit)throw Error(`AI Kit components are not available after initialization`);D=new Ne(l.aikit.stateStore,{staleTimeoutMinutes:x,gcIntervalMinutes:S,onBeforeSessionDelete:e=>{if(M===e&&j){let e=j;j=null,M=null,e.close().catch(()=>void 0)}A?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!l.aikit?.curated||!l.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-9hXRopDC.js`).then(e=>e.t),t=await e(l.aikit.curated,l.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&Q.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),A=new ne({createServer:()=>{if(!l.aikit)throw Error(`AI Kit components are not available after initialization`);return t(l.aikit,m)},createTransport:e=>new i(e),maxSessions:b,sessionTimeoutMinutes:x,onSessionStart:e=>D?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>D?.onSessionActivity(e),onSessionEnd:e=>D?.onSessionEnd(e)}),D.startGC(),M&&(D.onSessionStart(M,{transport:`http`}),D.onSessionActivity(M)),qe(()=>l.aikit?{curated:l.aikit.curated,stateStore:l.aikit.stateStore}:null),Q.info(`HTTP session runtime ready`,{maxSessions:b,sessionTimeoutMinutes:x,gcIntervalMinutes:S})}).catch(e=>Q.error(`Failed to start session manager`,f(e))),c===`auto`?l.ready.then(async()=>{try{let e=m.sources.map(e=>e.path).join(`, `);Q.info(`Running initial index`,{sourcePaths:e}),await l.runInitialIndex(),Q.info(`Initial index complete`)}catch(e){Q.error(`Initial index failed; will retry on aikit_reindex`,f(e))}}).catch(e=>Q.error(`AI Kit init or indexing failed`,f(e))):c===`smart`?l.ready.then(async()=>{try{if(!l.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(l.aikit.indexer,m,l.aikit.store),n=l.aikit.store;E=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),l.setSmartScheduler(t),Q.info(`Smart index scheduler started (HTTP mode)`)}catch(e){Q.error(`Failed to start smart index scheduler`,f(e))}}).catch(e=>Q.error(`AI Kit initialization failed`,f(e))):(l.ready.catch(e=>Q.error(`AI Kit initialization failed`,f(e))),Q.info(`Initial full indexing skipped in HTTP mode`,{indexMode:c})),r(l.ready,()=>l.aikit?{curated:l.aikit.curated,stateStore:l.aikit.stateStore}:null)}catch(e){Q.error(`Failed to load server modules`,f(e))}},100)}),I=async e=>{Q.info(`Shutdown signal received`,{signal:e}),E?.stop(),D?.stop(),await A?.closeAll().catch(()=>void 0),M&&D?.onSessionEnd(M),j&&(await j.close().catch(()=>void 0),j=null,M=null),re.close(),O&&await O.close(),process.exit(0)};process.on(`SIGINT`,()=>I(`SIGINT`)),process.on(`SIGTERM`,()=>I(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:n},{createLazyServer:i},{checkForUpdates:a,autoUpgradeScaffold:o},{RootsListChangedNotificationSchema:c}]=await Promise.all([import(`./config-C4mVyqAF.js`),import(`./server-jy-ICjJR.js`),import(`./version-check-gazMo-D4.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=e();Q.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),a(),o();let u=n(l),d=i(l,u),{server:p,startInit:m,ready:h,runInitialIndex:g}=d,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await p.connect(v),Q.info(`MCP server started`,{transport:`stdio`});let y=e=>{if(e.length===0)return!1;let n=e[0].uri,r=n.startsWith(`file://`)?s(n):n;return Q.info(`MCP roots resolved`,{rootUri:n,rootPath:r,rootCount:e.length}),t(l,r),l.allRoots=e.map(e=>{let t=e.uri;return t.startsWith(`file://`)?s(t):t}),!0},b=!1;try{b=y((await p.server.listRoots()).roots),b||Q.info(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(e){Q.warn(`MCP roots/list not supported by client; using cwd fallback`,{cwd:process.cwd(),...f(e)}),b=!0}b||=await new Promise(e=>{let t=setTimeout(()=>{Q.warn(`Timed out waiting for MCP roots/list_changed; using cwd fallback`,{cwd:process.cwd()}),e(!1)},5e3);p.server.setNotificationHandler(c,async()=>{clearTimeout(t);try{e(y((await p.server.listRoots()).roots))}catch(t){Q.warn(`roots/list retry failed after notification`,f(t)),e(!1)}})}),m();let x=null,S=()=>{x&&clearTimeout(x),x=setTimeout(async()=>{Q.info(`Auto-shutdown: no activity for 30 minutes — shutting down gracefully`);try{let e=d.aikit;e&&await Promise.all([e.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),e.graphStore.close().catch(()=>{}),e.store.close().catch(()=>{})])}catch{}process.exit(0)},18e5),x.unref&&x.unref()};S(),process.stdin.on(`data`,()=>S()),h.catch(e=>{Q.error(`Initialization failed — server will continue with limited tools`,f(e))}),h.then(()=>{qe(()=>d.aikit?{curated:d.aikit.curated,stateStore:d.aikit.stateStore}:null)}).catch(()=>{}),u===`auto`?g().catch(e=>Q.error(`Initial index failed`,f(e))):u===`smart`?h.then(async()=>{try{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(d.aikit.indexer,l,d.aikit.store),n=d.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),d.setSmartScheduler(t),Q.info(`Smart index scheduler started (stdio mode)`)}catch(e){Q.error(`Failed to start smart index scheduler`,f(e))}}).catch(e=>Q.error(`AI Kit init failed for smart scheduler`,f(e))):Q.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)}}Je();export{V as a,L as c,ae as d,R as f,Oe as i,ie as l,T as m,Pe as n,ye as o,re as p,je as r,ve as s,Le as t,B as u};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{t as e}from"./rolldown-runtime-DT7IzrpZ.js";import{createHash as t}from"node:crypto";import{dirname as n,isAbsolute as r,join as i}from"node:path";import{HealthBus as a,createLogger as o,serializeError as s}from"../../core/dist/index.js";import{mkdir as c,readFile as l,readdir as u,stat as d,unlink as f,writeFile as p}from"node:fs/promises";import{GIT_REF_SLUG_PATTERN as m,gitAvailable as h,gitCommitToRef as g,gitExec as _,slugForRef as v}from"../../tools/dist/index.js";var y=class{baseDir;constructor(e){this.baseDir=e}async initialize(){await c(this.baseDir,{recursive:!0})}async read(e){let t=i(this.baseDir,e);try{return await l(t,`utf-8`)}catch(e){if(e.code===`ENOENT`)return null;throw e}}async write(e,t,r){let a=i(this.baseDir,e);await c(n(a),{recursive:!0}),await p(a,t,{encoding:`utf-8`,flag:r?.exclusive?`wx`:`w`})}async delete(e){let t=i(this.baseDir,e);try{return await f(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=i(this.baseDir,e),r;try{r=await u(n)}catch{continue}for(let n of r){if(!n.endsWith(`.md`))continue;let r=`${e}/${n}`,a=i(this.baseDir,r);try{let e=await d(a);t.push({path:r,size:e.size})}catch{}}}return t}async exists(e){let t=i(this.baseDir,e);try{return await d(t),!0}catch{return!1}}async listDirectories(){try{return(await u(this.baseDir,{withFileTypes:!0})).filter(e=>e.isDirectory()&&/^[a-z][a-z0-9-]*$/.test(e.name)).map(e=>e.name)}catch{return[]}}async close(){}},b=e({CuratedKnowledgeManager:()=>w});const x=50*1024,S=`refs/aikit/knowledge`,C=o(`server`);var w=class{curatedDir;store;embedder;adapter;constructor(e,t,n,r=new y(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.slugify(e),a=await this.uniqueRelativePath(n,i),o=new Date().toISOString(),s={title:e,category:n,tags:r,created:o,updated:o,version:1,origin:`curated`,changelog:[{version:1,date:o,reason:`Initial creation`}]},c=this.serializeFile(t,s);try{await this.adapter.write(a,c,{exclusive:!0})}catch(e){throw e.code===`EEXIST`?Error(`Concurrent write collision for "${a}" — retry the operation`):e}return this.gitCommitKnowledge(a,c,`remember: ${e}\n\nCategory: ${n}\nTags: ${r.join(`, `)}`),await this.indexCuratedFileBestEffort(a,t,s,`remember`),{path:a}}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=>{C.warn(`File deleted but vector cleanup failed`,{sourcePath:n,...s(e)})}),this.gitDeleteKnowledgeRef(e),{path:e}}async history(e,t=20){if(e=this.guardPath(e),!h(this.curatedDir))return[];let n=this.knowledgeRefForPath(e);if(!n)return[];let r=_([`log`,`--format=%H|%aI|%s`,n,`-n`,String(t)],this.curatedDir);return r?r.split(`
|
|
2
|
+
`).filter(Boolean).map(e=>{let[t,n,...r]=e.split(`|`);return{sha:t,date:n,message:r.join(`|`)}}):[]}async diff(e,t,n){if(e=this.guardPath(e),!h(this.curatedDir))return``;if(!n){let r=await this.history(e,2);if(r.length===0)return``;n=r[0].sha,r.length>1&&!t&&(t=r[1].sha)}return t&&n?_([`diff`,`${t}:entry.md`,`${n}:entry.md`],this.curatedDir)??``:n?_([`show`,`${n}:entry.md`],this.curatedDir)??``:``}async recover(e){if(e=this.guardPath(e),await this.adapter.exists(e))throw Error(`Entry already exists on filesystem: ${e}. Use update() instead.`);if(!h(this.curatedDir))return null;let t=this.knowledgeRefForPath(e);if(!t)return null;let n=_([`show`,`${t}:entry.md`],this.curatedDir);if(!n)return null;await this.adapter.write(e,n);let{frontmatter:r,content:i}=this.parseFile(n);return await this.indexCuratedFile(e,i,r),{path:e,version:r.version??1}}async listOrphaned(){if(!h(this.curatedDir))return[];let e=_([`for-each-ref`,`--format=%(refname)|%(subject)`,`${S}/`],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(`${S}/`,``)}.md`;await this.adapter.exists(a)||t.push({ref:e,path:a,lastMessage:i})}return t}async read(e){e=this.guardPath(e);let t=await this.adapter.read(e);if(t==null)throw Error(`Curated entry not found: ${e}`);let{frontmatter:n,content:r}=this.parseFile(t),i=e.split(`/`)[0];return{path:e,title:n.title??e,category:i,tags:n.tags??[],version:n.version??1,created:n.created??``,updated:n.updated??``,contentPreview:r.slice(0,200),content:r}}async list(e){let t=[],n=e?.category?[e.category]:await this.discoverCategories();for(let r of n){let n=await this.adapter.list(r);for(let i of n){let n=await this.adapter.read(i.path);if(n==null)continue;let{frontmatter:a,content:o}=this.parseFile(n);e?.tag&&!(a.tags??[]).includes(e.tag)||t.push({path:i.path,title:a.title??i.path,category:r,tags:a.tags??[],version:a.version??1,created:a.created??``,updated:a.updated??``,contentPreview:o.slice(0,200)})}}return t}async reindexAll(){let e=await this.discoverCategories(),t=[],n=[];for(let r of e){let e=await this.adapter.list(r);for(let r of e){let e=r.path;try{let r=await this.adapter.read(e);if(r==null){t.push(`${e}: read failed`);continue}let{frontmatter:i,content:a}=this.parseFile(r);n.push({relativePath:e,content:a,frontmatter:i})}catch(n){C.error(`Failed to read curated file`,{relativePath:e,...s(n)}),t.push(`${e}: read failed`)}}}if(n.length===0)return{indexed:0,errors:t};let r=await this.embedder.embedBatch(n.map(e=>e.content)),i=new Date().toISOString(),a=n.map(e=>{let t=`.ai/curated/${e.relativePath}`;return{id:this.hashId(t,0),content:e.content,sourcePath:t,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:i,origin:`curated`,tags:e.frontmatter.tags,category:e.frontmatter.category,version:e.frontmatter.version}});return await this.store.upsert(a,r),{indexed:n.length,errors:t}}gitCommitKnowledge(e,t,n){try{if(!h(this.curatedDir))return;let r=this.knowledgeRefForPath(e);if(!r)return;g(r,`entry.md`,t,n,this.curatedDir)}catch{}}gitDeleteKnowledgeRef(e){try{if(!h(this.curatedDir))return;let t=this.knowledgeRefForPath(e);if(!t)return;_([`update-ref`,`-d`,t],this.curatedDir)}catch{}}knowledgeRefForPath(e){let t=e.replace(/\.md$/,``).split(`/`).map(e=>v(e)).join(`/`);return t.split(`/`).every(e=>m.test(e))?`${S}/${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(e,t,n,r){if(a.instance().isDegraded(`embedder`)){C.debug(`Skipping vector indexing — embedder degraded`,{relativePath:e,operation:r,subsystem:`embedder`});return}try{await this.indexCuratedFile(e,t,n)}catch(t){C.warn(`Curated file persisted but vector indexing deferred`,{relativePath:e,operation:r,...s(t)})}}async discoverCategories(){return this.adapter.listDirectories()}guardPath(e){let t=e.replace(/^\.ai\/curated\//,``);if(t.endsWith(`.md`)||(t+=`.md`),t.includes(`..`)||r(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`)>x)throw Error(`Content exceeds maximum size of ${x/1024}KB`)}slugify(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-|-$/g,``).slice(0,80)}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 t(`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
|
+
`)}\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
|
+
`),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{b as n,y as r,w as t};
|
|
@@ -155,6 +155,7 @@ declare class CuratedKnowledgeManager {
|
|
|
155
155
|
private gitDeleteKnowledgeRef;
|
|
156
156
|
private knowledgeRefForPath;
|
|
157
157
|
private indexCuratedFile;
|
|
158
|
+
private indexCuratedFileBestEffort;
|
|
158
159
|
private discoverCategories;
|
|
159
160
|
/**
|
|
160
161
|
* Normalize and validate a relative path within .ai/curated/.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./replay-interceptor-CGLyom5f.js";import{t}from"./curated-manager-D1u5qOwK.js";import{randomUUID as n}from"node:crypto";import{readFileSync as r}from"node:fs";import{dirname as i,resolve as a}from"node:path";import{fileURLToPath as o,pathToFileURL as s}from"node:url";import{parseArgs as c}from"node:util";import{createLogger as l,serializeError as u}from"../../core/dist/index.js";const d=`__pending__:`;function f(e){return e.startsWith(d)}function p(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function m(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var h=class{options;runtimes=new Map;maxSessions;sessionTimeoutMs;now;constructor(e){this.options=e,this.maxSessions=e.maxSessions??8,this.sessionTimeoutMs=(e.sessionTimeoutMinutes??30)*60*1e3,this.now=e.now??(()=>Date.now())}hasSession(e){return this.runtimes.has(e)}getSessionCount(){return this.runtimes.size}async handleRequest(e,t,n=e.body){let r=p(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){m(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){m(t,400,-32e3,`Session required`);return}if(i=await this.createRuntime(t),!i)return}await this.withRuntimeLock(i,async()=>{await i.transport.handleRequest(e,t,n),i.lastAccessAt=this.now();let r=i.transport.sessionId??i.id;e.method!==`DELETE`&&!f(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!f(r)&&await this.closeSession(r,{closeTransport:!1})})}async closeExpiredSessions(){let e=[...this.runtimes.values()].filter(e=>this.now()-e.lastAccessAt>=this.sessionTimeoutMs).map(e=>e.id);for(let t of e)await this.closeSession(t);return e.length}async closeSession(e,t={}){let n=this.runtimes.get(e);return n?(this.runtimes.delete(e),t.notifySessionEnd!==!1&&!f(e)&&this.options.onSessionEnd?.(e),t.closeTransport!==!1&&await n.transport.close().catch(()=>void 0),await n.server.close().catch(()=>void 0),!0):!1}async closeAll(){let e=[...this.runtimes.keys()];for(let t of e)await this.closeSession(t)}async createRuntime(e){if(await this.closeExpiredSessions(),this.runtimes.size>=this.maxSessions){m(e,503,-32003,`Session capacity reached`);return}let t=this.now(),r=await this.options.createServer(),i={id:`${d}${n()}`,transport:void 0,createdAt:t,lastAccessAt:t,server:r,requestChain:Promise.resolve()},a=this.options.createTransport({sessionIdGenerator:()=>n(),onsessioninitialized:async e=>{this.runtimes.delete(i.id),i.id=e,this.runtimes.set(e,i),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return i.transport=a,a.onclose=()=>{let e=i.transport.sessionId??i.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(i.id,i),await r.connect(a),i}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function g(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var _=class{stateStore;options;gcTimer=null;constructor(e,t={}){this.stateStore=e,this.options=t}onSessionStart(e,t){this.stateStore.sessionCreate(e,t)}onSessionActivity(e){this.stateStore.sessionTouch(e)}onSessionEnd(e){this.stateStore.sessionDelete(e),Promise.resolve(this.options.onSessionEndMaintenance?.(e)).catch(()=>{})}startGC(){if(this.gcTimer)return;let e=(this.options.gcIntervalMinutes??5)*60*1e3;this.gcTimer=setInterval(()=>{this.runGC()},e),this.gcTimer.unref()}runGC(){let e=this.getStaleSessionIds();for(let t of e)this.options.onBeforeSessionDelete?.(t),Promise.resolve(this.options.onSessionEndMaintenance?.(t)).catch(()=>{}),this.stateStore.sessionDelete(t);return e.length}stop(){this.gcTimer&&=(clearInterval(this.gcTimer),null)}getActiveSessions(){return this.stateStore.sessionList().length}listSessions(){return this.stateStore.sessionList()}getStaleSessionIds(e=Date.now()){let t=(this.options.staleTimeoutMinutes??30)*60*1e3;return this.stateStore.sessionList().filter(n=>{let r=g(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};function v(){try{let e=a(i(o(import.meta.url)),`..`,`..`,`..`,`package.json`);return JSON.parse(r(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}const y=l(`server`),b=/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;function x({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 S({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 C(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function w(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===s(e).href}catch{return!1}}function T(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function E(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 D(){return w()?c({allowPositionals:!0,options:{transport:{type:`string`,default:C()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:C(),port:process.env.AIKIT_PORT??`3210`}}function O(e){return`## Context\n${e.context}\n\n## Insight\n${e.insight}\n\n## Evidence\n${e.evidence}`}function k(t){e(e=>{(async()=>{let n=t();if(!n)return;let{jaccardSimilarity:r}=await import(`./supersession-9edUDEQ8.js`).then(e=>e.o),i=await n.curated.list({category:`lessons`});for(let t of e)i.some(e=>r(t.title,e.title)>.6)||(await n.curated.remember(t.title,O(t),`lessons`,[`lesson`,`auto-observed`,`detector:${t.detector}`]),i.push({path:`lessons/${t.title}`,title:t.title,category:`lessons`,tags:[`lesson`,`auto-observed`,`detector:${t.detector}`],version:1,created:new Date().toISOString(),updated:new Date().toISOString(),contentPreview:t.insight.slice(0,200)}))})().catch(()=>{})})}async function A(){let e=v(),t=D();process.on(`unhandledRejection`,e=>{y.error(`Unhandled rejection`,u(e))}),process.on(`uncaughtException`,e=>{y.error(`Uncaught exception — exiting`,u(e)),process.exit(1)});let r=(e,t)=>{e.then(async()=>{try{let{markPromoteRun:e,markPruneRun:n,prune:r,shouldRunStartupPrune:i,shouldRunWeeklyPromote:a}=await import(`../../tools/dist/index.js`),o=t();if(!o)return;if(i()){let e=await r({});n(),e.totalBytesFreed>0&&y.info(`Storage maintenance complete`,{forgeOrphans:e.forgeGroundOrphans.count,legacyLance:e.legacyLance.count,bytesFreed:e.totalBytesFreed});let{groupLessons:t,pruneLessons:i}=await import(`./evolution-DJhTM6nu.js`).then(e=>e.t),a=await i(o.curated,o.stateStore,{dryRun:!1});a.pruned.length>0&&y.info(`Startup lesson prune complete`,{pruned:a.pruned.length});let s=await t(o.curated,o.stateStore,{dryRun:!1});(s.groupsCreated>0||s.lessonsGrouped>0)&&y.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-OY53YCsT.js`).then(e=>e.o),{CuratedKnowledgeManager:s}=await import(`./curated-manager-D1u5qOwK.js`).then(e=>e.n),c=o.curated,l=new s(r(),c.store,c.embedder),u=await n(),d={...t,dryRun:!1},f=await i(a(u,d),l,d);e(),f.promoted.length>0&&y.info(`Weekly lesson promotion complete`,{promoted:f.promoted.length,candidates:f.candidates.length})}}catch(e){y.warn(`Startup maintenance failed (non-critical)`,u(e))}}).catch(()=>{})};if(y.info(`Starting MCP AI Kit server`,{version:e}),t.transport===`http`){let[{default:e},{loadConfig:i,resolveIndexMode:a},{registerDashboardRoutes:o,resolveDashboardDir:s},{registerSettingsRoutes:c,resolveSettingsDir:l},{createSettingsRouter:d},{authMiddleware:f,getOrCreateToken:p}]=await Promise.all([import(`express`),import(`./config-jGZ91cRx.js`),import(`./dashboard-static-FmfoS46e.js`),import(`./settings-static-BtvyIrza.js`),import(`./routes-CR3fI-HJ.js`),import(`./auth-Bz5dmZgR.js`).then(e=>e.t)]),m=i();y.info(`Config loaded`,{sourceCount:m.sources.length,storePath:m.store.path});let g=e();g.use(e.json({limit:`1mb`}));let v=Number(t.port),b=`http://localhost:${v}`,C=process.env.AIKIT_CORS_ORIGIN??b,w=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,D=E(`AIKIT_HTTP_MAX_SESSIONS`,8),O=E(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),A=E(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),j=S({limit:100,windowMs:6e4}),M=!1;g.use((e,t,n)=>{let r=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,i=x({requestOrigin:r,configuredOrigin:C,allowAnyOrigin:w,fallbackOrigin:b});if(i.warn&&!M&&(M=!0,y.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:r,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),r&&!i.allowOrigin){t.status(403).json({error:`Origin not allowed`});return}if(i.allowOrigin&&t.setHeader(`Access-Control-Allow-Origin`,i.allowOrigin),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID`),t.setHeader(`Access-Control-Expose-Headers`,`Mcp-Session-Id`),e.method===`OPTIONS`){t.status(204).end();return}n()});let N=p();console.error(`[aikit] Auth token: ~/.aikit/token`),g.use(f(N)),g.use(`/mcp`,(e,t,n)=>{let r=T(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(j.allow(r)){n();return}let i=Math.max(1,Math.ceil(j.getRetryAfterMs(r)/1e3));t.setHeader(`Retry-After`,String(i)),t.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})}),o(g,s(),y);let P=new Date().toISOString();g.use(`/settings/api`,d({log:y,mcpInfo:()=>({transport:`http`,port:v,pid:process.pid,startedAt:P})})),c(g,l(),y),g.get(`/health`,(e,t)=>{t.json({status:`ok`})});let F=!1,I=null,L=null,R=null,z=null,B=null,V=null,H=null,U=Promise.resolve(),W=async(e,t)=>{if(!F||!R||!z){t.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=U,i;U=new Promise(e=>{i=e}),await r;try{let r=T(e);if(!V){if(r){t.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new z({sessionIdGenerator:()=>n(),onsessioninitialized:async e=>{H=e,L?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&L?.onSessionEnd(e),H=null}});e.onclose=()=>{V===e&&(V=null),H===e.sessionId&&(H=null)},V=e,await R.connect(e)}let i=V;await i.handleRequest(e,t,e.body),e.method!==`DELETE`&&(!r&&i.sessionId?(H=i.sessionId,L?.onSessionStart(i.sessionId,{transport:`http`}),L?.onSessionActivity(i.sessionId)):r&&L?.onSessionActivity(r))}catch(e){if(y.error(`MCP handler error`,u(e)),!t.headersSent){let n=e instanceof Error?e.message:String(e),r=n.includes(`Not Acceptable`);t.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?n:`Internal server error`},id:null})}}finally{i()}},G=async(e,t)=>{let n=T(e);if(B&&(!V||n!==H)){await B.handleRequest(e,t,e.body);return}await W(e,t)};g.post(`/mcp`,G),g.get(`/mcp`,G),g.delete(`/mcp`,G);let K=g.listen(v,`127.0.0.1`,()=>{y.info(`MCP server listening`,{url:`http://127.0.0.1:${v}/mcp`,port:v}),setTimeout(async()=>{try{let[{createLazyServer:e,createMcpServer:t,ALL_TOOL_NAMES:n},{StreamableHTTPServerTransport:i},{checkForUpdates:o,autoUpgradeScaffold:s}]=await Promise.all([import(`./server-DGKTbYuR.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-D_uN0n0Y.js`)]);o(),s();let c=a(m),l=e(m,c);R=l.server,z=i,F=!0,y.info(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:n.length,resourceCount:2}),l.startInit(),l.ready.then(()=>{if(!l.aikit)throw Error(`AI Kit components are not available after initialization`);L=new _(l.aikit.stateStore,{staleTimeoutMinutes:O,gcIntervalMinutes:A,onBeforeSessionDelete:e=>{if(H===e&&V){let e=V;V=null,H=null,e.close().catch(()=>void 0)}B?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!l.aikit?.curated||!l.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-DJhTM6nu.js`).then(e=>e.t),t=await e(l.aikit.curated,l.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&y.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),B=new h({createServer:()=>{if(!l.aikit)throw Error(`AI Kit components are not available after initialization`);return t(l.aikit,m)},createTransport:e=>new i(e),maxSessions:D,sessionTimeoutMinutes:O,onSessionStart:e=>L?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>L?.onSessionActivity(e),onSessionEnd:e=>L?.onSessionEnd(e)}),L.startGC(),H&&(L.onSessionStart(H,{transport:`http`}),L.onSessionActivity(H)),k(()=>l.aikit?{curated:l.aikit.curated,stateStore:l.aikit.stateStore}:null),y.info(`HTTP session runtime ready`,{maxSessions:D,sessionTimeoutMinutes:O,gcIntervalMinutes:A})}).catch(e=>y.error(`Failed to start session manager`,u(e))),c===`auto`?l.ready.then(async()=>{try{let e=m.sources.map(e=>e.path).join(`, `);y.info(`Running initial index`,{sourcePaths:e}),await l.runInitialIndex(),y.info(`Initial index complete`)}catch(e){y.error(`Initial index failed; will retry on aikit_reindex`,u(e))}}).catch(e=>y.error(`AI Kit init or indexing failed`,u(e))):c===`smart`?l.ready.then(async()=>{try{if(!l.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(l.aikit.indexer,m,l.aikit.store),n=l.aikit.store;I=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),l.setSmartScheduler(t),y.info(`Smart index scheduler started (HTTP mode)`)}catch(e){y.error(`Failed to start smart index scheduler`,u(e))}}).catch(e=>y.error(`AI Kit initialization failed`,u(e))):(l.ready.catch(e=>y.error(`AI Kit initialization failed`,u(e))),y.info(`Initial full indexing skipped in HTTP mode`,{indexMode:c})),r(l.ready,()=>l.aikit?{curated:l.aikit.curated,stateStore:l.aikit.stateStore}:null)}catch(e){y.error(`Failed to load server modules`,u(e))}},100)}),q=async e=>{y.info(`Shutdown signal received`,{signal:e}),I?.stop(),L?.stop(),await B?.closeAll().catch(()=>void 0),H&&L?.onSessionEnd(H),V&&(await V.close().catch(()=>void 0),V=null,H=null),K.close(),R&&await R.close(),process.exit(0)};process.on(`SIGINT`,()=>q(`SIGINT`)),process.on(`SIGTERM`,()=>q(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:n},{createLazyServer:i},{checkForUpdates:a,autoUpgradeScaffold:s},{RootsListChangedNotificationSchema:c}]=await Promise.all([import(`./config-jGZ91cRx.js`),import(`./server-DGKTbYuR.js`),import(`./version-check-D_uN0n0Y.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=e();y.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),a(),s();let d=n(l),f=i(l,d),{server:p,startInit:m,ready:h,runInitialIndex:g}=f,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await p.connect(v),y.info(`MCP server started`,{transport:`stdio`});let b=e=>{if(e.length===0)return!1;let n=e[0].uri,r=n.startsWith(`file://`)?o(n):n;return y.info(`MCP roots resolved`,{rootUri:n,rootPath:r,rootCount:e.length}),t(l,r),l.allRoots=e.map(e=>{let t=e.uri;return t.startsWith(`file://`)?o(t):t}),!0},x=!1;try{x=b((await p.server.listRoots()).roots),x||y.info(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(e){y.warn(`MCP roots/list not supported by client; using cwd fallback`,{cwd:process.cwd(),...u(e)}),x=!0}x||=await new Promise(e=>{let t=setTimeout(()=>{y.warn(`Timed out waiting for MCP roots/list_changed; using cwd fallback`,{cwd:process.cwd()}),e(!1)},5e3);p.server.setNotificationHandler(c,async()=>{clearTimeout(t);try{e(b((await p.server.listRoots()).roots))}catch(t){y.warn(`roots/list retry failed after notification`,u(t)),e(!1)}})}),m();let S=null,C=()=>{S&&clearTimeout(S),S=setTimeout(async()=>{y.info(`Auto-shutdown: no activity for 30 minutes — shutting down gracefully`);try{let e=f.aikit;e&&await Promise.all([e.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),e.graphStore.close().catch(()=>{}),e.store.close().catch(()=>{})])}catch{}process.exit(0)},18e5),S.unref&&S.unref()};C(),process.stdin.on(`data`,()=>C()),h.catch(e=>{y.error(`Initialization failed — server will continue with limited tools`,u(e))}),h.then(()=>{k(()=>f.aikit?{curated:f.aikit.curated,stateStore:f.aikit.stateStore}:null)}).catch(()=>{}),d===`auto`?g().catch(e=>y.error(`Initial index failed`,u(e))):d===`smart`?h.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.aikit.indexer,l,f.aikit.store),n=f.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),f.setSmartScheduler(t),y.info(`Smart index scheduler started (stdio mode)`)}catch(e){y.error(`Failed to start smart index scheduler`,u(e))}}).catch(e=>y.error(`AI Kit init failed for smart scheduler`,u(e))):y.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:d}),r(h,()=>f.aikit?{curated:f.aikit.curated,stateStore:f.aikit.stateStore}:null)}}export{t as CuratedKnowledgeManager,S as createSlidingWindowRateLimiter,A as main,x as resolveCorsOrigin};
|
|
1
|
+
import{r as e}from"./replay-interceptor-CGLyom5f.js";import{t}from"./curated-manager-BrtqcmVm.js";import{randomUUID as n}from"node:crypto";import{readFileSync as r}from"node:fs";import{dirname as i,resolve as a}from"node:path";import{fileURLToPath as o,pathToFileURL as s}from"node:url";import{parseArgs as c}from"node:util";import{createLogger as l,serializeError as u}from"../../core/dist/index.js";const d=`__pending__:`;function f(e){return e.startsWith(d)}function p(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function m(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var h=class{options;runtimes=new Map;maxSessions;sessionTimeoutMs;now;constructor(e){this.options=e,this.maxSessions=e.maxSessions??8,this.sessionTimeoutMs=(e.sessionTimeoutMinutes??30)*60*1e3,this.now=e.now??(()=>Date.now())}hasSession(e){return this.runtimes.has(e)}getSessionCount(){return this.runtimes.size}async handleRequest(e,t,n=e.body){let r=p(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){m(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){m(t,400,-32e3,`Session required`);return}if(i=await this.createRuntime(t),!i)return}await this.withRuntimeLock(i,async()=>{await i.transport.handleRequest(e,t,n),i.lastAccessAt=this.now();let r=i.transport.sessionId??i.id;e.method!==`DELETE`&&!f(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!f(r)&&await this.closeSession(r,{closeTransport:!1})})}async closeExpiredSessions(){let e=[...this.runtimes.values()].filter(e=>this.now()-e.lastAccessAt>=this.sessionTimeoutMs).map(e=>e.id);for(let t of e)await this.closeSession(t);return e.length}async closeSession(e,t={}){let n=this.runtimes.get(e);return n?(this.runtimes.delete(e),t.notifySessionEnd!==!1&&!f(e)&&this.options.onSessionEnd?.(e),t.closeTransport!==!1&&await n.transport.close().catch(()=>void 0),await n.server.close().catch(()=>void 0),!0):!1}async closeAll(){let e=[...this.runtimes.keys()];for(let t of e)await this.closeSession(t)}async createRuntime(e){if(await this.closeExpiredSessions(),this.runtimes.size>=this.maxSessions){m(e,503,-32003,`Session capacity reached`);return}let t=this.now(),r=await this.options.createServer(),i={id:`${d}${n()}`,transport:void 0,createdAt:t,lastAccessAt:t,server:r,requestChain:Promise.resolve()},a=this.options.createTransport({sessionIdGenerator:()=>n(),onsessioninitialized:async e=>{this.runtimes.delete(i.id),i.id=e,this.runtimes.set(e,i),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return i.transport=a,a.onclose=()=>{let e=i.transport.sessionId??i.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(i.id,i),await r.connect(a),i}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function g(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var _=class{stateStore;options;gcTimer=null;constructor(e,t={}){this.stateStore=e,this.options=t}onSessionStart(e,t){this.stateStore.sessionCreate(e,t)}onSessionActivity(e){this.stateStore.sessionTouch(e)}onSessionEnd(e){this.stateStore.sessionDelete(e),Promise.resolve(this.options.onSessionEndMaintenance?.(e)).catch(()=>{})}startGC(){if(this.gcTimer)return;let e=(this.options.gcIntervalMinutes??5)*60*1e3;this.gcTimer=setInterval(()=>{this.runGC()},e),this.gcTimer.unref()}runGC(){let e=this.getStaleSessionIds();for(let t of e)this.options.onBeforeSessionDelete?.(t),Promise.resolve(this.options.onSessionEndMaintenance?.(t)).catch(()=>{}),this.stateStore.sessionDelete(t);return e.length}stop(){this.gcTimer&&=(clearInterval(this.gcTimer),null)}getActiveSessions(){return this.stateStore.sessionList().length}listSessions(){return this.stateStore.sessionList()}getStaleSessionIds(e=Date.now()){let t=(this.options.staleTimeoutMinutes??30)*60*1e3;return this.stateStore.sessionList().filter(n=>{let r=g(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};function v(){try{let e=a(i(o(import.meta.url)),`..`,`..`,`..`,`package.json`);return JSON.parse(r(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}const y=l(`server`),b=/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;function x({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 S({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 C(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function w(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===s(e).href}catch{return!1}}function T(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function E(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 D(){return w()?c({allowPositionals:!0,options:{transport:{type:`string`,default:C()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:C(),port:process.env.AIKIT_PORT??`3210`}}function O(e){return`## Context\n${e.context}\n\n## Insight\n${e.insight}\n\n## Evidence\n${e.evidence}`}function k(t){e(e=>{(async()=>{let n=t();if(!n)return;let{jaccardSimilarity:r}=await import(`./supersession-9edUDEQ8.js`).then(e=>e.o),i=await n.curated.list({category:`lessons`});for(let t of e)i.some(e=>r(t.title,e.title)>.6)||(await n.curated.remember(t.title,O(t),`lessons`,[`lesson`,`auto-observed`,`detector:${t.detector}`]),i.push({path:`lessons/${t.title}`,title:t.title,category:`lessons`,tags:[`lesson`,`auto-observed`,`detector:${t.detector}`],version:1,created:new Date().toISOString(),updated:new Date().toISOString(),contentPreview:t.insight.slice(0,200)}))})().catch(()=>{})})}async function A(){let e=v(),t=D();process.on(`unhandledRejection`,e=>{y.error(`Unhandled rejection`,u(e))}),process.on(`uncaughtException`,e=>{y.error(`Uncaught exception — exiting`,u(e)),process.exit(1)});let r=(e,t)=>{e.then(async()=>{try{let{markPromoteRun:e,markPruneRun:n,prune:r,shouldRunStartupPrune:i,shouldRunWeeklyPromote:a}=await import(`../../tools/dist/index.js`),o=t();if(!o)return;if(i()){let e=await r({});n(),e.totalBytesFreed>0&&y.info(`Storage maintenance complete`,{forgeOrphans:e.forgeGroundOrphans.count,legacyLance:e.legacyLance.count,bytesFreed:e.totalBytesFreed});let{groupLessons:t,pruneLessons:i}=await import(`./evolution-DJhTM6nu.js`).then(e=>e.t),a=await i(o.curated,o.stateStore,{dryRun:!1});a.pruned.length>0&&y.info(`Startup lesson prune complete`,{pruned:a.pruned.length});let s=await t(o.curated,o.stateStore,{dryRun:!1});(s.groupsCreated>0||s.lessonsGrouped>0)&&y.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-BppF9YlR.js`).then(e=>e.o),{CuratedKnowledgeManager:s}=await import(`./curated-manager-BrtqcmVm.js`).then(e=>e.n),c=o.curated,l=new s(r(),c.store,c.embedder),u=await n(),d={...t,dryRun:!1},f=await i(a(u,d),l,d);e(),f.promoted.length>0&&y.info(`Weekly lesson promotion complete`,{promoted:f.promoted.length,candidates:f.candidates.length})}}catch(e){y.warn(`Startup maintenance failed (non-critical)`,u(e))}}).catch(()=>{})};if(y.info(`Starting MCP AI Kit server`,{version:e}),t.transport===`http`){let[{default:e},{loadConfig:i,resolveIndexMode:a},{registerDashboardRoutes:o,resolveDashboardDir:s},{registerSettingsRoutes:c,resolveSettingsDir:l},{createSettingsRouter:d},{authMiddleware:f,getOrCreateToken:p}]=await Promise.all([import(`express`),import(`./config-jGZ91cRx.js`),import(`./dashboard-static-FmfoS46e.js`),import(`./settings-static-BtvyIrza.js`),import(`./routes-CR3fI-HJ.js`),import(`./auth-Bz5dmZgR.js`).then(e=>e.t)]),m=i();y.info(`Config loaded`,{sourceCount:m.sources.length,storePath:m.store.path});let g=e();g.use(e.json({limit:`1mb`}));let v=Number(t.port),b=`http://localhost:${v}`,C=process.env.AIKIT_CORS_ORIGIN??b,w=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,D=E(`AIKIT_HTTP_MAX_SESSIONS`,8),O=E(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),A=E(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),j=S({limit:100,windowMs:6e4}),M=!1;g.use((e,t,n)=>{let r=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,i=x({requestOrigin:r,configuredOrigin:C,allowAnyOrigin:w,fallbackOrigin:b});if(i.warn&&!M&&(M=!0,y.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:r,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),r&&!i.allowOrigin){t.status(403).json({error:`Origin not allowed`});return}if(i.allowOrigin&&t.setHeader(`Access-Control-Allow-Origin`,i.allowOrigin),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID`),t.setHeader(`Access-Control-Expose-Headers`,`Mcp-Session-Id`),e.method===`OPTIONS`){t.status(204).end();return}n()});let N=p();console.error(`[aikit] Auth token: ~/.aikit/token`),g.use(f(N)),g.use(`/mcp`,(e,t,n)=>{let r=T(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(j.allow(r)){n();return}let i=Math.max(1,Math.ceil(j.getRetryAfterMs(r)/1e3));t.setHeader(`Retry-After`,String(i)),t.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})}),o(g,s(),y);let P=new Date().toISOString();g.use(`/settings/api`,d({log:y,mcpInfo:()=>({transport:`http`,port:v,pid:process.pid,startedAt:P})})),c(g,l(),y),g.get(`/health`,(e,t)=>{t.json({status:`ok`})});let F=!1,I=null,L=null,R=null,z=null,B=null,V=null,H=null,U=Promise.resolve(),W=async(e,t)=>{if(!F||!R||!z){t.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=U,i;U=new Promise(e=>{i=e}),await r;try{let r=T(e);if(!V){if(r){t.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new z({sessionIdGenerator:()=>n(),onsessioninitialized:async e=>{H=e,L?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&L?.onSessionEnd(e),H=null}});e.onclose=()=>{V===e&&(V=null),H===e.sessionId&&(H=null)},V=e,await R.connect(e)}let i=V;await i.handleRequest(e,t,e.body),e.method!==`DELETE`&&(!r&&i.sessionId?(H=i.sessionId,L?.onSessionStart(i.sessionId,{transport:`http`}),L?.onSessionActivity(i.sessionId)):r&&L?.onSessionActivity(r))}catch(e){if(y.error(`MCP handler error`,u(e)),!t.headersSent){let n=e instanceof Error?e.message:String(e),r=n.includes(`Not Acceptable`);t.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?n:`Internal server error`},id:null})}}finally{i()}},G=async(e,t)=>{let n=T(e);if(B&&(!V||n!==H)){await B.handleRequest(e,t,e.body);return}await W(e,t)};g.post(`/mcp`,G),g.get(`/mcp`,G),g.delete(`/mcp`,G);let K=g.listen(v,`127.0.0.1`,()=>{y.info(`MCP server listening`,{url:`http://127.0.0.1:${v}/mcp`,port:v}),setTimeout(async()=>{try{let[{createLazyServer:e,createMcpServer:t,ALL_TOOL_NAMES:n},{StreamableHTTPServerTransport:i},{checkForUpdates:o,autoUpgradeScaffold:s}]=await Promise.all([import(`./server-CBbp-_E9.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-D_uN0n0Y.js`)]);o(),s();let c=a(m),l=e(m,c);R=l.server,z=i,F=!0,y.info(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:n.length,resourceCount:2}),l.startInit(),l.ready.then(()=>{if(!l.aikit)throw Error(`AI Kit components are not available after initialization`);L=new _(l.aikit.stateStore,{staleTimeoutMinutes:O,gcIntervalMinutes:A,onBeforeSessionDelete:e=>{if(H===e&&V){let e=V;V=null,H=null,e.close().catch(()=>void 0)}B?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!l.aikit?.curated||!l.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-DJhTM6nu.js`).then(e=>e.t),t=await e(l.aikit.curated,l.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&y.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),B=new h({createServer:()=>{if(!l.aikit)throw Error(`AI Kit components are not available after initialization`);return t(l.aikit,m)},createTransport:e=>new i(e),maxSessions:D,sessionTimeoutMinutes:O,onSessionStart:e=>L?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>L?.onSessionActivity(e),onSessionEnd:e=>L?.onSessionEnd(e)}),L.startGC(),H&&(L.onSessionStart(H,{transport:`http`}),L.onSessionActivity(H)),k(()=>l.aikit?{curated:l.aikit.curated,stateStore:l.aikit.stateStore}:null),y.info(`HTTP session runtime ready`,{maxSessions:D,sessionTimeoutMinutes:O,gcIntervalMinutes:A})}).catch(e=>y.error(`Failed to start session manager`,u(e))),c===`auto`?l.ready.then(async()=>{try{let e=m.sources.map(e=>e.path).join(`, `);y.info(`Running initial index`,{sourcePaths:e}),await l.runInitialIndex(),y.info(`Initial index complete`)}catch(e){y.error(`Initial index failed; will retry on aikit_reindex`,u(e))}}).catch(e=>y.error(`AI Kit init or indexing failed`,u(e))):c===`smart`?l.ready.then(async()=>{try{if(!l.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(l.aikit.indexer,m,l.aikit.store),n=l.aikit.store;I=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),l.setSmartScheduler(t),y.info(`Smart index scheduler started (HTTP mode)`)}catch(e){y.error(`Failed to start smart index scheduler`,u(e))}}).catch(e=>y.error(`AI Kit initialization failed`,u(e))):(l.ready.catch(e=>y.error(`AI Kit initialization failed`,u(e))),y.info(`Initial full indexing skipped in HTTP mode`,{indexMode:c})),r(l.ready,()=>l.aikit?{curated:l.aikit.curated,stateStore:l.aikit.stateStore}:null)}catch(e){y.error(`Failed to load server modules`,u(e))}},100)}),q=async e=>{y.info(`Shutdown signal received`,{signal:e}),I?.stop(),L?.stop(),await B?.closeAll().catch(()=>void 0),H&&L?.onSessionEnd(H),V&&(await V.close().catch(()=>void 0),V=null,H=null),K.close(),R&&await R.close(),process.exit(0)};process.on(`SIGINT`,()=>q(`SIGINT`)),process.on(`SIGTERM`,()=>q(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:n},{createLazyServer:i},{checkForUpdates:a,autoUpgradeScaffold:s},{RootsListChangedNotificationSchema:c}]=await Promise.all([import(`./config-jGZ91cRx.js`),import(`./server-CBbp-_E9.js`),import(`./version-check-D_uN0n0Y.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=e();y.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),a(),s();let d=n(l),f=i(l,d),{server:p,startInit:m,ready:h,runInitialIndex:g}=f,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await p.connect(v),y.info(`MCP server started`,{transport:`stdio`});let b=e=>{if(e.length===0)return!1;let n=e[0].uri,r=n.startsWith(`file://`)?o(n):n;return y.info(`MCP roots resolved`,{rootUri:n,rootPath:r,rootCount:e.length}),t(l,r),l.allRoots=e.map(e=>{let t=e.uri;return t.startsWith(`file://`)?o(t):t}),!0},x=!1;try{x=b((await p.server.listRoots()).roots),x||y.info(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(e){y.warn(`MCP roots/list not supported by client; using cwd fallback`,{cwd:process.cwd(),...u(e)}),x=!0}x||=await new Promise(e=>{let t=setTimeout(()=>{y.warn(`Timed out waiting for MCP roots/list_changed; using cwd fallback`,{cwd:process.cwd()}),e(!1)},5e3);p.server.setNotificationHandler(c,async()=>{clearTimeout(t);try{e(b((await p.server.listRoots()).roots))}catch(t){y.warn(`roots/list retry failed after notification`,u(t)),e(!1)}})}),m();let S=null,C=()=>{S&&clearTimeout(S),S=setTimeout(async()=>{y.info(`Auto-shutdown: no activity for 30 minutes — shutting down gracefully`);try{let e=f.aikit;e&&await Promise.all([e.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),e.graphStore.close().catch(()=>{}),e.store.close().catch(()=>{})])}catch{}process.exit(0)},18e5),S.unref&&S.unref()};C(),process.stdin.on(`data`,()=>C()),h.catch(e=>{y.error(`Initialization failed — server will continue with limited tools`,u(e))}),h.then(()=>{k(()=>f.aikit?{curated:f.aikit.curated,stateStore:f.aikit.stateStore}:null)}).catch(()=>{}),d===`auto`?g().catch(e=>y.error(`Initial index failed`,u(e))):d===`smart`?h.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.aikit.indexer,l,f.aikit.store),n=f.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),f.setSmartScheduler(t),y.info(`Smart index scheduler started (stdio mode)`)}catch(e){y.error(`Failed to start smart index scheduler`,u(e))}}).catch(e=>y.error(`AI Kit init failed for smart scheduler`,u(e))):y.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:d}),r(h,()=>f.aikit?{curated:f.aikit.curated,stateStore:f.aikit.stateStore}:null)}}export{t as CuratedKnowledgeManager,S as createSlidingWindowRateLimiter,A as main,x as resolveCorsOrigin};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./rolldown-runtime-DT7IzrpZ.js";import{r as t}from"./supersession-9edUDEQ8.js";import{t as n}from"./curated-manager-
|
|
1
|
+
import{t as e}from"./rolldown-runtime-DT7IzrpZ.js";import{r as t}from"./supersession-9edUDEQ8.js";import{t as n}from"./curated-manager-BrtqcmVm.js";import{a as r,s as i}from"./lessons-D7sdHa2e.js";import{existsSync as a,mkdirSync as o}from"node:fs";import{join as s}from"node:path";import{getGlobalDataDir as c,isUserInstalled as l,listWorkspaces as u}from"../../core/dist/index.js";var d=e({DEFAULT_PROMOTE_CONFIG:()=>f,collectWorkspaceLessons:()=>w,demoteLesson:()=>D,getGlobalCuratedDir:()=>C,promoteLessons:()=>E,scanForDuplicates:()=>T});const f={minWorkspaces:2,minAvgConfidence:80,similarityThreshold:.7,dryRun:!0};function p(e){return{minWorkspaces:Math.max(2,Math.trunc(e?.minWorkspaces??f.minWorkspaces)),minAvgConfidence:Math.min(100,Math.max(0,Math.trunc(e?.minAvgConfidence??f.minAvgConfidence))),similarityThreshold:Math.min(1,Math.max(0,e?.similarityThreshold??f.similarityThreshold)),dryRun:e?.dryRun??f.dryRun}}function m(e,n){let r=e.map(()=>[]);for(let i=0;i<e.length;i+=1)for(let a=i+1;a<e.length;a+=1)t(e[i].insight,e[a].insight)>=n&&(r[i].push(a),r[a].push(i));return r}function h(e){let t=new Set,n=[];for(let r=0;r<e.length;r+=1){if(t.has(r))continue;let i=[r],a=[];for(t.add(r);i.length>0;){let n=i.pop();if(n!==void 0){a.push(n);for(let r of e[n])t.has(r)||(t.add(r),i.push(r))}}n.push(a)}return n}function g(e){return new n(e,null,null)}function _(e){return(e??``).replace(/\s+/g,` `).trim()}function v(e){let t=_(e);return t.length<=80?t:`${t.slice(0,77).replace(/\s+\S*$/,``)}...`}function y(e){return r({title:v(e.insight),context:`Observed across ${e.foundIn.length} workspaces: ${e.foundIn.join(`, `)}`,insight:e.insight,evidence:[`Promoted from workspaces: ${e.foundIn.join(`, `)}`,`Average confidence: ${e.avgConfidence}/100`,`Reason: ${e.reason}`].join(`
|
|
2
2
|
`),confidence:e.avgConfidence,tags:[`lesson`,`promoted`,`global`]})}async function b(e,t){let n=await e.list({category:`lessons`});return(await Promise.all(n.map(async n=>{let r=await e.read(n.path),a=i(r.content),o=_(a.insight);return o?{workspace:t,path:n.path,title:a.title??r.title??n.title,insight:o,confidence:a.confidence??0}:null}))).filter(e=>e!==null)}async function x(e){return(await b(e,`global`)).map(e=>e.insight)}function S(e,n,r){return n.some(n=>t(n,e)>=r)}function C(){let e=s(c(),`global-knowledge`,`.ai`,`curated`);return a(e)||o(e,{recursive:!0}),e}async function w(e){let t=new Map;if(!l())return t;for(let e of u()){let n=s(e.workspacePath,`.ai`,`curated`);if(!a(n))continue;let r=await b(g(n),e.partition);r.length>0&&t.set(e.partition,r)}return t}function T(e,t=f){let n=p(t),r=[...e.values()].flat();if(r.length===0)return[];let i=h(m(r,n.similarityThreshold)),a=[];for(let e of i){let t=e.map(e=>r[e]),i=[...new Set(t.map(e=>e.workspace))].sort();if(i.length<n.minWorkspaces)continue;let o=Math.round(t.reduce((e,t)=>e+t.confidence,0)/t.length),s=[...t].sort((e,t)=>t.confidence-e.confidence||e.title.localeCompare(t.title)||e.path.localeCompare(t.path))[0];a.push({insight:s.insight,foundIn:i,avgConfidence:o,action:o>=n.minAvgConfidence?`promote`:`skip`,reason:o>=n.minAvgConfidence?`Shared across ${i.length} workspaces`:`Below confidence threshold`})}return a.sort((e,t)=>Number(t.action===`promote`)-Number(e.action===`promote`)||t.foundIn.length-e.foundIn.length||t.avgConfidence-e.avgConfidence||e.insight.localeCompare(t.insight))}async function E(e,t,n=f){let r=p(n),i=[],a=await x(t);for(let n of e){if(n.action!==`promote`||S(n.insight,a,r.similarityThreshold)||r.dryRun)continue;let e=await t.remember(v(n.insight),y(n),`lessons`,[`lesson`,`promoted`,`global`]);i.push(e.path),a.push(n.insight)}return{candidates:e,promoted:i}}async function D(e,t){try{return await e.forget(t,`Demoted from global knowledge partition`),{removed:!0,path:t}}catch(e){if(e instanceof Error&&/not found/i.test(e.message))return{removed:!1,path:t};throw e}}export{E as a,C as i,w as n,d as o,D as r,T as s,f as t};
|