@vpxa/aikit 0.1.301 → 0.1.303
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/embeddings/dist/index.js +1 -1
- package/packages/server/dist/bin.js +1 -1
- package/packages/server/dist/config-CaJwUDXI.js +2 -0
- package/packages/server/dist/config-_gMeJYrz.js +1 -0
- package/packages/server/dist/index.js +1 -1
- package/packages/server/dist/{server-CDWtY-Sp.js → server-DmTxBqKe.js} +123 -123
- package/packages/server/dist/{server-DSRcQgsx.js → server-o1JlU7yI.js} +123 -123
- package/packages/store/dist/index.js +1 -1
- package/packages/server/dist/config-B5gyZrbp.js +0 -2
- package/packages/server/dist/config-CcbU0fiV.js +0 -1
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{fork as e}from"node:child_process";import{randomUUID as t}from"node:crypto";import{existsSync as n}from"node:fs";import{dirname as r,join as i}from"node:path";import{fileURLToPath as a}from"node:url";import{CircuitBreaker as o,CircuitOpenError as s,EMBEDDING_DEFAULTS as c,HealthBus as l,MODEL_REGISTRY as u}from"../../core/dist/index.js";import{rm as d}from"node:fs/promises";import{homedir as f}from"node:os";var p=class{options;logger;healthBus=l.instance();cb;initTimeoutMs;requestTimeoutMs;maxRetries;retryBaseDelayMs;workerAvailable=!0;workerPath=i(r(a(import.meta.url)),`embedder-worker.js`);pendingRequests=new Map;childState=new WeakMap;childErrors=new WeakMap;child=null;readyChild=null;pendingInit=null;pendingShutdown=null;initializePromise=null;shutdownPromise=null;cooldownRespawnTimer=null;currentDimensions;currentModelId;coldStart=!0;constructor(e={}){this.options=e,this.logger=e.logger,this.healthBus.register(`embedder`),this.cb=new o({threshold:3,cooldownMs:6e4,name:`embedder`}),this.cb.on(`open`,()=>{this.healthBus.reportDegraded(`embedder`,`Circuit breaker open — consecutive timeouts`),this.startCooldownRespawn()}),this.cb.on(`closed`,()=>{this.healthBus.reportRecovered(`embedder`)}),this.initTimeoutMs=Math.max(0,e.initTimeoutMs??6e4),this.requestTimeoutMs=Math.max(0,e.requestTimeoutMs??(process.platform===`win32`?6e4:3e4)),this.maxRetries=Math.max(0,e.maxRetries??3),this.retryBaseDelayMs=Math.max(0,e.retryBaseDelayMs??500),this.currentDimensions=e.dimensions??c.dimensions,this.currentModelId=e.model??c.model}get dimensions(){return this.currentDimensions}get modelId(){return this.currentModelId}get isCircuitOpen(){return this.cb.isOpen()}async initialize(){if(!(this.readyChild&&this.child===this.readyChild)&&this.workerAvailable){if(!n(this.workerPath)){this.workerAvailable=!1,console.warn(`[aikit] Embedder worker not found at ${this.workerPath}. Embedding disabled - search will use keyword matching only. This usually means the npx cache is corrupted; restart to fix.`);return}if(this.initializePromise)return this.initializePromise;if(this.shutdownPromise){try{await this.shutdownPromise}catch{}if(this.readyChild&&this.child===this.readyChild)return}return this.initializePromise=this.startWorker().finally(()=>{this.initializePromise=null}),this.initializePromise}}async embed(e){if(!this.workerAvailable||(this.assertCircuitClosed(),await this.initialize(),!this.workerAvailable))throw Error(`Embedding worker is not available — embeddings cannot be computed. Check server logs for initialization errors.`);return this.sendVectorRequestWithRetry({type:`embed`,text:e})}async embedQuery(e){if(!this.workerAvailable||(this.assertCircuitClosed(),await this.initialize(),!this.workerAvailable))throw Error(`Embedding worker is not available — embeddings cannot be computed. Check server logs for initialization errors.`);return this.sendVectorRequestWithRetry({type:`embedQuery`,text:e})}async embedBatch(e,t){if(e.length===0)return[];if(!this.workerAvailable||(this.assertCircuitClosed(),await this.initialize(),!this.workerAvailable))throw Error(`Embedding worker is not available — embeddings cannot be computed. Check server logs for initialization errors.`);return this.withWorkerExitRetry(`embedBatch`,()=>this.sendBatchRequest(e,t))}async sendBatchRequest(e,n){await this.initialize();let r=this.requireReadyChild(),i=t(),a=new Promise((e,t)=>{this.pendingRequests.set(i,{child:r,resolve:t=>e(t),reject:t})});try{r.send({type:`embedBatch`,id:i,texts:e,batchSize:n})}catch(e){throw this.pendingRequests.delete(i),this.toError(e,`Failed to send embedBatch request to worker`)}let o=this.requestTimeoutMs>0?Math.max(this.requestTimeoutMs*3,9e4):0;if(o>0){let t,n=new Promise((n,r)=>{t=setTimeout(()=>{this.pendingRequests.delete(i),this.markWorkerUnresponsive(),r(Error(`Embedder embedBatch request timed out after ${o/1e3}s (${e.length} texts). The worker has been killed and will attempt to respawn automatically.`))},o)});try{return await Promise.race([a,n])}finally{t!==void 0&&clearTimeout(t)}}return a}async shutdown(){if(this.clearCooldownRespawnTimer(),this.shutdownPromise)return this.shutdownPromise;let e=this.child;if(!e)return;let t=this.requireChildState(e);t.shutdownRequested=!0,this.readyChild===e&&(this.readyChild=null),this.shutdownPromise=new Promise((t,n)=>{this.pendingShutdown={child:e,resolve:t,reject:n}}).finally(()=>{this.shutdownPromise=null});try{e.send({type:`shutdown`})}catch(t){let n=this.toError(t,`Failed to send shutdown request to worker`);throw this.clearChildReference(e),this.rejectPendingForChild(e,n),this.rejectLifecycleIfOwned(`shutdown`,e,n),n}return this.shutdownPromise}async startWorker(){this.child&&this.readyChild!==this.child&&(this.child=null),this.clearCooldownRespawnTimer(),this.coldStart=!0;let e=this.spawnChild();this.child=e,this.readyChild=null;let t=new Promise((t,n)=>{this.pendingInit={child:e,resolve:t,reject:n}});try{e.send({type:`init`,config:this.buildInitConfig()})}catch(t){let n=this.toError(t,`Failed to send init request to worker`);throw this.pendingInit=null,this.clearChildReference(e),n}if(this.initTimeoutMs>0){let n,r=new Promise((e,t)=>{n=setTimeout(()=>{t(Error(`Embedder worker initialization timed out after ${this.initTimeoutMs/1e3}s. The ONNX model may be downloading or the child process is stuck. Check network connectivity and disk space, or restart the server.`))},this.initTimeoutMs)});try{await Promise.race([t,r]);return}catch(t){this.pendingInit=null;try{e.kill()}catch{}throw this.clearChildReference(e),t}finally{n!==void 0&&clearTimeout(n)}}await t}spawnChild(){let t=e(this.workerPath,[],{env:this.buildChildEnv()});return this.childState.set(t,{idleExitNotified:!1,shutdownRequested:!1,terminated:!1}),t.on(`message`,e=>{this.handleChildMessage(t,e)}),t.once(`error`,e=>{this.handleChildFailure(t,this.toError(e,`Embedder worker failed`))}),t.once(`exit`,(e,n)=>{this.handleChildExit(t,e,n)}),t}handleChildMessage(e,t){switch(t.type){case`ready`:{this.currentDimensions=t.dimensions,this.currentModelId=t.modelId,this.healthBus.reportRecovered(`embedder`),this.child===e&&(this.readyChild=e,this.cb.getState()!==`closed`&&this.cb.reset());let n=this.pendingInit;n?.child===e&&(this.pendingInit=null,n.resolve());return}case`result`:{let n=this.pendingRequests.get(t.id);if(!n||n.child!==e)return;this.pendingRequests.delete(t.id),this.coldStart=!1,this.cb.recordSuccess(),n.resolve(new Float32Array(t.data));return}case`batchResult`:{let n=this.pendingRequests.get(t.id);if(!n||n.child!==e)return;if(this.pendingRequests.delete(t.id),!t.data||!Array.isArray(t.data)||t.data.length===0)n.reject(Error(`Worker returned empty or invalid batch result`));else{let e=t.data.map(e=>new Float32Array(e)),r=e.findIndex(e=>e.length===0);r>=0?n.reject(Error(`Worker returned zero-length vector at index ${r}`)):(this.coldStart=!1,this.cb.recordSuccess(),n.resolve(e))}return}case`error`:{let n=Error(t.message);if(this.childErrors.set(e,n),t.id===`init`){this.clearChildReference(e),this.rejectLifecycleIfOwned(`init`,e,n);return}if(t.id===`shutdown`){this.rejectLifecycleIfOwned(`shutdown`,e,n);return}let r=this.pendingRequests.get(t.id);if(!r||r.child!==e)return;this.pendingRequests.delete(t.id),r.reject(n);return}case`idle-exit`:{let t=this.requireChildState(e);t.idleExitNotified=!0,this.clearChildReference(e);return}}}handleChildExit(e,t,n){let r=this.requireChildState(e);if(r.terminated)return;r.terminated=!0,this.clearChildReference(e);let i=t===0&&n===null,a=r.shutdownRequested||r.idleExitNotified||i,o=this.childErrors.get(e)??Error(a?`Embedder worker exited before completing request`:`Embedder worker exited unexpectedly (code ${t??`null`}${n?`, signal ${n}`:``})`);this.rejectLifecycleIfOwned(`init`,e,o),a?this.resolveLifecycleIfOwned(`shutdown`,e):this.rejectLifecycleIfOwned(`shutdown`,e,o),this.rejectPendingForChild(e,o),a||this.cb.recordFailure()}handleChildFailure(e,t){let n=this.requireChildState(e);n.terminated||(n.terminated=!0,this.clearChildReference(e),this.rejectLifecycleIfOwned(`init`,e,t),this.rejectLifecycleIfOwned(`shutdown`,e,t),this.rejectPendingForChild(e,t))}async sendVectorRequestWithRetry(e){return this.withWorkerExitRetry(e.type,()=>this.sendVectorRequest(e))}async sendVectorRequest(e){await this.initialize();let n=this.requireReadyChild(),r=t(),i=this.requestTimeoutMs>0?this.coldStart?this.requestTimeoutMs*2:this.requestTimeoutMs:0,a=new Promise((e,t)=>{this.pendingRequests.set(r,{child:n,resolve:t=>e(t),reject:t})});try{n.send({...e,id:r})}catch(t){throw this.pendingRequests.delete(r),this.toError(t,`Failed to send ${e.type} request to worker`)}if(i>0){let t,n=new Promise((n,a)=>{t=setTimeout(()=>{this.pendingRequests.delete(r),this.markWorkerUnresponsive(),a(Error(`Embedder ${e.type} request timed out after ${i/1e3}s. The worker has been killed and will attempt to respawn automatically.`))},i)});try{return await Promise.race([a,n])}finally{t!==void 0&&clearTimeout(t)}}return a}async withWorkerExitRetry(e,t){let n=null,r=this.maxRetries;for(let i=0;i<=r;i++)try{return await t()}catch(t){let a=this.toError(t,`Failed to process ${e} request`);if(!this.isWorkerExitError(a))throw a;if(n??=a,i===0&&/exited/i.test(a.message)&&!/timed out/i.test(a.message)&&(r=Math.min(r,1)),i===r)throw n;let o=i+1,s=this.retryBaseDelayMs*2**i;if(this.healthBus.reportDegraded(`embedder`,`Worker crashed during ${e} — retrying (${o}/${r})`),this.logger?.warn?.(`Embedder retry ${o}/${r} after ${s}ms`,{requestType:e,delayMs:s,error:a.message}),this.child=null,this.readyChild=null,await this.wait(s),this.cb.isOpen())throw n??a}throw n??Error(`Failed to process ${e} request`)}isWorkerExitError(e){return/embedder worker exited|EPIPE|ECONNRESET|ERR_IPC_CHANNEL_CLOSED|channel closed|write after end/i.test(e.message)}wait(e){return new Promise(t=>{setTimeout(t,e)})}requireReadyChild(){if(!this.child||this.readyChild!==this.child)throw Error(`Embedder worker is not initialized`);return this.child}buildInitConfig(){return{model:this.options.model,dimensions:this.options.dimensions,nativeDim:this.options.nativeDim,queryPrefix:this.options.queryPrefix,pooling:this.options.pooling,interOpNumThreads:this.options.interOpNumThreads,intraOpNumThreads:this.options.intraOpNumThreads}}buildChildEnv(){return this.options.idleTimeoutMs===void 0?process.env:{...process.env,AIKIT_EMBED_IDLE_MS:String(this.options.idleTimeoutMs)}}requireChildState(e){let t=this.childState.get(e);if(!t)throw Error(`Embedder worker state not found`);return t}clearChildReference(e){this.child===e&&(this.child=null),this.readyChild===e&&(this.readyChild=null)}clearCooldownRespawnTimer(){this.cooldownRespawnTimer&&=(clearTimeout(this.cooldownRespawnTimer),null)}startCooldownRespawn(){this.clearCooldownRespawnTimer(),this.cooldownRespawnTimer=setTimeout(()=>{this.cooldownRespawnTimer=null,!this.child&&!this.shutdownPromise&&this.workerAvailable&&this.initialize().catch(()=>{})},6e4),this.logger?.warn?.(`Embedder circuit breaker OPEN — too many consecutive failures`,{cooldownMs:6e4})}markWorkerUnresponsive(){let e=this.child;if(e){try{e.kill()}catch{}this.clearChildReference(e),this.cb.recordFailure(),this.cb.isOpen()||setImmediate(()=>{!this.child&&this.workerAvailable&&!this.shutdownPromise&&this.initialize().catch(()=>{})})}}assertCircuitClosed(){if(this.cb.isOpen())throw new s(this.cb.remainingCooldownMs())}rejectPendingForChild(e,t){for(let[n,r]of this.pendingRequests)r.child===e&&(this.pendingRequests.delete(n),r.reject(t))}resolveLifecycleIfOwned(e,t){let n=this.pendingShutdown;!n||n.child!==t||(this.pendingShutdown=null,n.resolve())}rejectLifecycleIfOwned(e,t,n){let r=e===`init`?this.pendingInit:this.pendingShutdown;!r||r.child!==t||(e===`init`?this.pendingInit=null:this.pendingShutdown=null,r.reject(n))}toError(e,t){return e instanceof Error?e:Error(`${t}: ${String(e)}`)}};let m=null;function h(e){if(!(e instanceof Error))return!1;let t=e.code;return t===`ERR_MODULE_NOT_FOUND`||t===`MODULE_NOT_FOUND`?!0:/cannot find (module|package)|module not found/i.test(e.message)}async function g(){if(!m){try{m=await import(`@huggingface/transformers`)}catch(e){if(h(e)){let{createRequire:t}=await import(`node:module`),n=t(import.meta.url);try{m=n("@huggingface/transformers")}catch(t){let n=e instanceof Error?e.message:String(e),r=t instanceof Error?t.message:String(t);throw Error(`Unable to load @huggingface/transformers via ESM or CJS. ESM: ${n}; CJS: ${r}`)}}else throw e}m.env.cacheDir=i(f(),`.cache`,`huggingface`,`transformers-js`)}return m}var _=class{pipe=null;shutdownPromise=null;dimensions;modelId;nativeDim;queryPrefix;pooling;threadConfig;constructor(e={}){this.modelId=e.model??c.model;let t=u[this.modelId];if(this.nativeDim=e.nativeDim??t?.nativeDim??c.nativeDim,this.dimensions=e.dimensions??t?.dimensions??c.dimensions,this.dimensions>this.nativeDim)throw Error(`Configured dimensions (${this.dimensions}) exceeds model native output (${this.nativeDim}). Matryoshka truncation cannot upscale — dimensions must be <= nativeDim.`);this.queryPrefix=e.queryPrefix??t?.queryPrefix??this.detectQueryPrefix(this.modelId),this.pooling=e.pooling??t?.pooling??`mean`,this.threadConfig={interOp:e.interOpNumThreads??1,intraOp:e.intraOpNumThreads??4}}detectQueryPrefix(e){let t=e.toLowerCase();return t.includes(`bge`)||t.includes(`mxbai-embed`)&&!t.includes(`xsmall`)?`Represent this sentence for searching relevant passages: `:t.includes(`/e5-`)||t.includes(`multilingual-e5`)?`query: `:``}getPipelineOptions(e){let t=e.backends.onnx;t.wasm||={};let n=t.wasm;return n.numThreads=this.threadConfig.intraOp,{dtype:`q8`,session_options:{interOpNumThreads:this.threadConfig.interOp,intraOpNumThreads:this.threadConfig.intraOp}}}computeNorm(e){let t=0;for(let n=0;n<e.length;n++)t+=e[n]*e[n];return Math.sqrt(t)}truncateAndRenorm(e){if(this.dimensions>=this.nativeDim){let t=this.computeNorm(e);if(!Number.isFinite(t))throw Error(`Embedding produced non-finite norm — output contained NaN or Infinity`);if(t===0)throw Error(`Embedding produced zero-norm vector from ONNX output`);return e}let t=e.subarray(0,this.dimensions),n=this.computeNorm(t);if(!Number.isFinite(n))throw Error(`Embedding produced non-finite norm — output contained NaN or Infinity`);if(n===0)throw Error(`Embedding produced zero-norm vector after truncation — input may be degenerate`);let r=new Float32Array(this.dimensions);for(let e=0;e<this.dimensions;e++)r[e]=t[e]/n;return r}async initialize(){if(this.pipe)return;this.shutdownPromise=null;let{pipeline:e,env:t}=await g();try{this.pipe=await e(`feature-extraction`,this.modelId,this.getPipelineOptions(t))}catch(n){let r=n.message?.toLowerCase()??``;if(this.isCorruptionError(r)){let n=i(t.cacheDir??i(f(),`.cache`,`huggingface`,`transformers-js`),this.modelId);console.error(`[aikit:auto-heal] Detected corrupted model cache for "${this.modelId}". Clearing cache at ${n} and retrying download...`);try{await d(n,{recursive:!0,force:!0})}catch{}try{this.pipe=await e(`feature-extraction`,this.modelId,this.getPipelineOptions(t)),console.error(`[aikit:auto-heal] Model "${this.modelId}" re-downloaded successfully.`);return}catch(e){throw Error(`Failed to initialize embedding model "${this.modelId}" after auto-heal: ${e.message}`)}}throw Error(`Failed to initialize embedding model "${this.modelId}": ${n.message}`)}}isCorruptionError(e){return[`protobuf`,`invalid model`,`invalid onnx`,`unexpected end`,`unexpected token`,`failed to load`,`checksum`,`corrupt`,`could not load`,`onnx`,`malformed`].some(t=>e.includes(t))}async shutdown(){return this.shutdownPromise||=this._doShutdown(),this.shutdownPromise}async _doShutdown(){let e=this.pipe;if(e)try{let t=e;typeof t.dispose==`function`?await t.dispose():typeof t.model?.dispose==`function`&&await t.model.dispose()}catch{}finally{this.pipe=null}}async embed(e){this.pipe||await this.initialize();let t=await this.pipe?.(e,{pooling:this.pooling,normalize:!0});if(!t?.data)throw Error(`Embedding pipeline returned no output`);try{let e=new Float32Array(t.data);return this.truncateAndRenorm(e)}finally{t.dispose?.()}}async embedQuery(e){return this.embed(this.queryPrefix+e)}async embedBatch(e,t=64){if(e.length===0)return[];this.pipe||await this.initialize();let n=[];for(let r=0;r<e.length;r+=t){let i=e.slice(r,r+t),a=await this.pipe?.(i,{pooling:this.pooling,normalize:!0});if(!a?.data)throw Error(`Embedding pipeline returned no output`);try{if(i.length===1){let e=new Float32Array(a.data);n.push(this.truncateAndRenorm(e))}else for(let e=0;e<i.length;e++){let t=e*this.nativeDim,r=a.data.slice(t,t+this.nativeDim);n.push(this.truncateAndRenorm(new Float32Array(r)))}}finally{a.dispose?.()}}return n}};export{p as EmbedderProxy,_ as OnnxEmbedder};
|
|
1
|
+
import{fork as e}from"node:child_process";import{randomUUID as t}from"node:crypto";import{existsSync as n}from"node:fs";import{dirname as r,join as i}from"node:path";import{fileURLToPath as a}from"node:url";import{CircuitBreaker as o,CircuitOpenError as s,EMBEDDING_DEFAULTS as c,HealthBus as l,MODEL_REGISTRY as u}from"../../core/dist/index.js";import{rm as d}from"node:fs/promises";import{homedir as f}from"node:os";var p=class{options;logger;healthBus=l.instance();cb;initTimeoutMs;requestTimeoutMs;maxRetries;retryBaseDelayMs;workerAvailable=!0;workerPath=i(r(a(import.meta.url)),`embedder-worker.js`);pendingRequests=new Map;childState=new WeakMap;childErrors=new WeakMap;child=null;readyChild=null;pendingInit=null;pendingShutdown=null;initializePromise=null;shutdownPromise=null;cooldownRespawnTimer=null;currentDimensions;currentModelId;coldStart=!0;constructor(e={}){this.options=e,this.logger=e.logger,this.healthBus.register(`embedder`),this.cb=new o({threshold:3,cooldownMs:6e4,name:`embedder`}),this.cb.on(`open`,()=>{this.healthBus.reportDegraded(`embedder`,`Circuit breaker open — consecutive timeouts`),this.startCooldownRespawn()}),this.cb.on(`closed`,()=>{this.healthBus.reportRecovered(`embedder`)}),this.initTimeoutMs=Math.max(0,e.initTimeoutMs??6e4),this.requestTimeoutMs=Math.max(0,e.requestTimeoutMs??(process.platform===`win32`?1e4:3e4)),this.maxRetries=Math.max(0,e.maxRetries??3),this.retryBaseDelayMs=Math.max(0,e.retryBaseDelayMs??500),this.currentDimensions=e.dimensions??c.dimensions,this.currentModelId=e.model??c.model}get dimensions(){return this.currentDimensions}get modelId(){return this.currentModelId}get isCircuitOpen(){return this.cb.isOpen()}async initialize(){if(!(this.readyChild&&this.child===this.readyChild)&&this.workerAvailable){if(!n(this.workerPath)){this.workerAvailable=!1,console.warn(`[aikit] Embedder worker not found at ${this.workerPath}. Embedding disabled - search will use keyword matching only. This usually means the npx cache is corrupted; restart to fix.`);return}if(this.initializePromise)return this.initializePromise;if(this.shutdownPromise){try{await this.shutdownPromise}catch{}if(this.readyChild&&this.child===this.readyChild)return}return this.initializePromise=this.startWorker().finally(()=>{this.initializePromise=null}),this.initializePromise}}async embed(e){if(!this.workerAvailable)throw Error(`Embedding worker is not available — embeddings cannot be computed. Check server logs for initialization errors.`);if(this.assertCircuitClosed(),!this.readyChild&&this.initializePromise)throw Error(`Embedder not ready — initialization in progress. Falling back to keyword search.`);if(await this.initialize(),!this.workerAvailable)throw Error(`Embedding worker is not available — embeddings cannot be computed. Check server logs for initialization errors.`);return this.sendVectorRequestWithRetry({type:`embed`,text:e})}async embedQuery(e){if(!this.workerAvailable)throw Error(`Embedding worker is not available — embeddings cannot be computed. Check server logs for initialization errors.`);if(this.assertCircuitClosed(),!this.readyChild&&this.initializePromise)throw Error(`Embedder not ready — initialization in progress. Falling back to keyword search.`);if(await this.initialize(),!this.workerAvailable)throw Error(`Embedding worker is not available — embeddings cannot be computed. Check server logs for initialization errors.`);return this.sendVectorRequestWithRetry({type:`embedQuery`,text:e})}async embedBatch(e,t){if(e.length===0)return[];if(!this.workerAvailable||(this.assertCircuitClosed(),await this.initialize(),!this.workerAvailable))throw Error(`Embedding worker is not available — embeddings cannot be computed. Check server logs for initialization errors.`);return this.withWorkerExitRetry(`embedBatch`,()=>this.sendBatchRequest(e,t))}async sendBatchRequest(e,n){await this.initialize();let r=this.requireReadyChild(),i=t(),a=new Promise((e,t)=>{this.pendingRequests.set(i,{child:r,resolve:t=>e(t),reject:t})});try{r.send({type:`embedBatch`,id:i,texts:e,batchSize:n})}catch(e){throw this.pendingRequests.delete(i),this.toError(e,`Failed to send embedBatch request to worker`)}let o=this.requestTimeoutMs>0?Math.max(this.requestTimeoutMs*3,9e4):0;if(o>0){let t,n=new Promise((n,r)=>{t=setTimeout(()=>{this.pendingRequests.delete(i),this.markWorkerUnresponsive(),r(Error(`Embedder embedBatch request timed out after ${o/1e3}s (${e.length} texts). The worker has been killed and will attempt to respawn automatically.`))},o)});try{return await Promise.race([a,n])}finally{t!==void 0&&clearTimeout(t)}}return a}async shutdown(){if(this.clearCooldownRespawnTimer(),this.shutdownPromise)return this.shutdownPromise;let e=this.child;if(!e)return;let t=this.requireChildState(e);t.shutdownRequested=!0,this.readyChild===e&&(this.readyChild=null),this.shutdownPromise=new Promise((t,n)=>{this.pendingShutdown={child:e,resolve:t,reject:n}}).finally(()=>{this.shutdownPromise=null});try{e.send({type:`shutdown`})}catch(t){let n=this.toError(t,`Failed to send shutdown request to worker`);throw this.clearChildReference(e),this.rejectPendingForChild(e,n),this.rejectLifecycleIfOwned(`shutdown`,e,n),n}return this.shutdownPromise}async startWorker(){this.child&&this.readyChild!==this.child&&(this.child=null),this.clearCooldownRespawnTimer(),this.coldStart=!0;let e=this.spawnChild();this.child=e,this.readyChild=null;let t=new Promise((t,n)=>{this.pendingInit={child:e,resolve:t,reject:n}});try{e.send({type:`init`,config:this.buildInitConfig()})}catch(t){let n=this.toError(t,`Failed to send init request to worker`);throw this.pendingInit=null,this.clearChildReference(e),n}if(this.initTimeoutMs>0){let n,r=new Promise((e,t)=>{n=setTimeout(()=>{t(Error(`Embedder worker initialization timed out after ${this.initTimeoutMs/1e3}s. The ONNX model may be downloading or the child process is stuck. Check network connectivity and disk space, or restart the server.`))},this.initTimeoutMs)});try{await Promise.race([t,r]);return}catch(t){this.pendingInit=null;try{e.kill()}catch{}throw this.clearChildReference(e),t}finally{n!==void 0&&clearTimeout(n)}}await t}spawnChild(){let t=e(this.workerPath,[],{env:this.buildChildEnv()});return this.childState.set(t,{idleExitNotified:!1,shutdownRequested:!1,terminated:!1}),t.on(`message`,e=>{this.handleChildMessage(t,e)}),t.once(`error`,e=>{this.handleChildFailure(t,this.toError(e,`Embedder worker failed`))}),t.once(`exit`,(e,n)=>{this.handleChildExit(t,e,n)}),t}handleChildMessage(e,t){switch(t.type){case`ready`:{this.currentDimensions=t.dimensions,this.currentModelId=t.modelId,this.healthBus.reportRecovered(`embedder`),this.child===e&&(this.readyChild=e,this.cb.getState()!==`closed`&&this.cb.reset());let n=this.pendingInit;n?.child===e&&(this.pendingInit=null,n.resolve());return}case`result`:{let n=this.pendingRequests.get(t.id);if(!n||n.child!==e)return;this.pendingRequests.delete(t.id),this.coldStart=!1,this.cb.recordSuccess(),n.resolve(new Float32Array(t.data));return}case`batchResult`:{let n=this.pendingRequests.get(t.id);if(!n||n.child!==e)return;if(this.pendingRequests.delete(t.id),!t.data||!Array.isArray(t.data)||t.data.length===0)n.reject(Error(`Worker returned empty or invalid batch result`));else{let e=t.data.map(e=>new Float32Array(e)),r=e.findIndex(e=>e.length===0);r>=0?n.reject(Error(`Worker returned zero-length vector at index ${r}`)):(this.coldStart=!1,this.cb.recordSuccess(),n.resolve(e))}return}case`error`:{let n=Error(t.message);if(this.childErrors.set(e,n),t.id===`init`){this.clearChildReference(e),this.rejectLifecycleIfOwned(`init`,e,n);return}if(t.id===`shutdown`){this.rejectLifecycleIfOwned(`shutdown`,e,n);return}let r=this.pendingRequests.get(t.id);if(!r||r.child!==e)return;this.pendingRequests.delete(t.id),r.reject(n);return}case`idle-exit`:{let t=this.requireChildState(e);t.idleExitNotified=!0,this.clearChildReference(e);return}}}handleChildExit(e,t,n){let r=this.requireChildState(e);if(r.terminated)return;r.terminated=!0,this.clearChildReference(e);let i=t===0&&n===null,a=r.shutdownRequested||r.idleExitNotified||i,o=this.childErrors.get(e)??Error(a?`Embedder worker exited before completing request`:`Embedder worker exited unexpectedly (code ${t??`null`}${n?`, signal ${n}`:``})`);this.rejectLifecycleIfOwned(`init`,e,o),a?this.resolveLifecycleIfOwned(`shutdown`,e):this.rejectLifecycleIfOwned(`shutdown`,e,o),this.rejectPendingForChild(e,o),a||this.cb.recordFailure()}handleChildFailure(e,t){let n=this.requireChildState(e);n.terminated||(n.terminated=!0,this.clearChildReference(e),this.rejectLifecycleIfOwned(`init`,e,t),this.rejectLifecycleIfOwned(`shutdown`,e,t),this.rejectPendingForChild(e,t))}async sendVectorRequestWithRetry(e){return this.withWorkerExitRetry(e.type,()=>this.sendVectorRequest(e))}async sendVectorRequest(e){await this.initialize();let n=this.requireReadyChild(),r=t(),i=this.requestTimeoutMs>0?this.coldStart?this.requestTimeoutMs*2:this.requestTimeoutMs:0,a=new Promise((e,t)=>{this.pendingRequests.set(r,{child:n,resolve:t=>e(t),reject:t})});try{n.send({...e,id:r})}catch(t){throw this.pendingRequests.delete(r),this.toError(t,`Failed to send ${e.type} request to worker`)}if(i>0){let t,n=new Promise((n,a)=>{t=setTimeout(()=>{this.pendingRequests.delete(r),this.markWorkerUnresponsive(),a(Error(`Embedder ${e.type} request timed out after ${i/1e3}s. The worker has been killed and will attempt to respawn automatically.`))},i)});try{return await Promise.race([a,n])}finally{t!==void 0&&clearTimeout(t)}}return a}async withWorkerExitRetry(e,t){let n=null,r=this.maxRetries;for(let i=0;i<=r;i++)try{return await t()}catch(t){let a=this.toError(t,`Failed to process ${e} request`);if(!this.isWorkerExitError(a))throw a;if(n??=a,i===0&&/exited/i.test(a.message)&&!/timed out/i.test(a.message)&&(r=Math.min(r,1)),i===r)throw n;let o=i+1,s=this.retryBaseDelayMs*2**i;if(this.healthBus.reportDegraded(`embedder`,`Worker crashed during ${e} — retrying (${o}/${r})`),this.logger?.warn?.(`Embedder retry ${o}/${r} after ${s}ms`,{requestType:e,delayMs:s,error:a.message}),this.child=null,this.readyChild=null,await this.wait(s),this.cb.isOpen())throw n??a}throw n??Error(`Failed to process ${e} request`)}isWorkerExitError(e){return/embedder worker exited|EPIPE|ECONNRESET|ERR_IPC_CHANNEL_CLOSED|channel closed|write after end/i.test(e.message)}wait(e){return new Promise(t=>{setTimeout(t,e)})}requireReadyChild(){if(!this.child||this.readyChild!==this.child)throw Error(`Embedder worker is not initialized`);return this.child}buildInitConfig(){return{model:this.options.model,dimensions:this.options.dimensions,nativeDim:this.options.nativeDim,queryPrefix:this.options.queryPrefix,pooling:this.options.pooling,interOpNumThreads:this.options.interOpNumThreads,intraOpNumThreads:this.options.intraOpNumThreads}}buildChildEnv(){return this.options.idleTimeoutMs===void 0?process.env:{...process.env,AIKIT_EMBED_IDLE_MS:String(this.options.idleTimeoutMs)}}requireChildState(e){let t=this.childState.get(e);if(!t)throw Error(`Embedder worker state not found`);return t}clearChildReference(e){this.child===e&&(this.child=null),this.readyChild===e&&(this.readyChild=null)}clearCooldownRespawnTimer(){this.cooldownRespawnTimer&&=(clearTimeout(this.cooldownRespawnTimer),null)}startCooldownRespawn(){this.clearCooldownRespawnTimer(),this.cooldownRespawnTimer=setTimeout(()=>{this.cooldownRespawnTimer=null,!this.child&&!this.shutdownPromise&&this.workerAvailable&&this.initialize().catch(()=>{})},6e4),this.logger?.warn?.(`Embedder circuit breaker OPEN — too many consecutive failures`,{cooldownMs:6e4})}markWorkerUnresponsive(){let e=this.child;if(e){try{e.kill()}catch{}this.clearChildReference(e),this.cb.recordFailure(),this.cb.isOpen()||setImmediate(()=>{!this.child&&this.workerAvailable&&!this.shutdownPromise&&this.initialize().catch(()=>{})})}}assertCircuitClosed(){if(this.cb.isOpen())throw new s(this.cb.remainingCooldownMs())}rejectPendingForChild(e,t){for(let[n,r]of this.pendingRequests)r.child===e&&(this.pendingRequests.delete(n),r.reject(t))}resolveLifecycleIfOwned(e,t){let n=this.pendingShutdown;!n||n.child!==t||(this.pendingShutdown=null,n.resolve())}rejectLifecycleIfOwned(e,t,n){let r=e===`init`?this.pendingInit:this.pendingShutdown;!r||r.child!==t||(e===`init`?this.pendingInit=null:this.pendingShutdown=null,r.reject(n))}toError(e,t){return e instanceof Error?e:Error(`${t}: ${String(e)}`)}};let m=null;function h(e){if(!(e instanceof Error))return!1;let t=e.code;return t===`ERR_MODULE_NOT_FOUND`||t===`MODULE_NOT_FOUND`?!0:/cannot find (module|package)|module not found/i.test(e.message)}async function g(){if(!m){try{m=await import(`@huggingface/transformers`)}catch(e){if(h(e)){let{createRequire:t}=await import(`node:module`),n=t(import.meta.url);try{m=n("@huggingface/transformers")}catch(t){let n=e instanceof Error?e.message:String(e),r=t instanceof Error?t.message:String(t);throw Error(`Unable to load @huggingface/transformers via ESM or CJS. ESM: ${n}; CJS: ${r}`)}}else throw e}m.env.cacheDir=i(f(),`.cache`,`huggingface`,`transformers-js`)}return m}var _=class{pipe=null;shutdownPromise=null;dimensions;modelId;nativeDim;queryPrefix;pooling;threadConfig;constructor(e={}){this.modelId=e.model??c.model;let t=u[this.modelId];if(this.nativeDim=e.nativeDim??t?.nativeDim??c.nativeDim,this.dimensions=e.dimensions??t?.dimensions??c.dimensions,this.dimensions>this.nativeDim)throw Error(`Configured dimensions (${this.dimensions}) exceeds model native output (${this.nativeDim}). Matryoshka truncation cannot upscale — dimensions must be <= nativeDim.`);this.queryPrefix=e.queryPrefix??t?.queryPrefix??this.detectQueryPrefix(this.modelId),this.pooling=e.pooling??t?.pooling??`mean`,this.threadConfig={interOp:e.interOpNumThreads??1,intraOp:e.intraOpNumThreads??4}}detectQueryPrefix(e){let t=e.toLowerCase();return t.includes(`bge`)||t.includes(`mxbai-embed`)&&!t.includes(`xsmall`)?`Represent this sentence for searching relevant passages: `:t.includes(`/e5-`)||t.includes(`multilingual-e5`)?`query: `:``}getPipelineOptions(e){let t=e.backends.onnx;t.wasm||={};let n=t.wasm;return n.numThreads=this.threadConfig.intraOp,{dtype:`q8`,session_options:{interOpNumThreads:this.threadConfig.interOp,intraOpNumThreads:this.threadConfig.intraOp}}}computeNorm(e){let t=0;for(let n=0;n<e.length;n++)t+=e[n]*e[n];return Math.sqrt(t)}truncateAndRenorm(e){if(this.dimensions>=this.nativeDim){let t=this.computeNorm(e);if(!Number.isFinite(t))throw Error(`Embedding produced non-finite norm — output contained NaN or Infinity`);if(t===0)throw Error(`Embedding produced zero-norm vector from ONNX output`);return e}let t=e.subarray(0,this.dimensions),n=this.computeNorm(t);if(!Number.isFinite(n))throw Error(`Embedding produced non-finite norm — output contained NaN or Infinity`);if(n===0)throw Error(`Embedding produced zero-norm vector after truncation — input may be degenerate`);let r=new Float32Array(this.dimensions);for(let e=0;e<this.dimensions;e++)r[e]=t[e]/n;return r}async initialize(){if(this.pipe)return;this.shutdownPromise=null;let{pipeline:e,env:t}=await g();try{this.pipe=await e(`feature-extraction`,this.modelId,this.getPipelineOptions(t))}catch(n){let r=n.message?.toLowerCase()??``;if(this.isCorruptionError(r)){let n=i(t.cacheDir??i(f(),`.cache`,`huggingface`,`transformers-js`),this.modelId);console.error(`[aikit:auto-heal] Detected corrupted model cache for "${this.modelId}". Clearing cache at ${n} and retrying download...`);try{await d(n,{recursive:!0,force:!0})}catch{}try{this.pipe=await e(`feature-extraction`,this.modelId,this.getPipelineOptions(t)),console.error(`[aikit:auto-heal] Model "${this.modelId}" re-downloaded successfully.`);return}catch(e){throw Error(`Failed to initialize embedding model "${this.modelId}" after auto-heal: ${e.message}`)}}throw Error(`Failed to initialize embedding model "${this.modelId}": ${n.message}`)}}isCorruptionError(e){return[`protobuf`,`invalid model`,`invalid onnx`,`unexpected end`,`unexpected token`,`failed to load`,`checksum`,`corrupt`,`could not load`,`onnx`,`malformed`].some(t=>e.includes(t))}async shutdown(){return this.shutdownPromise||=this._doShutdown(),this.shutdownPromise}async _doShutdown(){let e=this.pipe;if(e)try{let t=e;typeof t.dispose==`function`?await t.dispose():typeof t.model?.dispose==`function`&&await t.model.dispose()}catch{}finally{this.pipe=null}}async embed(e){this.pipe||await this.initialize();let t=await this.pipe?.(e,{pooling:this.pooling,normalize:!0});if(!t?.data)throw Error(`Embedding pipeline returned no output`);try{let e=new Float32Array(t.data);return this.truncateAndRenorm(e)}finally{t.dispose?.()}}async embedQuery(e){return this.embed(this.queryPrefix+e)}async embedBatch(e,t=64){if(e.length===0)return[];this.pipe||await this.initialize();let n=[];for(let r=0;r<e.length;r+=t){let i=e.slice(r,r+t),a=await this.pipe?.(i,{pooling:this.pooling,normalize:!0});if(!a?.data)throw Error(`Embedding pipeline returned no output`);try{if(i.length===1){let e=new Float32Array(a.data);n.push(this.truncateAndRenorm(e))}else for(let e=0;e<i.length;e++){let t=e*this.nativeDim,r=a.data.slice(t,t+this.nativeDim);n.push(this.truncateAndRenorm(new Float32Array(r)))}}finally{a.dispose?.()}}return n}};export{p as EmbedderProxy,_ as OnnxEmbedder};
|
|
@@ -5,4 +5,4 @@ import{createHash as e,randomUUID as t}from"node:crypto";import{readFileSync as
|
|
|
5
5
|
`).length,fileHash:this.hash(e.content),indexedAt:t,origin:`curated`,tags:e.frontmatter.tags,category:e.frontmatter.category,version:e.frontmatter.version}});try{return await this.store.upsert(i,r),e.length}catch(t){O.error(`Failed to upsert curated batch`,{batchSize:e.length,...f(t)});for(let t of e)n.push(`${t.relativePath}: upsert failed`);return 0}}catch(r){if(e.length===1)return O.error(`Failed to embed curated item`,{relativePath:e[0].relativePath,...f(r)}),n.push(`${e[0].relativePath}: reindex failed`),0;O.warn(`Curated embed batch failed, retrying with smaller chunks`,{batchSize:e.length,...f(r)});let i=Math.ceil(e.length/2),a=e.slice(0,i),o=e.slice(i);return await this.embedAndUpsertBatch(a,t,n)+await this.embedAndUpsertBatch(o,t,n)}}gitCommitKnowledge(e,t,n){try{if(!h(this.curatedDir))return;let r=this.knowledgeRefForPath(e);if(!r)return;g(r,`entry.md`,t,n,this.curatedDir)}catch{}}gitDeleteKnowledgeRef(e){try{if(!h(this.curatedDir))return;let t=this.knowledgeRefForPath(e);if(!t)return;_([`update-ref`,`-d`,t],this.curatedDir)}catch{}}knowledgeRefForPath(e){let t=e.replace(/\.md$/,``).split(`/`).map(e=>v(e)).join(`/`);return t.split(`/`).every(e=>m.test(e))?`${D}/${t}`:null}async indexCuratedFile(e,t,n){let r=await this.embedder.embed(t),i=`.ai/curated/${e}`,a=new Date().toISOString(),o={id:this.hashId(i,0),content:t,sourcePath:i,contentType:`curated-knowledge`,headingPath:n.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:t.split(`
|
|
6
6
|
`).length,fileHash:this.hash(t),indexedAt:a,origin:`curated`,tags:n.tags,category:n.category,version:n.version};await this.store.upsert([o],[r])}async indexCuratedFileBestEffort(e,t,n,r){if(u.instance().isDegraded(`embedder`)){O.debug(`Skipping vector indexing — embedder degraded`,{relativePath:e,operation:r,subsystem:`embedder`});return}try{await this.indexCuratedFile(e,t,n)}catch(t){O.warn(`Curated file persisted but vector indexing deferred`,{relativePath:e,operation:r,...f(t)})}}async discoverCategories(){return this.adapter.listDirectories()}guardPath(e){let t=e.replace(/^\.ai\/curated\//,``);if(t.endsWith(`.md`)||(t+=`.md`),t.includes(`..`)||i(t))throw Error(`Invalid path: ${t}. Must be relative within .ai/curated/ directory.`);let n=t.split(`/`)[0];return this.validateCategoryName(n),t}validateCategoryName(e){if(!/^[a-z][a-z0-9-]*$/.test(e))throw Error(`Invalid category name: "${e}". Must be lowercase kebab-case (e.g., "decisions", "api-contracts").`)}validateContentSize(e){if(Buffer.byteLength(e,`utf-8`)>E)throw Error(`Content exceeds maximum size of ${E/1024}KB`)}slugify(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-|-$/g,``).slice(0,80)}normalizeTags(e){return[...new Set(e.map(e=>e.trim()).filter(Boolean))]}sameTags(e,t){if(e.length!==t.length)return!1;let n=new Set(e);return t.every(e=>n.has(e))}ensureCategoryPath(e,t){if(!e.startsWith(`${t}/`))throw Error(`Curated path "${e}" must stay within category "${t}"`)}async uniqueRelativePath(e,t){let n=`${e}/${t}.md`;if(!await this.adapter.exists(n))return n;for(let n=2;n<=100;n++){let r=`${e}/${t}-${n}.md`;if(!await this.adapter.exists(r))return r}throw Error(`Too many entries with slug "${t}" in category "${e}"`)}hash(t){return e(`sha256`).update(t).digest(`hex`).slice(0,16)}hashId(e,t){return this.hash(`${e}::${t}`)}serializeFile(e,t){return`${[`---`,`title: "${t.title.replace(/"/g,`\\"`)}"`,`category: ${t.category}`,`tags: [${t.tags.map(e=>`"${e}"`).join(`, `)}]`,`created: ${t.created}`,`updated: ${t.updated}`,`version: ${t.version}`,`origin: ${t.origin}`,`changelog:`,...t.changelog.map(e=>` - version: ${e.version}\n date: ${e.date}\n reason: "${e.reason.replace(/"/g,`\\"`)}"`),`---`].join(`
|
|
7
7
|
`)}\n\n${e}\n`}parseFile(e){let t=e.match(/^---\n([\s\S]*?)\n---\n\n?([\s\S]*)$/);if(!t)return{frontmatter:{title:`Untitled`,category:`notes`,tags:[],created:``,updated:``,version:1,origin:`curated`,changelog:[]},content:e};let n=t[1],r=t[2].trim(),i={},a=[],o=n.split(`
|
|
8
|
-
`),s=!1,c={};for(let e of o){if(/^changelog:\s*$/.test(e)){s=!0;continue}if(s){let t=e.match(/^\s+-\s+version:\s*(\d+)$/);if(t){c.version!=null&&a.push(c),c={version:parseInt(t[1],10)};continue}let n=e.match(/^\s+date:\s*(.+)$/);if(n){c.date=n[1].trim();continue}let r=e.match(/^\s+reason:\s*"?(.*?)"?\s*$/);if(r){c.reason=r[1];continue}/^\w/.test(e)&&(s=!1,c.version!=null&&a.push(c),c={});continue}let t=e.match(/^(\w+):\s*(.*)$/);if(t){let e=t[1],n=t[2];typeof n==`string`&&n.startsWith(`[`)&&n.endsWith(`]`)?n=n.slice(1,-1).split(`,`).map(e=>e.trim().replace(/^"|"$/g,``)).filter(e=>e.length>0):typeof n==`string`&&/^\d+$/.test(n)?n=parseInt(n,10):typeof n==`string`&&n.startsWith(`"`)&&n.endsWith(`"`)&&(n=n.slice(1,-1)),i[e]=n}}return c.version!=null&&a.push(c),{frontmatter:{title:i.title??`Untitled`,category:i.category??`notes`,tags:i.tags??[],created:i.created??``,updated:i.updated??``,version:i.version??1,origin:`curated`,changelog:a},content:r}}};const A=`__pending__:`;function j(e){return e.startsWith(A)}function M(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function N(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var P=class{options;runtimes=new Map;maxSessions;sessionTimeoutMs;now;constructor(e){this.options=e,this.maxSessions=e.maxSessions??8,this.sessionTimeoutMs=(e.sessionTimeoutMinutes??30)*60*1e3,this.now=e.now??(()=>Date.now())}hasSession(e){return this.runtimes.has(e)}getSessionCount(){return this.runtimes.size}async handleRequest(e,t,n=e.body){let r=M(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){N(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){N(t,400,-32e3,`Session required`);return}if(i=await this.createRuntime(t),!i)return}await this.withRuntimeLock(i,async()=>{await i.transport.handleRequest(e,t,n),i.lastAccessAt=this.now();let r=i.transport.sessionId??i.id;e.method!==`DELETE`&&!j(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!j(r)&&await this.closeSession(r,{closeTransport:!1})})}async closeExpiredSessions(){let e=[...this.runtimes.values()].filter(e=>this.now()-e.lastAccessAt>=this.sessionTimeoutMs).map(e=>e.id);for(let t of e)await this.closeSession(t);return e.length}async closeSession(e,t={}){let n=this.runtimes.get(e);return n?(this.runtimes.delete(e),t.notifySessionEnd!==!1&&!j(e)&&this.options.onSessionEnd?.(e),t.closeTransport!==!1&&await n.transport.close().catch(()=>void 0),await n.server.close().catch(()=>void 0),!0):!1}async closeAll(){let e=[...this.runtimes.keys()];for(let t of e)await this.closeSession(t)}async createRuntime(e){if(await this.closeExpiredSessions(),this.runtimes.size>=this.maxSessions){N(e,503,-32003,`Session capacity reached`);return}let n=this.now(),r=await this.options.createServer(),i={id:`${A}${t()}`,transport:void 0,createdAt:n,lastAccessAt:n,server:r,requestChain:Promise.resolve()},a=this.options.createTransport({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{this.runtimes.delete(i.id),i.id=e,this.runtimes.set(e,i),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return i.transport=a,a.onclose=()=>{let e=i.transport.sessionId??i.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(i.id,i),await r.connect(a),i}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function F(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var I=class{stateStore;options;gcTimer=null;constructor(e,t={}){this.stateStore=e,this.options=t}onSessionStart(e,t){this.stateStore.sessionCreate(e,t)}onSessionActivity(e){this.stateStore.sessionTouch(e)}onSessionEnd(e){this.stateStore.sessionDelete(e),Promise.resolve(this.options.onSessionEndMaintenance?.(e)).catch(()=>{})}startGC(){if(this.gcTimer)return;let e=(this.options.gcIntervalMinutes??5)*60*1e3;this.gcTimer=setInterval(()=>{this.runGC()},e),this.gcTimer.unref()}runGC(){let e=this.getStaleSessionIds();for(let t of e)this.options.onBeforeSessionDelete?.(t),Promise.resolve(this.options.onSessionEndMaintenance?.(t)).catch(()=>{}),this.stateStore.sessionDelete(t);return e.length}stop(){this.gcTimer&&=(clearInterval(this.gcTimer),null)}getActiveSessions(){return this.stateStore.sessionList().length}listSessions(){return this.stateStore.sessionList()}getStaleSessionIds(e=Date.now()){let t=(this.options.staleTimeoutMinutes??30)*60*1e3;return this.stateStore.sessionList().filter(n=>{let r=F(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};function L(){try{let e=o(r(s(import.meta.url)),`..`,`..`,`..`,`package.json`);return JSON.parse(n(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}const R=d(`server`);function z(e,t){return t?{version:e,...f(t)}:{version:e}}const B=/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;function V({requestOrigin:e,configuredOrigin:t,allowAnyOrigin:n,fallbackOrigin:r}){let i=t??r;return i===`*`?n?{allowOrigin:`*`,warn:!1}:e?B.test(e)?{allowOrigin:e,warn:!1}:{allowOrigin:null,warn:!0}:{allowOrigin:r,warn:!1}:{allowOrigin:i,warn:!1}}function H({limit:e,windowMs:t}){let n=new Map,r=(e,r)=>{let i=r-t,a=n.get(e)?.filter(e=>e>i)??[];return a.length===0?(n.delete(e),[]):(n.set(e,a),a)};return{allow(t,i=Date.now()){let a=r(t,i);return a.length>=e?!1:(a.push(i),n.set(t,a),!0)},getRetryAfterMs(n,i=Date.now()){let a=r(n,i);return a.length<e?0:Math.max(0,a[0]+t-i)}}}function U(e){return e.startsWith(`file://`)?s(e):e}function W(e){let t=o(e);return process.platform===`win32`?t.toLowerCase():t}function G(e){let t=new Map;for(let n of e){let e=U(n.uri);t.set(W(e),e)}return[...t.values()].sort((e,t)=>W(e).localeCompare(W(t)))}function K({config:e,roots:t}){let n=G(t);if(n.length===0)return null;let r=e.sources?.[0]?.path;if(r){let e=W(r),t=n.find(t=>W(t)===e);if(t)return t}return n[0]}function q({config:e,log:t,reconfigureForWorkspace:n,roots:r}){let i=G(r);if(i.length===0)return!1;let a=K({config:e,roots:i.map(e=>({uri:e}))});if(!a)return!1;let o=e.sources?.[0]?.path,s=o&&W(o)===W(a)?`configured-source`:`stable-sorted-root`;return t.debug(`MCP roots resolved`,{rootPath:a,rootCount:i.length,selectedBy:s}),n(e,a),e.allRoots=i,!0}async function J({config:e,indexMode:t,log:n,rootsChangedNotificationSchema:r,reconfigureForWorkspace:i,runInitialIndex:a,server:o,startInit:s,timeoutMs:c=5e3,getCwd:l=()=>process.cwd()}){let u=L(),d=!1,p=!1,m,h=o.server,g=e=>{let t=f(e),n=`${String(e)} ${String(t.message??``)}`.toLowerCase();return n.includes(`method not found`)||n.includes(`not supported`)||n.includes(`unsupported`)||n.includes(`unknown method`)||n.includes(`roots/list`)},_=()=>{d||(d=!0,s())},v=()=>{p||t!==`auto`||(p=!0,(async()=>{try{await a()}catch(e){n.error(`Initial index failed`,z(u,e))}})())},y=t=>t.length===0||(m&&=(clearTimeout(m),void 0),!q({config:e,log:n,reconfigureForWorkspace:i,roots:t}))?!1:(_(),v(),!0);try{if(y((await h.listRoots()).roots))return;n.debug(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(t){if(g(t)){n.warn(`MCP roots/list not supported by client; using cwd fallback`,{version:u,cwd:l(),...f(t)}),q({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:l()}]})&&(_(),v());return}n.warn(`MCP roots/list failed during bootstrap; waiting for roots/list_changed notification`,{version:u,cwd:l(),...f(t)})}h.setNotificationHandler(r,async()=>{try{y((await h.listRoots()).roots)}catch(e){n.warn(`roots/list retry failed after notification`,z(u,e))}}),m=setTimeout(()=>{let t=l();n.debug(`Timed out waiting for MCP roots/list_changed; falling back to cwd workspace`,{cwd:t}),q({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:t}]})&&(_(),v())},c)}function Y(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function X(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===c(e).href}catch{return!1}}function Z(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function Q(e,t){let n=process.env[e];if(!n)return t;let r=Number.parseInt(n,10);return Number.isFinite(r)&&r>0?r:t}function $(){return X()?l({allowPositionals:!0,options:{transport:{type:`string`,default:Y()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:Y(),port:process.env.AIKIT_PORT??`3210`}}async function ee(){let e=L(),n=$();process.on(`unhandledRejection`,t=>{R.error(`Unhandled rejection`,z(e,t))}),process.on(`uncaughtException`,t=>{R.error(`Uncaught exception — exiting`,z(e,t)),process.exit(1)});let r=(t,n)=>{t.then(async()=>{try{let{markPromoteRun:e,markPruneRun:t,prune:r,shouldRunStartupPrune:i,shouldRunWeeklyPromote:a}=await import(`../../tools/dist/index.js`),o=n();if(!o)return;if(i()){let e=await r({});t(),e.totalBytesFreed>0&&R.info(`Storage maintenance complete`,{forgeOrphans:e.forgeGroundOrphans.count,legacyLance:e.legacyLance.count,bytesFreed:e.totalBytesFreed});let{groupLessons:n,pruneLessons:i}=await import(`./evolution-DWaEE6XW.js`).then(e=>e.t),a=await i(o.curated,o.stateStore,{dryRun:!1});a.pruned.length>0&&R.info(`Startup lesson prune complete`,{pruned:a.pruned.length});let s=await n(o.curated,o.stateStore,{dryRun:!1});(s.groupsCreated>0||s.lessonsGrouped>0)&&R.info(`Startup lesson grouping complete`,{groupsCreated:s.groupsCreated,lessonsGrouped:s.lessonsGrouped})}if(a()){let{DEFAULT_PROMOTE_CONFIG:t,collectWorkspaceLessons:n,getGlobalCuratedDir:r,promoteLessons:i,scanForDuplicates:a}=await import(`./promotion-bQutAIz-.js`).then(e=>e.o),s=o.curated,c=new k(r(),s.store,s.embedder),l=await n(),u={...t,dryRun:!1},d=await i(a(l,u),c,u);e(),d.promoted.length>0&&R.info(`Weekly lesson promotion complete`,{promoted:d.promoted.length,candidates:d.candidates.length})}}catch(t){R.warn(`Startup maintenance failed (non-critical)`,z(e,t))}}).catch(()=>{})};if(R.info(`Starting MCP AI Kit server`,{version:e}),n.transport===`http`){let[{default:i},{loadConfig:a,resolveIndexMode:o},{registerDashboardRoutes:s,resolveDashboardDir:c},{registerSettingsRoutes:l,resolveSettingsDir:u},{createSettingsRouter:d},{authMiddleware:m,getOrCreateToken:h}]=await Promise.all([import(`express`),import(`./config-B5gyZrbp.js`),import(`./dashboard-static-CRfR1yKU.js`),import(`./settings-static-B3lnYvcb.js`),import(`./routes-KC-D2U8n.js`),import(`./auth-lzZKfxlV.js`)]),g=a();p(g.logging?.errorDetails===!0),g.configError&&R.warn(`Config load failure`,{error:g.configError}),R.info(`Config loaded`,{sourceCount:g.sources.length,storePath:g.store.path});let _=i();_.use(i.json({limit:`1mb`}));let v=Number(n.port),y=`http://localhost:${v}`,b=process.env.AIKIT_CORS_ORIGIN??y,x=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,S=Q(`AIKIT_HTTP_MAX_SESSIONS`,8),C=Q(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),w=Q(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),T=H({limit:100,windowMs:6e4}),E=!1;_.use((e,t,n)=>{let r=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,i=V({requestOrigin:r,configuredOrigin:b,allowAnyOrigin:x,fallbackOrigin:y});if(i.warn&&!E&&(E=!0,R.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:r,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),r&&!i.allowOrigin){t.status(403).json({error:`Origin not allowed`});return}if(i.allowOrigin&&t.setHeader(`Access-Control-Allow-Origin`,i.allowOrigin),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID`),t.setHeader(`Access-Control-Expose-Headers`,`Mcp-Session-Id`),e.method===`OPTIONS`){t.status(204).end();return}n()});let D=h();_.use(m(D)),_.use(`/mcp`,(e,t,n)=>{let r=Z(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(T.allow(r)){n();return}let i=Math.max(1,Math.ceil(T.getRetryAfterMs(r)/1e3));t.setHeader(`Retry-After`,String(i)),t.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})});let O=!1;_.use(`/mcp`,(e,t,n)=>{if(!O){let t=e.headers[`x-workspace-root`];typeof t==`string`&&t.length>0&&(g.sources[0]={path:t,excludePatterns:g.sources[0]?.excludePatterns??[]},g.allRoots=[t],O=!0,R.debug(`Workspace root applied from proxy header`,{wsRoot:t}))}n()}),s(_,c(),R);let k=new Date().toISOString();_.use(`/settings/api`,d({log:R,mcpInfo:()=>({transport:`http`,port:v,pid:process.pid,startedAt:k})})),l(_,u(),R),_.get(`/health`,(e,t)=>{t.json({status:`ok`})});let A=!1,j=null,M=null,N=null,F=null,L=null,B=null,U=null,W=null,G=Promise.resolve(),K=async(e,n)=>{if(!A||!N||!F){n.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=G,i;G=new Promise(e=>{i=e}),await r;try{let r=Z(e);if(!B){if(r){n.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new F({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{U=e,M?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&M?.onSessionEnd(e),U=null}});e.onclose=()=>{B===e&&(B=null),U===e.sessionId&&(U=null)},B=e,await N.connect(e)}let i=B;await i.handleRequest(e,n,e.body),e.method!==`DELETE`&&(!r&&i.sessionId?(U=i.sessionId,M?.onSessionStart(i.sessionId,{transport:`http`}),M?.onSessionActivity(i.sessionId)):r&&M?.onSessionActivity(r))}catch(e){if(R.error(`MCP handler error`,f(e)),!n.headersSent){let t=e instanceof Error?e.message:String(e),r=t.includes(`Not Acceptable`);n.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?t:`Internal server error`},id:null})}}finally{i()}},q=async(e,t)=>{let n=Z(e);if(L&&(!B||n!==U)){await L.handleRequest(e,t,e.body);return}await K(e,t)};_.post(`/mcp`,q),_.get(`/mcp`,q),_.delete(`/mcp`,q);let J=_.listen(v,`127.0.0.1`,()=>{R.info(`MCP server listening`,{url:`http://127.0.0.1:${v}/mcp`,port:v}),setTimeout(async()=>{try{let[{createLazyServer:t,createMcpServer:n,ALL_TOOL_NAMES:i},{StreamableHTTPServerTransport:a},{checkForUpdates:s,autoUpgradeScaffold:c}]=await Promise.all([import(`./server-DSRcQgsx.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-CJK1Fwmy.js`)]);s(),c(),setInterval(s,1440*60*1e3).unref();let l=o(g),u=t(g,l);W=async()=>{u.aikit&&await Promise.all([u.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),u.aikit.graphStore.close().catch(()=>{}),u.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),u.aikit.store.close().catch(()=>{})])},N=u.server,F=a,A=!0,R.debug(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:i.length,resourceCount:2}),u.startInit(),u.ready.then(()=>{if(!u.aikit)throw Error(`AI Kit components are not available after initialization`);M=new I(u.aikit.stateStore,{staleTimeoutMinutes:C,gcIntervalMinutes:w,onBeforeSessionDelete:e=>{if(U===e&&B){let e=B;B=null,U=null,e.close().catch(()=>void 0)}L?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!u.aikit?.curated||!u.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-DWaEE6XW.js`).then(e=>e.t),t=await e(u.aikit.curated,u.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&R.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),L=new P({createServer:()=>{if(!u.aikit)throw Error(`AI Kit components are not available after initialization`);return n(u.aikit,g)},createTransport:e=>new a(e),maxSessions:S,sessionTimeoutMinutes:C,onSessionStart:e=>M?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>M?.onSessionActivity(e),onSessionEnd:e=>M?.onSessionEnd(e)}),M.startGC(),U&&(M.onSessionStart(U,{transport:`http`}),M.onSessionActivity(U)),R.info(`HTTP session runtime ready`,{maxSessions:S,sessionTimeoutMinutes:C,gcIntervalMinutes:w})}).catch(e=>R.error(`Failed to start session manager`,f(e))),l===`auto`?u.ready.then(async()=>{try{let e=g.sources.map(e=>e.path).join(`, `);R.info(`Running initial index`,{sourcePaths:e}),await u.runInitialIndex(),R.info(`Initial index complete`)}catch(t){R.error(`Initial index failed; will retry on aikit_reindex`,z(e,t))}}).catch(t=>R.error(`AI Kit init or indexing failed`,z(e,t))):l===`smart`?u.ready.then(async()=>{try{if(!u.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(u.aikit.indexer,g,u.aikit.store),n=u.aikit.store;j=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),u.setSmartScheduler(t),R.debug(`Smart index scheduler started (HTTP mode)`)}catch(t){R.error(`Failed to start smart index scheduler`,z(e,t))}}).catch(t=>R.error(`AI Kit initialization failed`,z(e,t))):(u.ready.catch(t=>R.error(`AI Kit initialization failed`,z(e,t))),R.info(`Initial full indexing skipped in HTTP mode`,{indexMode:l})),r(u.ready,()=>u.aikit?{curated:u.aikit.curated,stateStore:u.aikit.stateStore}:null)}catch(t){R.error(`Failed to load server modules`,z(e,t))}},100)}),Y=!1,X=async e=>{Y||(Y=!0,R.info(`Shutdown signal received`,{signal:e}),j?.stop(),M?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await L?.closeAll().catch(()=>void 0),U&&M?.onSessionEnd(U),B&&(await B.close().catch(()=>void 0),B=null,U=null),J.close(),N&&await N.close(),await W?.().catch(()=>void 0),process.exit(0))};process.on(`SIGINT`,()=>X(`SIGINT`)),process.on(`SIGTERM`,()=>X(`SIGTERM`))}else{let[{loadConfig:t,reconfigureForWorkspace:n,resolveIndexMode:i},{createLazyServer:a},{checkForUpdates:o,autoUpgradeScaffold:s},{RootsListChangedNotificationSchema:c}]=await Promise.all([import(`./config-B5gyZrbp.js`),import(`./server-DSRcQgsx.js`),import(`./version-check-CJK1Fwmy.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=t();p(l.logging?.errorDetails===!0),l.configError&&R.warn(`Config load failure`,{error:l.configError}),R.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),o(),s(),setInterval(o,1440*60*1e3).unref();let u=i(l),d=a(l,u),{server:f,startInit:m,ready:h,runInitialIndex:g}=d,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await f.connect(v),R.debug(`MCP server started`,{transport:`stdio`}),await J({config:l,indexMode:u,log:R,rootsChangedNotificationSchema:c,reconfigureForWorkspace:n,runInitialIndex:g,server:f,startInit:m});let y=null,b=null,x=!1,S=async e=>{x||(x=!0,R.info(`Shutdown signal received`,{signal:e}),y&&=(clearTimeout(y),null),b?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await v.close().catch(()=>void 0),await f.close().catch(()=>void 0),d.aikit&&await Promise.all([d.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),d.aikit.graphStore.close().catch(()=>{}),d.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),d.aikit.store.close().catch(()=>{})]),process.exit(0))},C=()=>{y&&clearTimeout(y),y=setTimeout(async()=>{R.info(`Auto-shutdown: no activity for 30 minutes — releasing resources`);try{let e=d.aikit;e&&(e.embedder.shutdown?.().catch(()=>{}),e.store.releaseMemory?.(),e.graphStore.releaseMemory?.())}catch{}},18e5),y.unref&&y.unref()};C(),process.stdin.on(`data`,()=>C()),process.stdin.on(`end`,()=>void S(`stdin-end`)),process.stdin.on(`close`,()=>void S(`stdin-close`)),process.stdin.on(`error`,()=>void S(`stdin-error`)),process.on(`SIGINT`,()=>void S(`SIGINT`)),process.on(`SIGTERM`,()=>void S(`SIGTERM`)),h.catch(t=>{R.error(`Initialization failed — server will continue with limited tools`,z(e,t))}),u===`smart`?h.then(async()=>{try{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(d.aikit.indexer,l,d.aikit.store);b=t;let n=d.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),d.setSmartScheduler(t),R.debug(`Smart index scheduler started (stdio mode)`)}catch(t){R.error(`Failed to start smart index scheduler`,z(e,t))}}).catch(t=>R.error(`AI Kit init failed for smart scheduler`,z(e,t))):R.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:u}),r(h,()=>d.aikit?{curated:d.aikit.curated,stateStore:d.aikit.stateStore}:null)}}ee();export{T as n,k as t};
|
|
8
|
+
`),s=!1,c={};for(let e of o){if(/^changelog:\s*$/.test(e)){s=!0;continue}if(s){let t=e.match(/^\s+-\s+version:\s*(\d+)$/);if(t){c.version!=null&&a.push(c),c={version:parseInt(t[1],10)};continue}let n=e.match(/^\s+date:\s*(.+)$/);if(n){c.date=n[1].trim();continue}let r=e.match(/^\s+reason:\s*"?(.*?)"?\s*$/);if(r){c.reason=r[1];continue}/^\w/.test(e)&&(s=!1,c.version!=null&&a.push(c),c={});continue}let t=e.match(/^(\w+):\s*(.*)$/);if(t){let e=t[1],n=t[2];typeof n==`string`&&n.startsWith(`[`)&&n.endsWith(`]`)?n=n.slice(1,-1).split(`,`).map(e=>e.trim().replace(/^"|"$/g,``)).filter(e=>e.length>0):typeof n==`string`&&/^\d+$/.test(n)?n=parseInt(n,10):typeof n==`string`&&n.startsWith(`"`)&&n.endsWith(`"`)&&(n=n.slice(1,-1)),i[e]=n}}return c.version!=null&&a.push(c),{frontmatter:{title:i.title??`Untitled`,category:i.category??`notes`,tags:i.tags??[],created:i.created??``,updated:i.updated??``,version:i.version??1,origin:`curated`,changelog:a},content:r}}};const A=`__pending__:`;function j(e){return e.startsWith(A)}function M(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function N(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var P=class{options;runtimes=new Map;maxSessions;sessionTimeoutMs;now;constructor(e){this.options=e,this.maxSessions=e.maxSessions??8,this.sessionTimeoutMs=(e.sessionTimeoutMinutes??30)*60*1e3,this.now=e.now??(()=>Date.now())}hasSession(e){return this.runtimes.has(e)}getSessionCount(){return this.runtimes.size}async handleRequest(e,t,n=e.body){let r=M(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){N(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){N(t,400,-32e3,`Session required`);return}if(i=await this.createRuntime(t),!i)return}await this.withRuntimeLock(i,async()=>{await i.transport.handleRequest(e,t,n),i.lastAccessAt=this.now();let r=i.transport.sessionId??i.id;e.method!==`DELETE`&&!j(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!j(r)&&await this.closeSession(r,{closeTransport:!1})})}async closeExpiredSessions(){let e=[...this.runtimes.values()].filter(e=>this.now()-e.lastAccessAt>=this.sessionTimeoutMs).map(e=>e.id);for(let t of e)await this.closeSession(t);return e.length}async closeSession(e,t={}){let n=this.runtimes.get(e);return n?(this.runtimes.delete(e),t.notifySessionEnd!==!1&&!j(e)&&this.options.onSessionEnd?.(e),t.closeTransport!==!1&&await n.transport.close().catch(()=>void 0),await n.server.close().catch(()=>void 0),!0):!1}async closeAll(){let e=[...this.runtimes.keys()];for(let t of e)await this.closeSession(t)}async createRuntime(e){if(await this.closeExpiredSessions(),this.runtimes.size>=this.maxSessions){N(e,503,-32003,`Session capacity reached`);return}let n=this.now(),r=await this.options.createServer(),i={id:`${A}${t()}`,transport:void 0,createdAt:n,lastAccessAt:n,server:r,requestChain:Promise.resolve()},a=this.options.createTransport({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{this.runtimes.delete(i.id),i.id=e,this.runtimes.set(e,i),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return i.transport=a,a.onclose=()=>{let e=i.transport.sessionId??i.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(i.id,i),await r.connect(a),i}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function F(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var I=class{stateStore;options;gcTimer=null;constructor(e,t={}){this.stateStore=e,this.options=t}onSessionStart(e,t){this.stateStore.sessionCreate(e,t)}onSessionActivity(e){this.stateStore.sessionTouch(e)}onSessionEnd(e){this.stateStore.sessionDelete(e),Promise.resolve(this.options.onSessionEndMaintenance?.(e)).catch(()=>{})}startGC(){if(this.gcTimer)return;let e=(this.options.gcIntervalMinutes??5)*60*1e3;this.gcTimer=setInterval(()=>{this.runGC()},e),this.gcTimer.unref()}runGC(){let e=this.getStaleSessionIds();for(let t of e)this.options.onBeforeSessionDelete?.(t),Promise.resolve(this.options.onSessionEndMaintenance?.(t)).catch(()=>{}),this.stateStore.sessionDelete(t);return e.length}stop(){this.gcTimer&&=(clearInterval(this.gcTimer),null)}getActiveSessions(){return this.stateStore.sessionList().length}listSessions(){return this.stateStore.sessionList()}getStaleSessionIds(e=Date.now()){let t=(this.options.staleTimeoutMinutes??30)*60*1e3;return this.stateStore.sessionList().filter(n=>{let r=F(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};function L(){try{let e=o(r(s(import.meta.url)),`..`,`..`,`..`,`package.json`);return JSON.parse(n(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}const R=d(`server`);function z(e,t){return t?{version:e,...f(t)}:{version:e}}const B=/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;function V({requestOrigin:e,configuredOrigin:t,allowAnyOrigin:n,fallbackOrigin:r}){let i=t??r;return i===`*`?n?{allowOrigin:`*`,warn:!1}:e?B.test(e)?{allowOrigin:e,warn:!1}:{allowOrigin:null,warn:!0}:{allowOrigin:r,warn:!1}:{allowOrigin:i,warn:!1}}function H({limit:e,windowMs:t}){let n=new Map,r=(e,r)=>{let i=r-t,a=n.get(e)?.filter(e=>e>i)??[];return a.length===0?(n.delete(e),[]):(n.set(e,a),a)};return{allow(t,i=Date.now()){let a=r(t,i);return a.length>=e?!1:(a.push(i),n.set(t,a),!0)},getRetryAfterMs(n,i=Date.now()){let a=r(n,i);return a.length<e?0:Math.max(0,a[0]+t-i)}}}function U(e){return e.startsWith(`file://`)?s(e):e}function W(e){let t=o(e);return process.platform===`win32`?t.toLowerCase():t}function G(e){let t=new Map;for(let n of e){let e=U(n.uri);t.set(W(e),e)}return[...t.values()].sort((e,t)=>W(e).localeCompare(W(t)))}function K({config:e,roots:t}){let n=G(t);if(n.length===0)return null;let r=e.sources?.[0]?.path;if(r){let e=W(r),t=n.find(t=>W(t)===e);if(t)return t}return n[0]}function q({config:e,log:t,reconfigureForWorkspace:n,roots:r}){let i=G(r);if(i.length===0)return!1;let a=K({config:e,roots:i.map(e=>({uri:e}))});if(!a)return!1;let o=e.sources?.[0]?.path,s=o&&W(o)===W(a)?`configured-source`:`stable-sorted-root`;return t.debug(`MCP roots resolved`,{rootPath:a,rootCount:i.length,selectedBy:s}),n(e,a),e.allRoots=i,!0}async function J({config:e,indexMode:t,log:n,rootsChangedNotificationSchema:r,reconfigureForWorkspace:i,runInitialIndex:a,server:o,startInit:s,timeoutMs:c=5e3,getCwd:l=()=>process.cwd()}){let u=L(),d=!1,p=!1,m,h=o.server,g=e=>{let t=f(e),n=`${String(e)} ${String(t.message??``)}`.toLowerCase();return n.includes(`method not found`)||n.includes(`not supported`)||n.includes(`unsupported`)||n.includes(`unknown method`)||n.includes(`roots/list`)||n.includes(`timed out`)},_=()=>{d||(d=!0,s())},v=()=>{p||t!==`auto`||(p=!0,(async()=>{try{await a()}catch(e){n.error(`Initial index failed`,z(u,e))}})())},y=t=>t.length===0||(m&&=(clearTimeout(m),void 0),!q({config:e,log:n,reconfigureForWorkspace:i,roots:t}))?!1:(_(),v(),!0);try{if(y((await h.listRoots()).roots))return;n.debug(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(t){if(g(t)){n.warn(`MCP roots/list not supported by client; using cwd fallback`,{version:u,cwd:l(),...f(t)}),q({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:l()}]})&&(_(),v());return}n.warn(`MCP roots/list failed during bootstrap; waiting for roots/list_changed notification`,{version:u,cwd:l(),...f(t)})}h.setNotificationHandler(r,async()=>{try{y((await h.listRoots()).roots)}catch(e){n.warn(`roots/list retry failed after notification`,z(u,e))}}),m=setTimeout(()=>{let t=l();n.debug(`Timed out waiting for MCP roots/list_changed; falling back to cwd workspace`,{cwd:t}),q({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:t}]})&&(_(),v())},c)}function Y(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function X(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===c(e).href}catch{return!1}}function Z(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function Q(e,t){let n=process.env[e];if(!n)return t;let r=Number.parseInt(n,10);return Number.isFinite(r)&&r>0?r:t}function $(){return X()?l({allowPositionals:!0,options:{transport:{type:`string`,default:Y()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:Y(),port:process.env.AIKIT_PORT??`3210`}}async function ee(){let e=L(),n=$();process.on(`unhandledRejection`,t=>{R.error(`Unhandled rejection`,z(e,t))}),process.on(`uncaughtException`,t=>{R.error(`Uncaught exception — exiting`,z(e,t)),process.exit(1)});let r=(t,n)=>{t.then(async()=>{try{let{markPromoteRun:e,markPruneRun:t,prune:r,shouldRunStartupPrune:i,shouldRunWeeklyPromote:a}=await import(`../../tools/dist/index.js`),o=n();if(!o)return;if(i()){let e=await r({});t(),e.totalBytesFreed>0&&R.info(`Storage maintenance complete`,{forgeOrphans:e.forgeGroundOrphans.count,legacyLance:e.legacyLance.count,bytesFreed:e.totalBytesFreed});let{groupLessons:n,pruneLessons:i}=await import(`./evolution-DWaEE6XW.js`).then(e=>e.t),a=await i(o.curated,o.stateStore,{dryRun:!1});a.pruned.length>0&&R.info(`Startup lesson prune complete`,{pruned:a.pruned.length});let s=await n(o.curated,o.stateStore,{dryRun:!1});(s.groupsCreated>0||s.lessonsGrouped>0)&&R.info(`Startup lesson grouping complete`,{groupsCreated:s.groupsCreated,lessonsGrouped:s.lessonsGrouped})}if(a()){let{DEFAULT_PROMOTE_CONFIG:t,collectWorkspaceLessons:n,getGlobalCuratedDir:r,promoteLessons:i,scanForDuplicates:a}=await import(`./promotion-bQutAIz-.js`).then(e=>e.o),s=o.curated,c=new k(r(),s.store,s.embedder),l=await n(),u={...t,dryRun:!1},d=await i(a(l,u),c,u);e(),d.promoted.length>0&&R.info(`Weekly lesson promotion complete`,{promoted:d.promoted.length,candidates:d.candidates.length})}}catch(t){R.warn(`Startup maintenance failed (non-critical)`,z(e,t))}}).catch(()=>{})};if(R.info(`Starting MCP AI Kit server`,{version:e}),n.transport===`http`){let[{default:i},{loadConfig:a,resolveIndexMode:o},{registerDashboardRoutes:s,resolveDashboardDir:c},{registerSettingsRoutes:l,resolveSettingsDir:u},{createSettingsRouter:d},{authMiddleware:m,getOrCreateToken:h}]=await Promise.all([import(`express`),import(`./config-CaJwUDXI.js`),import(`./dashboard-static-CRfR1yKU.js`),import(`./settings-static-B3lnYvcb.js`),import(`./routes-KC-D2U8n.js`),import(`./auth-lzZKfxlV.js`)]),g=a();p(g.logging?.errorDetails===!0),g.configError&&R.warn(`Config load failure`,{error:g.configError}),R.info(`Config loaded`,{sourceCount:g.sources.length,storePath:g.store.path});let _=i();_.use(i.json({limit:`1mb`}));let v=Number(n.port),y=`http://localhost:${v}`,b=process.env.AIKIT_CORS_ORIGIN??y,x=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,S=Q(`AIKIT_HTTP_MAX_SESSIONS`,8),C=Q(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),w=Q(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),T=H({limit:100,windowMs:6e4}),E=!1;_.use((e,t,n)=>{let r=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,i=V({requestOrigin:r,configuredOrigin:b,allowAnyOrigin:x,fallbackOrigin:y});if(i.warn&&!E&&(E=!0,R.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:r,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),r&&!i.allowOrigin){t.status(403).json({error:`Origin not allowed`});return}if(i.allowOrigin&&t.setHeader(`Access-Control-Allow-Origin`,i.allowOrigin),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID`),t.setHeader(`Access-Control-Expose-Headers`,`Mcp-Session-Id`),e.method===`OPTIONS`){t.status(204).end();return}n()});let D=h();_.use(m(D)),_.use(`/mcp`,(e,t,n)=>{let r=Z(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(T.allow(r)){n();return}let i=Math.max(1,Math.ceil(T.getRetryAfterMs(r)/1e3));t.setHeader(`Retry-After`,String(i)),t.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})});let O=!1;_.use(`/mcp`,(e,t,n)=>{if(!O){let t=e.headers[`x-workspace-root`];typeof t==`string`&&t.length>0&&(g.sources[0]={path:t,excludePatterns:g.sources[0]?.excludePatterns??[]},g.allRoots=[t],O=!0,R.debug(`Workspace root applied from proxy header`,{wsRoot:t}))}n()}),s(_,c(),R);let k=new Date().toISOString();_.use(`/settings/api`,d({log:R,mcpInfo:()=>({transport:`http`,port:v,pid:process.pid,startedAt:k})})),l(_,u(),R),_.get(`/health`,(e,t)=>{t.json({status:`ok`})});let A=!1,j=null,M=null,N=null,F=null,L=null,B=null,U=null,W=null,G=Promise.resolve(),K=async(e,n)=>{if(!A||!N||!F){n.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=G,i;G=new Promise(e=>{i=e}),await r;try{let r=Z(e);if(!B){if(r){n.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new F({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{U=e,M?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&M?.onSessionEnd(e),U=null}});e.onclose=()=>{B===e&&(B=null),U===e.sessionId&&(U=null)},B=e,await N.connect(e)}let i=B;await i.handleRequest(e,n,e.body),e.method!==`DELETE`&&(!r&&i.sessionId?(U=i.sessionId,M?.onSessionStart(i.sessionId,{transport:`http`}),M?.onSessionActivity(i.sessionId)):r&&M?.onSessionActivity(r))}catch(e){if(R.error(`MCP handler error`,f(e)),!n.headersSent){let t=e instanceof Error?e.message:String(e),r=t.includes(`Not Acceptable`);n.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?t:`Internal server error`},id:null})}}finally{i()}},q=async(e,t)=>{let n=Z(e);if(L&&(!B||n!==U)){await L.handleRequest(e,t,e.body);return}await K(e,t)};_.post(`/mcp`,q),_.get(`/mcp`,q),_.delete(`/mcp`,q);let J=_.listen(v,`127.0.0.1`,()=>{R.info(`MCP server listening`,{url:`http://127.0.0.1:${v}/mcp`,port:v}),setTimeout(async()=>{try{let[{createLazyServer:t,createMcpServer:n,ALL_TOOL_NAMES:i},{StreamableHTTPServerTransport:a},{checkForUpdates:s,autoUpgradeScaffold:c}]=await Promise.all([import(`./server-o1JlU7yI.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-CJK1Fwmy.js`)]);s(),c(),setInterval(s,1440*60*1e3).unref();let l=o(g),u=t(g,l);W=async()=>{u.aikit&&await Promise.all([u.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),u.aikit.graphStore.close().catch(()=>{}),u.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),u.aikit.store.close().catch(()=>{})])},N=u.server,F=a,A=!0,R.debug(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:i.length,resourceCount:2}),u.startInit(),u.ready.then(()=>{if(!u.aikit)throw Error(`AI Kit components are not available after initialization`);M=new I(u.aikit.stateStore,{staleTimeoutMinutes:C,gcIntervalMinutes:w,onBeforeSessionDelete:e=>{if(U===e&&B){let e=B;B=null,U=null,e.close().catch(()=>void 0)}L?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!u.aikit?.curated||!u.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-DWaEE6XW.js`).then(e=>e.t),t=await e(u.aikit.curated,u.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&R.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),L=new P({createServer:()=>{if(!u.aikit)throw Error(`AI Kit components are not available after initialization`);return n(u.aikit,g)},createTransport:e=>new a(e),maxSessions:S,sessionTimeoutMinutes:C,onSessionStart:e=>M?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>M?.onSessionActivity(e),onSessionEnd:e=>M?.onSessionEnd(e)}),M.startGC(),U&&(M.onSessionStart(U,{transport:`http`}),M.onSessionActivity(U)),R.info(`HTTP session runtime ready`,{maxSessions:S,sessionTimeoutMinutes:C,gcIntervalMinutes:w})}).catch(e=>R.error(`Failed to start session manager`,f(e))),l===`auto`?u.ready.then(async()=>{try{let e=g.sources.map(e=>e.path).join(`, `);R.info(`Running initial index`,{sourcePaths:e}),await u.runInitialIndex(),R.info(`Initial index complete`)}catch(t){R.error(`Initial index failed; will retry on aikit_reindex`,z(e,t))}}).catch(t=>R.error(`AI Kit init or indexing failed`,z(e,t))):l===`smart`?u.ready.then(async()=>{try{if(!u.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(u.aikit.indexer,g,u.aikit.store),n=u.aikit.store;j=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),u.setSmartScheduler(t),R.debug(`Smart index scheduler started (HTTP mode)`)}catch(t){R.error(`Failed to start smart index scheduler`,z(e,t))}}).catch(t=>R.error(`AI Kit initialization failed`,z(e,t))):(u.ready.catch(t=>R.error(`AI Kit initialization failed`,z(e,t))),R.info(`Initial full indexing skipped in HTTP mode`,{indexMode:l})),r(u.ready,()=>u.aikit?{curated:u.aikit.curated,stateStore:u.aikit.stateStore}:null)}catch(t){R.error(`Failed to load server modules`,z(e,t))}},100)}),Y=!1,X=async e=>{Y||(Y=!0,R.info(`Shutdown signal received`,{signal:e}),j?.stop(),M?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await L?.closeAll().catch(()=>void 0),U&&M?.onSessionEnd(U),B&&(await B.close().catch(()=>void 0),B=null,U=null),J.close(),N&&await N.close(),await W?.().catch(()=>void 0),process.exit(0))};process.on(`SIGINT`,()=>X(`SIGINT`)),process.on(`SIGTERM`,()=>X(`SIGTERM`))}else{let[{loadConfig:t,reconfigureForWorkspace:n,resolveIndexMode:i},{createLazyServer:a},{checkForUpdates:o,autoUpgradeScaffold:s},{RootsListChangedNotificationSchema:c}]=await Promise.all([import(`./config-CaJwUDXI.js`),import(`./server-o1JlU7yI.js`),import(`./version-check-CJK1Fwmy.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=t();p(l.logging?.errorDetails===!0),l.configError&&R.warn(`Config load failure`,{error:l.configError}),R.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),o(),s(),setInterval(o,1440*60*1e3).unref();let u=i(l),d=a(l,u),{server:f,startInit:m,ready:h,runInitialIndex:g}=d,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await f.connect(v),R.debug(`MCP server started`,{transport:`stdio`}),await J({config:l,indexMode:u,log:R,rootsChangedNotificationSchema:c,reconfigureForWorkspace:n,runInitialIndex:g,server:f,startInit:m});let y=null,b=null,x=!1,S=async e=>{x||(x=!0,R.info(`Shutdown signal received`,{signal:e}),y&&=(clearTimeout(y),null),b?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await v.close().catch(()=>void 0),await f.close().catch(()=>void 0),d.aikit&&await Promise.all([d.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),d.aikit.graphStore.close().catch(()=>{}),d.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),d.aikit.store.close().catch(()=>{})]),process.exit(0))},C=()=>{y&&clearTimeout(y),y=setTimeout(async()=>{R.info(`Auto-shutdown: no activity for 30 minutes — releasing resources`);try{let e=d.aikit;e&&(e.embedder.shutdown?.().catch(()=>{}),e.store.releaseMemory?.(),e.graphStore.releaseMemory?.())}catch{}},18e5),y.unref&&y.unref()};C(),process.stdin.on(`data`,()=>C()),process.stdin.on(`end`,()=>void S(`stdin-end`)),process.stdin.on(`close`,()=>void S(`stdin-close`)),process.stdin.on(`error`,()=>void S(`stdin-error`)),process.on(`SIGINT`,()=>void S(`SIGINT`)),process.on(`SIGTERM`,()=>void S(`SIGTERM`)),h.catch(t=>{R.error(`Initialization failed — server will continue with limited tools`,z(e,t))}),u===`smart`?h.then(async()=>{try{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(d.aikit.indexer,l,d.aikit.store);b=t;let n=d.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),d.setSmartScheduler(t),R.debug(`Smart index scheduler started (stdio mode)`)}catch(t){R.error(`Failed to start smart index scheduler`,z(e,t))}}).catch(t=>R.error(`AI Kit init failed for smart scheduler`,z(e,t))):R.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:u}),r(h,()=>d.aikit?{curated:d.aikit.curated,stateStore:d.aikit.stateStore}:null)}}ee();export{T as n,k as t};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{o as e,t}from"./supersession-DO_ZROFl.js";import{existsSync as n,mkdirSync as r,readFileSync as i,writeFileSync as a}from"node:fs";import{dirname as o,isAbsolute as s,relative as c,resolve as l}from"node:path";import{fileURLToPath as u}from"node:url";import{AIKIT_RUNTIME_PATHS as d,EMBEDDING_DEFAULTS as f,computePartitionKey as p,createLogger as m,getPartitionDir as h,migrateLegacyWorkspaceLayout as g,serializeError as _}from"../../core/dist/index.js";const v={workingToEpisodicAccesses:2,episodicToSemanticReferences:3,semanticToProceduralVerifications:5},y={working:1,episodic:2,semantic:4,procedural:12};function b(e,t=v){switch(e.tier){case`working`:if(e.accessCount>=t.workingToEpisodicAccesses)return`episodic`;break;case`episodic`:if(e.accessCount>=t.workingToEpisodicAccesses+t.episodicToSemanticReferences)return`semantic`;break;case`semantic`:if(e.accessCount>=t.workingToEpisodicAccesses+t.episodicToSemanticReferences+t.semanticToProceduralVerifications)return`procedural`;break;case`procedural`:break;default:break}}function x(e,t,n){e.memoryMetaUpdateTier(t,n)}const S={stabilityHours:168,accessMultiplier:1.5,flagThreshold:.1,maxStabilityHours:8760};function C(e){return{...S,...e}}function w(e,t){if(!e)return t;let n=Date.parse(e);return Number.isNaN(n)?t:n}function T(e){return e&&e in y?e:`working`}function E(e,t,n,r=S,i){let a=typeof r==`string`?T(r):`working`,o=C(typeof r==`string`?i:r),s=w(e,w(n,Date.now())),c=Math.max(0,Date.now()-s)/(1e3*60*60),l=Math.min(o.stabilityHours*y[a]*o.accessMultiplier**Math.max(0,t),o.maxStabilityHours);return Math.exp(-c/l)}function D(e,t,n){let r=e.memoryMetaGet(t);if(!r)return;let i=E(r.lastAccessedAt,r.accessCount,r.createdAt,r.tier,n);return r.retentionScore!==i&&e.memoryMetaUpdateScore(t,i),e.memoryMetaGet(t)??{...r,retentionScore:i}}function O(e,t,n){e.memoryMetaGet(t)||e.memoryMetaCreate(t),e.memoryMetaTouch(t);let r=e.memoryMetaGet(t);if(!r)return 1;let i=E(r.lastAccessedAt,r.accessCount,r.createdAt,r.tier,n);return e.memoryMetaUpdateScore(t,i),i}function k(e,t){let n=C(t);return e.memoryMetaList().map(t=>D(e,t.entryId,n)??t).filter(e=>e.retentionScore<n.flagThreshold).sort((e,t)=>e.retentionScore-t.retentionScore)}const A=o(u(import.meta.url)),j=m(`server`),M=[`auto`,`manual`,`smart`],N={model:f.model,dimensions:f.dimensions,childProcess:!0,idleTimeoutMs:3e5};function P(e){return typeof e==`string`&&M.includes(e)}function F(e,t,n){let r=l(e),i=c(l(t),r);if(i.startsWith(`..`)||s(i))throw Error(`Config ${n} path escapes allowed root: ${e} is not under ${t}`);return r}function I(e,t){let n=l(e),r=c(l(t),n);return!(r.startsWith(`..`)||s(r))}function L(e){return h(p(e))}function R(e,t,n,r,i){let a=r?l(t,r):t;if(!n)return F(a,t,i);let o=l(e,n);return I(o,t)?r&&l(o)===l(t)?F(a,t,i):F(o,t,i):F(a,t,i)}function z(e){let t=[e.store?.path,e.curated?.path,e.onboardDir,e.stateDir];for(let e of t)e&&r(e,{recursive:!0})}function B(e,t){g(t);let n=L(t);e.store={...e.store,path:R(t,n,e.store?.path,d.data,`store`)},e.curated={...e.curated,path:R(t,n,e.curated?.path,d.curated,`curated`)},e.onboardDir=R(t,n,e.onboardDir,d.onboard,`onboard`),e.stateDir=R(t,n,e.stateDir,d.state,`state`)}function V(e){let t=process.env.AIKIT_INDEX_MODE;if(P(t))return t;if(e.indexMode)return e.indexMode;let n=process.env.AIKIT_AUTO_INDEX;return n===void 0?e.autoIndex===void 0?`smart`:e.autoIndex?`auto`:`manual`:n===`true`?`auto`:`manual`}function H(){let r=process.env.AIKIT_CONFIG_PATH??(n(l(process.cwd(),`aikit.config.json`))?l(process.cwd(),`aikit.config.json`):l(A,`..`,`..`,`..`,`aikit.config.json`));try{if(!n(r))return j.info(`No config file found, using defaults`,{configPath:r}),W();let a=i(r,`utf-8`),s=JSON.parse(a),c={...N,...s.embedding};if(s.embedding=c,s.memory={retention:{...S,...s.memory?.retention},lessons:{...e,...s.memory?.lessons},consolidation:{...v,...s.memory?.consolidation},supersession:{...t,...s.memory?.supersession}},s.logging?.errorDetails!==void 0&&typeof s.logging.errorDetails!=`boolean`)throw Error(`Config logging.errorDetails must be a boolean`);if(s.logging={errorDetails:s.logging?.errorDetails===!0},!s.sources||!Array.isArray(s.sources)||s.sources.length===0)throw Error(`Config must have at least one source`);if(!s.store?.path)throw Error(`Config must specify store.path`);if(s.autoIndex!==void 0&&typeof s.autoIndex!=`boolean`)throw Error(`Config autoIndex must be a boolean`);if(s.indexMode!==void 0&&!P(s.indexMode))throw Error(`Config indexMode must be one of: ${M.join(`, `)}`);if(typeof c.model!=`string`||c.model.trim()===``)throw Error(`Config embedding.model must be a non-empty string`);if(c.nativeDim!==void 0&&(!Number.isInteger(c.nativeDim)||c.nativeDim<=0))throw Error(`Config embedding.nativeDim must be a positive integer`);if(c.dimensions!==void 0&&(!Number.isInteger(c.dimensions)||c.dimensions<=0))throw Error(`Config embedding.dimensions must be a positive integer`);if(c.dimensions!==void 0&&c.nativeDim!==void 0&&c.dimensions>c.nativeDim)throw Error(`Config embedding.dimensions must not exceed embedding.nativeDim`);if(c.queryPrefix!==void 0&&typeof c.queryPrefix!=`string`)throw Error(`Config embedding.queryPrefix must be a string`);let u=o(r);return s.sources=s.sources.map(e=>({...e,path:F(l(u,e.path),u,`source`)})),G(s,r),B(s,u),s.indexMode=V(s),s}catch(e){let t=`Failed to load config from ${r}. ${e instanceof Error?e.message:String(e)}`;console.error(`\n ⚠ CONFIG ERROR — ${t}\n Check that the file exists, is valid JSON, and all required fields are present.\n`),j.error(`Failed to load config`,{configPath:r,..._(e)}),j.warn(`Falling back to default configuration`,{configPath:r});let n=W();return n.configError=t,n}}const U=[`.git/**`,`**/node_modules/**`,`*.lock`,`pnpm-lock.yaml`,`package-lock.json`,`**/dist/**`,`**/build/**`,`**/out/**`,`**/.output/**`,`**/cdk.out/**`,`**/.next/**`,`**/.nuxt/**`,`**/.vercel/**`,`**/.serverless/**`,`**/.turbo/**`,`**/.cache/**`,`**/.parcel-cache/**`,`**/coverage/**`,`**/.terraform/**`,`**/__pycache__/**`,`**/.venv/**`,`**/.docusaurus/**`,`**/.temp/**`,`**/tmp/**`];function W(){let n=process.env.AIKIT_WORKSPACE_ROOT??process.cwd(),r=L(n),i={sources:[{path:n,excludePatterns:[...U]}],serverName:`aikit`,indexing:{chunkSize:800,chunkOverlap:150,minChunkSize:100},embedding:{...N},store:{backend:`sqlite-vec`,path:l(r,d.data)},curated:{path:l(r,d.curated)},memory:{retention:{...S},lessons:{...e},consolidation:{...v},supersession:{...t}},logging:{errorDetails:!1},onboardDir:l(r,d.onboard),stateDir:l(r,d.state)};return i.indexMode=V(i),i}function G(e,t){let n=e.configVersion??0;if(n>=1)return e;if(n<1)for(let t of e.sources){t.excludePatterns=t.excludePatterns??[];let e=new Set(t.excludePatterns);for(let n of U)e.has(n)||t.excludePatterns.push(n)}e.configVersion=1;try{a(t,`${JSON.stringify(e,null,2)}\n`,`utf-8`),j.info(`Config auto-upgraded`,{from:n,to:1,configPath:t})}catch(e){j.warn(`Failed to write upgraded config`,{configPath:t,..._(e)})}return e}function K(e,t){if(!n(t))throw Error(`Workspace root does not exist: ${t}`);g(t),j.debug(`Reconfiguring for workspace root`,{workspaceRoot:t});try{process.chdir(t),j.debug(`Changed process cwd to workspace root`,{cwd:process.cwd()})}catch(e){j.warn(`Failed to chdir to workspace root`,{workspaceRoot:t,..._(e)})}e.sources=[{path:t,excludePatterns:e.sources[0]?.excludePatterns??[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],B(e,t),z(e)}export{U as DEFAULT_EXCLUDE_PATTERNS,b as a,v as i,H as loadConfig,D as n,x as o,O as r,K as reconfigureForWorkspace,V as resolveIndexMode,k as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{o as e,t}from"./supersession-CWEne3av.js";import{existsSync as n,mkdirSync as r,readFileSync as i,writeFileSync as a}from"node:fs";import{dirname as o,isAbsolute as s,relative as c,resolve as l}from"node:path";import{fileURLToPath as u}from"node:url";import{AIKIT_RUNTIME_PATHS as d,EMBEDDING_DEFAULTS as f,computePartitionKey as p,createLogger as m,getPartitionDir as h,migrateLegacyWorkspaceLayout as g,serializeError as _}from"../../core/dist/index.js";const v={workingToEpisodicAccesses:2,episodicToSemanticReferences:3,semanticToProceduralVerifications:5},y={working:1,episodic:2,semantic:4,procedural:12};function b(e,t=v){switch(e.tier){case`working`:if(e.accessCount>=t.workingToEpisodicAccesses)return`episodic`;break;case`episodic`:if(e.accessCount>=t.workingToEpisodicAccesses+t.episodicToSemanticReferences)return`semantic`;break;case`semantic`:if(e.accessCount>=t.workingToEpisodicAccesses+t.episodicToSemanticReferences+t.semanticToProceduralVerifications)return`procedural`;break;case`procedural`:break;default:break}}function x(e,t,n){e.memoryMetaUpdateTier(t,n)}const S={stabilityHours:168,accessMultiplier:1.5,flagThreshold:.1,maxStabilityHours:8760};function C(e){return{...S,...e}}function w(e,t){if(!e)return t;let n=Date.parse(e);return Number.isNaN(n)?t:n}function T(e){return e&&e in y?e:`working`}function E(e,t,n,r=S,i){let a=typeof r==`string`?T(r):`working`,o=C(typeof r==`string`?i:r),s=w(e,w(n,Date.now())),c=Math.max(0,Date.now()-s)/(1e3*60*60),l=Math.min(o.stabilityHours*y[a]*o.accessMultiplier**Math.max(0,t),o.maxStabilityHours);return Math.exp(-c/l)}function D(e,t,n){let r=e.memoryMetaGet(t);if(!r)return;let i=E(r.lastAccessedAt,r.accessCount,r.createdAt,r.tier,n);return r.retentionScore!==i&&e.memoryMetaUpdateScore(t,i),e.memoryMetaGet(t)??{...r,retentionScore:i}}function O(e,t,n){e.memoryMetaGet(t)||e.memoryMetaCreate(t),e.memoryMetaTouch(t);let r=e.memoryMetaGet(t);if(!r)return 1;let i=E(r.lastAccessedAt,r.accessCount,r.createdAt,r.tier,n);return e.memoryMetaUpdateScore(t,i),i}function k(e,t){let n=C(t);return e.memoryMetaList().map(t=>D(e,t.entryId,n)??t).filter(e=>e.retentionScore<n.flagThreshold).sort((e,t)=>e.retentionScore-t.retentionScore)}const A=o(u(import.meta.url)),j=m(`server`),M=[`auto`,`manual`,`smart`],N={model:f.model,dimensions:f.dimensions,childProcess:!0,idleTimeoutMs:3e5};function P(e){return typeof e==`string`&&M.includes(e)}function F(e,t,n){let r=l(e),i=c(l(t),r);if(i.startsWith(`..`)||s(i))throw Error(`Config ${n} path escapes allowed root: ${e} is not under ${t}`);return r}function I(e,t){let n=l(e),r=c(l(t),n);return!(r.startsWith(`..`)||s(r))}function L(e){return h(p(e))}function R(e,t,n,r,i){let a=r?l(t,r):t;if(!n)return F(a,t,i);let o=l(e,n);return I(o,t)?r&&l(o)===l(t)?F(a,t,i):F(o,t,i):F(a,t,i)}function z(e){let t=[e.store?.path,e.curated?.path,e.onboardDir,e.stateDir];for(let e of t)e&&r(e,{recursive:!0})}function B(e,t){g(t);let n=L(t);e.store={...e.store,path:R(t,n,e.store?.path,d.data,`store`)},e.curated={...e.curated,path:R(t,n,e.curated?.path,d.curated,`curated`)},e.onboardDir=R(t,n,e.onboardDir,d.onboard,`onboard`),e.stateDir=R(t,n,e.stateDir,d.state,`state`)}function V(e){let t=process.env.AIKIT_INDEX_MODE;if(P(t))return t;if(e.indexMode)return e.indexMode;let n=process.env.AIKIT_AUTO_INDEX;return n===void 0?e.autoIndex===void 0?`smart`:e.autoIndex?`auto`:`manual`:n===`true`?`auto`:`manual`}function H(){let r=process.env.AIKIT_CONFIG_PATH??(n(l(process.cwd(),`aikit.config.json`))?l(process.cwd(),`aikit.config.json`):l(A,`..`,`..`,`..`,`aikit.config.json`));try{if(!n(r))return j.info(`No config file found, using defaults`,{configPath:r}),W();let a=i(r,`utf-8`),s=JSON.parse(a),c={...N,...s.embedding};if(s.embedding=c,s.memory={retention:{...S,...s.memory?.retention},lessons:{...e,...s.memory?.lessons},consolidation:{...v,...s.memory?.consolidation},supersession:{...t,...s.memory?.supersession}},s.logging?.errorDetails!==void 0&&typeof s.logging.errorDetails!=`boolean`)throw Error(`Config logging.errorDetails must be a boolean`);if(s.logging={errorDetails:s.logging?.errorDetails===!0},!s.sources||!Array.isArray(s.sources)||s.sources.length===0)throw Error(`Config must have at least one source`);if(!s.store?.path)throw Error(`Config must specify store.path`);if(s.autoIndex!==void 0&&typeof s.autoIndex!=`boolean`)throw Error(`Config autoIndex must be a boolean`);if(s.indexMode!==void 0&&!P(s.indexMode))throw Error(`Config indexMode must be one of: ${M.join(`, `)}`);if(typeof c.model!=`string`||c.model.trim()===``)throw Error(`Config embedding.model must be a non-empty string`);if(c.nativeDim!==void 0&&(!Number.isInteger(c.nativeDim)||c.nativeDim<=0))throw Error(`Config embedding.nativeDim must be a positive integer`);if(c.dimensions!==void 0&&(!Number.isInteger(c.dimensions)||c.dimensions<=0))throw Error(`Config embedding.dimensions must be a positive integer`);if(c.dimensions!==void 0&&c.nativeDim!==void 0&&c.dimensions>c.nativeDim)throw Error(`Config embedding.dimensions must not exceed embedding.nativeDim`);if(c.queryPrefix!==void 0&&typeof c.queryPrefix!=`string`)throw Error(`Config embedding.queryPrefix must be a string`);let u=o(r);return s.sources=s.sources.map(e=>({...e,path:F(l(u,e.path),u,`source`)})),G(s,r),B(s,u),s.indexMode=V(s),s}catch(e){let t=`Failed to load config from ${r}. ${e instanceof Error?e.message:String(e)}`;console.error(`\n ⚠ CONFIG ERROR — ${t}\n Check that the file exists, is valid JSON, and all required fields are present.\n`),j.error(`Failed to load config`,{configPath:r,..._(e)}),j.warn(`Falling back to default configuration`,{configPath:r});let n=W();return n.configError=t,n}}const U=[`.git/**`,`**/node_modules/**`,`*.lock`,`pnpm-lock.yaml`,`package-lock.json`,`**/dist/**`,`**/build/**`,`**/out/**`,`**/.output/**`,`**/cdk.out/**`,`**/.next/**`,`**/.nuxt/**`,`**/.vercel/**`,`**/.serverless/**`,`**/.turbo/**`,`**/.cache/**`,`**/.parcel-cache/**`,`**/coverage/**`,`**/.terraform/**`,`**/__pycache__/**`,`**/.venv/**`,`**/.docusaurus/**`,`**/.temp/**`,`**/tmp/**`];function W(){let n=process.env.AIKIT_WORKSPACE_ROOT??process.cwd(),r=L(n),i={sources:[{path:n,excludePatterns:[...U]}],serverName:`aikit`,indexing:{chunkSize:800,chunkOverlap:150,minChunkSize:100},embedding:{...N},store:{backend:`sqlite-vec`,path:l(r,d.data)},curated:{path:l(r,d.curated)},memory:{retention:{...S},lessons:{...e},consolidation:{...v},supersession:{...t}},logging:{errorDetails:!1},onboardDir:l(r,d.onboard),stateDir:l(r,d.state)};return i.indexMode=V(i),i}function G(e,t){let n=e.configVersion??0;if(n>=1)return e;if(n<1)for(let t of e.sources){t.excludePatterns=t.excludePatterns??[];let e=new Set(t.excludePatterns);for(let n of U)e.has(n)||t.excludePatterns.push(n)}e.configVersion=1;try{a(t,`${JSON.stringify(e,null,2)}\n`,`utf-8`),j.info(`Config auto-upgraded`,{from:n,to:1,configPath:t})}catch(e){j.warn(`Failed to write upgraded config`,{configPath:t,..._(e)})}return e}function K(e,t){if(!n(t))throw Error(`Workspace root does not exist: ${t}`);g(t),j.debug(`Reconfiguring for workspace root`,{workspaceRoot:t});try{process.chdir(t),j.debug(`Changed process cwd to workspace root`,{cwd:process.cwd()})}catch(e){j.warn(`Failed to chdir to workspace root`,{workspaceRoot:t,..._(e)})}e.sources=[{path:t,excludePatterns:e.sources[0]?.excludePatterns??[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],B(e,t),z(e)}export{U as DEFAULT_EXCLUDE_PATTERNS,b as a,v as i,H as loadConfig,D as n,x as o,O as r,K as reconfigureForWorkspace,V as resolveIndexMode,k as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./curated-manager-i5QA4c79.js";import{randomUUID as t}from"node:crypto";import{readFileSync as n}from"node:fs";import{dirname as r,resolve as i}from"node:path";import{fileURLToPath as a,pathToFileURL as o}from"node:url";import{parseArgs as s}from"node:util";import{createLogger as c,serializeError as l,setDetailedErrorLoggingEnabled as u}from"../../core/dist/index.js";const d=`__pending__:`;function f(e){return e.startsWith(d)}function p(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function m(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var h=class{options;runtimes=new Map;maxSessions;sessionTimeoutMs;now;constructor(e){this.options=e,this.maxSessions=e.maxSessions??8,this.sessionTimeoutMs=(e.sessionTimeoutMinutes??30)*60*1e3,this.now=e.now??(()=>Date.now())}hasSession(e){return this.runtimes.has(e)}getSessionCount(){return this.runtimes.size}async handleRequest(e,t,n=e.body){let r=p(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){m(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){m(t,400,-32e3,`Session required`);return}if(i=await this.createRuntime(t),!i)return}await this.withRuntimeLock(i,async()=>{await i.transport.handleRequest(e,t,n),i.lastAccessAt=this.now();let r=i.transport.sessionId??i.id;e.method!==`DELETE`&&!f(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!f(r)&&await this.closeSession(r,{closeTransport:!1})})}async closeExpiredSessions(){let e=[...this.runtimes.values()].filter(e=>this.now()-e.lastAccessAt>=this.sessionTimeoutMs).map(e=>e.id);for(let t of e)await this.closeSession(t);return e.length}async closeSession(e,t={}){let n=this.runtimes.get(e);return n?(this.runtimes.delete(e),t.notifySessionEnd!==!1&&!f(e)&&this.options.onSessionEnd?.(e),t.closeTransport!==!1&&await n.transport.close().catch(()=>void 0),await n.server.close().catch(()=>void 0),!0):!1}async closeAll(){let e=[...this.runtimes.keys()];for(let t of e)await this.closeSession(t)}async createRuntime(e){if(await this.closeExpiredSessions(),this.runtimes.size>=this.maxSessions){m(e,503,-32003,`Session capacity reached`);return}let n=this.now(),r=await this.options.createServer(),i={id:`${d}${t()}`,transport:void 0,createdAt:n,lastAccessAt:n,server:r,requestChain:Promise.resolve()},a=this.options.createTransport({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{this.runtimes.delete(i.id),i.id=e,this.runtimes.set(e,i),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return i.transport=a,a.onclose=()=>{let e=i.transport.sessionId??i.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(i.id,i),await r.connect(a),i}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function g(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var _=class{stateStore;options;gcTimer=null;constructor(e,t={}){this.stateStore=e,this.options=t}onSessionStart(e,t){this.stateStore.sessionCreate(e,t)}onSessionActivity(e){this.stateStore.sessionTouch(e)}onSessionEnd(e){this.stateStore.sessionDelete(e),Promise.resolve(this.options.onSessionEndMaintenance?.(e)).catch(()=>{})}startGC(){if(this.gcTimer)return;let e=(this.options.gcIntervalMinutes??5)*60*1e3;this.gcTimer=setInterval(()=>{this.runGC()},e),this.gcTimer.unref()}runGC(){let e=this.getStaleSessionIds();for(let t of e)this.options.onBeforeSessionDelete?.(t),Promise.resolve(this.options.onSessionEndMaintenance?.(t)).catch(()=>{}),this.stateStore.sessionDelete(t);return e.length}stop(){this.gcTimer&&=(clearInterval(this.gcTimer),null)}getActiveSessions(){return this.stateStore.sessionList().length}listSessions(){return this.stateStore.sessionList()}getStaleSessionIds(e=Date.now()){let t=(this.options.staleTimeoutMinutes??30)*60*1e3;return this.stateStore.sessionList().filter(n=>{let r=g(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};function v(){try{let e=i(r(a(import.meta.url)),`..`,`..`,`..`,`package.json`);return JSON.parse(n(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}const y=c(`server`);function b(e,t){return t?{version:e,...l(t)}:{version:e}}const x=/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;function S({requestOrigin:e,configuredOrigin:t,allowAnyOrigin:n,fallbackOrigin:r}){let i=t??r;return i===`*`?n?{allowOrigin:`*`,warn:!1}:e?x.test(e)?{allowOrigin:e,warn:!1}:{allowOrigin:null,warn:!0}:{allowOrigin:r,warn:!1}:{allowOrigin:i,warn:!1}}function C({limit:e,windowMs:t}){let n=new Map,r=(e,r)=>{let i=r-t,a=n.get(e)?.filter(e=>e>i)??[];return a.length===0?(n.delete(e),[]):(n.set(e,a),a)};return{allow(t,i=Date.now()){let a=r(t,i);return a.length>=e?!1:(a.push(i),n.set(t,a),!0)},getRetryAfterMs(n,i=Date.now()){let a=r(n,i);return a.length<e?0:Math.max(0,a[0]+t-i)}}}function w(e){return e.startsWith(`file://`)?a(e):e}function T(e){let t=i(e);return process.platform===`win32`?t.toLowerCase():t}function E(e){let t=new Map;for(let n of e){let e=w(n.uri);t.set(T(e),e)}return[...t.values()].sort((e,t)=>T(e).localeCompare(T(t)))}function D({config:e,roots:t}){let n=E(t);if(n.length===0)return null;let r=e.sources?.[0]?.path;if(r){let e=T(r),t=n.find(t=>T(t)===e);if(t)return t}return n[0]}function O({config:e,log:t,reconfigureForWorkspace:n,roots:r}){let i=E(r);if(i.length===0)return!1;let a=D({config:e,roots:i.map(e=>({uri:e}))});if(!a)return!1;let o=e.sources?.[0]?.path,s=o&&T(o)===T(a)?`configured-source`:`stable-sorted-root`;return t.debug(`MCP roots resolved`,{rootPath:a,rootCount:i.length,selectedBy:s}),n(e,a),e.allRoots=i,!0}async function k({config:e,indexMode:t,log:n,rootsChangedNotificationSchema:r,reconfigureForWorkspace:i,runInitialIndex:a,server:o,startInit:s,timeoutMs:c=5e3,getCwd:u=()=>process.cwd()}){let d=v(),f=!1,p=!1,m,h=o.server,g=e=>{let t=l(e),n=`${String(e)} ${String(t.message??``)}`.toLowerCase();return n.includes(`method not found`)||n.includes(`not supported`)||n.includes(`unsupported`)||n.includes(`unknown method`)||n.includes(`roots/list`)},_=()=>{f||(f=!0,s())},y=()=>{p||t!==`auto`||(p=!0,(async()=>{try{await a()}catch(e){n.error(`Initial index failed`,b(d,e))}})())},x=t=>t.length===0||(m&&=(clearTimeout(m),void 0),!O({config:e,log:n,reconfigureForWorkspace:i,roots:t}))?!1:(_(),y(),!0);try{if(x((await h.listRoots()).roots))return;n.debug(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(t){if(g(t)){n.warn(`MCP roots/list not supported by client; using cwd fallback`,{version:d,cwd:u(),...l(t)}),O({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:u()}]})&&(_(),y());return}n.warn(`MCP roots/list failed during bootstrap; waiting for roots/list_changed notification`,{version:d,cwd:u(),...l(t)})}h.setNotificationHandler(r,async()=>{try{x((await h.listRoots()).roots)}catch(e){n.warn(`roots/list retry failed after notification`,b(d,e))}}),m=setTimeout(()=>{let t=u();n.debug(`Timed out waiting for MCP roots/list_changed; falling back to cwd workspace`,{cwd:t}),O({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:t}]})&&(_(),y())},c)}function A(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function j(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===o(e).href}catch{return!1}}function M(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function N(e,t){let n=process.env[e];if(!n)return t;let r=Number.parseInt(n,10);return Number.isFinite(r)&&r>0?r:t}function P(){return j()?s({allowPositionals:!0,options:{transport:{type:`string`,default:A()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:A(),port:process.env.AIKIT_PORT??`3210`}}async function F(){let n=v(),r=P();process.on(`unhandledRejection`,e=>{y.error(`Unhandled rejection`,b(n,e))}),process.on(`uncaughtException`,e=>{y.error(`Uncaught exception — exiting`,b(n,e)),process.exit(1)});let i=(t,r)=>{t.then(async()=>{try{let{markPromoteRun:t,markPruneRun:n,prune:i,shouldRunStartupPrune:a,shouldRunWeeklyPromote:o}=await import(`../../tools/dist/index.js`),s=r();if(!s)return;if(a()){let e=await i({});n(),e.totalBytesFreed>0&&y.info(`Storage maintenance complete`,{forgeOrphans:e.forgeGroundOrphans.count,legacyLance:e.legacyLance.count,bytesFreed:e.totalBytesFreed});let{groupLessons:t,pruneLessons:r}=await import(`./evolution-BX_zTSdj.js`).then(e=>e.t),a=await r(s.curated,s.stateStore,{dryRun:!1});a.pruned.length>0&&y.info(`Startup lesson prune complete`,{pruned:a.pruned.length});let o=await t(s.curated,s.stateStore,{dryRun:!1});(o.groupsCreated>0||o.lessonsGrouped>0)&&y.info(`Startup lesson grouping complete`,{groupsCreated:o.groupsCreated,lessonsGrouped:o.lessonsGrouped})}if(o()){let{DEFAULT_PROMOTE_CONFIG:n,collectWorkspaceLessons:r,getGlobalCuratedDir:i,promoteLessons:a,scanForDuplicates:o}=await import(`./promotion-DmwIVl0c.js`).then(e=>e.o),c=s.curated,l=new e(i(),c.store,c.embedder),u=await r(),d={...n,dryRun:!1},f=await a(o(u,d),l,d);t(),f.promoted.length>0&&y.info(`Weekly lesson promotion complete`,{promoted:f.promoted.length,candidates:f.candidates.length})}}catch(e){y.warn(`Startup maintenance failed (non-critical)`,b(n,e))}}).catch(()=>{})};if(y.info(`Starting MCP AI Kit server`,{version:n}),r.transport===`http`){let[{default:e},{loadConfig:a,resolveIndexMode:o},{registerDashboardRoutes:s,resolveDashboardDir:c},{registerSettingsRoutes:d,resolveSettingsDir:f},{createSettingsRouter:p},{authMiddleware:m,getOrCreateToken:g}]=await Promise.all([import(`express`),import(`./config-CcbU0fiV.js`),import(`./dashboard-static-FmfoS46e.js`),import(`./settings-static-BtvyIrza.js`),import(`./routes-1wkXLxXe.js`),import(`./auth-Bz5dmZgR.js`).then(e=>e.t)]),v=a();u(v.logging?.errorDetails===!0),v.configError&&y.warn(`Config load failure`,{error:v.configError}),y.info(`Config loaded`,{sourceCount:v.sources.length,storePath:v.store.path});let x=e();x.use(e.json({limit:`1mb`}));let w=Number(r.port),T=`http://localhost:${w}`,E=process.env.AIKIT_CORS_ORIGIN??T,D=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,O=N(`AIKIT_HTTP_MAX_SESSIONS`,8),k=N(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),A=N(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),j=C({limit:100,windowMs:6e4}),P=!1;x.use((e,t,n)=>{let r=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,i=S({requestOrigin:r,configuredOrigin:E,allowAnyOrigin:D,fallbackOrigin:T});if(i.warn&&!P&&(P=!0,y.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:r,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),r&&!i.allowOrigin){t.status(403).json({error:`Origin not allowed`});return}if(i.allowOrigin&&t.setHeader(`Access-Control-Allow-Origin`,i.allowOrigin),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID`),t.setHeader(`Access-Control-Expose-Headers`,`Mcp-Session-Id`),e.method===`OPTIONS`){t.status(204).end();return}n()});let F=g();x.use(m(F)),x.use(`/mcp`,(e,t,n)=>{let r=M(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(j.allow(r)){n();return}let i=Math.max(1,Math.ceil(j.getRetryAfterMs(r)/1e3));t.setHeader(`Retry-After`,String(i)),t.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})});let I=!1;x.use(`/mcp`,(e,t,n)=>{if(!I){let t=e.headers[`x-workspace-root`];typeof t==`string`&&t.length>0&&(v.sources[0]={path:t,excludePatterns:v.sources[0]?.excludePatterns??[]},v.allRoots=[t],I=!0,y.debug(`Workspace root applied from proxy header`,{wsRoot:t}))}n()}),s(x,c(),y);let L=new Date().toISOString();x.use(`/settings/api`,p({log:y,mcpInfo:()=>({transport:`http`,port:w,pid:process.pid,startedAt:L})})),d(x,f(),y),x.get(`/health`,(e,t)=>{t.json({status:`ok`})});let R=!1,z=null,B=null,V=null,H=null,U=null,W=null,G=null,K=null,q=Promise.resolve(),J=async(e,n)=>{if(!R||!V||!H){n.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=q,i;q=new Promise(e=>{i=e}),await r;try{let r=M(e);if(!W){if(r){n.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new H({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{G=e,B?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&B?.onSessionEnd(e),G=null}});e.onclose=()=>{W===e&&(W=null),G===e.sessionId&&(G=null)},W=e,await V.connect(e)}let i=W;await i.handleRequest(e,n,e.body),e.method!==`DELETE`&&(!r&&i.sessionId?(G=i.sessionId,B?.onSessionStart(i.sessionId,{transport:`http`}),B?.onSessionActivity(i.sessionId)):r&&B?.onSessionActivity(r))}catch(e){if(y.error(`MCP handler error`,l(e)),!n.headersSent){let t=e instanceof Error?e.message:String(e),r=t.includes(`Not Acceptable`);n.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?t:`Internal server error`},id:null})}}finally{i()}},Y=async(e,t)=>{let n=M(e);if(U&&(!W||n!==G)){await U.handleRequest(e,t,e.body);return}await J(e,t)};x.post(`/mcp`,Y),x.get(`/mcp`,Y),x.delete(`/mcp`,Y);let X=x.listen(w,`127.0.0.1`,()=>{y.info(`MCP server listening`,{url:`http://127.0.0.1:${w}/mcp`,port:w}),setTimeout(async()=>{try{let[{createLazyServer:e,createMcpServer:t,ALL_TOOL_NAMES:r},{StreamableHTTPServerTransport:a},{checkForUpdates:s,autoUpgradeScaffold:c}]=await Promise.all([import(`./server-CDWtY-Sp.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-yzdUDXHC.js`)]);s(),c(),setInterval(s,1440*60*1e3).unref();let u=o(v),d=e(v,u);K=async()=>{d.aikit&&await Promise.all([d.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),d.aikit.graphStore.close().catch(()=>{}),d.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),d.aikit.store.close().catch(()=>{})])},V=d.server,H=a,R=!0,y.debug(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:r.length,resourceCount:2}),d.startInit(),d.ready.then(()=>{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);B=new _(d.aikit.stateStore,{staleTimeoutMinutes:k,gcIntervalMinutes:A,onBeforeSessionDelete:e=>{if(G===e&&W){let e=W;W=null,G=null,e.close().catch(()=>void 0)}U?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!d.aikit?.curated||!d.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-BX_zTSdj.js`).then(e=>e.t),t=await e(d.aikit.curated,d.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&y.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),U=new h({createServer:()=>{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);return t(d.aikit,v)},createTransport:e=>new a(e),maxSessions:O,sessionTimeoutMinutes:k,onSessionStart:e=>B?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>B?.onSessionActivity(e),onSessionEnd:e=>B?.onSessionEnd(e)}),B.startGC(),G&&(B.onSessionStart(G,{transport:`http`}),B.onSessionActivity(G)),y.info(`HTTP session runtime ready`,{maxSessions:O,sessionTimeoutMinutes:k,gcIntervalMinutes:A})}).catch(e=>y.error(`Failed to start session manager`,l(e))),u===`auto`?d.ready.then(async()=>{try{let e=v.sources.map(e=>e.path).join(`, `);y.info(`Running initial index`,{sourcePaths:e}),await d.runInitialIndex(),y.info(`Initial index complete`)}catch(e){y.error(`Initial index failed; will retry on aikit_reindex`,b(n,e))}}).catch(e=>y.error(`AI Kit init or indexing failed`,b(n,e))):u===`smart`?d.ready.then(async()=>{try{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(d.aikit.indexer,v,d.aikit.store),n=d.aikit.store;z=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),d.setSmartScheduler(t),y.debug(`Smart index scheduler started (HTTP mode)`)}catch(e){y.error(`Failed to start smart index scheduler`,b(n,e))}}).catch(e=>y.error(`AI Kit initialization failed`,b(n,e))):(d.ready.catch(e=>y.error(`AI Kit initialization failed`,b(n,e))),y.info(`Initial full indexing skipped in HTTP mode`,{indexMode:u})),i(d.ready,()=>d.aikit?{curated:d.aikit.curated,stateStore:d.aikit.stateStore}:null)}catch(e){y.error(`Failed to load server modules`,b(n,e))}},100)}),Z=!1,Q=async e=>{Z||(Z=!0,y.info(`Shutdown signal received`,{signal:e}),z?.stop(),B?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await U?.closeAll().catch(()=>void 0),G&&B?.onSessionEnd(G),W&&(await W.close().catch(()=>void 0),W=null,G=null),X.close(),V&&await V.close(),await K?.().catch(()=>void 0),process.exit(0))};process.on(`SIGINT`,()=>Q(`SIGINT`)),process.on(`SIGTERM`,()=>Q(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:r},{createLazyServer:a},{checkForUpdates:o,autoUpgradeScaffold:s},{RootsListChangedNotificationSchema:c}]=await Promise.all([import(`./config-CcbU0fiV.js`),import(`./server-CDWtY-Sp.js`),import(`./version-check-yzdUDXHC.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=e();u(l.logging?.errorDetails===!0),l.configError&&y.warn(`Config load failure`,{error:l.configError}),y.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),o(),s(),setInterval(o,1440*60*1e3).unref();let d=r(l),f=a(l,d),{server:p,startInit:m,ready:h,runInitialIndex:g}=f,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await p.connect(v),y.debug(`MCP server started`,{transport:`stdio`}),await k({config:l,indexMode:d,log:y,rootsChangedNotificationSchema:c,reconfigureForWorkspace:t,runInitialIndex:g,server:p,startInit:m});let x=null,S=null,C=!1,w=async e=>{C||(C=!0,y.info(`Shutdown signal received`,{signal:e}),x&&=(clearTimeout(x),null),S?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await v.close().catch(()=>void 0),await p.close().catch(()=>void 0),f.aikit&&await Promise.all([f.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),f.aikit.graphStore.close().catch(()=>{}),f.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),f.aikit.store.close().catch(()=>{})]),process.exit(0))},T=()=>{x&&clearTimeout(x),x=setTimeout(async()=>{y.info(`Auto-shutdown: no activity for 30 minutes — releasing resources`);try{let e=f.aikit;e&&(e.embedder.shutdown?.().catch(()=>{}),e.store.releaseMemory?.(),e.graphStore.releaseMemory?.())}catch{}},18e5),x.unref&&x.unref()};T(),process.stdin.on(`data`,()=>T()),process.stdin.on(`end`,()=>void w(`stdin-end`)),process.stdin.on(`close`,()=>void w(`stdin-close`)),process.stdin.on(`error`,()=>void w(`stdin-error`)),process.on(`SIGINT`,()=>void w(`SIGINT`)),process.on(`SIGTERM`,()=>void w(`SIGTERM`)),h.catch(e=>{y.error(`Initialization failed — server will continue with limited tools`,b(n,e))}),d===`smart`?h.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.aikit.indexer,l,f.aikit.store);S=t;let n=f.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),f.setSmartScheduler(t),y.debug(`Smart index scheduler started (stdio mode)`)}catch(e){y.error(`Failed to start smart index scheduler`,b(n,e))}}).catch(e=>y.error(`AI Kit init failed for smart scheduler`,b(n,e))):y.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:d}),i(h,()=>f.aikit?{curated:f.aikit.curated,stateStore:f.aikit.stateStore}:null)}}export{e as CuratedKnowledgeManager,O as applyWorkspaceRoots,k as bootstrapWorkspaceRoots,C as createSlidingWindowRateLimiter,F as main,S as resolveCorsOrigin,D as selectWorkspaceRoot};
|
|
1
|
+
import{t as e}from"./curated-manager-i5QA4c79.js";import{randomUUID as t}from"node:crypto";import{readFileSync as n}from"node:fs";import{dirname as r,resolve as i}from"node:path";import{fileURLToPath as a,pathToFileURL as o}from"node:url";import{parseArgs as s}from"node:util";import{createLogger as c,serializeError as l,setDetailedErrorLoggingEnabled as u}from"../../core/dist/index.js";const d=`__pending__:`;function f(e){return e.startsWith(d)}function p(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function m(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var h=class{options;runtimes=new Map;maxSessions;sessionTimeoutMs;now;constructor(e){this.options=e,this.maxSessions=e.maxSessions??8,this.sessionTimeoutMs=(e.sessionTimeoutMinutes??30)*60*1e3,this.now=e.now??(()=>Date.now())}hasSession(e){return this.runtimes.has(e)}getSessionCount(){return this.runtimes.size}async handleRequest(e,t,n=e.body){let r=p(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){m(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){m(t,400,-32e3,`Session required`);return}if(i=await this.createRuntime(t),!i)return}await this.withRuntimeLock(i,async()=>{await i.transport.handleRequest(e,t,n),i.lastAccessAt=this.now();let r=i.transport.sessionId??i.id;e.method!==`DELETE`&&!f(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!f(r)&&await this.closeSession(r,{closeTransport:!1})})}async closeExpiredSessions(){let e=[...this.runtimes.values()].filter(e=>this.now()-e.lastAccessAt>=this.sessionTimeoutMs).map(e=>e.id);for(let t of e)await this.closeSession(t);return e.length}async closeSession(e,t={}){let n=this.runtimes.get(e);return n?(this.runtimes.delete(e),t.notifySessionEnd!==!1&&!f(e)&&this.options.onSessionEnd?.(e),t.closeTransport!==!1&&await n.transport.close().catch(()=>void 0),await n.server.close().catch(()=>void 0),!0):!1}async closeAll(){let e=[...this.runtimes.keys()];for(let t of e)await this.closeSession(t)}async createRuntime(e){if(await this.closeExpiredSessions(),this.runtimes.size>=this.maxSessions){m(e,503,-32003,`Session capacity reached`);return}let n=this.now(),r=await this.options.createServer(),i={id:`${d}${t()}`,transport:void 0,createdAt:n,lastAccessAt:n,server:r,requestChain:Promise.resolve()},a=this.options.createTransport({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{this.runtimes.delete(i.id),i.id=e,this.runtimes.set(e,i),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return i.transport=a,a.onclose=()=>{let e=i.transport.sessionId??i.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(i.id,i),await r.connect(a),i}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function g(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var _=class{stateStore;options;gcTimer=null;constructor(e,t={}){this.stateStore=e,this.options=t}onSessionStart(e,t){this.stateStore.sessionCreate(e,t)}onSessionActivity(e){this.stateStore.sessionTouch(e)}onSessionEnd(e){this.stateStore.sessionDelete(e),Promise.resolve(this.options.onSessionEndMaintenance?.(e)).catch(()=>{})}startGC(){if(this.gcTimer)return;let e=(this.options.gcIntervalMinutes??5)*60*1e3;this.gcTimer=setInterval(()=>{this.runGC()},e),this.gcTimer.unref()}runGC(){let e=this.getStaleSessionIds();for(let t of e)this.options.onBeforeSessionDelete?.(t),Promise.resolve(this.options.onSessionEndMaintenance?.(t)).catch(()=>{}),this.stateStore.sessionDelete(t);return e.length}stop(){this.gcTimer&&=(clearInterval(this.gcTimer),null)}getActiveSessions(){return this.stateStore.sessionList().length}listSessions(){return this.stateStore.sessionList()}getStaleSessionIds(e=Date.now()){let t=(this.options.staleTimeoutMinutes??30)*60*1e3;return this.stateStore.sessionList().filter(n=>{let r=g(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};function v(){try{let e=i(r(a(import.meta.url)),`..`,`..`,`..`,`package.json`);return JSON.parse(n(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}const y=c(`server`);function b(e,t){return t?{version:e,...l(t)}:{version:e}}const x=/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;function S({requestOrigin:e,configuredOrigin:t,allowAnyOrigin:n,fallbackOrigin:r}){let i=t??r;return i===`*`?n?{allowOrigin:`*`,warn:!1}:e?x.test(e)?{allowOrigin:e,warn:!1}:{allowOrigin:null,warn:!0}:{allowOrigin:r,warn:!1}:{allowOrigin:i,warn:!1}}function C({limit:e,windowMs:t}){let n=new Map,r=(e,r)=>{let i=r-t,a=n.get(e)?.filter(e=>e>i)??[];return a.length===0?(n.delete(e),[]):(n.set(e,a),a)};return{allow(t,i=Date.now()){let a=r(t,i);return a.length>=e?!1:(a.push(i),n.set(t,a),!0)},getRetryAfterMs(n,i=Date.now()){let a=r(n,i);return a.length<e?0:Math.max(0,a[0]+t-i)}}}function w(e){return e.startsWith(`file://`)?a(e):e}function T(e){let t=i(e);return process.platform===`win32`?t.toLowerCase():t}function E(e){let t=new Map;for(let n of e){let e=w(n.uri);t.set(T(e),e)}return[...t.values()].sort((e,t)=>T(e).localeCompare(T(t)))}function D({config:e,roots:t}){let n=E(t);if(n.length===0)return null;let r=e.sources?.[0]?.path;if(r){let e=T(r),t=n.find(t=>T(t)===e);if(t)return t}return n[0]}function O({config:e,log:t,reconfigureForWorkspace:n,roots:r}){let i=E(r);if(i.length===0)return!1;let a=D({config:e,roots:i.map(e=>({uri:e}))});if(!a)return!1;let o=e.sources?.[0]?.path,s=o&&T(o)===T(a)?`configured-source`:`stable-sorted-root`;return t.debug(`MCP roots resolved`,{rootPath:a,rootCount:i.length,selectedBy:s}),n(e,a),e.allRoots=i,!0}async function k({config:e,indexMode:t,log:n,rootsChangedNotificationSchema:r,reconfigureForWorkspace:i,runInitialIndex:a,server:o,startInit:s,timeoutMs:c=5e3,getCwd:u=()=>process.cwd()}){let d=v(),f=!1,p=!1,m,h=o.server,g=e=>{let t=l(e),n=`${String(e)} ${String(t.message??``)}`.toLowerCase();return n.includes(`method not found`)||n.includes(`not supported`)||n.includes(`unsupported`)||n.includes(`unknown method`)||n.includes(`roots/list`)||n.includes(`timed out`)},_=()=>{f||(f=!0,s())},y=()=>{p||t!==`auto`||(p=!0,(async()=>{try{await a()}catch(e){n.error(`Initial index failed`,b(d,e))}})())},x=t=>t.length===0||(m&&=(clearTimeout(m),void 0),!O({config:e,log:n,reconfigureForWorkspace:i,roots:t}))?!1:(_(),y(),!0);try{if(x((await h.listRoots()).roots))return;n.debug(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(t){if(g(t)){n.warn(`MCP roots/list not supported by client; using cwd fallback`,{version:d,cwd:u(),...l(t)}),O({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:u()}]})&&(_(),y());return}n.warn(`MCP roots/list failed during bootstrap; waiting for roots/list_changed notification`,{version:d,cwd:u(),...l(t)})}h.setNotificationHandler(r,async()=>{try{x((await h.listRoots()).roots)}catch(e){n.warn(`roots/list retry failed after notification`,b(d,e))}}),m=setTimeout(()=>{let t=u();n.debug(`Timed out waiting for MCP roots/list_changed; falling back to cwd workspace`,{cwd:t}),O({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:t}]})&&(_(),y())},c)}function A(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function j(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===o(e).href}catch{return!1}}function M(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function N(e,t){let n=process.env[e];if(!n)return t;let r=Number.parseInt(n,10);return Number.isFinite(r)&&r>0?r:t}function P(){return j()?s({allowPositionals:!0,options:{transport:{type:`string`,default:A()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:A(),port:process.env.AIKIT_PORT??`3210`}}async function F(){let n=v(),r=P();process.on(`unhandledRejection`,e=>{y.error(`Unhandled rejection`,b(n,e))}),process.on(`uncaughtException`,e=>{y.error(`Uncaught exception — exiting`,b(n,e)),process.exit(1)});let i=(t,r)=>{t.then(async()=>{try{let{markPromoteRun:t,markPruneRun:n,prune:i,shouldRunStartupPrune:a,shouldRunWeeklyPromote:o}=await import(`../../tools/dist/index.js`),s=r();if(!s)return;if(a()){let e=await i({});n(),e.totalBytesFreed>0&&y.info(`Storage maintenance complete`,{forgeOrphans:e.forgeGroundOrphans.count,legacyLance:e.legacyLance.count,bytesFreed:e.totalBytesFreed});let{groupLessons:t,pruneLessons:r}=await import(`./evolution-BX_zTSdj.js`).then(e=>e.t),a=await r(s.curated,s.stateStore,{dryRun:!1});a.pruned.length>0&&y.info(`Startup lesson prune complete`,{pruned:a.pruned.length});let o=await t(s.curated,s.stateStore,{dryRun:!1});(o.groupsCreated>0||o.lessonsGrouped>0)&&y.info(`Startup lesson grouping complete`,{groupsCreated:o.groupsCreated,lessonsGrouped:o.lessonsGrouped})}if(o()){let{DEFAULT_PROMOTE_CONFIG:n,collectWorkspaceLessons:r,getGlobalCuratedDir:i,promoteLessons:a,scanForDuplicates:o}=await import(`./promotion-DmwIVl0c.js`).then(e=>e.o),c=s.curated,l=new e(i(),c.store,c.embedder),u=await r(),d={...n,dryRun:!1},f=await a(o(u,d),l,d);t(),f.promoted.length>0&&y.info(`Weekly lesson promotion complete`,{promoted:f.promoted.length,candidates:f.candidates.length})}}catch(e){y.warn(`Startup maintenance failed (non-critical)`,b(n,e))}}).catch(()=>{})};if(y.info(`Starting MCP AI Kit server`,{version:n}),r.transport===`http`){let[{default:e},{loadConfig:a,resolveIndexMode:o},{registerDashboardRoutes:s,resolveDashboardDir:c},{registerSettingsRoutes:d,resolveSettingsDir:f},{createSettingsRouter:p},{authMiddleware:m,getOrCreateToken:g}]=await Promise.all([import(`express`),import(`./config-_gMeJYrz.js`),import(`./dashboard-static-FmfoS46e.js`),import(`./settings-static-BtvyIrza.js`),import(`./routes-1wkXLxXe.js`),import(`./auth-Bz5dmZgR.js`).then(e=>e.t)]),v=a();u(v.logging?.errorDetails===!0),v.configError&&y.warn(`Config load failure`,{error:v.configError}),y.info(`Config loaded`,{sourceCount:v.sources.length,storePath:v.store.path});let x=e();x.use(e.json({limit:`1mb`}));let w=Number(r.port),T=`http://localhost:${w}`,E=process.env.AIKIT_CORS_ORIGIN??T,D=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,O=N(`AIKIT_HTTP_MAX_SESSIONS`,8),k=N(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),A=N(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),j=C({limit:100,windowMs:6e4}),P=!1;x.use((e,t,n)=>{let r=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,i=S({requestOrigin:r,configuredOrigin:E,allowAnyOrigin:D,fallbackOrigin:T});if(i.warn&&!P&&(P=!0,y.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:r,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),r&&!i.allowOrigin){t.status(403).json({error:`Origin not allowed`});return}if(i.allowOrigin&&t.setHeader(`Access-Control-Allow-Origin`,i.allowOrigin),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID`),t.setHeader(`Access-Control-Expose-Headers`,`Mcp-Session-Id`),e.method===`OPTIONS`){t.status(204).end();return}n()});let F=g();x.use(m(F)),x.use(`/mcp`,(e,t,n)=>{let r=M(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(j.allow(r)){n();return}let i=Math.max(1,Math.ceil(j.getRetryAfterMs(r)/1e3));t.setHeader(`Retry-After`,String(i)),t.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})});let I=!1;x.use(`/mcp`,(e,t,n)=>{if(!I){let t=e.headers[`x-workspace-root`];typeof t==`string`&&t.length>0&&(v.sources[0]={path:t,excludePatterns:v.sources[0]?.excludePatterns??[]},v.allRoots=[t],I=!0,y.debug(`Workspace root applied from proxy header`,{wsRoot:t}))}n()}),s(x,c(),y);let L=new Date().toISOString();x.use(`/settings/api`,p({log:y,mcpInfo:()=>({transport:`http`,port:w,pid:process.pid,startedAt:L})})),d(x,f(),y),x.get(`/health`,(e,t)=>{t.json({status:`ok`})});let R=!1,z=null,B=null,V=null,H=null,U=null,W=null,G=null,K=null,q=Promise.resolve(),J=async(e,n)=>{if(!R||!V||!H){n.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=q,i;q=new Promise(e=>{i=e}),await r;try{let r=M(e);if(!W){if(r){n.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new H({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{G=e,B?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&B?.onSessionEnd(e),G=null}});e.onclose=()=>{W===e&&(W=null),G===e.sessionId&&(G=null)},W=e,await V.connect(e)}let i=W;await i.handleRequest(e,n,e.body),e.method!==`DELETE`&&(!r&&i.sessionId?(G=i.sessionId,B?.onSessionStart(i.sessionId,{transport:`http`}),B?.onSessionActivity(i.sessionId)):r&&B?.onSessionActivity(r))}catch(e){if(y.error(`MCP handler error`,l(e)),!n.headersSent){let t=e instanceof Error?e.message:String(e),r=t.includes(`Not Acceptable`);n.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?t:`Internal server error`},id:null})}}finally{i()}},Y=async(e,t)=>{let n=M(e);if(U&&(!W||n!==G)){await U.handleRequest(e,t,e.body);return}await J(e,t)};x.post(`/mcp`,Y),x.get(`/mcp`,Y),x.delete(`/mcp`,Y);let X=x.listen(w,`127.0.0.1`,()=>{y.info(`MCP server listening`,{url:`http://127.0.0.1:${w}/mcp`,port:w}),setTimeout(async()=>{try{let[{createLazyServer:e,createMcpServer:t,ALL_TOOL_NAMES:r},{StreamableHTTPServerTransport:a},{checkForUpdates:s,autoUpgradeScaffold:c}]=await Promise.all([import(`./server-DmTxBqKe.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-yzdUDXHC.js`)]);s(),c(),setInterval(s,1440*60*1e3).unref();let u=o(v),d=e(v,u);K=async()=>{d.aikit&&await Promise.all([d.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),d.aikit.graphStore.close().catch(()=>{}),d.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),d.aikit.store.close().catch(()=>{})])},V=d.server,H=a,R=!0,y.debug(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:r.length,resourceCount:2}),d.startInit(),d.ready.then(()=>{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);B=new _(d.aikit.stateStore,{staleTimeoutMinutes:k,gcIntervalMinutes:A,onBeforeSessionDelete:e=>{if(G===e&&W){let e=W;W=null,G=null,e.close().catch(()=>void 0)}U?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!d.aikit?.curated||!d.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-BX_zTSdj.js`).then(e=>e.t),t=await e(d.aikit.curated,d.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&y.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),U=new h({createServer:()=>{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);return t(d.aikit,v)},createTransport:e=>new a(e),maxSessions:O,sessionTimeoutMinutes:k,onSessionStart:e=>B?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>B?.onSessionActivity(e),onSessionEnd:e=>B?.onSessionEnd(e)}),B.startGC(),G&&(B.onSessionStart(G,{transport:`http`}),B.onSessionActivity(G)),y.info(`HTTP session runtime ready`,{maxSessions:O,sessionTimeoutMinutes:k,gcIntervalMinutes:A})}).catch(e=>y.error(`Failed to start session manager`,l(e))),u===`auto`?d.ready.then(async()=>{try{let e=v.sources.map(e=>e.path).join(`, `);y.info(`Running initial index`,{sourcePaths:e}),await d.runInitialIndex(),y.info(`Initial index complete`)}catch(e){y.error(`Initial index failed; will retry on aikit_reindex`,b(n,e))}}).catch(e=>y.error(`AI Kit init or indexing failed`,b(n,e))):u===`smart`?d.ready.then(async()=>{try{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(d.aikit.indexer,v,d.aikit.store),n=d.aikit.store;z=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),d.setSmartScheduler(t),y.debug(`Smart index scheduler started (HTTP mode)`)}catch(e){y.error(`Failed to start smart index scheduler`,b(n,e))}}).catch(e=>y.error(`AI Kit initialization failed`,b(n,e))):(d.ready.catch(e=>y.error(`AI Kit initialization failed`,b(n,e))),y.info(`Initial full indexing skipped in HTTP mode`,{indexMode:u})),i(d.ready,()=>d.aikit?{curated:d.aikit.curated,stateStore:d.aikit.stateStore}:null)}catch(e){y.error(`Failed to load server modules`,b(n,e))}},100)}),Z=!1,Q=async e=>{Z||(Z=!0,y.info(`Shutdown signal received`,{signal:e}),z?.stop(),B?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await U?.closeAll().catch(()=>void 0),G&&B?.onSessionEnd(G),W&&(await W.close().catch(()=>void 0),W=null,G=null),X.close(),V&&await V.close(),await K?.().catch(()=>void 0),process.exit(0))};process.on(`SIGINT`,()=>Q(`SIGINT`)),process.on(`SIGTERM`,()=>Q(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:r},{createLazyServer:a},{checkForUpdates:o,autoUpgradeScaffold:s},{RootsListChangedNotificationSchema:c}]=await Promise.all([import(`./config-_gMeJYrz.js`),import(`./server-DmTxBqKe.js`),import(`./version-check-yzdUDXHC.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=e();u(l.logging?.errorDetails===!0),l.configError&&y.warn(`Config load failure`,{error:l.configError}),y.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),o(),s(),setInterval(o,1440*60*1e3).unref();let d=r(l),f=a(l,d),{server:p,startInit:m,ready:h,runInitialIndex:g}=f,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await p.connect(v),y.debug(`MCP server started`,{transport:`stdio`}),await k({config:l,indexMode:d,log:y,rootsChangedNotificationSchema:c,reconfigureForWorkspace:t,runInitialIndex:g,server:p,startInit:m});let x=null,S=null,C=!1,w=async e=>{C||(C=!0,y.info(`Shutdown signal received`,{signal:e}),x&&=(clearTimeout(x),null),S?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await v.close().catch(()=>void 0),await p.close().catch(()=>void 0),f.aikit&&await Promise.all([f.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),f.aikit.graphStore.close().catch(()=>{}),f.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),f.aikit.store.close().catch(()=>{})]),process.exit(0))},T=()=>{x&&clearTimeout(x),x=setTimeout(async()=>{y.info(`Auto-shutdown: no activity for 30 minutes — releasing resources`);try{let e=f.aikit;e&&(e.embedder.shutdown?.().catch(()=>{}),e.store.releaseMemory?.(),e.graphStore.releaseMemory?.())}catch{}},18e5),x.unref&&x.unref()};T(),process.stdin.on(`data`,()=>T()),process.stdin.on(`end`,()=>void w(`stdin-end`)),process.stdin.on(`close`,()=>void w(`stdin-close`)),process.stdin.on(`error`,()=>void w(`stdin-error`)),process.on(`SIGINT`,()=>void w(`SIGINT`)),process.on(`SIGTERM`,()=>void w(`SIGTERM`)),h.catch(e=>{y.error(`Initialization failed — server will continue with limited tools`,b(n,e))}),d===`smart`?h.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.aikit.indexer,l,f.aikit.store);S=t;let n=f.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),f.setSmartScheduler(t),y.debug(`Smart index scheduler started (stdio mode)`)}catch(e){y.error(`Failed to start smart index scheduler`,b(n,e))}}).catch(e=>y.error(`AI Kit init failed for smart scheduler`,b(n,e))):y.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:d}),i(h,()=>f.aikit?{curated:f.aikit.curated,stateStore:f.aikit.stateStore}:null)}}export{e as CuratedKnowledgeManager,O as applyWorkspaceRoots,k as bootstrapWorkspaceRoots,C as createSlidingWindowRateLimiter,F as main,S as resolveCorsOrigin,D as selectWorkspaceRoot};
|