@vpxa/aikit 0.1.139 → 0.1.141

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vpxa/aikit",
3
- "version": "0.1.139",
3
+ "version": "0.1.141",
4
4
  "type": "module",
5
5
  "description": "Local-first AI developer toolkit — knowledge base, code analysis, context management, and developer tools for LLM agents",
6
6
  "license": "MIT",
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{rm as e}from"node:fs/promises";import{homedir as t}from"node:os";import{join as n}from"node:path";import{EMBEDDING_DEFAULTS as r}from"../../core/dist/index.js";let i=null;async function a(){return i||(i=await import(`@huggingface/transformers`),i.env.cacheDir=n(t(),`.cache`,`huggingface`,`transformers-js`)),i}var o=class{pipe=null;shutdownPromise=null;dimensions;modelId;nativeDim;queryPrefix;threadConfig;constructor(e){if(this.modelId=e?.model??r.model,this.nativeDim=e?.nativeDim??1024,this.dimensions=e?.dimensions??r.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??this.detectQueryPrefix(this.modelId),this.threadConfig={interOp:e?.interOpNumThreads??1,intraOp:e?.intraOpNumThreads??4}}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}}}truncateAndRenorm(e){if(this.dimensions>=this.nativeDim)return e;let t=e.subarray(0,this.dimensions),n=0;for(let e=0;e<t.length;e++)n+=t[e]*t[e];if(n=Math.sqrt(n),n===0)return new Float32Array(this.dimensions);let r=new Float32Array(this.dimensions);for(let e=0;e<this.dimensions;e++)r[e]=t[e]/n;return r}detectQueryPrefix(e){let t=e.toLowerCase();return t.includes(`bge`)||t.includes(`mxbai-embed`)?`Represent this sentence for searching relevant passages: `:t.includes(`/e5-`)||t.includes(`multilingual-e5`)?`query: `:``}async initialize(){if(this.pipe)return;this.shutdownPromise=null;let{pipeline:r,env:i}=await a();try{this.pipe=await r(`feature-extraction`,this.modelId,this.getPipelineOptions(i))}catch(a){let o=a.message?.toLowerCase()??``;if(this.isCorruptionError(o)){let a=n(i.cacheDir??n(t(),`.cache`,`huggingface`,`transformers-js`),this.modelId);console.error(`[aikit:auto-heal] Detected corrupted model cache for "${this.modelId}". Clearing cache at ${a} and retrying download...`);try{await e(a,{recursive:!0,force:!0})}catch{}try{this.pipe=await r(`feature-extraction`,this.modelId,this.getPipelineOptions(i)),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}": ${a.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:`mean`,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:`mean`,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}};let s=null,c=null,l=!1;const u=Number(process.env.AIKIT_EMBED_IDLE_MS),d=Number.isFinite(u)&&u>=0?u:6e4,f=Number(process.env.AIKIT_EMBED_MAX_RSS_MB),p=Number.isFinite(f)&&f>0?f:1536;function m(){let e=process.memoryUsage;return(typeof e.rss==`function`?e.rss():e().rss)/(1024*1024)>p}function h(e){process.send?.(e)}function g(){c&&=(clearTimeout(c),null)}async function _(){if(!s)return;let e=s;s=null,await e.shutdown?.()}async function v(e,t){l&&process.exit(e),l=!0,g(),t?.notifyIdle&&h({type:`idle-exit`});try{await _()}finally{process.exit(e)}}function y(){g(),d!==0&&(c=setTimeout(()=>{v(0,{notifyIdle:!0})},d))}function b(e){return Array.from(e)}function x(e){return e instanceof Error?e.message:String(e)}function S(){if(!s)throw Error(`Embedder not initialized`);return s}async function C(e,t){h({type:`error`,id:e,message:x(t)})}async function w(e){g();try{switch(e.type){case`init`:await _(),s=new o(e.config),await s.initialize(),h({type:`ready`,dimensions:s.dimensions,modelId:s.modelId});break;case`embed`:{let t=await S().embed(e.text);h({type:`result`,id:e.id,data:b(t)});break}case`embedBatch`:{let t=await S().embedBatch(e.texts,e.batchSize);h({type:`batchResult`,id:e.id,data:t.map(e=>b(e))});break}case`embedQuery`:{let t=await S().embedQuery(e.text);h({type:`result`,id:e.id,data:b(t)});break}case`shutdown`:await v(0);return}}catch(t){if(await C(e.type===`shutdown`?`shutdown`:e.type===`init`?`init`:e.id,t),e.type===`init`){await v(1);return}}if(m()){await v(0,{notifyIdle:!0});return}y()}async function T(e,t){await C(e,t),await v(1)}process.on(`message`,e=>{w(e)}),process.on(`SIGTERM`,()=>{v(0)}),process.on(`uncaughtException`,e=>{T(`fatal`,e)}),process.on(`unhandledRejection`,e=>{T(`fatal`,e)});export{};
2
+ import{rm as e}from"node:fs/promises";import{homedir as t}from"node:os";import{join as n}from"node:path";import{EMBEDDING_DEFAULTS as r}from"../../core/dist/index.js";let i=null;async function a(){return i||(i=await import(`@huggingface/transformers`),i.env.cacheDir=n(t(),`.cache`,`huggingface`,`transformers-js`)),i}var o=class{pipe=null;shutdownPromise=null;dimensions;modelId;nativeDim;queryPrefix;threadConfig;constructor(e){if(this.modelId=e?.model??r.model,this.nativeDim=e?.nativeDim??1024,this.dimensions=e?.dimensions??r.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??this.detectQueryPrefix(this.modelId),this.threadConfig={interOp:e?.interOpNumThreads??1,intraOp:e?.intraOpNumThreads??4}}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}detectQueryPrefix(e){let t=e.toLowerCase();return t.includes(`bge`)||t.includes(`mxbai-embed`)?`Represent this sentence for searching relevant passages: `:t.includes(`/e5-`)||t.includes(`multilingual-e5`)?`query: `:``}async initialize(){if(this.pipe)return;this.shutdownPromise=null;let{pipeline:r,env:i}=await a();try{this.pipe=await r(`feature-extraction`,this.modelId,this.getPipelineOptions(i))}catch(a){let o=a.message?.toLowerCase()??``;if(this.isCorruptionError(o)){let a=n(i.cacheDir??n(t(),`.cache`,`huggingface`,`transformers-js`),this.modelId);console.error(`[aikit:auto-heal] Detected corrupted model cache for "${this.modelId}". Clearing cache at ${a} and retrying download...`);try{await e(a,{recursive:!0,force:!0})}catch{}try{this.pipe=await r(`feature-extraction`,this.modelId,this.getPipelineOptions(i)),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}": ${a.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:`mean`,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:`mean`,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}};let s=null,c=null,l=!1;const u=Number(process.env.AIKIT_EMBED_IDLE_MS),d=Number.isFinite(u)&&u>=0?u:6e4,f=Number(process.env.AIKIT_EMBED_MAX_RSS_MB),p=Number.isFinite(f)&&f>0?f:1536;function m(){let e=process.memoryUsage;return(typeof e.rss==`function`?e.rss():e().rss)/(1024*1024)>p}function h(e){process.send?.(e)}function g(){c&&=(clearTimeout(c),null)}async function _(){if(!s)return;let e=s;s=null,await e.shutdown?.()}async function v(e,t){l&&process.exit(e),l=!0,g(),t?.notifyIdle&&h({type:`idle-exit`});try{await _()}finally{process.exit(e)}}function y(){g(),d!==0&&(c=setTimeout(()=>{v(0,{notifyIdle:!0})},d))}function b(e){return Array.from(e)}function x(e){return e instanceof Error?e.message:String(e)}function S(){if(!s)throw Error(`Embedder not initialized`);return s}async function C(e,t){h({type:`error`,id:e,message:x(t)})}async function w(e){g();try{switch(e.type){case`init`:await _(),s=new o(e.config),await s.initialize(),h({type:`ready`,dimensions:s.dimensions,modelId:s.modelId});break;case`embed`:{let t=await S().embed(e.text);h({type:`result`,id:e.id,data:b(t)});break}case`embedBatch`:{let t=await S().embedBatch(e.texts,e.batchSize);h({type:`batchResult`,id:e.id,data:t.map(e=>b(e))});break}case`embedQuery`:{let t=await S().embedQuery(e.text);h({type:`result`,id:e.id,data:b(t)});break}case`shutdown`:await v(0);return}}catch(t){if(await C(e.type===`shutdown`?`shutdown`:e.type===`init`?`init`:e.id,t),e.type===`init`){await v(1);return}}if(m()){await v(0,{notifyIdle:!0});return}y()}async function T(e,t){await C(e,t),await v(1)}process.on(`message`,e=>{w(e)}),process.on(`SIGTERM`,()=>{v(0)}),process.on(`uncaughtException`,e=>{T(`fatal`,e)}),process.on(`unhandledRejection`,e=>{T(`fatal`,e)});export{};
@@ -104,6 +104,7 @@ declare class OnnxEmbedder implements IEmbedder {
104
104
  intraOpNumThreads?: number;
105
105
  });
106
106
  private getPipelineOptions;
107
+ private computeNorm;
107
108
  /**
108
109
  * Matryoshka truncation: slice to targetDim and re-normalize.
109
110
  * Only applied when targetDim < nativeDim.
@@ -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{EMBEDDING_DEFAULTS as o}from"../../core/dist/index.js";import{rm as s}from"node:fs/promises";import{homedir as c}from"node:os";var l=class{options;logger;maxRetries;retryBaseDelayMs;workerAvailable=!0;workerPath=i(r(a(import.meta.url)),`embedder-worker.js`);pendingRequests=new Map;childState=new WeakMap;child=null;readyChild=null;pendingInit=null;pendingShutdown=null;initializePromise=null;shutdownPromise=null;currentDimensions;currentModelId;constructor(e={}){this.options=e,this.logger=e.logger,this.maxRetries=Math.max(0,e.maxRetries??3),this.retryBaseDelayMs=Math.max(0,e.retryBaseDelayMs??500),this.currentDimensions=e.dimensions??o.dimensions,this.currentModelId=e.model??o.model}get dimensions(){return this.currentDimensions}get modelId(){return this.currentModelId}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||(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||(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||(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`)}return a}async shutdown(){if(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);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}return 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.child===e&&(this.readyChild=e);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),n.resolve(new Float32Array(t.data));return}case`batchResult`:{let n=this.pendingRequests.get(t.id);if(!n||n.child!==e)return;this.pendingRequests.delete(t.id),n.resolve(t.data.map(e=>new Float32Array(e)));return}case`error`:{let n=Error(t.message);if(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=r.shutdownRequested||r.idleExitNotified,a=Error(i?`Embedder worker exited before completing request`:`Embedder worker exited unexpectedly (code ${t??`null`}${n?`, signal ${n}`:``})`);this.rejectLifecycleIfOwned(`init`,e,a),i?this.resolveLifecycleIfOwned(`shutdown`,e):this.rejectLifecycleIfOwned(`shutdown`,e,a),this.rejectPendingForChild(e,a)}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=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`)}return i}async withWorkerExitRetry(e,t){let n=null;for(let r=0;r<=this.maxRetries;r++)try{return await t()}catch(t){let i=this.toError(t,`Failed to process ${e} request`);if(!this.isWorkerExitError(i))throw i;if(n??=i,r===this.maxRetries)throw n;let a=r+1,o=this.retryBaseDelayMs*2**r;this.logger?.warn?.(`Embedder retry ${a}/${this.maxRetries} after ${o}ms`,{requestType:e,delayMs:o,error:i.message}),this.child=null,this.readyChild=null,await this.wait(o)}throw n??Error(`Failed to process ${e} request`)}isWorkerExitError(e){return/embedder worker exited/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,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)}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 u=null;async function d(){return u||(u=await import(`@huggingface/transformers`),u.env.cacheDir=i(c(),`.cache`,`huggingface`,`transformers-js`)),u}var f=class{pipe=null;shutdownPromise=null;dimensions;modelId;nativeDim;queryPrefix;threadConfig;constructor(e){if(this.modelId=e?.model??o.model,this.nativeDim=e?.nativeDim??1024,this.dimensions=e?.dimensions??o.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??this.detectQueryPrefix(this.modelId),this.threadConfig={interOp:e?.interOpNumThreads??1,intraOp:e?.intraOpNumThreads??4}}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}}}truncateAndRenorm(e){if(this.dimensions>=this.nativeDim)return e;let t=e.subarray(0,this.dimensions),n=0;for(let e=0;e<t.length;e++)n+=t[e]*t[e];if(n=Math.sqrt(n),n===0)return new Float32Array(this.dimensions);let r=new Float32Array(this.dimensions);for(let e=0;e<this.dimensions;e++)r[e]=t[e]/n;return r}detectQueryPrefix(e){let t=e.toLowerCase();return t.includes(`bge`)||t.includes(`mxbai-embed`)?`Represent this sentence for searching relevant passages: `:t.includes(`/e5-`)||t.includes(`multilingual-e5`)?`query: `:``}async initialize(){if(this.pipe)return;this.shutdownPromise=null;let{pipeline:e,env:t}=await d();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(c(),`.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 s(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:`mean`,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:`mean`,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{l as EmbedderProxy,f 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{EMBEDDING_DEFAULTS as o}from"../../core/dist/index.js";import{rm as s}from"node:fs/promises";import{homedir as c}from"node:os";var l=class{options;logger;maxRetries;retryBaseDelayMs;workerAvailable=!0;workerPath=i(r(a(import.meta.url)),`embedder-worker.js`);pendingRequests=new Map;childState=new WeakMap;child=null;readyChild=null;pendingInit=null;pendingShutdown=null;initializePromise=null;shutdownPromise=null;currentDimensions;currentModelId;constructor(e={}){this.options=e,this.logger=e.logger,this.maxRetries=Math.max(0,e.maxRetries??3),this.retryBaseDelayMs=Math.max(0,e.retryBaseDelayMs??500),this.currentDimensions=e.dimensions??o.dimensions,this.currentModelId=e.model??o.model}get dimensions(){return this.currentDimensions}get modelId(){return this.currentModelId}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||(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||(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||(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`)}return a}async shutdown(){if(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);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}return 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.child===e&&(this.readyChild=e);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),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}`)):n.resolve(e)}return}case`error`:{let n=Error(t.message);if(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=r.shutdownRequested||r.idleExitNotified,a=Error(i?`Embedder worker exited before completing request`:`Embedder worker exited unexpectedly (code ${t??`null`}${n?`, signal ${n}`:``})`);this.rejectLifecycleIfOwned(`init`,e,a),i?this.resolveLifecycleIfOwned(`shutdown`,e):this.rejectLifecycleIfOwned(`shutdown`,e,a),this.rejectPendingForChild(e,a)}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=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`)}return i}async withWorkerExitRetry(e,t){let n=null;for(let r=0;r<=this.maxRetries;r++)try{return await t()}catch(t){let i=this.toError(t,`Failed to process ${e} request`);if(!this.isWorkerExitError(i))throw i;if(n??=i,r===this.maxRetries)throw n;let a=r+1,o=this.retryBaseDelayMs*2**r;this.logger?.warn?.(`Embedder retry ${a}/${this.maxRetries} after ${o}ms`,{requestType:e,delayMs:o,error:i.message}),this.child=null,this.readyChild=null,await this.wait(o)}throw n??Error(`Failed to process ${e} request`)}isWorkerExitError(e){return/embedder worker exited/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,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)}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 u=null;async function d(){return u||(u=await import(`@huggingface/transformers`),u.env.cacheDir=i(c(),`.cache`,`huggingface`,`transformers-js`)),u}var f=class{pipe=null;shutdownPromise=null;dimensions;modelId;nativeDim;queryPrefix;threadConfig;constructor(e){if(this.modelId=e?.model??o.model,this.nativeDim=e?.nativeDim??1024,this.dimensions=e?.dimensions??o.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??this.detectQueryPrefix(this.modelId),this.threadConfig={interOp:e?.interOpNumThreads??1,intraOp:e?.intraOpNumThreads??4}}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}detectQueryPrefix(e){let t=e.toLowerCase();return t.includes(`bge`)||t.includes(`mxbai-embed`)?`Represent this sentence for searching relevant passages: `:t.includes(`/e5-`)||t.includes(`multilingual-e5`)?`query: `:``}async initialize(){if(this.pipe)return;this.shutdownPromise=null;let{pipeline:e,env:t}=await d();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(c(),`.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 s(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:`mean`,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:`mean`,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{l as EmbedderProxy,f as OnnxEmbedder};
@@ -1,6 +1,6 @@
1
- import{copyFileSync as e,cpSync as t,existsSync as n,mkdirSync as r,readFileSync as i,readdirSync as a,rmSync as o,rmdirSync as s,symlinkSync as c,unlinkSync as l,writeFileSync as u}from"node:fs";import{basename as d,dirname as f,join as p,relative as m}from"node:path";import{parse as h}from"yaml";import{execSync as g,spawnSync as _}from"node:child_process";import{tmpdir as v}from"node:os";const y=[`spec`,`design`,`plan`,`task`,`execute`,`verify`];function b(e){let t=e.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);if(!t)return{data:{},body:e};let n=h(t[1]),r={};if(n&&typeof n==`object`&&!Array.isArray(n))for(let[e,t]of Object.entries(n))r[e]=String(t);return{data:r,body:t[2]}}function x(e){return e.split(/[-_]/g).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}function S(e){let t=y.indexOf(e);if(t!==-1)return t;let n=e.lastIndexOf(`.`);if(n!==-1){let t=e.slice(n+1),r=y.indexOf(t);if(r!==-1)return r}return 1/0}var C=class{format=`claude-plugin`;detect(e){return n(p(e,`.claude-plugin`,`plugin.json`))}async parse(e,t){let n=this.readPluginJson(e),r=this.discoverSteps(e);await this.materializeNativeSteps(e,r,t);let i=this.discoverAgents(e),a=r.map(({step:e})=>e);return{name:this.readString(n.name)??d(e),version:this.readString(n.version)??`1.0.0`,description:this.readString(n.description)??``,author:this.readString(n.author),steps:a,agents:i,artifacts_dir:`.spec`,install:[]}}readPluginJson(e){let t=p(e,`.claude-plugin`,`plugin.json`);return JSON.parse(i(t,`utf-8`))}readString(e){return typeof e==`string`?e:void 0}discoverSteps(e){let t=p(e,`skills`);if(!n(t))return[];let r=a(t,{withFileTypes:!0}).filter(e=>e.isDirectory()).map(e=>e.name).map(t=>this.readStep(e,t)).filter(e=>e!==null).sort((e,t)=>{let n=Number(e.metadata.order),r=Number(t.metadata.order),i=Number.isFinite(n),a=Number.isFinite(r);if(i&&a)return n-r;if(i)return-1;if(a)return 1;let o=S(e.step.id),s=S(t.step.id);return o===s?e.step.id.localeCompare(t.step.id):o-s});return r.map((e,t)=>({...e,step:{...e.step,requires:t>0?[r[t-1].step.id]:[]}}))}readStep(e,t){let r=p(e,`skills`,t,`SKILL.md`);if(!n(r))return null;let a=i(r,`utf-8`),{data:o,body:s}=b(a),c=o.name||x(t),l=o.description||`${c} step`;return{step:{id:t,name:c,instruction:`steps/${t}/README.md`,produces:[`${t}.md`],requires:[],agents:[],description:l},metadata:o,content:a,body:s}}syncStepAssets(e,r,i){let a=[`references`,`assets`,`scripts`];for(let s of r)for(let r of a){let a=p(e,`skills`,s.id,r),c=p(e,`steps`,s.id,r);if(n(a)){if(n(c)){if(!i)continue;o(c,{recursive:!0,force:!0})}t(a,c,{recursive:!0})}}}async materializeNativeSteps(e,t,n){for(let i of t){let t=p(e,`steps`,i.step.id);r(t,{recursive:!0});let a=n?.transform?await n.transform({content:i.content,sourceFormat:`claude-plugin`,stepName:i.step.id,metadata:i.metadata}):this.buildStepReadme(i.step.name,i.step.description,i.body);u(p(t,`README.md`),a,`utf-8`)}this.syncStepAssets(e,t.map(({step:e})=>e),n?.forceAssetSync)}buildStepReadme(e,t,n){return[`# ${e}`,``,t,``,`---`,``,n.trim()].join(`
1
+ import{copyFileSync as e,cpSync as t,existsSync as n,mkdirSync as r,readFileSync as i,readdirSync as a,renameSync as o,rmSync as s,rmdirSync as c,symlinkSync as l,unlinkSync as u,writeFileSync as d}from"node:fs";import{basename as f,dirname as p,join as m,relative as h}from"node:path";import{parse as g}from"yaml";import{execSync as _,spawnSync as v}from"node:child_process";import{tmpdir as y}from"node:os";const b=[`spec`,`design`,`plan`,`task`,`execute`,`verify`];function x(e){let t=e.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);if(!t)return{data:{},body:e};let n=g(t[1]),r={};if(n&&typeof n==`object`&&!Array.isArray(n))for(let[e,t]of Object.entries(n))r[e]=String(t);return{data:r,body:t[2]}}function S(e){return e.split(/[-_]/g).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}function C(e){let t=b.indexOf(e);if(t!==-1)return t;let n=e.lastIndexOf(`.`);if(n!==-1){let t=e.slice(n+1),r=b.indexOf(t);if(r!==-1)return r}return 1/0}var w=class{format=`claude-plugin`;detect(e){return n(m(e,`.claude-plugin`,`plugin.json`))}async parse(e,t){let n=this.readPluginJson(e),r=this.discoverSteps(e);await this.materializeNativeSteps(e,r,t);let i=this.discoverAgents(e),a=r.map(({step:e})=>e);return{name:this.readString(n.name)??f(e),version:this.readString(n.version)??`1.0.0`,description:this.readString(n.description)??``,author:this.readString(n.author),steps:a,agents:i,artifacts_dir:`.spec`,install:[]}}readPluginJson(e){let t=m(e,`.claude-plugin`,`plugin.json`);return JSON.parse(i(t,`utf-8`))}readString(e){return typeof e==`string`?e:void 0}discoverSteps(e){let t=m(e,`skills`);if(!n(t))return[];let r=a(t,{withFileTypes:!0}).filter(e=>e.isDirectory()).map(e=>e.name).map(t=>this.readStep(e,t)).filter(e=>e!==null).sort((e,t)=>{let n=Number(e.metadata.order),r=Number(t.metadata.order),i=Number.isFinite(n),a=Number.isFinite(r);if(i&&a)return n-r;if(i)return-1;if(a)return 1;let o=C(e.step.id),s=C(t.step.id);return o===s?e.step.id.localeCompare(t.step.id):o-s});return r.map((e,t)=>({...e,step:{...e.step,requires:t>0?[r[t-1].step.id]:[]}}))}readStep(e,t){let r=m(e,`skills`,t,`SKILL.md`);if(!n(r))return null;let a=i(r,`utf-8`),{data:o,body:s}=x(a),c=o.name||S(t),l=o.description||`${c} step`;return{step:{id:t,name:c,instruction:`steps/${t}/README.md`,produces:[`${t}.md`],requires:[],agents:[],description:l},metadata:o,content:a,body:s}}syncStepAssets(e,r,i){let a=[`references`,`assets`,`scripts`];for(let o of r)for(let r of a){let a=m(e,`skills`,o.id,r),c=m(e,`steps`,o.id,r);if(n(a)){if(n(c)){if(!i)continue;s(c,{recursive:!0,force:!0})}t(a,c,{recursive:!0})}}}async materializeNativeSteps(e,t,n){for(let i of t){let t=m(e,`steps`,i.step.id);r(t,{recursive:!0});let a=n?.transform?await n.transform({content:i.content,sourceFormat:`claude-plugin`,stepName:i.step.id,metadata:i.metadata}):this.buildStepReadme(i.step.name,i.step.description,i.body);d(m(t,`README.md`),a,`utf-8`)}this.syncStepAssets(e,t.map(({step:e})=>e),n?.forceAssetSync)}buildStepReadme(e,t,n){return[`# ${e}`,``,t,``,`---`,``,n.trim()].join(`
2
2
  `).trimEnd().concat(`
3
- `)}discoverAgents(e){let t=p(e,`agents`);return n(t)?a(t,{withFileTypes:!0}).filter(e=>e.isFile()&&e.name.endsWith(`.md`)).map(e=>`agents/${e.name}`):[]}},w=class{format=`copilot`;detect(e){return n(p(e,`.github`,`agents`))}async parse(e,t){let n=a(p(e,`.github`,`agents`),{withFileTypes:!0}).filter(e=>e.isFile()&&e.name.endsWith(`.md`)).map(e=>`.github/agents/${e.name}`),r=n.map(e=>this.getStepId(e)),i=n.map((e,t)=>{let n=r[t];return{id:n,name:n.charAt(0).toUpperCase()+n.slice(1),instruction:`steps/${n}/README.md`,produces:[`${n}.md`],requires:t>0?[r[t-1]]:[],agents:[e],description:`${n} agent step`}});return await this.materializeSteps(e,i,t),{name:d(e),version:`1.0.0`,description:`Copilot agents flow from ${d(e)}`,steps:i,agents:n,artifacts_dir:`.spec`,install:[]}}getStepId(e){return d(e,`.md`).toLowerCase().replace(/\.agent$/,``)}async materializeSteps(e,t,n){for(let a of t){let t=a.agents[0];if(!t)continue;let o=i(p(e,t),`utf-8`),s=p(e,`steps`,a.id),c=p(s,`README.md`);r(s,{recursive:!0}),u(c,n?.transform?await n.transform({content:o,sourceFormat:`copilot`,stepName:a.id,metadata:{sourcePath:t,displayName:a.name}}):`# ${a.name}\n\n${o}`,`utf-8`)}}},T=class{format=`native`;detect(e){return n(p(e,`flow.json`))}async parse(e){let t=i(p(e,`flow.json`),`utf-8`);return JSON.parse(t)}},E=class{format=`openspec`;detect(e){return!!(n(p(e,`openspec`,`config.yaml`))||n(p(e,`schemas`))&&this.findSchemaYaml(e))}async parse(e,t){let n=this.readMeta(e),r=this.loadSchema(e),i=this.buildStepsFromSchema(r);return await this.materializeSteps(e,i,r,t),{name:n.name,version:n.version,description:r.description??n.description,author:n.author,steps:i,agents:[],artifacts_dir:`openspec`,install:[]}}readMeta(e){let t=p(e,`package.json`);if(n(t))try{let n=JSON.parse(i(t,`utf-8`));return{name:n.name??d(e),version:n.version??`0.1.0`,description:n.description??`OpenSpec flow`,author:n.author}}catch{}return{name:d(e),version:`0.1.0`,description:`OpenSpec flow`}}readConfigSchema(e){let t=p(e,`openspec`,`config.yaml`);if(!n(t))return`spec-driven`;try{let e=h(i(t,`utf-8`));return typeof e?.schema==`string`&&e.schema.trim().length>0?e.schema:`spec-driven`}catch{return`spec-driven`}}resolveSchemaDir(e){let t=this.readConfigSchema(e),r=p(e,`openspec`,`schemas`,t);if(n(p(r,`schema.yaml`)))return r;let i=p(e,`schemas`,t);if(n(p(i,`schema.yaml`)))return i;try{let e=p(g(`npm root -g`,{encoding:`utf-8`,timeout:5e3,stdio:[`ignore`,`pipe`,`ignore`]}).trim(),`@fission-ai`,`openspec`,`schemas`,t);if(n(p(e,`schema.yaml`)))return e}catch{}return null}parseSchemaArtifacts(e){try{let t=h(e);if(!t||!Array.isArray(t.artifacts))return null;let n=t.artifacts.map(e=>this.normalizeArtifact(e)).filter(e=>e!==null);return n.length===0?null:{name:typeof t.name==`string`&&t.name.trim().length>0?t.name:this.readString(t.schema)??`spec-driven`,version:typeof t.version==`number`?t.version:1,description:this.readString(t.description),artifacts:n,apply:this.normalizeApply(t.apply)}}catch{return null}}loadSchema(e){let t=this.resolveSchemaDir(e);if(t){let e=p(t,`schema.yaml`);try{let t=i(e,`utf-8`),n=this.parseSchemaArtifacts(t);if(n)return n}catch{}}return this.discoverSchemaFromDirectory(e)}discoverSchemaFromDirectory(e){let t=[p(e,`openspec`,`schemas`),p(e,`schemas`)];for(let e of t)if(n(e))try{let t=a(e,{withFileTypes:!0}).filter(e=>e.isDirectory());for(let r of t){let t=p(e,r.name,`schema.yaml`);if(n(t))try{let e=this.parseSchemaArtifacts(i(t,`utf-8`));if(e)return e}catch{}}}catch{}let r=[],o=p(e,`openspec`),s=[],c=this.collectMarkdownFiles(o);for(let e of c){let t=m(o,e).replace(/\\/g,`/`),n=this.toStepIdFromMarkdown(t);!n||s.includes(n)||(r.push({id:n,generates:t,description:`${this.humanizeStepName(n)} phase`,template:d(e),requires:s.length>0?[s[s.length-1]]:[]}),s.push(n))}return{name:this.readConfigSchema(e),version:1,artifacts:r}}collectMarkdownFiles(e){if(!n(e))return[];let t=[];try{let n=a(e,{withFileTypes:!0}).sort((e,t)=>e.name.localeCompare(t.name));for(let r of n){let n=p(e,r.name);if(r.isFile()&&r.name.toLowerCase().endsWith(`.md`)){t.push(n);continue}r.isDirectory()&&t.push(...this.collectMarkdownFiles(n))}}catch{}return t}hasFileRecursive(e,t){if(!n(e))return!1;try{let n=a(e,{withFileTypes:!0});for(let r of n)if(r.isFile()&&r.name===t||r.isDirectory()&&this.hasFileRecursive(p(e,r.name),t))return!0}catch{}return!1}findSchemaYaml(e){let t=p(e,`schemas`);if(!n(t))return!1;try{return a(t,{withFileTypes:!0}).filter(e=>e.isDirectory()).some(e=>n(p(t,e.name,`schema.yaml`)))}catch{return!1}}toStepIdFromMarkdown(e){let t=e.replace(/\\/g,`/`).split(`/`).filter(Boolean);if(t.length===0)return null;let n=(t[t.length-1]??``).replace(/\.md$/i,``);return(n.toLowerCase()===`readme`&&t.length>1?t[t.length-2]:n).toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)||null}buildStepsFromSchema(e){let t=e.artifacts.map(e=>({id:e.id,name:this.humanizeStepName(e.id),instruction:`steps/${e.id}/README.md`,produces:e.generates?[e.generates]:[],requires:e.requires,agents:[],description:e.description}));return e.apply&&t.push({id:`apply`,name:`Apply`,instruction:`steps/apply/README.md`,produces:[],requires:e.apply.requires,agents:[],description:`Implement the tasks, writing code and tests according to the design`}),t}async materializeSteps(e,t,i,a){let o=this.resolveSchemaDir(e),s=new Map(i.artifacts.map(e=>[e.id,e]));for(let c of t){let t=p(e,`steps`,c.id),l=p(t,`README.md`);r(t,{recursive:!0});let d=this.resolveInstructionContent(o,c.id,s.get(c.id),i.apply);if(!d){n(l)||u(l,`# ${c.name}\n\n${c.description}\n`,`utf-8`);continue}u(l,a?.transform?await a.transform({content:d,sourceFormat:`openspec`,stepName:c.id,metadata:{schemaName:i.name,displayName:c.name,description:c.description,produces:c.produces,requires:c.requires}}):`# ${c.name}\n\n${d}`,`utf-8`)}}resolveInstructionContent(e,t,r,a){if(t===`apply`&&a?.instruction)return a.instruction;if(!r)return null;if(r.instruction)return r.instruction;if(e&&r.template){let t=p(e,`templates`,r.template);if(n(t))try{return i(t,`utf-8`)}catch{}}return r.description||null}normalizeArtifact(e){if(!e||typeof e!=`object`)return null;let t=e,n=this.readString(t.id),r=this.readString(t.generates);return!n||!r?null:{id:n,generates:r,description:this.readString(t.description)??`${this.humanizeStepName(n)} phase`,template:this.readString(t.template)??``,instruction:this.readString(t.instruction),requires:this.readStringArray(t.requires)}}normalizeApply(e){if(!e||typeof e!=`object`)return;let t=e;return{requires:this.readStringArray(t.requires),tracks:this.readString(t.tracks)??null,instruction:this.readString(t.instruction)}}readString(e){return typeof e==`string`&&e.trim().length>0?e:void 0}readStringArray(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`&&e.length>0):[]}humanizeStepName(e){return e.split(/[-_]/g).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}};const D={name:`aikit:basic`,version:`0.1.0`,description:`Quick development flow for bug fixes, small features, and refactoring`,steps:[{id:`design`,name:`Design Gate`,instruction:`steps/design/README.md`,produces:[`design-decisions.md`],requires:[],agents:[`Researcher-Alpha`,`Researcher-Beta`,`Researcher-Gamma`,`Researcher-Delta`],description:`Evaluate task type, run brainstorming for features, FORGE classification. Auto-skips for bug fixes and refactors.`},{id:`assess`,name:`Assessment`,instruction:`steps/assess/README.md`,produces:[`assessment.md`],requires:[`design-decisions.md`],agents:[`Explorer`,`Researcher-Alpha`],description:`Understand scope, analyze codebase, identify approach`},{id:`implement`,name:`Implementation`,instruction:`steps/implement/README.md`,produces:[`progress.md`],requires:[`assessment.md`],agents:[`Implementer`,`Frontend`],description:`Write code following the assessment plan`},{id:`verify`,name:`Verification`,instruction:`steps/verify/README.md`,produces:[`verify-report.md`],requires:[`progress.md`],agents:[`Code-Reviewer-Alpha`,`Security`],description:`Review code, run tests, validate changes`}],agents:[],artifacts_dir:`.spec`,install:[]},O={name:`aikit:advanced`,version:`0.1.0`,description:`Full development flow for new features, API design, and architecture changes`,steps:[{id:`design`,name:`Design Gate`,instruction:`steps/design/README.md`,produces:[`design-decisions.md`],requires:[],agents:[`Researcher-Alpha`,`Researcher-Beta`,`Researcher-Gamma`,`Researcher-Delta`],description:`Full brainstorming, FORGE classification, decision protocol with parallel research. ADR for critical-tier tasks.`},{id:`spec`,name:`Specification`,instruction:`steps/spec/README.md`,produces:[`spec.md`],requires:[`design-decisions.md`],agents:[`Researcher-Alpha`],description:`Elicit requirements, clarify scope, define acceptance criteria`},{id:`plan`,name:`Planning`,instruction:`steps/plan/README.md`,produces:[`plan.md`],requires:[`spec.md`],agents:[`Planner`,`Explorer`],description:`Analyze codebase, design architecture, create implementation plan`},{id:`task`,name:`Task Breakdown`,instruction:`steps/task/README.md`,produces:[`tasks.md`],requires:[`plan.md`],agents:[`Planner`,`Architect-Reviewer-Alpha`],description:`Break plan into ordered implementation tasks with dependencies`},{id:`execute`,name:`Execution`,instruction:`steps/execute/README.md`,produces:[`progress.md`],requires:[`tasks.md`],agents:[`Orchestrator`,`Implementer`,`Frontend`,`Refactor`],description:`Implement all tasks, write code, write tests`},{id:`verify`,name:`Verification`,instruction:`steps/verify/README.md`,produces:[`verify-report.md`],requires:[`progress.md`],agents:[`Code-Reviewer-Alpha`,`Code-Reviewer-Beta`,`Architect-Reviewer-Alpha`,`Architect-Reviewer-Beta`,`Security`],description:`Dual code review, architecture review, security review, test validation`}],agents:[],artifacts_dir:`.spec`,install:[]};function k(){return[{manifest:D,scaffoldDir:`scaffold/_preview/flows/aikit-basic`},{manifest:O,scaffoldDir:`scaffold/_preview/flows/aikit-advanced`}]}const A=`<!-- aikit foundation context -->`,j=`<!-- end foundation context -->`;function M(e){let t=e.artifacts_dir||`.spec`;return`${A}
3
+ `)}discoverAgents(e){let t=m(e,`agents`);return n(t)?a(t,{withFileTypes:!0}).filter(e=>e.isFile()&&e.name.endsWith(`.md`)).map(e=>`agents/${e.name}`):[]}},T=class{format=`copilot`;detect(e){return n(m(e,`.github`,`agents`))}async parse(e,t){let n=a(m(e,`.github`,`agents`),{withFileTypes:!0}).filter(e=>e.isFile()&&e.name.endsWith(`.md`)).map(e=>`.github/agents/${e.name}`),r=n.map(e=>this.getStepId(e)),i=n.map((e,t)=>{let n=r[t];return{id:n,name:n.charAt(0).toUpperCase()+n.slice(1),instruction:`steps/${n}/README.md`,produces:[`${n}.md`],requires:t>0?[r[t-1]]:[],agents:[e],description:`${n} agent step`}});return await this.materializeSteps(e,i,t),{name:f(e),version:`1.0.0`,description:`Copilot agents flow from ${f(e)}`,steps:i,agents:n,artifacts_dir:`.spec`,install:[]}}getStepId(e){return f(e,`.md`).toLowerCase().replace(/\.agent$/,``)}async materializeSteps(e,t,n){for(let a of t){let t=a.agents[0];if(!t)continue;let o=i(m(e,t),`utf-8`),s=m(e,`steps`,a.id),c=m(s,`README.md`);r(s,{recursive:!0}),d(c,n?.transform?await n.transform({content:o,sourceFormat:`copilot`,stepName:a.id,metadata:{sourcePath:t,displayName:a.name}}):`# ${a.name}\n\n${o}`,`utf-8`)}}},E=class{format=`native`;detect(e){return n(m(e,`flow.json`))}async parse(e){let t=i(m(e,`flow.json`),`utf-8`);return JSON.parse(t)}},D=class{format=`openspec`;detect(e){return!!(n(m(e,`openspec`,`config.yaml`))||n(m(e,`schemas`))&&this.findSchemaYaml(e))}async parse(e,t){let n=this.readMeta(e),r=this.loadSchema(e),i=this.buildStepsFromSchema(r);return await this.materializeSteps(e,i,r,t),{name:n.name,version:n.version,description:r.description??n.description,author:n.author,steps:i,agents:[],artifacts_dir:`openspec`,install:[]}}readMeta(e){let t=m(e,`package.json`);if(n(t))try{let n=JSON.parse(i(t,`utf-8`));return{name:n.name??f(e),version:n.version??`0.1.0`,description:n.description??`OpenSpec flow`,author:n.author}}catch{}return{name:f(e),version:`0.1.0`,description:`OpenSpec flow`}}readConfigSchema(e){let t=m(e,`openspec`,`config.yaml`);if(!n(t))return`spec-driven`;try{let e=g(i(t,`utf-8`));return typeof e?.schema==`string`&&e.schema.trim().length>0?e.schema:`spec-driven`}catch{return`spec-driven`}}resolveSchemaDir(e){let t=this.readConfigSchema(e),r=m(e,`openspec`,`schemas`,t);if(n(m(r,`schema.yaml`)))return r;let i=m(e,`schemas`,t);if(n(m(i,`schema.yaml`)))return i;try{let e=m(_(`npm root -g`,{encoding:`utf-8`,timeout:5e3,stdio:[`ignore`,`pipe`,`ignore`]}).trim(),`@fission-ai`,`openspec`,`schemas`,t);if(n(m(e,`schema.yaml`)))return e}catch{}return null}parseSchemaArtifacts(e){try{let t=g(e);if(!t||!Array.isArray(t.artifacts))return null;let n=t.artifacts.map(e=>this.normalizeArtifact(e)).filter(e=>e!==null);return n.length===0?null:{name:typeof t.name==`string`&&t.name.trim().length>0?t.name:this.readString(t.schema)??`spec-driven`,version:typeof t.version==`number`?t.version:1,description:this.readString(t.description),artifacts:n,apply:this.normalizeApply(t.apply)}}catch{return null}}loadSchema(e){let t=this.resolveSchemaDir(e);if(t){let e=m(t,`schema.yaml`);try{let t=i(e,`utf-8`),n=this.parseSchemaArtifacts(t);if(n)return n}catch{}}return this.discoverSchemaFromDirectory(e)}discoverSchemaFromDirectory(e){let t=[m(e,`openspec`,`schemas`),m(e,`schemas`)];for(let e of t)if(n(e))try{let t=a(e,{withFileTypes:!0}).filter(e=>e.isDirectory());for(let r of t){let t=m(e,r.name,`schema.yaml`);if(n(t))try{let e=this.parseSchemaArtifacts(i(t,`utf-8`));if(e)return e}catch{}}}catch{}let r=[],o=m(e,`openspec`),s=[],c=this.collectMarkdownFiles(o);for(let e of c){let t=h(o,e).replace(/\\/g,`/`),n=this.toStepIdFromMarkdown(t);!n||s.includes(n)||(r.push({id:n,generates:t,description:`${this.humanizeStepName(n)} phase`,template:f(e),requires:s.length>0?[s[s.length-1]]:[]}),s.push(n))}return{name:this.readConfigSchema(e),version:1,artifacts:r}}collectMarkdownFiles(e){if(!n(e))return[];let t=[];try{let n=a(e,{withFileTypes:!0}).sort((e,t)=>e.name.localeCompare(t.name));for(let r of n){let n=m(e,r.name);if(r.isFile()&&r.name.toLowerCase().endsWith(`.md`)){t.push(n);continue}r.isDirectory()&&t.push(...this.collectMarkdownFiles(n))}}catch{}return t}hasFileRecursive(e,t){if(!n(e))return!1;try{let n=a(e,{withFileTypes:!0});for(let r of n)if(r.isFile()&&r.name===t||r.isDirectory()&&this.hasFileRecursive(m(e,r.name),t))return!0}catch{}return!1}findSchemaYaml(e){let t=m(e,`schemas`);if(!n(t))return!1;try{return a(t,{withFileTypes:!0}).filter(e=>e.isDirectory()).some(e=>n(m(t,e.name,`schema.yaml`)))}catch{return!1}}toStepIdFromMarkdown(e){let t=e.replace(/\\/g,`/`).split(`/`).filter(Boolean);if(t.length===0)return null;let n=(t[t.length-1]??``).replace(/\.md$/i,``);return(n.toLowerCase()===`readme`&&t.length>1?t[t.length-2]:n).toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)||null}buildStepsFromSchema(e){let t=e.artifacts.map(e=>({id:e.id,name:this.humanizeStepName(e.id),instruction:`steps/${e.id}/README.md`,produces:e.generates?[e.generates]:[],requires:e.requires,agents:[],description:e.description}));return e.apply&&t.push({id:`apply`,name:`Apply`,instruction:`steps/apply/README.md`,produces:[],requires:e.apply.requires,agents:[],description:`Implement the tasks, writing code and tests according to the design`}),t}async materializeSteps(e,t,i,a){let o=this.resolveSchemaDir(e),s=new Map(i.artifacts.map(e=>[e.id,e]));for(let c of t){let t=m(e,`steps`,c.id),l=m(t,`README.md`);r(t,{recursive:!0});let u=this.resolveInstructionContent(o,c.id,s.get(c.id),i.apply);if(!u){n(l)||d(l,`# ${c.name}\n\n${c.description}\n`,`utf-8`);continue}d(l,a?.transform?await a.transform({content:u,sourceFormat:`openspec`,stepName:c.id,metadata:{schemaName:i.name,displayName:c.name,description:c.description,produces:c.produces,requires:c.requires}}):`# ${c.name}\n\n${u}`,`utf-8`)}}resolveInstructionContent(e,t,r,a){if(t===`apply`&&a?.instruction)return a.instruction;if(!r)return null;if(r.instruction)return r.instruction;if(e&&r.template){let t=m(e,`templates`,r.template);if(n(t))try{return i(t,`utf-8`)}catch{}}return r.description||null}normalizeArtifact(e){if(!e||typeof e!=`object`)return null;let t=e,n=this.readString(t.id),r=this.readString(t.generates);return!n||!r?null:{id:n,generates:r,description:this.readString(t.description)??`${this.humanizeStepName(n)} phase`,template:this.readString(t.template)??``,instruction:this.readString(t.instruction),requires:this.readStringArray(t.requires)}}normalizeApply(e){if(!e||typeof e!=`object`)return;let t=e;return{requires:this.readStringArray(t.requires),tracks:this.readString(t.tracks)??null,instruction:this.readString(t.instruction)}}readString(e){return typeof e==`string`&&e.trim().length>0?e:void 0}readStringArray(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`&&e.length>0):[]}humanizeStepName(e){return e.split(/[-_]/g).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}};const O={name:`aikit:basic`,version:`0.1.0`,description:`Quick development flow for bug fixes, small features, and refactoring`,steps:[{id:`design`,name:`Design Gate`,instruction:`steps/design/README.md`,produces:[`design-decisions.md`],requires:[],agents:[`Researcher-Alpha`,`Researcher-Beta`,`Researcher-Gamma`,`Researcher-Delta`],description:`Evaluate task type, run brainstorming for features, FORGE classification. Auto-skips for bug fixes and refactors.`},{id:`assess`,name:`Assessment`,instruction:`steps/assess/README.md`,produces:[`assessment.md`],requires:[`design-decisions.md`],agents:[`Explorer`,`Researcher-Alpha`],description:`Understand scope, analyze codebase, identify approach`},{id:`implement`,name:`Implementation`,instruction:`steps/implement/README.md`,produces:[`progress.md`],requires:[`assessment.md`],agents:[`Implementer`,`Frontend`],description:`Write code following the assessment plan`},{id:`verify`,name:`Verification`,instruction:`steps/verify/README.md`,produces:[`verify-report.md`],requires:[`progress.md`],agents:[`Code-Reviewer-Alpha`,`Security`],description:`Review code, run tests, validate changes`}],agents:[],artifacts_dir:`.spec`,install:[]},k={name:`aikit:advanced`,version:`0.1.0`,description:`Full development flow for new features, API design, and architecture changes`,steps:[{id:`design`,name:`Design Gate`,instruction:`steps/design/README.md`,produces:[`design-decisions.md`],requires:[],agents:[`Researcher-Alpha`,`Researcher-Beta`,`Researcher-Gamma`,`Researcher-Delta`],description:`Full brainstorming, FORGE classification, decision protocol with parallel research. ADR for critical-tier tasks.`},{id:`spec`,name:`Specification`,instruction:`steps/spec/README.md`,produces:[`spec.md`],requires:[`design-decisions.md`],agents:[`Researcher-Alpha`],description:`Elicit requirements, clarify scope, define acceptance criteria`},{id:`plan`,name:`Planning`,instruction:`steps/plan/README.md`,produces:[`plan.md`],requires:[`spec.md`],agents:[`Planner`,`Explorer`],description:`Analyze codebase, design architecture, create implementation plan`},{id:`task`,name:`Task Breakdown`,instruction:`steps/task/README.md`,produces:[`tasks.md`],requires:[`plan.md`],agents:[`Planner`,`Architect-Reviewer-Alpha`],description:`Break plan into ordered implementation tasks with dependencies`},{id:`execute`,name:`Execution`,instruction:`steps/execute/README.md`,produces:[`progress.md`],requires:[`tasks.md`],agents:[`Orchestrator`,`Implementer`,`Frontend`,`Refactor`],description:`Implement all tasks, write code, write tests`},{id:`verify`,name:`Verification`,instruction:`steps/verify/README.md`,produces:[`verify-report.md`],requires:[`progress.md`],agents:[`Code-Reviewer-Alpha`,`Code-Reviewer-Beta`,`Architect-Reviewer-Alpha`,`Architect-Reviewer-Beta`,`Security`],description:`Dual code review, architecture review, security review, test validation`}],agents:[],artifacts_dir:`.spec`,install:[]};function A(){return[{manifest:O,scaffoldDir:`scaffold/_preview/flows/aikit-basic`},{manifest:k,scaffoldDir:`scaffold/_preview/flows/aikit-advanced`}]}const j=`<!-- aikit foundation context -->`,M=`<!-- end foundation context -->`;function N(e){let t=e.artifacts_dir||`.spec`;return`${j}
4
4
  You are operating within the @vpxa/aikit framework.
5
5
  - Use aikit MCP tools for all search, analysis, and memory operations
6
6
  - Follow agents defined in AGENTS.md for delegation
@@ -8,8 +8,8 @@ You are operating within the @vpxa/aikit framework.
8
8
  - Track state via the unified flow tool (for example: flow with action "status" or "step")
9
9
  - Active flow: ${e.name} v${e.version}
10
10
  - Artifacts go in: .flows/{topic-slug}/${t}/ (resolved at runtime via flow action "start")
11
- ${j}`}var N=class{injectPreamble(e,t){let r=M(t);if(!n(e)){u(e,`${r}\n`,`utf-8`);return}let a=i(e,`utf-8`),o=a.indexOf(A),s=a.indexOf(j);if(o!==-1&&s!==-1){u(e,`${a.slice(0,o)}${r}${a.slice(s+31)}`,`utf-8`);return}u(e,`${r}\n\n${a}`,`utf-8`)}removePreamble(e){if(!n(e))return;let t=i(e,`utf-8`),r=t.indexOf(A),a=t.indexOf(j);r===-1||a===-1||u(e,(t.slice(0,r)+t.slice(a+31)).replace(/^\n+/,``).replace(/\n{3,}/g,`
11
+ ${M}`}var P=class{injectPreamble(e,t){let r=N(t);if(!n(e)){d(e,`${r}\n`,`utf-8`);return}let a=i(e,`utf-8`),o=a.indexOf(j),s=a.indexOf(M);if(o!==-1&&s!==-1){d(e,`${a.slice(0,o)}${r}${a.slice(s+31)}`,`utf-8`);return}d(e,`${r}\n\n${a}`,`utf-8`)}removePreamble(e){if(!n(e))return;let t=i(e,`utf-8`),r=t.indexOf(j),a=t.indexOf(M);r===-1||a===-1||d(e,(t.slice(0,r)+t.slice(a+31)).replace(/^\n+/,``).replace(/\n{3,}/g,`
12
12
 
13
- `),`utf-8`)}getTargetFiles(e){let t=[],r=p(e,`.github`,`copilot-instructions.md`);n(r)&&t.push(r);let i=p(e,`CLAUDE.md`);n(i)&&t.push(i);let a=p(e,`AGENTS.md`);return n(a)&&t.push(a),t}};function P(e){if(!e||typeof e!=`object`||!(`stderr`in e))return``;let t=e.stderr;return Buffer.isBuffer(t)?t.toString().trim():typeof t==`string`?t.trim():``}function F(e){try{return new URL(e).hostname}catch{}return e.match(/^[^@]+@([^:]+):/)?.[1]??`<host>`}function I(e,t,n){let r=[`Git operation failed for: ${e}`],i=F(e),a=t.includes(`ETIMEDOUT`)||t.includes(`SIGTERM`)||t.toLowerCase().includes(`timed out`),o=n.includes(`Authentication failed`)||n.includes(`could not read Username`)||n.includes(`terminal prompts disabled`)||n.includes(`401`)||n.includes(`403`)||n.includes(`Permission denied`),s=n.includes(`SSL certificate`)||n.includes(`unable to access`)&&n.includes(`SSL`),c=n.includes(`Could not resolve host`)||n.includes(`Name or service not known`),l=n.includes(`SAML`)||n.includes(`single sign-on`);return o||l?(r.push(``),r.push(`Cause: Authentication required or credentials not configured.`),r.push(``),r.push(`To fix this, ensure git can access this repository:`),r.push(``),r.push(` Option 1 - SSH key:`),r.push(` 1. Generate an SSH key: ssh-keygen -t ed25519`),r.push(` 2. Add the public key to your Git hosting account`),r.push(` 3. Use the SSH URL instead: git@<host>:<org>/<repo>.git`),r.push(``),r.push(` Option 2 - Personal Access Token (PAT):`),r.push(` 1. Create a PAT in your Git hosting Settings > Developer settings > Tokens`),r.push(` 2. For GitHub Enterprise with SAML SSO, authorize the token for your org`),r.push(` 3. Configure git credentials:`),r.push(` git config --global credential.helper store`),r.push(` git clone ${e} (enter PAT as password)`),r.push(``),r.push(` Option 3 - Git Credential Manager:`),r.push(` 1. Install: https://github.com/git-ecosystem/git-credential-manager`),r.push(` 2. Run: git clone ${e}`),r.push(` 3. Follow the browser-based auth prompt`),r.push(``),r.push(`After configuring credentials, retry: aikit flow add ${e}`)):a?(r.push(``),r.push(`Cause: Connection timed out - the server did not respond within 60 seconds.`),r.push(``),r.push(`Possible reasons:`),r.push(` - The repository requires VPN access. Ensure your VPN is connected`),r.push(` - The host is behind a firewall or corporate proxy`),r.push(` - The URL may be incorrect`),r.push(``),r.push(`Diagnostics:`),r.push(` 1. Verify the URL is correct: ${e}`),r.push(` 2. Test connectivity: git ls-remote ${e}`),r.push(` 3. If behind a proxy, configure git:`),r.push(` git config --global http.proxy http://proxy:port`),r.push(``),r.push(`If this is a corporate/internal host, you may need to:`),r.push(` - Connect to the corporate VPN`),r.push(` - Add the host to your SSH config or git config`),r.push(` - Ask your IT team to allowlist your machine`),r.push(``),r.push(`After resolving, retry: aikit flow add ${e}`)):s?(r.push(``),r.push(`Cause: SSL/TLS certificate verification failed.`),r.push(``),r.push(`This often happens with corporate proxies or self-signed certificates.`),r.push(``),r.push(`To fix:`),r.push(` 1. If your company uses a custom CA, add it:`),r.push(` git config --global http.sslCAInfo /path/to/ca-bundle.crt`),r.push(` 2. As a last resort (not recommended for production):`),r.push(` git config --global http.sslVerify false`),r.push(``),r.push(`After resolving, retry: aikit flow add ${e}`)):c?(r.push(``),r.push(`Cause: Cannot resolve hostname.`),r.push(``),r.push(`Check:`),r.push(` 1. Is the URL correct? ${e}`),r.push(` 2. Are you connected to the internet/VPN?`),r.push(` 3. Can you resolve the host? ping ${i}`),r.push(``),r.push(`After resolving, retry: aikit flow add ${e}`)):(r.push(``),r.push(`Error: ${t}`),n&&r.push(`Details: ${n}`),r.push(``),r.push(`Troubleshooting:`),r.push(` 1. Verify the URL is a valid git repository: git ls-remote ${e}`),r.push(` 2. Check your git credentials and network connectivity`),r.push(` 3. If the repo requires auth, configure credentials first (PAT or SSH key)`),r.push(``),r.push(`After resolving, retry: aikit flow add ${e}`)),r.join(`
14
- `)}function L(){try{return _(`git`,[`credential-manager`,`--version`],{stdio:`pipe`,timeout:5e3}).status===0}catch{return!1}}function R(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`authentication failed`)||n.includes(`could not read username`)||n.includes(`saml sso`)||n.includes(`terminal prompts disabled`)||n.includes(`host key verification failed`)||n.includes(`permission denied`)||n.includes(`403`)||n.includes(`401`)}var z=class{flowsDir;constructor(e){this.flowsDir=e}clone(e,t){let r=this.repoNameFromUrl(e),i=p(this.flowsDir,r);if(n(i))if(!n(p(i,`.git`)))o(i,{recursive:!0,force:!0});else return{success:!1,error:`Flow "${r}" already installed at ${i}. Use update instead.`};try{if(this.ensureFlowsDir(),t){let n=process.platform===`win32`?`bat`:`sh`,r=p(v(),`git-askpass-${Date.now()}.${n}`);process.platform===`win32`?u(r,`@echo ${t}`,{mode:448}):u(r,`#!/bin/sh\necho "${t}"`,{mode:448});try{let t=_(`git`,[`clone`,`--depth`,`1`,e,i],{stdio:`pipe`,timeout:6e4,env:{...process.env,GIT_TERMINAL_PROMPT:`0`,GIT_ASKPASS:r}});if(t.status!==0){let e=t.stderr?.toString().trim()??``;throw Error(e||t.error?.message||`git clone failed`)}}finally{try{l(r)}catch{}}}else{let t=_(`git`,[`clone`,`--depth`,`1`,e,i],{stdio:`pipe`,timeout:6e4,env:{...process.env,GIT_TERMINAL_PROMPT:`0`,GIT_ASKPASS:``}});if(t.status!==0){let e=t.stderr?.toString().trim()??``;throw Error(e||t.error?.message||`git clone failed`)}}return{success:!0,data:i}}catch(r){n(i)&&o(i,{recursive:!0,force:!0});let a=P(r),s=r instanceof Error?r.message:String(r);if(!t&&R(s,a)&&L()){let t=F(e)||e;console.log(`\nAuthentication required for ${t}.\nGit Credential Manager detected - opening browser for login...\n(If a browser window does not open, check your terminal for a device code.)\n`);try{if(this.ensureFlowsDir(),_(`git`,[`clone`,`--depth`,`1`,e,i],{stdio:`inherit`,timeout:12e4,env:{...process.env,GIT_TERMINAL_PROMPT:`1`}}).status===0)return{success:!0,data:i};n(i)&&o(i,{recursive:!0,force:!0})}catch{n(i)&&o(i,{recursive:!0,force:!0})}}return{success:!1,error:I(e,s,a)}}}update(e){if(!n(e))return{success:!1,error:`Install path not found: ${e}`};try{return g(`git pull --ff-only`,{cwd:e,stdio:`pipe`,timeout:6e4,env:{...process.env,GIT_TERMINAL_PROMPT:`0`,GIT_ASKPASS:``}}),{success:!0}}catch(t){let n=e;try{n=g(`git remote get-url origin`,{cwd:e,stdio:`pipe`,timeout:1e4}).toString().trim()}catch{}let r=P(t),i=t instanceof Error?t.message:String(t);if(R(i,r)&&L()){let t=F(n)||n;console.log(`\nAuthentication required for ${t}.\nGit Credential Manager detected - opening browser for login...\n`);try{if(_(`git`,[`pull`,`--ff-only`],{cwd:e,stdio:`inherit`,timeout:12e4,env:{...process.env,GIT_TERMINAL_PROMPT:`1`}}).status===0)return{success:!0}}catch{}}return{success:!1,error:I(n,i,r)}}}copyLocal(e,r){let i=p(this.flowsDir,r);if(n(i))return{success:!1,error:`Flow "${r}" already installed at ${i}`};try{return this.ensureFlowsDir(),t(e,i,{recursive:!0}),{success:!0,data:i}}catch(e){return{success:!1,error:`Copy failed: ${e instanceof Error?e.message:String(e)}`}}}remove(e){if(!n(e))return{success:!0};try{return o(e,{recursive:!0,force:!0}),{success:!0}}catch(e){return{success:!1,error:`Remove failed: ${e instanceof Error?e.message:String(e)}`}}}runInstallDeps(e){for(let t of e)try{if(t.startsWith(`npm:`)){g(`npx skills add ${t.slice(4)} -g`,{stdio:`pipe`,timeout:12e4});continue}if(t.endsWith(`.git`)||t.includes(`github.com`)){g(`npx skills add ${t} -g`,{stdio:`pipe`,timeout:12e4});continue}return{success:!1,error:`Unknown install entry format: ${t}`}}catch(e){return{success:!1,error:`Install dependency failed for "${t}": ${e instanceof Error?e.message:String(e)}`}}return{success:!0}}getLocalCommit(e){try{return g(`git rev-parse HEAD`,{cwd:e,stdio:`pipe`,timeout:1e4,env:{...process.env,GIT_TERMINAL_PROMPT:`0`}}).toString().trim()||null}catch{return null}}getRemoteCommit(e){try{return g(`git ls-remote origin HEAD`,{cwd:e,stdio:`pipe`,timeout:3e4,env:{...process.env,GIT_TERMINAL_PROMPT:`0`}}).toString().trim().split(/\s+/)[0]||null}catch{return null}}hasUpdates(e){let t=this.getLocalCommit(e);if(!t)return{success:!1,error:`Could not determine local commit (not a git repo?)`};let n=this.getRemoteCommit(e);return n?{success:!0,data:{localCommit:t,remoteCommit:n,hasUpdates:t!==n}}:{success:!1,error:`Could not reach remote to check for updates`}}repoNameFromUrl(e){return d(e).replace(/\.git$/,``)}ensureFlowsDir(){n(this.flowsDir)||r(this.flowsDir,{recursive:!0})}};const B=[new T,new C,new w,new E];function V(e){let t=B.find(t=>t.format===e);if(!t)throw Error(`No adapter for format: ${e}`);return t}function H(e){for(let t of B)if(t.detect(e))return t;return null}var U=class{async load(e,t){if(!n(e))return{success:!1,error:`Source directory not found: ${e}`};let r=H(e);if(!r)return{success:!1,error:`No format adapter matches source: ${e}`};try{let n=await r.parse(e,t),i=this.validate(n);return i.success?{success:!0,data:{manifest:n,format:r.format}}:i}catch(e){return{success:!1,error:`Failed to parse flow: ${e instanceof Error?e.message:String(e)}`}}}async loadWithFormat(e,t,n){let r=V(t);try{let t=await r.parse(e,n),i=this.validate(t);return i.success?{success:!0,data:t}:i}catch(e){return{success:!1,error:`Failed to parse flow: ${e instanceof Error?e.message:String(e)}`}}}validate(e){let t=[];e.name?.trim()||t.push(`Missing flow name`),e.version?.trim()||t.push(`Missing flow version`),e.steps?.length||t.push(`Flow must have at least one step`);let n=new Set(e.steps.map(e=>e.id));for(let r of e.steps??[]){r.id?.trim()||t.push(`Step missing id`),r.instruction?.trim()||t.push(`Step "${r.id}" missing instruction path`);for(let e of r.requires??[])n.has(e)||t.push(`Step "${r.id}" requires unknown step "${e}"`)}return n.size!==(e.steps?.length??0)&&t.push(`Duplicate step IDs found`),t.length>0?{success:!1,error:`Validation failed:\n${t.join(`
15
- `)}`}:{success:!0}}};function W(){return k().map(e=>({name:e.manifest.name,version:e.manifest.version,source:`builtin`,sourceType:`builtin`,installPath:e.scaffoldDir,format:`native`,registeredAt:`1970-01-01T00:00:00.000Z`,updatedAt:`1970-01-01T00:00:00.000Z`,manifest:e.manifest}))}var G=class{registryPath;constructor(e){this.registryPath=e}load(){if(!n(this.registryPath))return{version:1,flows:{}};try{let e=i(this.registryPath,`utf-8`);return JSON.parse(e)}catch{return{version:1,flows:{}}}}save(e){let t=f(this.registryPath);n(t)||r(t,{recursive:!0}),u(this.registryPath,JSON.stringify(e,null,2),`utf-8`)}register(e){let t=this.load();return t.flows[e.name]=e,this.save(t),{success:!0}}unregister(e){let t=this.load();return t.flows[e]?(delete t.flows[e],this.save(t),{success:!0}):{success:!1,error:`Flow "${e}" not found in registry`}}get(e){return this.load().flows[e]||(W().find(t=>t.name===e)??null)}list(){let e=this.load(),t=new Set(Object.keys(e.flows)),n=Object.values(e.flows);for(let e of W())t.has(e.name)||n.push(e);return n}has(e){return e in this.load().flows?!0:W().some(t=>t.name===e)}},K=class{flowsDir;epilogueConfig;constructor(e,t={before:[],after:[]}){this.flowsDir=e,this.epilogueConfig=t}slugify(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``)||`flow`}generateSlug(e){let t=this.slugify(e);if(!n(p(this.flowsDir,t)))return t;for(let e=2;e<=100;e+=1){let r=`${t}-${e}`;if(!n(p(this.flowsDir,r)))return r}throw Error(`Unable to allocate a flow run slug for topic "${e}"`)}getMetaPath(e){return p(this.flowsDir,e,`meta.json`)}buildStepSequence(e){return[...this.epilogueConfig.before.map(e=>({id:e.id,phase:`before`})),...e.steps.map(e=>({id:e.id,phase:`flow`})),...this.epilogueConfig.after.map(e=>({id:e.id,phase:`after`}))]}readMeta(e){let t=this.getMetaPath(e);if(!n(t))return null;try{let e=i(t,`utf-8`);return JSON.parse(e)}catch{return null}}writeMeta(e,t){let i=p(this.flowsDir,e);n(i)||r(i,{recursive:!0}),u(this.getMetaPath(e),JSON.stringify(t,null,2),`utf-8`)}normalizeMeta(e){let t=e;return t.completedTokens??=[],t.executionLog??=[],t}hasCompletedExecution(e,t){return e.executionLog.some(n=>n.stepId===t&&e.completedTokens.includes(n.token))}markCrashedExecution(e){let t=e.currentToken;if(!(!t||e.completedTokens.includes(t)))for(let n=e.executionLog.length-1;n>=0;--n){let r=e.executionLog[n];if(r.token===t&&r.outcome===`in-progress`){r.outcome=`crashed`;break}}}finalizeCurrentStep(e,t,n){let r=e.currentToken;if(r){e.completedTokens.includes(r)||e.completedTokens.push(r);for(let i=e.executionLog.length-1;i>=0;--i){let a=e.executionLog[i];if(a.token===r){a.completedAt=n,a.outcome=t;break}}}e.currentToken=void 0}activateStep(e,t,n,r){let i=n;for(;i<t.length;){let n=t[i];if(e.currentStep=n.id,e.phase=n.phase,r?.force||!this.hasCompletedExecution(e,n.id)){this.markCrashedExecution(e);let t=Date.now(),r=new Date(t).toISOString(),i=`${n.id}-${t}`;e.currentToken=i,e.executionLog.push({stepId:n.id,token:i,startedAt:r,outcome:`in-progress`});return}n.phase===`flow`?e.completedSteps.includes(n.id)||e.completedSteps.push(n.id):e.completedEpilogueSteps.includes(n.id)||e.completedEpilogueSteps.push(n.id),i+=1}e.currentStep=null,e.currentToken=void 0,e.status=`completed`,e.phase=`after`}findActiveRun(){if(!n(this.flowsDir))return null;for(let e of a(this.flowsDir,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=this.readMeta(e.name);if(t?.status===`active`)return{slug:e.name,meta:t}}return null}metaToState(e,t){let n=this.normalizeMeta(t),r=n.phase??`flow`;return{flow:n.flow,status:n.status,currentStep:n.currentStep,currentToken:n.currentToken,completedSteps:n.completedSteps,completedTokens:n.completedTokens,skippedSteps:n.skippedSteps,executionLog:n.executionLog,artifacts:n.artifacts,startedAt:n.startedAt,updatedAt:n.updatedAt,slug:e,runDir:p(this.flowsDir,e),topic:n.topic,phase:r,isEpilogue:r!==`flow`,roots:n.roots,primaryRoot:n.primaryRoot}}start(e,t,n){let i=this.findActiveRun();if(i)return{success:!1,error:`Flow "${i.meta.flow}" is already active. Reset it first.`};let a=this.buildStepSequence(t);if(!a.length)return{success:!1,error:`Flow has no steps`};try{let i=(n??t.description)||e,o=this.generateSlug(i),s=p(this.flowsDir,o),c=new Date().toISOString(),l=a[0],u={id:o,flow:e,flowVersion:t.version,topic:i,status:`active`,currentStep:l.id,currentToken:void 0,completedSteps:[],completedTokens:[],skippedSteps:[],executionLog:[],artifactsDir:t.artifacts_dir,artifacts:{},startedAt:c,updatedAt:c,phase:l.phase,completedEpilogueSteps:[],skippedEpilogueSteps:[]};return this.activateStep(u,a,0),r(s,{recursive:!0}),r(p(s,t.artifacts_dir),{recursive:!0}),this.writeMeta(o,u),{success:!0,data:this.metaToState(o,u)}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}step(e,t){let r=this.findActiveRun();if(!r)return{success:!1,error:`No active flow`};if(r.meta.status!==`active`)return{success:!1,error:`Flow is ${r.meta.status}, not active`};if(!r.meta.currentStep)return{success:!1,error:`No current step`};let i=r.meta.currentStep,a=this.buildStepSequence(t),o=a.findIndex(e=>e.id===i);if(o===-1)return{success:!1,error:`Current step "${r.meta.currentStep}" not found in manifest`};let s=a[o],c=new Date().toISOString(),l=this.normalizeMeta(r.meta);switch(e){case`next`:if(s.phase===`flow`){let e=t.steps.find(e=>e.id===i);if(e&&e.produces.length>0){let a=p(p(this.flowsDir,r.slug),t.artifacts_dir),o=e.produces.filter(e=>!n(p(a,e)));if(o.length>0)return{success:!1,error:`Step "${i}" cannot advance — missing required artifacts in ${t.artifacts_dir}/: ${o.join(`, `)}. Create these files before advancing.`}}}s.phase===`flow`?l.completedSteps.includes(i)||l.completedSteps.push(i):l.completedEpilogueSteps.includes(i)||l.completedEpilogueSteps.push(i),this.finalizeCurrentStep(l,`completed`,c),this.activateStep(l,a,o+1);break;case`skip`:s.phase===`flow`?l.skippedSteps.includes(i)||l.skippedSteps.push(i):l.skippedEpilogueSteps.includes(i)||l.skippedEpilogueSteps.push(i),this.finalizeCurrentStep(l,`skipped`,c),this.activateStep(l,a,o+1);break;case`redo`:this.markCrashedExecution(l),s.phase===`flow`?(l.completedSteps=l.completedSteps.filter(e=>e!==i),l.skippedSteps=l.skippedSteps.filter(e=>e!==i)):(l.completedEpilogueSteps=l.completedEpilogueSteps.filter(e=>e!==i),l.skippedEpilogueSteps=l.skippedEpilogueSteps.filter(e=>e!==i)),l.currentToken=void 0,this.activateStep(l,a,o,{force:!0});break}return l.updatedAt=c,this.writeMeta(r.slug,l),{success:!0,data:this.metaToState(r.slug,l)}}getStatus(){let e=this.findActiveRun();return e?{success:!0,data:this.metaToState(e.slug,e.meta)}:{success:!1,error:`No active flow`}}reset(){let e=this.findActiveRun();return e?(e.meta.status=`abandoned`,e.meta.currentStep=null,e.meta.updatedAt=new Date().toISOString(),this.writeMeta(e.slug,e.meta),{success:!0}):{success:!0}}recordArtifact(e,t){let n=this.findActiveRun();return n?(n.meta.artifacts[e]=t,n.meta.updatedAt=new Date().toISOString(),this.writeMeta(n.slug,n.meta),{success:!0}):{success:!1,error:`No active flow`}}listRuns(e){if(!n(this.flowsDir))return[];let t=[];for(let n of a(this.flowsDir,{withFileTypes:!0})){if(!n.isDirectory())continue;let r=this.readMeta(n.name);r&&(e?.flow&&r.flow!==e.flow||e?.status&&r.status!==e.status||t.push({id:n.name,flow:r.flow,topic:r.topic,status:r.status,currentStep:r.currentStep,startedAt:r.startedAt,updatedAt:r.updatedAt}))}return t.sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))}},q=class{createSymlinks(t,i,a,o){let s=this.getTargets(t,i);for(let t of s){n(t.baseDir)||r(t.baseDir,{recursive:!0});for(let r of o.agents){let i=p(a,r);if(!n(i))continue;let o=this.getAgentStem(r),s=p(t.baseDir,`${o}${t.extension}`);n(s)&&l(s);let u=m(f(s),i);try{c(u,s,`file`)}catch{try{e(i,s)}catch(e){console.warn(`Failed to create symlink or copy fallback for ${i}: ${e instanceof Error?e.message:String(e)}`)}}}}}removeSymlinks(e,t){let r=this.getTargets(e,t);for(let e of r)if(n(e.baseDir))try{let t=a(e.baseDir,{withFileTypes:!0});for(let n of t)!n.isFile()&&!n.isSymbolicLink()||l(p(e.baseDir,n.name));a(e.baseDir).length===0&&s(e.baseDir)}catch{}}getTargets(e,t){return[{ide:`copilot`,baseDir:p(e,`.github`,`agents`,`flows`,t),extension:`.agent.md`},{ide:`claude-code`,baseDir:p(e,`.claude`,`agents`,`flows`,t),extension:`.md`}]}getAgentStem(e){return d(e).replace(/\.agent\.md$/,``).replace(/\.md$/,``)}};export{C as ClaudePluginAdapter,w as CopilotAdapter,U as FlowLoader,G as FlowRegistryManager,K as FlowStateMachine,N as FoundationIntegration,z as GitInstaller,T as NativeAdapter,E as OpenSpecAdapter,q as SymlinkManager,k as getBuiltinFlows};
13
+ `),`utf-8`)}getTargetFiles(e){let t=[],r=m(e,`.github`,`copilot-instructions.md`);n(r)&&t.push(r);let i=m(e,`CLAUDE.md`);n(i)&&t.push(i);let a=m(e,`AGENTS.md`);return n(a)&&t.push(a),t}};function F(e){if(!e||typeof e!=`object`||!(`stderr`in e))return``;let t=e.stderr;return Buffer.isBuffer(t)?t.toString().trim():typeof t==`string`?t.trim():``}function I(e){try{return new URL(e).hostname}catch{}return e.match(/^[^@]+@([^:]+):/)?.[1]??`<host>`}function L(e,t,n){let r=[`Git operation failed for: ${e}`],i=I(e),a=t.includes(`ETIMEDOUT`)||t.includes(`SIGTERM`)||t.toLowerCase().includes(`timed out`),o=n.includes(`Authentication failed`)||n.includes(`could not read Username`)||n.includes(`terminal prompts disabled`)||n.includes(`401`)||n.includes(`403`)||n.includes(`Permission denied`),s=n.includes(`SSL certificate`)||n.includes(`unable to access`)&&n.includes(`SSL`),c=n.includes(`Could not resolve host`)||n.includes(`Name or service not known`),l=n.includes(`SAML`)||n.includes(`single sign-on`);return o||l?(r.push(``),r.push(`Cause: Authentication required or credentials not configured.`),r.push(``),r.push(`To fix this, ensure git can access this repository:`),r.push(``),r.push(` Option 1 - SSH key:`),r.push(` 1. Generate an SSH key: ssh-keygen -t ed25519`),r.push(` 2. Add the public key to your Git hosting account`),r.push(` 3. Use the SSH URL instead: git@<host>:<org>/<repo>.git`),r.push(``),r.push(` Option 2 - Personal Access Token (PAT):`),r.push(` 1. Create a PAT in your Git hosting Settings > Developer settings > Tokens`),r.push(` 2. For GitHub Enterprise with SAML SSO, authorize the token for your org`),r.push(` 3. Configure git credentials:`),r.push(` git config --global credential.helper store`),r.push(` git clone ${e} (enter PAT as password)`),r.push(``),r.push(` Option 3 - Git Credential Manager:`),r.push(` 1. Install: https://github.com/git-ecosystem/git-credential-manager`),r.push(` 2. Run: git clone ${e}`),r.push(` 3. Follow the browser-based auth prompt`),r.push(``),r.push(`After configuring credentials, retry: aikit flow add ${e}`)):a?(r.push(``),r.push(`Cause: Connection timed out - the server did not respond within 60 seconds.`),r.push(``),r.push(`Possible reasons:`),r.push(` - The repository requires VPN access. Ensure your VPN is connected`),r.push(` - The host is behind a firewall or corporate proxy`),r.push(` - The URL may be incorrect`),r.push(``),r.push(`Diagnostics:`),r.push(` 1. Verify the URL is correct: ${e}`),r.push(` 2. Test connectivity: git ls-remote ${e}`),r.push(` 3. If behind a proxy, configure git:`),r.push(` git config --global http.proxy http://proxy:port`),r.push(``),r.push(`If this is a corporate/internal host, you may need to:`),r.push(` - Connect to the corporate VPN`),r.push(` - Add the host to your SSH config or git config`),r.push(` - Ask your IT team to allowlist your machine`),r.push(``),r.push(`After resolving, retry: aikit flow add ${e}`)):s?(r.push(``),r.push(`Cause: SSL/TLS certificate verification failed.`),r.push(``),r.push(`This often happens with corporate proxies or self-signed certificates.`),r.push(``),r.push(`To fix:`),r.push(` 1. If your company uses a custom CA, add it:`),r.push(` git config --global http.sslCAInfo /path/to/ca-bundle.crt`),r.push(` 2. As a last resort (not recommended for production):`),r.push(` git config --global http.sslVerify false`),r.push(``),r.push(`After resolving, retry: aikit flow add ${e}`)):c?(r.push(``),r.push(`Cause: Cannot resolve hostname.`),r.push(``),r.push(`Check:`),r.push(` 1. Is the URL correct? ${e}`),r.push(` 2. Are you connected to the internet/VPN?`),r.push(` 3. Can you resolve the host? ping ${i}`),r.push(``),r.push(`After resolving, retry: aikit flow add ${e}`)):(r.push(``),r.push(`Error: ${t}`),n&&r.push(`Details: ${n}`),r.push(``),r.push(`Troubleshooting:`),r.push(` 1. Verify the URL is a valid git repository: git ls-remote ${e}`),r.push(` 2. Check your git credentials and network connectivity`),r.push(` 3. If the repo requires auth, configure credentials first (PAT or SSH key)`),r.push(``),r.push(`After resolving, retry: aikit flow add ${e}`)),r.join(`
14
+ `)}function R(){try{return v(`git`,[`credential-manager`,`--version`],{stdio:`pipe`,timeout:5e3}).status===0}catch{return!1}}function z(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`authentication failed`)||n.includes(`could not read username`)||n.includes(`saml sso`)||n.includes(`terminal prompts disabled`)||n.includes(`host key verification failed`)||n.includes(`permission denied`)||n.includes(`403`)||n.includes(`401`)}var B=class{flowsDir;constructor(e){this.flowsDir=e}clone(e,t){let r=this.repoNameFromUrl(e),i=m(this.flowsDir,r);if(n(i))if(!n(m(i,`.git`)))s(i,{recursive:!0,force:!0});else return{success:!1,error:`Flow "${r}" already installed at ${i}. Use update instead.`};try{if(this.ensureFlowsDir(),t){let n=process.platform===`win32`?`bat`:`sh`,r=m(y(),`git-askpass-${Date.now()}.${n}`);process.platform===`win32`?d(r,`@echo ${t}`,{mode:448}):d(r,`#!/bin/sh\necho "${t}"`,{mode:448});try{let t=v(`git`,[`clone`,`--depth`,`1`,e,i],{stdio:`pipe`,timeout:6e4,env:{...process.env,GIT_TERMINAL_PROMPT:`0`,GIT_ASKPASS:r}});if(t.status!==0){let e=t.stderr?.toString().trim()??``;throw Error(e||t.error?.message||`git clone failed`)}}finally{try{u(r)}catch{}}}else{let t=v(`git`,[`clone`,`--depth`,`1`,e,i],{stdio:`pipe`,timeout:6e4,env:{...process.env,GIT_TERMINAL_PROMPT:`0`,GIT_ASKPASS:``}});if(t.status!==0){let e=t.stderr?.toString().trim()??``;throw Error(e||t.error?.message||`git clone failed`)}}return{success:!0,data:i}}catch(r){n(i)&&s(i,{recursive:!0,force:!0});let a=F(r),o=r instanceof Error?r.message:String(r);if(!t&&z(o,a)&&R()){let t=I(e)||e;console.log(`\nAuthentication required for ${t}.\nGit Credential Manager detected - opening browser for login...\n(If a browser window does not open, check your terminal for a device code.)\n`);try{if(this.ensureFlowsDir(),v(`git`,[`clone`,`--depth`,`1`,e,i],{stdio:`inherit`,timeout:12e4,env:{...process.env,GIT_TERMINAL_PROMPT:`1`}}).status===0)return{success:!0,data:i};n(i)&&s(i,{recursive:!0,force:!0})}catch{n(i)&&s(i,{recursive:!0,force:!0})}}return{success:!1,error:L(e,o,a)}}}update(e){if(!n(e))return{success:!1,error:`Install path not found: ${e}`};try{return _(`git pull --ff-only`,{cwd:e,stdio:`pipe`,timeout:6e4,env:{...process.env,GIT_TERMINAL_PROMPT:`0`,GIT_ASKPASS:``}}),{success:!0}}catch(t){let n=e;try{n=_(`git remote get-url origin`,{cwd:e,stdio:`pipe`,timeout:1e4}).toString().trim()}catch{}let r=F(t),i=t instanceof Error?t.message:String(t);if(z(i,r)&&R()){let t=I(n)||n;console.log(`\nAuthentication required for ${t}.\nGit Credential Manager detected - opening browser for login...\n`);try{if(v(`git`,[`pull`,`--ff-only`],{cwd:e,stdio:`inherit`,timeout:12e4,env:{...process.env,GIT_TERMINAL_PROMPT:`1`}}).status===0)return{success:!0}}catch{}}return{success:!1,error:L(n,i,r)}}}copyLocal(e,r){let i=m(this.flowsDir,r);if(n(i))return{success:!1,error:`Flow "${r}" already installed at ${i}`};try{return this.ensureFlowsDir(),t(e,i,{recursive:!0}),{success:!0,data:i}}catch(e){return{success:!1,error:`Copy failed: ${e instanceof Error?e.message:String(e)}`}}}remove(e){if(!n(e))return{success:!0};try{return s(e,{recursive:!0,force:!0}),{success:!0}}catch(e){return{success:!1,error:`Remove failed: ${e instanceof Error?e.message:String(e)}`}}}runInstallDeps(e){for(let t of e)try{if(t.startsWith(`npm:`)){_(`npx skills add ${t.slice(4)} -g`,{stdio:`pipe`,timeout:12e4});continue}if(t.endsWith(`.git`)||t.includes(`github.com`)){_(`npx skills add ${t} -g`,{stdio:`pipe`,timeout:12e4});continue}return{success:!1,error:`Unknown install entry format: ${t}`}}catch(e){return{success:!1,error:`Install dependency failed for "${t}": ${e instanceof Error?e.message:String(e)}`}}return{success:!0}}getLocalCommit(e){try{return _(`git rev-parse HEAD`,{cwd:e,stdio:`pipe`,timeout:1e4,env:{...process.env,GIT_TERMINAL_PROMPT:`0`}}).toString().trim()||null}catch{return null}}getRemoteCommit(e){try{return _(`git ls-remote origin HEAD`,{cwd:e,stdio:`pipe`,timeout:3e4,env:{...process.env,GIT_TERMINAL_PROMPT:`0`}}).toString().trim().split(/\s+/)[0]||null}catch{return null}}hasUpdates(e){let t=this.getLocalCommit(e);if(!t)return{success:!1,error:`Could not determine local commit (not a git repo?)`};let n=this.getRemoteCommit(e);return n?{success:!0,data:{localCommit:t,remoteCommit:n,hasUpdates:t!==n}}:{success:!1,error:`Could not reach remote to check for updates`}}repoNameFromUrl(e){return f(e).replace(/\.git$/,``)}ensureFlowsDir(){n(this.flowsDir)||r(this.flowsDir,{recursive:!0})}};const V=[new E,new w,new T,new D];function H(e){let t=V.find(t=>t.format===e);if(!t)throw Error(`No adapter for format: ${e}`);return t}function U(e){for(let t of V)if(t.detect(e))return t;return null}var W=class{async load(e,t){if(!n(e))return{success:!1,error:`Source directory not found: ${e}`};let r=U(e);if(!r)return{success:!1,error:`No format adapter matches source: ${e}`};try{let n=await r.parse(e,t),i=this.validate(n);return i.success?{success:!0,data:{manifest:n,format:r.format}}:i}catch(e){return{success:!1,error:`Failed to parse flow: ${e instanceof Error?e.message:String(e)}`}}}async loadWithFormat(e,t,n){let r=H(t);try{let t=await r.parse(e,n),i=this.validate(t);return i.success?{success:!0,data:t}:i}catch(e){return{success:!1,error:`Failed to parse flow: ${e instanceof Error?e.message:String(e)}`}}}validate(e){let t=[];e.name?.trim()||t.push(`Missing flow name`),e.version?.trim()||t.push(`Missing flow version`),e.steps?.length||t.push(`Flow must have at least one step`);let n=new Set(e.steps.map(e=>e.id));for(let r of e.steps??[]){r.id?.trim()||t.push(`Step missing id`),r.instruction?.trim()||t.push(`Step "${r.id}" missing instruction path`);for(let e of r.requires??[])n.has(e)||t.push(`Step "${r.id}" requires unknown step "${e}"`)}return n.size!==(e.steps?.length??0)&&t.push(`Duplicate step IDs found`),t.length>0?{success:!1,error:`Validation failed:\n${t.join(`
15
+ `)}`}:{success:!0}}};function G(){return A().map(e=>({name:e.manifest.name,version:e.manifest.version,source:`builtin`,sourceType:`builtin`,installPath:e.scaffoldDir,format:`native`,registeredAt:`1970-01-01T00:00:00.000Z`,updatedAt:`1970-01-01T00:00:00.000Z`,manifest:e.manifest}))}var K=class{registryPath;constructor(e){this.registryPath=e}load(){if(!n(this.registryPath))return{version:1,flows:{}};try{let e=i(this.registryPath,`utf-8`);return JSON.parse(e)}catch{return{version:1,flows:{}}}}save(e){let t=p(this.registryPath);n(t)||r(t,{recursive:!0}),d(this.registryPath,JSON.stringify(e,null,2),`utf-8`)}register(e){let t=this.load();return t.flows[e.name]=e,this.save(t),{success:!0}}unregister(e){let t=this.load();return t.flows[e]?(delete t.flows[e],this.save(t),{success:!0}):{success:!1,error:`Flow "${e}" not found in registry`}}get(e){return this.load().flows[e]||(G().find(t=>t.name===e)??null)}list(){let e=this.load(),t=new Set(Object.keys(e.flows)),n=Object.values(e.flows);for(let e of G())t.has(e.name)||n.push(e);return n}has(e){return e in this.load().flows?!0:G().some(t=>t.name===e)}},q=class{flowsDir;epilogueConfig;constructor(e,t={before:[],after:[]}){this.flowsDir=e,this.epilogueConfig=t}slugify(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``)||`flow`}generateSlug(e){let t=this.slugify(e);if(!n(m(this.flowsDir,t)))return t;for(let e=2;e<=100;e+=1){let r=`${t}-${e}`;if(!n(m(this.flowsDir,r)))return r}throw Error(`Unable to allocate a flow run slug for topic "${e}"`)}getMetaPath(e){return m(this.flowsDir,e,`meta.json`)}buildStepSequence(e){return[...this.epilogueConfig.before.map(e=>({id:e.id,phase:`before`})),...e.steps.map(e=>({id:e.id,phase:`flow`})),...this.epilogueConfig.after.map(e=>({id:e.id,phase:`after`}))]}readMeta(e){let t=this.getMetaPath(e);if(!n(t))return null;try{let e=i(t,`utf-8`);return JSON.parse(e)}catch{return null}}writeMeta(e,t){let i=m(this.flowsDir,e);n(i)||r(i,{recursive:!0});let a=this.getMetaPath(e),s=`${a}.tmp`;d(s,JSON.stringify(t,null,2),`utf-8`),o(s,a)}normalizeMeta(e){let t=e;return t.completedTokens??=[],t.executionLog??=[],t}hasCompletedExecution(e,t){return e.executionLog.some(n=>n.stepId===t&&e.completedTokens.includes(n.token))}markCrashedExecution(e){let t=e.currentToken;if(!(!t||e.completedTokens.includes(t)))for(let n=e.executionLog.length-1;n>=0;--n){let r=e.executionLog[n];if(r.token===t&&r.outcome===`in-progress`){r.outcome=`crashed`;break}}}finalizeCurrentStep(e,t,n){let r=e.currentToken;if(r){e.completedTokens.includes(r)||e.completedTokens.push(r);for(let i=e.executionLog.length-1;i>=0;--i){let a=e.executionLog[i];if(a.token===r){a.completedAt=n,a.outcome=t;break}}}e.currentToken=void 0}activateStep(e,t,n,r){let i=n;for(;i<t.length;){let n=t[i];if(e.currentStep=n.id,e.phase=n.phase,r?.force||!this.hasCompletedExecution(e,n.id)){this.markCrashedExecution(e);let t=Date.now(),r=new Date(t).toISOString(),i=`${n.id}-${t}`;e.currentToken=i,e.executionLog.push({stepId:n.id,token:i,startedAt:r,outcome:`in-progress`});return}n.phase===`flow`?e.completedSteps.includes(n.id)||e.completedSteps.push(n.id):e.completedEpilogueSteps.includes(n.id)||e.completedEpilogueSteps.push(n.id),i+=1}e.currentStep=null,e.currentToken=void 0,e.status=`completed`,e.phase=`after`}findActiveRun(){if(!n(this.flowsDir))return null;for(let e of a(this.flowsDir,{withFileTypes:!0})){if(!e.isDirectory())continue;let t=this.readMeta(e.name);if(t?.status===`active`)return{slug:e.name,meta:t}}return null}metaToState(e,t){let n=this.normalizeMeta(t),r=n.phase??`flow`;return{flow:n.flow,status:n.status,currentStep:n.currentStep,currentToken:n.currentToken,completedSteps:n.completedSteps,completedTokens:n.completedTokens,skippedSteps:n.skippedSteps,executionLog:n.executionLog,artifacts:n.artifacts,startedAt:n.startedAt,updatedAt:n.updatedAt,slug:e,runDir:m(this.flowsDir,e),topic:n.topic,phase:r,isEpilogue:r!==`flow`,roots:n.roots,primaryRoot:n.primaryRoot}}start(e,t,n){let i=this.findActiveRun();if(i)return{success:!1,error:`Flow "${i.meta.flow}" is already active. Reset it first.`};let a=this.buildStepSequence(t);if(!a.length)return{success:!1,error:`Flow has no steps`};try{let i=(n??t.description)||e,o=this.generateSlug(i),s=m(this.flowsDir,o),c=new Date().toISOString(),l=a[0],u={id:o,flow:e,flowVersion:t.version,topic:i,status:`active`,currentStep:l.id,currentToken:void 0,completedSteps:[],completedTokens:[],skippedSteps:[],executionLog:[],artifactsDir:t.artifacts_dir,artifacts:{},startedAt:c,updatedAt:c,phase:l.phase,completedEpilogueSteps:[],skippedEpilogueSteps:[]};return this.activateStep(u,a,0),r(s,{recursive:!0}),r(m(s,t.artifacts_dir),{recursive:!0}),this.writeMeta(o,u),{success:!0,data:this.metaToState(o,u)}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}step(e,t){let r=this.findActiveRun();if(!r)return{success:!1,error:`No active flow`};if(r.meta.status!==`active`)return{success:!1,error:`Flow is ${r.meta.status}, not active`};if(!r.meta.currentStep)return{success:!1,error:`No current step`};let i=r.meta.currentStep,a=this.buildStepSequence(t),o=a.findIndex(e=>e.id===i);if(o===-1)return{success:!1,error:`Current step "${r.meta.currentStep}" not found in manifest`};let s=a[o],c=new Date().toISOString(),l=this.normalizeMeta(r.meta);switch(e){case`next`:if(s.phase===`flow`){let e=t.steps.find(e=>e.id===i);if(e&&e.produces.length>0){let a=m(m(this.flowsDir,r.slug),t.artifacts_dir),o=e.produces.filter(e=>!n(m(a,e)));if(o.length>0)return{success:!1,error:`Step "${i}" cannot advance — missing required artifacts in ${t.artifacts_dir}/: ${o.join(`, `)}. Create these files before advancing.`}}}s.phase===`flow`?l.completedSteps.includes(i)||l.completedSteps.push(i):l.completedEpilogueSteps.includes(i)||l.completedEpilogueSteps.push(i),this.finalizeCurrentStep(l,`completed`,c),this.activateStep(l,a,o+1);break;case`skip`:s.phase===`flow`?l.skippedSteps.includes(i)||l.skippedSteps.push(i):l.skippedEpilogueSteps.includes(i)||l.skippedEpilogueSteps.push(i),this.finalizeCurrentStep(l,`skipped`,c),this.activateStep(l,a,o+1);break;case`redo`:this.markCrashedExecution(l),s.phase===`flow`?(l.completedSteps=l.completedSteps.filter(e=>e!==i),l.skippedSteps=l.skippedSteps.filter(e=>e!==i)):(l.completedEpilogueSteps=l.completedEpilogueSteps.filter(e=>e!==i),l.skippedEpilogueSteps=l.skippedEpilogueSteps.filter(e=>e!==i)),l.currentToken=void 0,this.activateStep(l,a,o,{force:!0});break}return l.updatedAt=c,this.writeMeta(r.slug,l),{success:!0,data:this.metaToState(r.slug,l)}}getStatus(){let e=this.findActiveRun();return e?{success:!0,data:this.metaToState(e.slug,e.meta)}:{success:!1,error:`No active flow`}}reset(){let e=this.findActiveRun();return e?(e.meta.status=`abandoned`,e.meta.currentStep=null,e.meta.updatedAt=new Date().toISOString(),this.writeMeta(e.slug,e.meta),{success:!0}):{success:!0}}recordArtifact(e,t){let n=this.findActiveRun();return n?(n.meta.artifacts[e]=t,n.meta.updatedAt=new Date().toISOString(),this.writeMeta(n.slug,n.meta),{success:!0}):{success:!1,error:`No active flow`}}listRuns(e){if(!n(this.flowsDir))return[];let t=[];for(let n of a(this.flowsDir,{withFileTypes:!0})){if(!n.isDirectory())continue;let r=this.readMeta(n.name);r&&(e?.flow&&r.flow!==e.flow||e?.status&&r.status!==e.status||t.push({id:n.name,flow:r.flow,topic:r.topic,status:r.status,currentStep:r.currentStep,startedAt:r.startedAt,updatedAt:r.updatedAt}))}return t.sort((e,t)=>t.updatedAt.localeCompare(e.updatedAt))}},J=class{createSymlinks(t,i,a,o){let s=this.getTargets(t,i);for(let t of s){n(t.baseDir)||r(t.baseDir,{recursive:!0});for(let r of o.agents){let i=m(a,r);if(!n(i))continue;let o=this.getAgentStem(r),s=m(t.baseDir,`${o}${t.extension}`);n(s)&&u(s);let c=h(p(s),i);try{l(c,s,`file`)}catch{try{e(i,s)}catch(e){console.warn(`Failed to create symlink or copy fallback for ${i}: ${e instanceof Error?e.message:String(e)}`)}}}}}removeSymlinks(e,t){let r=this.getTargets(e,t);for(let e of r)if(n(e.baseDir))try{let t=a(e.baseDir,{withFileTypes:!0});for(let n of t)!n.isFile()&&!n.isSymbolicLink()||u(m(e.baseDir,n.name));a(e.baseDir).length===0&&c(e.baseDir)}catch{}}getTargets(e,t){return[{ide:`copilot`,baseDir:m(e,`.github`,`agents`,`flows`,t),extension:`.agent.md`},{ide:`claude-code`,baseDir:m(e,`.claude`,`agents`,`flows`,t),extension:`.md`}]}getAgentStem(e){return f(e).replace(/\.agent\.md$/,``).replace(/\.md$/,``)}};export{w as ClaudePluginAdapter,T as CopilotAdapter,W as FlowLoader,K as FlowRegistryManager,q as FlowStateMachine,P as FoundationIntegration,B as GitInstaller,E as NativeAdapter,D as OpenSpecAdapter,J as SymlinkManager,A as getBuiltinFlows};
@@ -1 +1 @@
1
- import{createHash as e}from"node:crypto";import{existsSync as t,readFileSync as n,realpathSync as r,statSync as i,writeFileSync as a}from"node:fs";import{lstat as o,readFile as s,readdir as c,stat as l}from"node:fs/promises";import{dirname as u,extname as d,join as f,relative as p,resolve as m}from"node:path";import{AIKIT_PATHS as h,FILE_LIMITS as g,createLogger as _,detectContentType as v,serializeError as y}from"../../core/dist/index.js";import{minimatch as b}from"minimatch";import{availableParallelism as x,loadavg as S}from"node:os";import{createChunkerSync as C}from"../../chunker/dist/index.js";function w(t){return e(`sha256`).update(t).digest(`hex`).slice(0,16)}function T(t,n){let r=`${t}:${n}`;return e(`sha256`).update(r).digest(`hex`).slice(0,16)}const E=_(`indexer`);var D=class e{static BINARY_EXTENSIONS=new Set(`.node,.so,.dylib,.dll,.wasm,.bin,.exe,.png,.jpg,.jpeg,.gif,.bmp,.ico,.webp,.svg,.mp3,.mp4,.wav,.avi,.mov,.flac,.zip,.gz,.tar,.bz2,.7z,.rar,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.ttf,.otf,.woff,.woff2,.eot,.pyc,.class,.o,.obj,.a,.lib`.split(`,`));async crawl(e){let t=[],n=new Set;return await this.walkDir(e.rootDir,e.rootDir,e.excludePatterns,t,n),t}async walkDir(t,n,i,a,u){let m;try{m=await c(t,{withFileTypes:!0})}catch(e){let n=e.code;(n===`EACCES`||n===`EPERM`)&&E.warn(`Permission denied, skipping directory`,{dir:t});return}for(let c of m){let m=f(t,c.name),_=p(n,m).replace(/\\/g,`/`);if(!this.isExcluded(_,i)){if(c.isDirectory()){if(c.name.startsWith(`.`)&&!(c.name===h.ai.slice(1)&&_.startsWith(h.ai)))continue;try{if((await o(m)).isSymbolicLink())continue}catch{continue}let e;try{e=r(m)}catch{continue}if(u.has(e))continue;u.add(e),await this.walkDir(m,n,i,a,u)}else if(c.isFile()){let t=d(c.name).toLowerCase();if(e.BINARY_EXTENSIONS.has(t))continue;try{if((await l(m)).size>g.maxFileSizeBytes)continue;let e=await s(m,`utf-8`);if(e.includes(`\0`))continue;a.push({relativePath:_,absolutePath:m,content:e,extension:t})}catch{}}}}}isExcluded(e,t){return t.some(t=>b(e,t,{dot:!0}))}};const O=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.mjs`,`.cjs`]),k=[{pattern:/^export\s+(?:async\s+)?function\s+(\w+)/gm,kind:`function`,exported:!0},{pattern:/^export\s+(?:default\s+)?class\s+(\w+)/gm,kind:`class`,exported:!0},{pattern:/^export\s+interface\s+(\w+)/gm,kind:`interface`,exported:!0},{pattern:/^export\s+type\s+(\w+)/gm,kind:`type`,exported:!0},{pattern:/^export\s+(?:const|let)\s+(\w+)/gm,kind:`const`,exported:!0},{pattern:/^export\s+enum\s+(\w+)/gm,kind:`enum`,exported:!0},{pattern:/^(?:async\s+)?function\s+(\w+)/gm,kind:`function`,exported:!1},{pattern:/^class\s+(\w+)/gm,kind:`class`,exported:!1},{pattern:/^interface\s+(\w+)/gm,kind:`interface`,exported:!1},{pattern:/^type\s+(\w+)/gm,kind:`type`,exported:!1},{pattern:/^enum\s+(\w+)/gm,kind:`enum`,exported:!1}],A=[/import\s+(?:(?:type\s+)?(?:(?:\{[^}]*\}|[\w*]+)\s+from\s+)?)['"]([^'"]+)['"]/g,/import\(\s*['"]([^'"]+)['"]\s*\)/g,/require\(\s*['"]([^'"]+)['"]\s*\)/g];function j(t,n,r){return e(`sha256`).update(`${t}:${n}:${r}`).digest(`hex`).slice(0,16)}function M(t,n,r){return e(`sha256`).update(`${t}-${r}-${n}`).digest(`hex`).slice(0,16)}function N(e,t){return f(u(t),e).replace(/\\/g,`/`).replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,``)}function P(e){return e.replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,``)}function F(e,t,n){let r=d(t).toLowerCase();if(!O.has(r))return{nodes:[],edges:[]};let i=[],a=[],o=new Date().toISOString(),s=new Set,c=P(t),l=j(`module`,c,c);i.push({id:l,type:`module`,name:t,properties:{ext:r},sourcePath:t,createdAt:o});for(let{pattern:n,kind:r,exported:c}of k){let u=new RegExp(n.source,n.flags),d;for(;(d=u.exec(e))!==null;){let e=d[1],n=`${r}:${e}`;if(s.has(n))continue;s.add(n);let u=j(r,e,t);i.push({id:u,type:r,name:e,properties:{exported:c},sourcePath:t,createdAt:o}),a.push({id:M(l,u,`defines`),fromId:l,toId:u,type:`defines`,weight:c?1:.5})}}let u=n?.workspacePackages,f=new Set;for(let n of A){let r=new RegExp(n.source,n.flags),i;for(;(i=r.exec(e))!==null;){let e=i[1];if(f.has(e))continue;let n;if(e.startsWith(`.`))n=N(e,t);else if(u){let t=e.startsWith(`@`)?e.split(`/`).slice(0,2).join(`/`):e.split(`/`)[0],r=u.get(t);if(!r)continue;n=r}else continue;f.add(e);let r=P(n),o=j(`module`,r,r);a.push({id:M(l,o,`imports`),fromId:l,toId:o,type:`imports`,properties:{source:e}})}}return{nodes:i,edges:a}}const I=_(`hash-cache`);var L=class{cache;filePath;dirty=!1;constructor(e){this.filePath=m(e,`file-hashes.json`),this.cache=new Map}load(){if(t(this.filePath))try{let e=n(this.filePath,`utf-8`),t=JSON.parse(e);this.cache=new Map(Object.entries(t)),I.info(`Hash cache loaded`,{entries:this.cache.size})}catch(e){I.warn(`Hash cache load failed, starting fresh`,{err:e}),this.cache=new Map}}get(e){return this.cache.get(e)}set(e,t){this.cache.set(e,t),this.dirty=!0}delete(e){this.cache.delete(e)&&(this.dirty=!0)}flush(){if(this.dirty)try{let e={};for(let[t,n]of this.cache)e[t]=n;a(this.filePath,JSON.stringify(e),`utf-8`),this.dirty=!1}catch(e){I.warn(`Hash cache flush failed`,{err:e})}}clear(){this.cache.clear(),this.dirty=!0,this.flush()}get size(){return this.cache.size}};const R=_(`indexer`),z=()=>new Promise(e=>setImmediate(e));async function B(e,t,n,r){let i=0;async function a(){for(;i<e.length;){let n=i++;try{await t(e[n])}catch(t){r?.(e[n],t)}n%10==0&&await z()}}await Promise.all(Array.from({length:Math.min(n,e.length)},()=>a()))}function V(e){let t=x(),n=S()[0]/t;return n>1.5?2:n>1?Math.max(2,Math.floor(e/2)):e}const H=Math.max(2,Math.min(4,Math.floor(x()*.5)));var U=class{embedder;store;crawler;indexing=!1;graphStore;hashCache;get isIndexing(){return this.indexing}constructor(e,t){this.embedder=e,this.store=t,this.crawler=new D}normalizeChunkText(e){return e.replace(/^\/\/ File: [^\n]*\n?/,``).toLowerCase().replace(/\s+/g,` `).trim()}setGraphStore(e){this.graphStore=e}setHashCache(e){this.hashCache=e}async index(e,t){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{return await this.doIndex(e,t,{})}finally{this.indexing=!1}}async getChangedFiles(e){let t=e.indexing.concurrency??H,n=await this.crawlSources(e),{filesToProcess:r}=await this.planIndexWork(n,t,{});return r.map(e=>e.relativePath)}async indexFiles(e,t,n){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{return await this.doIndexFiles(e,t,n)}finally{this.indexing=!1}}async doIndex(e,t,n={}){let r=Date.now(),i=e.indexing.concurrency??H;t?.({phase:`crawling`,filesTotal:0,filesProcessed:0,chunksTotal:0,chunksProcessed:0});let a=await this.crawlSources(e),{filesToProcess:o,filesSkipped:s,pathsToRemove:c}=await this.planIndexWork(a,i,{skipHashCheck:n.skipHashCheck}),{filesProcessed:l,chunksCreated:u,chunksDeduped:d}=await this.processFiles(a,o,i,t,{graphCleared:n.graphCleared}),f=await this.cleanupRemovedFiles(c,i,o.length,l,u,t);return this.hashCache?.flush(),t?.({phase:`done`,filesTotal:o.length,filesProcessed:l,chunksTotal:u,chunksProcessed:u}),{filesProcessed:l,filesSkipped:s,chunksCreated:u,chunksDeduped:d,filesRemoved:f,durationMs:Date.now()-r}}async doIndexFiles(e,t,n){let r=Date.now(),i=e.indexing.concurrency??H,a=new Set(t);if(a.size===0)return{filesProcessed:0,filesSkipped:0,chunksCreated:0,chunksDeduped:0,filesRemoved:0,durationMs:Date.now()-r};n?.({phase:`crawling`,filesTotal:0,filesProcessed:0,chunksTotal:0,chunksProcessed:0});let o=await this.crawlSources(e),{filesToProcess:s,filesSkipped:c}=await this.planIndexWork(o,i,{requestedPaths:a}),{filesProcessed:l,chunksCreated:u,chunksDeduped:d}=await this.processFiles(o,s,i,n,{});return this.hashCache?.flush(),n?.({phase:`done`,filesTotal:s.length,filesProcessed:l,chunksTotal:u,chunksProcessed:u}),{filesProcessed:l,filesSkipped:c,chunksCreated:u,chunksDeduped:d,filesRemoved:0,durationMs:Date.now()-r}}async crawlSources(e){return(await Promise.all(e.sources.map(e=>this.crawler.crawl({rootDir:e.path,excludePatterns:e.excludePatterns})))).flat()}async planIndexWork(e,t,n){let r=n.requestedPaths,i=r?e.filter(e=>r.has(e.relativePath)):e;if(n.skipHashCheck)return{filesToProcess:i,filesSkipped:0,pathsToRemove:[]};let a=r?[]:await this.getPathsToRemove(e),o=0,s=[];return await B(i,async e=>{let t=w(e.content);if(this.hashCache){if(this.hashCache.get(e.relativePath)===t){o++;return}}else{let n=await this.store.getBySourcePath(e.relativePath);if(n.length>0&&n[0].fileHash===t){o++;return}}s.push(e)},V(t),(e,t)=>R.error(`Hash check failed`,{sourcePath:e.relativePath,...y(t)})),{filesToProcess:s,filesSkipped:o,pathsToRemove:a}}async getPathsToRemove(e){let t=await this.store.listSourcePaths(),n=new Set(e.map(e=>e.relativePath));return t.filter(e=>!n.has(e)&&!e.startsWith(`${h.aiCurated}/`))}async buildWorkspacePackageMap(e){let t=new Map;for(let n of e)if(n.relativePath.endsWith(`package.json`))try{let e=JSON.parse(n.content);if(typeof e.name!=`string`||e.name.length===0)continue;let r=n.relativePath===`package.json`?``:n.relativePath.replace(/\/package\.json$/,``),i=``;if(typeof e.exports==`string`)i=e.exports;else if(e.exports&&typeof e.exports==`object`){let t=e.exports,n=t[`.`]??t;if(typeof n==`string`)i=n;else if(n&&typeof n==`object`){let e=n,t=e.import??e.module??e.default??e.require;typeof t==`string`&&(i=t)}}!i&&typeof e.module==`string`&&(i=e.module),!i&&typeof e.main==`string`&&(i=e.main);let a=i.replace(/^\.\//,``).replace(/^dist\//,`src/`).replace(/\.(ts|js|mjs|cjs|tsx|jsx)$/,``),o=a?r?`${r}/${a}`:a:r?`${r}/src/index`:`src/index`;t.set(e.name,o)}catch{}return t}async processFiles(t,n,r,i,a={}){let o=0,s=0,c=0,l=n.length,u=this.graphStore?await this.buildWorkspacePackageMap(t):void 0,d=new Map,f=[],p=[],m=0,h=[],g=[],_=new Map,b=0,x=async()=>{if(h.length===0)return;let e=h,t=g,n=_;h=[],g=[],_=new Map,b=0,await this.store.upsert(e,t);for(let[e,t]of n)this.hashCache?.set(e,t)},S=async()=>{if(this.graphStore){try{f.length>0&&await this.graphStore.upsertNodes(f),p.length>0&&await this.graphStore.upsertEdges(p)}catch(e){R.warn(`Graph batch flush failed`,y(e))}f=[],p=[],m=0}};return await B(n,async t=>{i?.({phase:`chunking`,filesTotal:l,filesProcessed:o,chunksTotal:s,chunksProcessed:s,currentFile:t.relativePath});let n=v(t.relativePath),r=C(t.extension).chunk(t.content,{sourcePath:t.relativePath,contentType:n});if(r.length===0)return;let E=w(t.content),D=new Date().toISOString(),O=(e,n,r)=>({id:T(t.relativePath,n),content:e.text,sourcePath:e.sourcePath,contentType:e.contentType,headingPath:e.headingPath,chunkIndex:e.chunkIndex,totalChunks:e.totalChunks,startLine:e.startLine,endLine:e.endLine,fileHash:E,contentHash:r,indexedAt:D,origin:`indexed`,tags:[],version:1}),k=[],A=[];for(let t=0;t<r.length;t++){let n=r[t],i=e(`sha256`).update(this.normalizeChunkText(n.text)).digest(`hex`),a=O(n,t,i),o=d.get(i);if(o&&this.store.upsertWithoutVector){A.push({record:a,sourceRecordId:o}),c++;continue}d.set(i,a.id),k.push({chunk:n,record:a})}i?.({phase:`embedding`,filesTotal:l,filesProcessed:o,chunksTotal:s+r.length,chunksProcessed:s,currentFile:t.relativePath});let j=k.length>0?await this.embedder.embedBatch(k.map(({chunk:e})=>e.text)):[],M=k.map(({record:e})=>e);if(i?.({phase:`storing`,filesTotal:l,filesProcessed:o,chunksTotal:s+r.length,chunksProcessed:s,currentFile:t.relativePath}),M.length>0&&(h.push(...M),g.push(...j),_.set(t.relativePath,E),b++,b>=20&&await x()),A.length>0&&h.length>0&&await x(),this.store.upsertWithoutVector)for(let{record:e,sourceRecordId:t}of A)await this.store.upsertWithoutVector(e,t);if(M.length===0&&A.length>0&&this.hashCache?.set(t.relativePath,E),this.graphStore)try{a.graphCleared||await this.graphStore.deleteBySourcePath(t.relativePath);let e=F(t.content,t.relativePath,{workspacePackages:u});e.nodes.length>0&&f.push(...e.nodes),e.edges.length>0&&p.push(...e.edges),m++,m>=50&&await S()}catch(e){R.warn(`Graph extraction failed`,{sourcePath:t.relativePath,...y(e)})}o++,s+=r.length},V(r),(e,t)=>R.error(`Processing failed`,{sourcePath:e.relativePath,...y(t)})),await x(),await S(),{filesProcessed:o,chunksCreated:s,chunksDeduped:c}}async cleanupRemovedFiles(e,t,n,r,i,a){if(e.length===0)return 0;let o=0;return a?.({phase:`cleanup`,filesTotal:n,filesProcessed:r,chunksTotal:i,chunksProcessed:i}),await B(e,async e=>{await this.store.deleteBySourcePath(e),this.hashCache?.delete(e),this.graphStore&&await this.graphStore.deleteBySourcePath(e).catch(t=>R.warn(`Graph cleanup failed`,{sourcePath:e,...y(t)})),o++},V(t),(e,t)=>R.error(`Cleanup failed`,{sourcePath:e,...y(t)})),o}async reindexAll(e,t){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{if(await this.store.dropTable(),this.graphStore)try{let e=await this.graphStore.getStats();e.nodeCount>0&&(await this.graphStore.clear(),R.info(`Graph store cleared`,{nodeCount:e.nodeCount,edgeCount:e.edgeCount}))}catch(e){R.warn(`Graph store clear failed`,y(e))}return await this.doReindex(e,t)}catch(e){throw this.indexing=!1,e}}async doReindex(e,t){try{return await this.doIndex(e,t,{skipHashCheck:!0,graphCleared:!0})}finally{this.indexing=!1}}async getStats(){return this.store.getStats()}};const W=_(`smart-index`),G=1.5;var K=class{indexer;config;store;trickleTimer=null;stopped=!1;trickleIntervalMs;batchSize;priorityQueue=[];changedFiles=[];lastRefreshTime=0;refreshing=!1;constructor(e,t,n){this.indexer=e,this.config=t,this.store=n,this.trickleIntervalMs=t.indexing.trickleIntervalMs??this.readPositiveIntEnv(`AIKIT_SMART_TRICKLE_MS`,3e4),this.batchSize=t.indexing.trickleBatchSize??this.readPositiveIntEnv(`AIKIT_SMART_BATCH_SIZE`,1)}start(){this.trickleTimer&&=(clearTimeout(this.trickleTimer),null),this.stopped=!1,W.info(`Smart index scheduler started (trickle mode)`,{intervalMs:this.trickleIntervalMs,batchSize:this.batchSize}),this.scheduleTick()}stop(){this.stopped=!0,this.trickleTimer&&=(clearTimeout(this.trickleTimer),null)}prioritize(...e){let t=[...new Set(e.filter(Boolean))].filter(e=>{try{return!i(e).isDirectory()}catch{return W.debug(`Skipping non-existent path`,{path:e}),!1}});for(let e of t){let t=this.priorityQueue.indexOf(e);t>=0&&this.priorityQueue.splice(t,1)}for(let e of t.reverse())this.priorityQueue.unshift(e);this.priorityQueue.length>500&&(this.priorityQueue.length=500),t.length>0&&W.info(`Files prioritized for trickle indexing`,{added:t.length,queued:this.priorityQueue.length})}getState(){return{mode:`smart`,queueSize:this.priorityQueue.length,changedFilesSize:this.changedFiles.length,intervalMs:this.trickleIntervalMs,batchSize:this.batchSize,running:this.trickleTimer!==null}}readPositiveIntEnv(e,t){let n=Number(process.env[e]);return Number.isFinite(n)&&n>0?n:t}scheduleTick(){this.trickleTimer=setTimeout(()=>void this.tick(),this.trickleIntervalMs),this.trickleTimer.unref&&this.trickleTimer.unref()}async tick(){if(!this.stopped)try{if(this.indexer.isIndexing){W.info(`Skipping trickle tick — indexing already in progress`);return}let e=this.getCpuCount(),t=S()[0];if(e>0&&t/e>G){W.info(`Skipping trickle tick — system load too high`,{load:t.toFixed(2),cpuCount:e,threshold:G});return}let n=await this.pickFiles();if(n.length===0){await this.maybeRefreshChangedFiles();return}W.info(`Trickle indexing tick started`,{count:n.length,files:n});let r=await this.indexer.indexFiles(this.config,n);if(this.store)try{await this.store.createFtsIndex()}catch(e){W.warn(`FTS index rebuild failed after trickle tick`,{error:String(e)})}this.changedFiles=this.changedFiles.filter(e=>!n.includes(e)),W.info(`Trickle indexing tick complete`,{filesProcessed:r.filesProcessed,filesSkipped:r.filesSkipped,chunksCreated:r.chunksCreated})}catch(e){let t=String(e);if(t.includes(`not initialized`)||t.includes(`has been closed`)){W.warn(`Store closed — stopping smart index scheduler`,{error:t}),this.stop();return}W.error(`Trickle indexing tick failed`,{error:t})}finally{this.stopped||this.scheduleTick()}}getCpuCount(){try{return typeof x==`function`?x():4}catch{return 4}}async pickFiles(){let e=[];for(;e.length<this.batchSize&&this.priorityQueue.length>0;){let t=this.priorityQueue.shift();t&&!e.includes(t)&&e.push(t)}if(e.length<this.batchSize)for(await this.maybeRefreshChangedFiles();e.length<this.batchSize&&this.changedFiles.length>0;){let t=this.changedFiles.shift();t&&!e.includes(t)&&e.push(t)}return e}async maybeRefreshChangedFiles(){let e=Date.now();if(!(this.refreshing||this.changedFiles.length>0&&e-this.lastRefreshTime<6e5)){this.refreshing=!0;try{this.changedFiles=await this.indexer.getChangedFiles(this.config),this.lastRefreshTime=e,this.changedFiles.length>0&&W.info(`Refreshed changed files for trickle indexing`,{count:this.changedFiles.length})}catch(e){let t=String(e);if(t.includes(`not initialized`)||t.includes(`has been closed`)){W.warn(`Store closed — stopping smart index scheduler`,{error:t}),this.stop();return}W.error(`Failed to refresh changed files for trickle indexing`,{error:t})}finally{this.refreshing=!1}}}};export{L as FileHashCache,D as FilesystemCrawler,U as IncrementalIndexer,K as SmartIndexScheduler,F as extractGraph,T as generateRecordId,w as hashContent};
1
+ import{createHash as e}from"node:crypto";import{existsSync as t,readFileSync as n,realpathSync as r,statSync as i,writeFileSync as a}from"node:fs";import{lstat as o,readFile as s,readdir as c,stat as l}from"node:fs/promises";import{dirname as u,extname as d,join as f,relative as p,resolve as m}from"node:path";import{AIKIT_PATHS as h,FILE_LIMITS as g,createLogger as _,detectContentType as v,serializeError as y}from"../../core/dist/index.js";import{minimatch as b}from"minimatch";import{availableParallelism as x,loadavg as S}from"node:os";import{createChunkerSync as C}from"../../chunker/dist/index.js";function w(t){return e(`sha256`).update(t).digest(`hex`).slice(0,16)}function T(t,n){let r=`${t}:${n}`;return e(`sha256`).update(r).digest(`hex`).slice(0,16)}const E=_(`indexer`);var D=class e{static BINARY_EXTENSIONS=new Set(`.node,.so,.dylib,.dll,.wasm,.bin,.exe,.png,.jpg,.jpeg,.gif,.bmp,.ico,.webp,.svg,.mp3,.mp4,.wav,.avi,.mov,.flac,.zip,.gz,.tar,.bz2,.7z,.rar,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.ttf,.otf,.woff,.woff2,.eot,.pyc,.class,.o,.obj,.a,.lib`.split(`,`));async crawl(e){let t=[],n=new Set;return await this.walkDir(e.rootDir,e.rootDir,e.excludePatterns,t,n),t}async walkDir(t,n,i,a,u){let m;try{m=await c(t,{withFileTypes:!0})}catch(e){let n=e.code;(n===`EACCES`||n===`EPERM`)&&E.warn(`Permission denied, skipping directory`,{dir:t});return}for(let c of m){let m=f(t,c.name),_=p(n,m).replace(/\\/g,`/`);if(!this.isExcluded(_,i)){if(c.isDirectory()){if(c.name.startsWith(`.`)&&!(c.name===h.ai.slice(1)&&_.startsWith(h.ai)))continue;try{if((await o(m)).isSymbolicLink())continue}catch{continue}let e;try{e=r(m)}catch{continue}if(u.has(e))continue;u.add(e),await this.walkDir(m,n,i,a,u)}else if(c.isFile()){let t=d(c.name).toLowerCase();if(e.BINARY_EXTENSIONS.has(t))continue;try{if((await l(m)).size>g.maxFileSizeBytes)continue;let e=await s(m,`utf-8`);if(e.includes(`\0`))continue;a.push({relativePath:_,absolutePath:m,content:e,extension:t})}catch{}}}}}isExcluded(e,t){return t.some(t=>b(e,t,{dot:!0}))}};const O=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.mjs`,`.cjs`]),k=[{pattern:/^export\s+(?:async\s+)?function\s+(\w+)/gm,kind:`function`,exported:!0},{pattern:/^export\s+(?:default\s+)?class\s+(\w+)/gm,kind:`class`,exported:!0},{pattern:/^export\s+interface\s+(\w+)/gm,kind:`interface`,exported:!0},{pattern:/^export\s+type\s+(\w+)/gm,kind:`type`,exported:!0},{pattern:/^export\s+(?:const|let)\s+(\w+)/gm,kind:`const`,exported:!0},{pattern:/^export\s+enum\s+(\w+)/gm,kind:`enum`,exported:!0},{pattern:/^(?:async\s+)?function\s+(\w+)/gm,kind:`function`,exported:!1},{pattern:/^class\s+(\w+)/gm,kind:`class`,exported:!1},{pattern:/^interface\s+(\w+)/gm,kind:`interface`,exported:!1},{pattern:/^type\s+(\w+)/gm,kind:`type`,exported:!1},{pattern:/^enum\s+(\w+)/gm,kind:`enum`,exported:!1}],A=[/import\s+(?:(?:type\s+)?(?:(?:\{[^}]*\}|[\w*]+)\s+from\s+)?)['"]([^'"]+)['"]/g,/import\(\s*['"]([^'"]+)['"]\s*\)/g,/require\(\s*['"]([^'"]+)['"]\s*\)/g];function j(t,n,r){return e(`sha256`).update(`${t}:${n}:${r}`).digest(`hex`).slice(0,16)}function M(t,n,r){return e(`sha256`).update(`${t}-${r}-${n}`).digest(`hex`).slice(0,16)}function N(e,t){return f(u(t),e).replace(/\\/g,`/`).replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,``)}function P(e){return e.replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,``)}function F(e,t,n){let r=d(t).toLowerCase();if(!O.has(r))return{nodes:[],edges:[]};let i=[],a=[],o=new Date().toISOString(),s=new Set,c=P(t),l=j(`module`,c,c);i.push({id:l,type:`module`,name:t,properties:{ext:r},sourcePath:t,createdAt:o});for(let{pattern:n,kind:r,exported:c}of k){let u=new RegExp(n.source,n.flags),d;for(;(d=u.exec(e))!==null;){let e=d[1],n=`${r}:${e}`;if(s.has(n))continue;s.add(n);let u=j(r,e,t);i.push({id:u,type:r,name:e,properties:{exported:c},sourcePath:t,createdAt:o}),a.push({id:M(l,u,`defines`),fromId:l,toId:u,type:`defines`,weight:c?1:.5})}}let u=n?.workspacePackages,f=new Set;for(let n of A){let r=new RegExp(n.source,n.flags),i;for(;(i=r.exec(e))!==null;){let e=i[1];if(f.has(e))continue;let n;if(e.startsWith(`.`))n=N(e,t);else if(u){let t=e.startsWith(`@`)?e.split(`/`).slice(0,2).join(`/`):e.split(`/`)[0],r=u.get(t);if(!r)continue;n=r}else continue;f.add(e);let r=P(n),o=j(`module`,r,r);a.push({id:M(l,o,`imports`),fromId:l,toId:o,type:`imports`,properties:{source:e}})}}return{nodes:i,edges:a}}const I=_(`hash-cache`);var L=class{cache;filePath;dirty=!1;constructor(e){this.filePath=m(e,`file-hashes.json`),this.cache=new Map}load(){if(t(this.filePath))try{let e=n(this.filePath,`utf-8`),t=JSON.parse(e);this.cache=new Map(Object.entries(t)),I.info(`Hash cache loaded`,{entries:this.cache.size})}catch(e){I.warn(`Hash cache load failed, starting fresh`,{err:e}),this.cache=new Map}}get(e){return this.cache.get(e)}set(e,t){this.cache.set(e,t),this.dirty=!0}delete(e){this.cache.delete(e)&&(this.dirty=!0)}flush(){if(this.dirty)try{let e={};for(let[t,n]of this.cache)e[t]=n;a(this.filePath,JSON.stringify(e),`utf-8`),this.dirty=!1}catch(e){I.warn(`Hash cache flush failed`,{err:e})}}clear(){this.cache.clear(),this.dirty=!0,this.flush()}get size(){return this.cache.size}};const R=_(`indexer`),z=()=>new Promise(e=>setImmediate(e));async function B(e,t,n,r){let i=0;async function a(){for(;i<e.length;){let n=i++;try{await t(e[n])}catch(t){r?.(e[n],t)}n%10==0&&await z()}}await Promise.all(Array.from({length:Math.min(n,e.length)},()=>a()))}function V(e){let t=x(),n=S()[0]/t;return n>1.5?2:n>1?Math.max(2,Math.floor(e/2)):e}const H=Math.max(2,Math.min(4,Math.floor(x()*.5)));var U=class{embedder;store;crawler;indexing=!1;graphStore;hashCache;get isIndexing(){return this.indexing}constructor(e,t){this.embedder=e,this.store=t,this.crawler=new D}normalizeChunkText(e){return e.replace(/^\/\/ File: [^\n]*\n?/,``).toLowerCase().replace(/\s+/g,` `).trim()}setGraphStore(e){this.graphStore=e}setHashCache(e){this.hashCache=e}async index(e,t){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{return await this.doIndex(e,t,{})}finally{this.indexing=!1}}async getChangedFiles(e){let t=e.indexing.concurrency??H,n=await this.crawlSources(e),{filesToProcess:r}=await this.planIndexWork(n,t,{});return r.map(e=>e.relativePath)}async indexFiles(e,t,n){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{return await this.doIndexFiles(e,t,n)}finally{this.indexing=!1}}async doIndex(e,t,n={}){let r=Date.now(),i=e.indexing.concurrency??H;t?.({phase:`crawling`,filesTotal:0,filesProcessed:0,chunksTotal:0,chunksProcessed:0});let a=await this.crawlSources(e),{filesToProcess:o,filesSkipped:s,pathsToRemove:c}=await this.planIndexWork(a,i,{skipHashCheck:n.skipHashCheck}),{filesProcessed:l,chunksCreated:u,chunksDeduped:d}=await this.processFiles(a,o,i,t,{graphCleared:n.graphCleared}),f=await this.cleanupRemovedFiles(c,i,o.length,l,u,t);return this.hashCache?.flush(),t?.({phase:`done`,filesTotal:o.length,filesProcessed:l,chunksTotal:u,chunksProcessed:u}),{filesProcessed:l,filesSkipped:s,chunksCreated:u,chunksDeduped:d,filesRemoved:f,durationMs:Date.now()-r}}async doIndexFiles(e,t,n){let r=Date.now(),i=e.indexing.concurrency??H,a=new Set(t);if(a.size===0)return{filesProcessed:0,filesSkipped:0,chunksCreated:0,chunksDeduped:0,filesRemoved:0,durationMs:Date.now()-r};n?.({phase:`crawling`,filesTotal:0,filesProcessed:0,chunksTotal:0,chunksProcessed:0});let o=await this.crawlSources(e),{filesToProcess:s,filesSkipped:c}=await this.planIndexWork(o,i,{requestedPaths:a}),{filesProcessed:l,chunksCreated:u,chunksDeduped:d}=await this.processFiles(o,s,i,n,{});return this.hashCache?.flush(),n?.({phase:`done`,filesTotal:s.length,filesProcessed:l,chunksTotal:u,chunksProcessed:u}),{filesProcessed:l,filesSkipped:c,chunksCreated:u,chunksDeduped:d,filesRemoved:0,durationMs:Date.now()-r}}async crawlSources(e){return(await Promise.all(e.sources.map(e=>this.crawler.crawl({rootDir:e.path,excludePatterns:e.excludePatterns})))).flat()}async planIndexWork(e,t,n){let r=n.requestedPaths,i;if(r){let t=e=>e.replace(/\\/g,`/`).toLowerCase(),n=new Set([...r].map(t));i=e.filter(e=>n.has(t(e.relativePath))||n.has(t(e.absolutePath)))}else i=e;if(n.skipHashCheck)return{filesToProcess:i,filesSkipped:0,pathsToRemove:[]};let a=r?[]:await this.getPathsToRemove(e),o=0,s=[];return await B(i,async e=>{let t=w(e.content);if(this.hashCache){if(this.hashCache.get(e.relativePath)===t){o++;return}}else{let n=await this.store.getBySourcePath(e.relativePath);if(n.length>0&&n[0].fileHash===t){o++;return}}s.push(e)},V(t),(e,t)=>R.error(`Hash check failed`,{sourcePath:e.relativePath,...y(t)})),{filesToProcess:s,filesSkipped:o,pathsToRemove:a}}async getPathsToRemove(e){let t=await this.store.listSourcePaths(),n=new Set(e.map(e=>e.relativePath));return t.filter(e=>!n.has(e)&&!e.startsWith(`${h.aiCurated}/`))}async buildWorkspacePackageMap(e){let t=new Map;for(let n of e)if(n.relativePath.endsWith(`package.json`))try{let e=JSON.parse(n.content);if(typeof e.name!=`string`||e.name.length===0)continue;let r=n.relativePath===`package.json`?``:n.relativePath.replace(/\/package\.json$/,``),i=``;if(typeof e.exports==`string`)i=e.exports;else if(e.exports&&typeof e.exports==`object`){let t=e.exports,n=t[`.`]??t;if(typeof n==`string`)i=n;else if(n&&typeof n==`object`){let e=n,t=e.import??e.module??e.default??e.require;typeof t==`string`&&(i=t)}}!i&&typeof e.module==`string`&&(i=e.module),!i&&typeof e.main==`string`&&(i=e.main);let a=i.replace(/^\.\//,``).replace(/^dist\//,`src/`).replace(/\.(ts|js|mjs|cjs|tsx|jsx)$/,``),o=a?r?`${r}/${a}`:a:r?`${r}/src/index`:`src/index`;t.set(e.name,o)}catch{}return t}async processFiles(t,n,r,i,a={}){let o=0,s=0,c=0,l=n.length,u=this.graphStore?await this.buildWorkspacePackageMap(t):void 0,d=new Map,f=[],p=[],m=0,h=[],g=[],_=new Map,b=0,x=async()=>{if(h.length===0)return;let e=h,t=g,n=_;h=[],g=[],_=new Map,b=0;try{await this.store.upsert(e,t);for(let[e,t]of n)this.hashCache?.set(e,t)}catch(r){h.push(...e),g.push(...t);for(let[e,t]of n)_.set(e,t);throw r}},S=async()=>{if(this.graphStore){try{f.length>0&&await this.graphStore.upsertNodes(f),p.length>0&&await this.graphStore.upsertEdges(p)}catch(e){R.warn(`Graph batch flush failed`,y(e))}f=[],p=[],m=0}};return await B(n,async t=>{i?.({phase:`chunking`,filesTotal:l,filesProcessed:o,chunksTotal:s,chunksProcessed:s,currentFile:t.relativePath});let n=v(t.relativePath),r=C(t.extension).chunk(t.content,{sourcePath:t.relativePath,contentType:n});if(r.length===0)return;let E=w(t.content),D=new Date().toISOString(),O=(e,n,r)=>({id:T(t.relativePath,n),content:e.text,sourcePath:e.sourcePath,contentType:e.contentType,headingPath:e.headingPath,chunkIndex:e.chunkIndex,totalChunks:e.totalChunks,startLine:e.startLine,endLine:e.endLine,fileHash:E,contentHash:r,indexedAt:D,origin:`indexed`,tags:[],version:1}),k=[],A=[];for(let t=0;t<r.length;t++){let n=r[t],i=e(`sha256`).update(this.normalizeChunkText(n.text)).digest(`hex`),a=O(n,t,i),o=d.get(i);if(o&&this.store.upsertWithoutVector){A.push({record:a,sourceRecordId:o}),c++;continue}d.set(i,a.id),k.push({chunk:n,record:a})}i?.({phase:`embedding`,filesTotal:l,filesProcessed:o,chunksTotal:s+r.length,chunksProcessed:s,currentFile:t.relativePath});let j=k.length>0?await this.embedder.embedBatch(k.map(({chunk:e})=>e.text)):[],M=k.map(({record:e})=>e);if(i?.({phase:`storing`,filesTotal:l,filesProcessed:o,chunksTotal:s+r.length,chunksProcessed:s,currentFile:t.relativePath}),M.length>0&&(h.push(...M),g.push(...j),_.set(t.relativePath,E),b++,b>=20&&await x()),A.length>0&&h.length>0&&await x(),this.store.upsertWithoutVector)for(let{record:e,sourceRecordId:t}of A)await this.store.upsertWithoutVector(e,t);if(M.length===0&&A.length>0&&this.hashCache?.set(t.relativePath,E),this.graphStore)try{a.graphCleared||await this.graphStore.deleteBySourcePath(t.relativePath);let e=F(t.content,t.relativePath,{workspacePackages:u});e.nodes.length>0&&f.push(...e.nodes),e.edges.length>0&&p.push(...e.edges),m++,m>=50&&await S()}catch(e){R.warn(`Graph extraction failed`,{sourcePath:t.relativePath,...y(e)})}o++,s+=r.length},V(r),(e,t)=>R.error(`Processing failed`,{sourcePath:e.relativePath,...y(t)})),await x(),await S(),{filesProcessed:o,chunksCreated:s,chunksDeduped:c}}async cleanupRemovedFiles(e,t,n,r,i,a){if(e.length===0)return 0;let o=0;return a?.({phase:`cleanup`,filesTotal:n,filesProcessed:r,chunksTotal:i,chunksProcessed:i}),await B(e,async e=>{await this.store.deleteBySourcePath(e),this.hashCache?.delete(e),this.graphStore&&await this.graphStore.deleteBySourcePath(e).catch(t=>R.warn(`Graph cleanup failed`,{sourcePath:e,...y(t)})),o++},V(t),(e,t)=>R.error(`Cleanup failed`,{sourcePath:e,...y(t)})),o}async reindexAll(e,t){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{if(await this.store.dropTable(),this.graphStore)try{let e=await this.graphStore.getStats();e.nodeCount>0&&(await this.graphStore.clear(),R.info(`Graph store cleared`,{nodeCount:e.nodeCount,edgeCount:e.edgeCount}))}catch(e){R.warn(`Graph store clear failed`,y(e))}return await this.doReindex(e,t)}catch(e){throw this.indexing=!1,e}}async doReindex(e,t){try{return await this.doIndex(e,t,{skipHashCheck:!0,graphCleared:!0})}finally{this.indexing=!1}}async getStats(){return this.store.getStats()}};const W=_(`smart-index`),G=1.5;var K=class{indexer;config;store;trickleTimer=null;stopped=!1;trickleIntervalMs;batchSize;priorityQueue=[];changedFiles=[];lastRefreshTime=0;refreshing=!1;constructor(e,t,n){this.indexer=e,this.config=t,this.store=n,this.trickleIntervalMs=t.indexing.trickleIntervalMs??this.readPositiveIntEnv(`AIKIT_SMART_TRICKLE_MS`,3e4),this.batchSize=t.indexing.trickleBatchSize??this.readPositiveIntEnv(`AIKIT_SMART_BATCH_SIZE`,1)}start(){this.trickleTimer&&=(clearTimeout(this.trickleTimer),null),this.stopped=!1,W.info(`Smart index scheduler started (trickle mode)`,{intervalMs:this.trickleIntervalMs,batchSize:this.batchSize}),this.scheduleTick()}stop(){this.stopped=!0,this.trickleTimer&&=(clearTimeout(this.trickleTimer),null)}prioritize(...e){let t=[...new Set(e.filter(Boolean))].filter(e=>{try{return!i(e).isDirectory()}catch{return W.debug(`Skipping non-existent path`,{path:e}),!1}});for(let e of t){let t=this.priorityQueue.indexOf(e);t>=0&&this.priorityQueue.splice(t,1)}for(let e of t.reverse())this.priorityQueue.unshift(e);this.priorityQueue.length>500&&(this.priorityQueue.length=500),t.length>0&&W.info(`Files prioritized for trickle indexing`,{added:t.length,queued:this.priorityQueue.length})}getState(){return{mode:`smart`,queueSize:this.priorityQueue.length,changedFilesSize:this.changedFiles.length,intervalMs:this.trickleIntervalMs,batchSize:this.batchSize,running:this.trickleTimer!==null}}readPositiveIntEnv(e,t){let n=Number(process.env[e]);return Number.isFinite(n)&&n>0?n:t}scheduleTick(){this.trickleTimer=setTimeout(()=>void this.tick(),this.trickleIntervalMs),this.trickleTimer.unref&&this.trickleTimer.unref()}async tick(){if(!this.stopped)try{if(this.indexer.isIndexing){W.info(`Skipping trickle tick — indexing already in progress`);return}let e=this.getCpuCount(),t=S()[0];if(e>0&&t/e>G){W.info(`Skipping trickle tick — system load too high`,{load:t.toFixed(2),cpuCount:e,threshold:G});return}let n=await this.pickFiles();if(n.length===0){await this.maybeRefreshChangedFiles();return}W.info(`Trickle indexing tick started`,{count:n.length,files:n});let r=await this.indexer.indexFiles(this.config,n);if(this.store)try{await this.store.createFtsIndex()}catch(e){W.warn(`FTS index rebuild failed after trickle tick`,{error:String(e)})}this.changedFiles=this.changedFiles.filter(e=>!n.includes(e)),W.info(`Trickle indexing tick complete`,{filesProcessed:r.filesProcessed,filesSkipped:r.filesSkipped,chunksCreated:r.chunksCreated})}catch(e){let t=String(e);if(t.includes(`not initialized`)||t.includes(`has been closed`)){W.warn(`Store closed — stopping smart index scheduler`,{error:t}),this.stop();return}W.error(`Trickle indexing tick failed`,{error:t})}finally{this.stopped||this.scheduleTick()}}getCpuCount(){try{return typeof x==`function`?x():4}catch{return 4}}async pickFiles(){let e=[];for(;e.length<this.batchSize&&this.priorityQueue.length>0;){let t=this.priorityQueue.shift();t&&!e.includes(t)&&e.push(t)}if(e.length<this.batchSize)for(await this.maybeRefreshChangedFiles();e.length<this.batchSize&&this.changedFiles.length>0;){let t=this.changedFiles.shift();t&&!e.includes(t)&&e.push(t)}return e}async maybeRefreshChangedFiles(){let e=Date.now();if(!(this.refreshing||this.changedFiles.length>0&&e-this.lastRefreshTime<6e5)){this.refreshing=!0;try{this.changedFiles=await this.indexer.getChangedFiles(this.config),this.lastRefreshTime=e,this.changedFiles.length>0&&W.info(`Refreshed changed files for trickle indexing`,{count:this.changedFiles.length})}catch(e){let t=String(e);if(t.includes(`not initialized`)||t.includes(`has been closed`)){W.warn(`Store closed — stopping smart index scheduler`,{error:t}),this.stop();return}W.error(`Failed to refresh changed files for trickle indexing`,{error:t})}finally{this.refreshing=!1}}}};export{L as FileHashCache,D as FilesystemCrawler,U as IncrementalIndexer,K as SmartIndexScheduler,F as extractGraph,T as generateRecordId,w as hashContent};
@@ -1 +1 @@
1
- import{t as e}from"./curated-manager-BkSgtNC2.js";import{readFileSync as t}from"node:fs";import{dirname as n,resolve as r}from"node:path";import{fileURLToPath as i,pathToFileURL as a}from"node:url";import{parseArgs as o}from"node:util";import{createLogger as s,serializeError as c}from"../../core/dist/index.js";const l=n(i(import.meta.url)),u=(()=>{try{let e=r(l,`..`,`..`,`..`,`package.json`);return JSON.parse(t(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}})(),d=s(`server`);function f(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}const{values:p}=(()=>{let e=process.argv[1];if(!e)return!1;try{return import.meta.url===a(e).href}catch{return!1}})()?o({allowPositionals:!0,options:{transport:{type:`string`,default:f()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}):{values:{transport:f(),port:process.env.AIKIT_PORT??`3210`}};async function m(){if(process.on(`unhandledRejection`,e=>{d.error(`Unhandled rejection`,c(e))}),d.info(`Starting MCP AI Kit server`,{version:u}),p.transport===`http`){let[{default:e},{loadConfig:t,resolveIndexMode:n},{registerDashboardRoutes:r,resolveDashboardDir:i},{registerSettingsRoutes:a,resolveSettingsDir:o},{createSettingsRouter:s}]=await Promise.all([import(`express`),import(`./config-D4z6-EcI.js`),import(`./dashboard-static-BfIe0Si1.js`),import(`./settings-static-BosGZSPf.js`),import(`./routes-OaSHcA6x.js`)]),l=t();d.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path});let u=e();u.use(e.json());let f=Number(p.port);u.use((e,t,n)=>{if(t.setHeader(`Access-Control-Allow-Origin`,process.env.AIKIT_CORS_ORIGIN??`http://localhost:${f}`),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization`),e.method===`OPTIONS`){t.status(204).end();return}n()}),r(u,i(),d);let m=new Date().toISOString();u.use(`/settings/api`,s({log:d,mcpInfo:()=>({transport:`http`,port:f,pid:process.pid,startedAt:m})})),a(u,o(),d),u.get(`/health`,(e,t)=>{t.json({status:`ok`})});let h=!1,g=null,_=null,v=null,y=Promise.resolve();u.post(`/mcp`,async(e,t)=>{if(!h||!_||!v){t.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let n=y,r;y=new Promise(e=>{r=e}),await n;try{let n=new v({sessionIdGenerator:void 0});await _.connect(n),await n.handleRequest(e,t,e.body),n.close()}catch(e){if(d.error(`MCP handler error`,c(e)),!t.headersSent){let n=e instanceof Error?e.message:String(e),r=n.includes(`Not Acceptable`);t.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?n:`Internal server error`},id:null})}}finally{r()}}),u.get(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))}),u.delete(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))});let b=u.listen(f,`127.0.0.1`,()=>{d.info(`MCP server listening`,{url:`http://127.0.0.1:${f}/mcp`,port:f}),setTimeout(async()=>{try{let[{createLazyServer:e,ALL_TOOL_NAMES:t},{StreamableHTTPServerTransport:r},{checkForUpdates:i,autoUpgradeScaffold:a}]=await Promise.all([import(`./server-Ceit0yIx.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-Bj07vc5x.js`)]);i(),a();let o=n(l),s=e(l,o);_=s.server,v=r,h=!0,d.info(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:t.length,resourceCount:2}),s.startInit(),o===`auto`?s.ready.then(async()=>{try{let e=l.sources.map(e=>e.path).join(`, `);d.info(`Running initial index`,{sourcePaths:e}),await s.runInitialIndex(),d.info(`Initial index complete`)}catch(e){d.error(`Initial index failed; will retry on aikit_reindex`,c(e))}}).catch(e=>d.error(`AI Kit init or indexing failed`,c(e))):o===`smart`?s.ready.then(async()=>{try{if(!s.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(s.aikit.indexer,l,s.aikit.store),n=s.aikit.store;g=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),s.setSmartScheduler(t),d.info(`Smart index scheduler started (HTTP mode)`)}catch(e){d.error(`Failed to start smart index scheduler`,c(e))}}).catch(e=>d.error(`AI Kit initialization failed`,c(e))):(s.ready.catch(e=>d.error(`AI Kit initialization failed`,c(e))),d.info(`Initial full indexing skipped in HTTP mode`,{indexMode:o}))}catch(e){d.error(`Failed to load server modules`,c(e))}},100)}),x=async e=>{d.info(`Shutdown signal received`,{signal:e}),g?.stop(),b.close(),_&&await _.close(),process.exit(0)};process.on(`SIGINT`,()=>x(`SIGINT`)),process.on(`SIGTERM`,()=>x(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:n},{createLazyServer:r},{checkForUpdates:a,autoUpgradeScaffold:o},{RootsListChangedNotificationSchema:s}]=await Promise.all([import(`./config-D4z6-EcI.js`),import(`./server-Ceit0yIx.js`),import(`./version-check-Bj07vc5x.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=e();d.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),a(),o();let u=n(l),f=r(l,u),{server:p,startInit:m,ready:h,runInitialIndex:g}=f,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await p.connect(v),d.info(`MCP server started`,{transport:`stdio`});let y=e=>{if(e.length===0)return!1;let n=e[0].uri,r=n.startsWith(`file://`)?i(n):n;return d.info(`MCP roots resolved`,{rootUri:n,rootPath:r,rootCount:e.length}),t(l,r),l.allRoots=e.map(e=>{let t=e.uri;return t.startsWith(`file://`)?i(t):t}),!0},b=!1;try{b=y((await p.server.listRoots()).roots),b||d.info(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(e){d.warn(`MCP roots/list not supported by client; using cwd fallback`,{cwd:process.cwd(),...c(e)}),b=!0}b||=await new Promise(e=>{let t=setTimeout(()=>{d.warn(`Timed out waiting for MCP roots/list_changed; using cwd fallback`,{cwd:process.cwd()}),e(!1)},5e3);p.server.setNotificationHandler(s,async()=>{clearTimeout(t);try{e(y((await p.server.listRoots()).roots))}catch(t){d.warn(`roots/list retry failed after notification`,c(t)),e(!1)}})}),m();let x=null,S=()=>{x&&clearTimeout(x),x=setTimeout(()=>{d.info(`Auto-shutdown: no activity for 30 minutes — exiting`),process.exit(0)},18e5),x.unref&&x.unref()};S(),process.stdin.on(`data`,()=>S()),h.catch(e=>{d.error(`Initialization failed — server will continue with limited tools`,c(e))}),u===`auto`?g().catch(e=>d.error(`Initial index failed`,c(e))):u===`smart`?h.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.aikit.indexer,l,f.aikit.store),n=f.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),f.setSmartScheduler(t),d.info(`Smart index scheduler started (stdio mode)`)}catch(e){d.error(`Failed to start smart index scheduler`,c(e))}}).catch(e=>d.error(`AI Kit init failed for smart scheduler`,c(e))):d.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:u})}}m().catch(e=>{d.error(`Fatal error`,c(e)),process.exit(1)});export{e as CuratedKnowledgeManager};
1
+ import{t as e}from"./curated-manager-BkSgtNC2.js";import{readFileSync as t}from"node:fs";import{dirname as n,resolve as r}from"node:path";import{fileURLToPath as i,pathToFileURL as a}from"node:url";import{parseArgs as o}from"node:util";import{createLogger as s,serializeError as c}from"../../core/dist/index.js";const l=n(i(import.meta.url)),u=(()=>{try{let e=r(l,`..`,`..`,`..`,`package.json`);return JSON.parse(t(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}})(),d=s(`server`);function f(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}const{values:p}=(()=>{let e=process.argv[1];if(!e)return!1;try{return import.meta.url===a(e).href}catch{return!1}})()?o({allowPositionals:!0,options:{transport:{type:`string`,default:f()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}):{values:{transport:f(),port:process.env.AIKIT_PORT??`3210`}};async function m(){if(process.on(`unhandledRejection`,e=>{d.error(`Unhandled rejection`,c(e))}),process.on(`uncaughtException`,e=>{d.error(`Uncaught exception — exiting`,c(e)),process.exit(1)}),d.info(`Starting MCP AI Kit server`,{version:u}),p.transport===`http`){let[{default:e},{loadConfig:t,resolveIndexMode:n},{registerDashboardRoutes:r,resolveDashboardDir:i},{registerSettingsRoutes:a,resolveSettingsDir:o},{createSettingsRouter:s}]=await Promise.all([import(`express`),import(`./config-D4z6-EcI.js`),import(`./dashboard-static-BfIe0Si1.js`),import(`./settings-static-BosGZSPf.js`),import(`./routes-OaSHcA6x.js`)]),l=t();d.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path});let u=e();u.use(e.json());let f=Number(p.port);u.use((e,t,n)=>{if(t.setHeader(`Access-Control-Allow-Origin`,process.env.AIKIT_CORS_ORIGIN??`http://localhost:${f}`),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization`),e.method===`OPTIONS`){t.status(204).end();return}n()}),r(u,i(),d);let m=new Date().toISOString();u.use(`/settings/api`,s({log:d,mcpInfo:()=>({transport:`http`,port:f,pid:process.pid,startedAt:m})})),a(u,o(),d),u.get(`/health`,(e,t)=>{t.json({status:`ok`})});let h=!1,g=null,_=null,v=null,y=Promise.resolve();u.post(`/mcp`,async(e,t)=>{if(!h||!_||!v){t.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let n=y,r;y=new Promise(e=>{r=e}),await n;try{let n=new v({sessionIdGenerator:void 0});await _.connect(n),await n.handleRequest(e,t,e.body),n.close()}catch(e){if(d.error(`MCP handler error`,c(e)),!t.headersSent){let n=e instanceof Error?e.message:String(e),r=n.includes(`Not Acceptable`);t.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?n:`Internal server error`},id:null})}}finally{r()}}),u.get(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))}),u.delete(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))});let b=u.listen(f,`127.0.0.1`,()=>{d.info(`MCP server listening`,{url:`http://127.0.0.1:${f}/mcp`,port:f}),setTimeout(async()=>{try{let[{createLazyServer:e,ALL_TOOL_NAMES:t},{StreamableHTTPServerTransport:r},{checkForUpdates:i,autoUpgradeScaffold:a}]=await Promise.all([import(`./server-DmbZccrE.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-Bj07vc5x.js`)]);i(),a();let o=n(l),s=e(l,o);_=s.server,v=r,h=!0,d.info(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:t.length,resourceCount:2}),s.startInit(),o===`auto`?s.ready.then(async()=>{try{let e=l.sources.map(e=>e.path).join(`, `);d.info(`Running initial index`,{sourcePaths:e}),await s.runInitialIndex(),d.info(`Initial index complete`)}catch(e){d.error(`Initial index failed; will retry on aikit_reindex`,c(e))}}).catch(e=>d.error(`AI Kit init or indexing failed`,c(e))):o===`smart`?s.ready.then(async()=>{try{if(!s.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(s.aikit.indexer,l,s.aikit.store),n=s.aikit.store;g=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),s.setSmartScheduler(t),d.info(`Smart index scheduler started (HTTP mode)`)}catch(e){d.error(`Failed to start smart index scheduler`,c(e))}}).catch(e=>d.error(`AI Kit initialization failed`,c(e))):(s.ready.catch(e=>d.error(`AI Kit initialization failed`,c(e))),d.info(`Initial full indexing skipped in HTTP mode`,{indexMode:o}))}catch(e){d.error(`Failed to load server modules`,c(e))}},100)}),x=async e=>{d.info(`Shutdown signal received`,{signal:e}),g?.stop(),b.close(),_&&await _.close(),process.exit(0)};process.on(`SIGINT`,()=>x(`SIGINT`)),process.on(`SIGTERM`,()=>x(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:n},{createLazyServer:r},{checkForUpdates:a,autoUpgradeScaffold:o},{RootsListChangedNotificationSchema:s}]=await Promise.all([import(`./config-D4z6-EcI.js`),import(`./server-DmbZccrE.js`),import(`./version-check-Bj07vc5x.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=e();d.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),a(),o();let u=n(l),f=r(l,u),{server:p,startInit:m,ready:h,runInitialIndex:g}=f,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await p.connect(v),d.info(`MCP server started`,{transport:`stdio`});let y=e=>{if(e.length===0)return!1;let n=e[0].uri,r=n.startsWith(`file://`)?i(n):n;return d.info(`MCP roots resolved`,{rootUri:n,rootPath:r,rootCount:e.length}),t(l,r),l.allRoots=e.map(e=>{let t=e.uri;return t.startsWith(`file://`)?i(t):t}),!0},b=!1;try{b=y((await p.server.listRoots()).roots),b||d.info(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(e){d.warn(`MCP roots/list not supported by client; using cwd fallback`,{cwd:process.cwd(),...c(e)}),b=!0}b||=await new Promise(e=>{let t=setTimeout(()=>{d.warn(`Timed out waiting for MCP roots/list_changed; using cwd fallback`,{cwd:process.cwd()}),e(!1)},5e3);p.server.setNotificationHandler(s,async()=>{clearTimeout(t);try{e(y((await p.server.listRoots()).roots))}catch(t){d.warn(`roots/list retry failed after notification`,c(t)),e(!1)}})}),m();let x=null,S=()=>{x&&clearTimeout(x),x=setTimeout(async()=>{d.info(`Auto-shutdown: no activity for 30 minutes — shutting down gracefully`);try{let e=f.aikit;e&&await Promise.all([e.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),e.graphStore.close().catch(()=>{}),e.store.close().catch(()=>{})])}catch{}process.exit(0)},18e5),x.unref&&x.unref()};S(),process.stdin.on(`data`,()=>S()),h.catch(e=>{d.error(`Initialization failed — server will continue with limited tools`,c(e))}),u===`auto`?g().catch(e=>d.error(`Initial index failed`,c(e))):u===`smart`?h.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.aikit.indexer,l,f.aikit.store),n=f.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),f.setSmartScheduler(t),d.info(`Smart index scheduler started (stdio mode)`)}catch(e){d.error(`Failed to start smart index scheduler`,c(e))}}).catch(e=>d.error(`AI Kit init failed for smart scheduler`,c(e))):d.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:u})}}m().catch(e=>{d.error(`Fatal error`,c(e)),process.exit(1)});export{e as CuratedKnowledgeManager};