@vpxa/aikit 0.1.306 → 0.1.307

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.306",
3
+ "version": "0.1.307",
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",
@@ -14,19 +14,19 @@ at session start and available as \`mcp_aikit_*\` prefixed tool calls.
14
14
  1. **AI Kit tools are available immediately** — they appear as \`mcp_aikit_search\`, \`mcp_aikit_file_summary\`, etc.
15
15
  2. **Prefer AI Kit tools over raw shell/file operations** — they provide structured, token-efficient results
16
16
  3. **Check for active flows** — use \`mcp_aikit_flow\` with action: 'status' to see if a guided workflow is running
17
- 4. **Use context compression** — \`mcp_aikit_compact\`, \`mcp_aikit_digest\`, and \`mcp_aikit_stratum_card\` reduce token consumption 5-20x\n\n---\n\n${t}`}getHermesDir(e){let t=e??this.getPathModule();if(process.platform===`win32`){let e=process.env.LOCALAPPDATA??t.resolve(z(),`AppData`,`Local`);return t.resolve(e,`hermes`)}return t.resolve(z(),`.hermes`)}getPathModule(){return process.platform===`win32`?F:N}},zn=class extends W{id=`opencode`;name=`OpenCode`;family=`opencode`;platforms=[`win32`,`darwin`,`linux`];scope=`user`;configKey=`mcp`;async detect(){if(!this.isPlatformSupported())return!1;let e=this.getPathModule(),t=z();return[e.resolve(t,`.config`,`opencode`),e.resolve(t,`.opencode`)].some(e=>w(e))}getConfigPath(){return this.getPathModule().resolve(z(),`.config`,`opencode`,`opencode.jsonc`)}async registerMcp(e,t){let n=await this.readConfig();n[this.configKey]||(n[this.configKey]={});let r=n[this.configKey];r[e]={type:`local`,command:[t.command,...t.args||[]]},await this.writeConfig(n)}getScaffoldRoot(){return this.getPathModule().resolve(z(),`.config`,`opencode`)}getScaffoldPaths(){let e=this.getPathModule(),t=this.getScaffoldRoot();return t?{agents:e.resolve(t,`agents`),skills:e.resolve(t,`skills`),prompts:null,flows:e.resolve(t,`flows`),commands:null,instructions:e.resolve(t,`OPENCODE.md`),manifest:e.resolve(t,`.aikit-scaffold.json`),hooks:null}:super.getScaffoldPaths()}getPathModule(){return process.platform===`win32`?F:N}},Bn=class extends W{id=`zed`;name=`Zed`;family=`zed`;platforms=[`win32`,`darwin`,`linux`];scope=`user`;configKey=`context_servers`;async detect(){return this.isPlatformSupported()?w(this.getConfigDir()):!1}getConfigPath(){return this.getPathModule().resolve(this.getConfigDir(),`settings.json`)}async registerMcp(e,t){let{type:n,...r}=t,i={...r,env:r.env??{}};await super.registerMcp(e,i)}getScaffoldRoot(){return this.getConfigDir()}getScaffoldPaths(){let e=this.getPathModule(),t=this.getConfigDir();return{agents:e.resolve(t,`prompts`),skills:null,prompts:e.resolve(t,`prompts`),flows:null,commands:null,instructions:null,manifest:e.resolve(t,`.aikit-scaffold.json`),hooks:null}}getConfigDir(){let e=this.getPathModule();return process.platform===`win32`?e.resolve(process.env.APPDATA||z(),`Zed`):e.resolve(z(),`.config`,`zed`)}getPathModule(){return process.platform===`win32`?F:N}};const Vn=[new Nn,new Pn,new Fn,new kn,new An,new In,new Mn,new On,new jn,new En,new Ln,new Dn,new Bn,new zn,new Rn];async function Hn(e){let t=e?.scope?Vn.filter(t=>t.scope===e.scope):Vn;return(await Promise.allSettled(t.map(async e=>await e.detect()?e:null))).flatMap(e=>e.status!==`fulfilled`||e.value===null?[]:[e.value])}const Un={SessionStart:{copilot:`SessionStart`,claude:`PreToolCall`,copilotCli:`sessionStart`},PreToolUse:{copilot:`PreToolUse`,claude:`PreToolCall`,copilotCli:`preToolUse`},PostToolUse:{copilot:`PostToolUse`,claude:`PostToolCall`,copilotCli:`postToolUse`},SubagentStart:{copilot:`SubagentStart`,claude:`PreToolCall`,copilotCli:`subagentStart`},PreCompact:{copilot:`PreCompact`,claude:`PreToolCall`,copilotCli:`preCompact`},Stop:{copilot:`Stop`,claude:`PostToolCall`,copilotCli:`stop`}},Wn={fileRead:{copilot:[`read_file`,`readFile`],claude:[`Read`],copilotCli:[`read_file`]},fileWrite:{copilot:[`editFiles`,`replace_string_in_file`,`create_file`],claude:[`Write`,`Edit`],copilotCli:[`editFiles`,`replace_string_in_file`]},fileSearch:{copilot:[`grep_search`,`semantic_search`,`find`],claude:[`Bash`],copilotCli:[`grep_search`]}},Gn={"privacy-guard":{id:`privacy-guard`,event:`PreToolUse`,tier:`safety`,description:`Blocks reads of secret-bearing env files, key material, SSH paths, and credential artifacts.`,script:`privacy-guard.mjs`,matcher:[`fileRead`],scope:`user`,patterns:[`.env`,`*.pem`,`*.key`,`id_rsa*`,`.ssh/*`,`*credentials*`,`*.secret`]},"scout-guard":{id:`scout-guard`,event:`PreToolUse`,tier:`safety`,description:`Blocks reads and searches inside generated, dependency, and git object directories.`,script:`scout-guard.mjs`,matcher:[`fileRead`,`fileSearch`],scope:`user`,patterns:[`node_modules/`,`dist/`,`.git/objects/`,`vendor/`,`build/`]},"subagent-context":{id:`subagent-context`,event:`SubagentStart`,tier:`efficiency`,description:`Injects compact project context into each subagent spawn to reduce repeated discovery.`,script:`subagent-context.mjs`,scope:`user`},"pre-compact-save":{id:`pre-compact-save`,event:`PreCompact`,tier:`efficiency`,description:`Persists critical state before context compaction truncates recent session history.`,script:`pre-compact-save.mjs`,scope:`user`},"post-edit-check":{id:`post-edit-check`,event:`PostToolUse`,tier:`nudge`,description:`After repeated file edits, injects a validation reminder so checks are not skipped.`,script:`post-edit-check.mjs`,matcher:[`fileWrite`],scope:`user`},"session-init":{id:`session-init`,event:`SessionStart`,tier:`nudge`,description:`Detects project stack and injects workspace metadata and environment context at startup.`,script:`session-init.mjs`,scope:`user`},"session-observer":{id:`session-observer`,event:`PostToolUse`,tier:`efficiency`,description:`Captures tool usage patterns for autonomous lesson extraction. Writes to session buffer.`,script:`session-observer.mjs`,scope:`user`},"session-learn":{id:`session-learn`,event:`Stop`,tier:`efficiency`,description:`Nudges final pattern analysis on buffered observations at session end.`,script:`session-learn.mjs`,scope:`user`}},Kn={PreCompact:3e3,PostToolUse:3e3},qn={copilot:`hooks.json`,claude:`hooks-settings.json`,copilotCli:`hooks.json`};function Jn(e,t){return(e.matcher||[]).flatMap(e=>{let n=Wn[e];if(!n)throw Error(`Unknown hook matcher: ${e}`);return n[t]||[]})}function Yn(e,t,n,r){let i=`${n}/${e.script}`;return Jn(e,r),r===`copilot`?{event:t,steps:[{type:`command`,command:`node`,args:[i],timeout:Kn[e.event]||5e3}]}:r===`claude`?{type:`command`,command:`node ${i}`}:{command:`node`,args:[i]}}function Xn(e,t){if(e===`copilot`){let n=Object.values(Gn).map(n=>{let r=Un[n.event]?.[e];if(!r)throw Error(`Unsupported hook event ${n.event} for ${e}`);return Yn(n,r,t,e)});return[{path:qn[e],content:JSON.stringify({hooks:n},null,2)}]}let n={};for(let r of Object.values(Gn)){let i=Un[r.event]?.[e];if(!i)throw Error(`Unsupported hook event ${r.event} for ${e}`);n[i]||=[],n[i].push(Yn(r,i,t,e))}return[{path:qn[e],content:JSON.stringify({hooks:n},null,2)}]}function Zn(){return[`_runtime.mjs`,...Object.values(Gn).map(e=>e.script)]}function Qn(){let e=$n();if(e)return e;let t={command:b.command,args:b.args?[...b.args]:void 0,type:b.type};if(process.platform!==`win32`){let e=process.env.PATH;e&&(t.env={PATH:e});try{let e=tn(`which`,[`node`],{encoding:`utf-8`,timeout:3e3}).trim();e&&w(e)&&(t.command=e)}catch{}}return t}function $n(){let e=M(z(),`.aikit`,`current-version.json`);if(!w(e))return null;try{let t=JSON.parse(E(e,`utf-8`));if(typeof t.version!=`string`||t.version.length===0)return null;let n=M(z(),`.aikit`,`versions`,`v${t.version}`,`packages`,`server`,`dist`,`bin.js`);if(!w(n))return null;let r={command:process.execPath,args:[n,`serve`],type:`stdio`};return process.platform!==`win32`&&process.env.PATH&&(r.env={PATH:process.env.PATH}),r}catch{return null}}const er=new Set([`VS Code`,`VS Code Insiders`,`VSCodium`]);function tr(e,t,n){let r=P(z(),`.copilot`,`instructions`,`copilot-instructions.md`);!w(r)||n.has(r)||(T(j(r),{recursive:!0}),A(r,`---\napplyTo: "**"\n---\n\n${e}\n---\n\n${t}`,`utf-8`),n.add(r))}function nr(e,t=!1){if(!er.has(e.name))return;let n=P(j(e.getConfigPath()),`settings.json`),r={};if(w(n))try{let e=E(n,`utf-8`);r=JSON.parse(e)}catch{console.log(` ${e.name}: skipped settings.json (invalid JSON)`);return}let i=!1;for(let[e,n]of Object.entries(fe))if(typeof n==`object`&&n){let t=typeof r[e]==`object`&&r[e]!==null?r[e]:{},a={...t,...n};JSON.stringify(a)!==JSON.stringify(t)&&(r[e]=a,i=!0)}else (t||!(e in r))&&(r[e]=n,i=!0);i&&(A(n,`${JSON.stringify(r,null,2)}\n`,`utf-8`),console.log(` ${e.name}: updated settings.json`))}async function rr(r,o,s,c,l=!1){let u=new Map,d=new Set,f=le(`aikit`,s),p=pe(`aikit`,s);for(let e of o)e.getScaffoldRoot()!==null&&u.set(e.id,e);if(tr(f,p,d),u.size===0){d.size>0?console.log(` Instruction files: ${[...d].join(`, `)}`):console.log(` No IDEs with global scaffold support detected.`);return}let m=await n(r,`copilot`),ee=await n(r,`opencode`),te=await n(r,`hermes-agent`),ne=e=>{let t=new Map;for(let n of e){let e=n.path.indexOf(`/`);if(e===-1)continue;let r=n.path.substring(0,e);if(r===`agents`||r===`prompts`){let i=t.get(r)??[];i.push({path:n.path.substring(e+1),content:n.content}),t.set(r,i)}else if(r===`.opencode`){let r=n.path.indexOf(`/`,e+1);if(r!==-1&&n.path.substring(e+1,r)===`agents`){let e=t.get(`agents`)??[];e.push({path:n.path.substring(r+1),content:n.content}),t.set(`agents`,e)}}}return t},re=ne(m),ie=ne(ee),h=ne(te),ae=await n(r,`skills`),g=new Set;for(let e of ae){let t=e.path.indexOf(`/`);t!==-1&&g.add(e.path.substring(0,t))}let _=await n(r,`flows`),v=new Set;for(let e of _){let t=e.path.indexOf(`/`);t!==-1&&v.add(e.path.substring(0,t))}let y=await n(r,`claude-code`),oe=P(r,`scaffold`,`general`,`hooks`,`scripts`),b=w(oe)?oe:P(import.meta.dirname,`../../../../../scaffold/general/hooks/scripts`),se=Zn(),x=new Set,ce=new Set,S=new Set,ue=(n,r,o,s)=>{let u=s.get(o);if(!n||!r||!u||u.length===0)return;let d=`${o}:${r}:${n}`;if(x.has(d))return;x.add(d);let f=e(r)??a(c);f.version=c,i(u,n,f,o,l),t(r,f),S.add(j(r))},C=(n,r,o,s)=>{if(!n||!r||s.length===0)return;let u=`${o}:${r}:${n}`;if(x.has(u))return;if(x.add(u),o===`flows`&&!ce.has(n)){for(let e of v){let t=P(n,e,`skills`);w(t)&&(k(t,{recursive:!0,force:!0}),console.log(` ${j(r)}: migrated ${e} flow to steps/ layout`))}ce.add(n)}let d=e(r)??a(c);d.version=c,i(s,n,d,o,l),t(r,d),S.add(j(r))},de=(e,t,n)=>{!e||!t||C(e,t,`hooks`,[...Xn(n,P(e,`scripts`).replace(/\\/g,`/`)),...se.map(e=>({path:`scripts/${e}`,content:E(P(b,e),`utf-8`)}))])};for(let e of u.values()){let t=e.getScaffoldPaths(),n=e.family===`opencode`?ie:e.family===`hermes`?h:re;ue(t.agents,t.manifest,`agents`,n),ue(t.prompts,t.manifest,`prompts`,n),C(t.skills,t.manifest,`skills`,ae),C(t.flows,t.manifest,`flows`,_),C(t.commands,t.manifest,`commands`,y),de(t.hooks,t.manifest,e.family===`claude`?`claude`:`copilot`)}for(let e of S)console.log(` ${e}: scaffold updated (${g.size} skills)`);for(let e of u.values()){let t=e.getScaffoldPaths().instructions;!t||d.has(t)||(T(j(t),{recursive:!0}),A(t,e.buildInstructionContent(f,p),`utf-8`),d.add(t))}d.size>0&&console.log(` Instruction files: ${[...d].join(`, `)}`)}function ir(e){let t=[];for(let n of e){let e=n.getScaffoldRoot();if(e)if(er.has(n.name)){let r=n.getInstructionsRoot()??e;t.push(P(r,`kb.instructions.md`)),t.push(P(r,`aikit.instructions.md`))}else n.name===`Cursor`||n.name===`Cursor Nightly`?t.push(P(e,`rules`,`kb.mdc`)):n.name===`Windsurf`&&t.push(P(e,`rules`,`kb.md`))}for(let e of t)w(e)&&(xe(e),console.log(` Removed legacy file: ${e}`))}async function ar(e){let t=h,n=S(),r=JSON.parse(E(P(n,`package.json`),`utf-8`)).version;console.log(`Initializing @vpxa/aikit v${r}...\n`);let i=Oe();T(i,{recursive:!0}),console.log(` Global data store: ${i}`),Ne({version:1,workspaces:{}}),console.log(` Created registry.json`);let a=await Hn({scope:`user`});if(a.length===0)console.log(`
18
- No supported IDEs detected. You can manually add the MCP server config.`);else{console.log(`\n Detected ${a.length} IDE(s):`);let n=Qn();for(let e of a)try{await e.registerMcp(t,n),console.log(` ${e.name}: configured ${t}`)}catch(t){console.log(` ${e.name}: failed to configure (${t.message})`)}for(let t of a)nr(t,e.force)}console.log(`
19
- Installing scaffold files:`),await rr(n,a,t,r,e.force),ir(a),console.log(`
17
+ 4. **Use context compression** — \`mcp_aikit_compact\`, \`mcp_aikit_digest\`, and \`mcp_aikit_stratum_card\` reduce token consumption 5-20x\n\n---\n\n${t}`}getHermesDir(e){let t=e??this.getPathModule();if(process.platform===`win32`){let e=process.env.LOCALAPPDATA??t.resolve(z(),`AppData`,`Local`);return t.resolve(e,`hermes`)}return t.resolve(z(),`.hermes`)}getPathModule(){return process.platform===`win32`?F:N}},zn=class extends W{id=`opencode`;name=`OpenCode`;family=`opencode`;platforms=[`win32`,`darwin`,`linux`];scope=`user`;configKey=`mcp`;async detect(){if(!this.isPlatformSupported())return!1;let e=this.getPathModule(),t=z();return[e.resolve(t,`.config`,`opencode`),e.resolve(t,`.opencode`)].some(e=>w(e))}getConfigPath(){return this.getPathModule().resolve(z(),`.config`,`opencode`,`opencode.jsonc`)}async registerMcp(e,t){let n=await this.readConfig();n[this.configKey]||(n[this.configKey]={});let r=n[this.configKey];r[e]={type:`local`,command:[t.command,...t.args||[]]},await this.writeConfig(n)}getScaffoldRoot(){return this.getPathModule().resolve(z(),`.config`,`opencode`)}getScaffoldPaths(){let e=this.getPathModule(),t=this.getScaffoldRoot();return t?{agents:e.resolve(t,`agents`),skills:e.resolve(t,`skills`),prompts:null,flows:e.resolve(t,`flows`),commands:null,instructions:e.resolve(t,`OPENCODE.md`),manifest:e.resolve(t,`.aikit-scaffold.json`),hooks:null}:super.getScaffoldPaths()}getPathModule(){return process.platform===`win32`?F:N}},Bn=class extends W{id=`zed`;name=`Zed`;family=`zed`;platforms=[`win32`,`darwin`,`linux`];scope=`user`;configKey=`context_servers`;async detect(){return this.isPlatformSupported()?w(this.getConfigDir()):!1}getConfigPath(){return this.getPathModule().resolve(this.getConfigDir(),`settings.json`)}async registerMcp(e,t){let{type:n,...r}=t,i={...r,env:r.env??{}};await super.registerMcp(e,i)}getScaffoldRoot(){return this.getConfigDir()}getScaffoldPaths(){let e=this.getPathModule(),t=this.getConfigDir();return{agents:e.resolve(t,`prompts`),skills:null,prompts:e.resolve(t,`prompts`),flows:null,commands:null,instructions:null,manifest:e.resolve(t,`.aikit-scaffold.json`),hooks:null}}getConfigDir(){let e=this.getPathModule();return process.platform===`win32`?e.resolve(process.env.APPDATA||z(),`Zed`):e.resolve(z(),`.config`,`zed`)}getPathModule(){return process.platform===`win32`?F:N}};const Vn=[new Nn,new Pn,new Fn,new kn,new An,new In,new Mn,new On,new jn,new En,new Ln,new Dn,new Bn,new zn,new Rn];async function Hn(e){let t=e?.scope?Vn.filter(t=>t.scope===e.scope):Vn;return(await Promise.allSettled(t.map(async e=>await e.detect()?e:null))).flatMap(e=>e.status!==`fulfilled`||e.value===null?[]:[e.value])}const Un=[`copilot`,`claude`,`copilotCli`,`hermes`],Wn={SessionStart:{copilot:`SessionStart`,claude:`PreToolCall`,copilotCli:`sessionStart`,hermes:`SessionStart`},PreToolUse:{copilot:`PreToolUse`,claude:`PreToolCall`,copilotCli:`preToolUse`,hermes:`PreToolUse`},PostToolUse:{copilot:`PostToolUse`,claude:`PostToolCall`,copilotCli:`postToolUse`,hermes:`PostToolUse`},SubagentStart:{copilot:`SubagentStart`,claude:`PreToolCall`,copilotCli:`subagentStart`,hermes:`SubagentStart`},PreCompact:{copilot:`PreCompact`,claude:`PreToolCall`,copilotCli:`preCompact`,hermes:`PreCompact`},Stop:{copilot:`Stop`,claude:`PostToolCall`,copilotCli:`stop`,hermes:`Stop`}},Gn={fileRead:{copilot:[`read_file`,`readFile`],claude:[`Read`],copilotCli:[`read_file`],hermes:[`read_file`]},fileWrite:{copilot:[`editFiles`,`replace_string_in_file`,`create_file`],claude:[`Write`,`Edit`],copilotCli:[`editFiles`,`replace_string_in_file`],hermes:[`write_file`,`patch`]},fileSearch:{copilot:[`grep_search`,`semantic_search`,`find`],claude:[`Bash`],copilotCli:[`grep_search`],hermes:[`search_files`]}},Kn={"privacy-guard":{id:`privacy-guard`,event:`PreToolUse`,tier:`safety`,description:`Blocks reads of secret-bearing env files, key material, SSH paths, and credential artifacts.`,script:`privacy-guard.mjs`,matcher:[`fileRead`],scope:`user`,patterns:[`.env`,`*.pem`,`*.key`,`id_rsa*`,`.ssh/*`,`*credentials*`,`*.secret`]},"scout-guard":{id:`scout-guard`,event:`PreToolUse`,tier:`safety`,description:`Blocks reads and searches inside generated, dependency, and git object directories.`,script:`scout-guard.mjs`,matcher:[`fileRead`,`fileSearch`],scope:`user`,patterns:[`node_modules/`,`dist/`,`.git/objects/`,`vendor/`,`build/`]},"subagent-context":{id:`subagent-context`,event:`SubagentStart`,tier:`efficiency`,description:`Injects compact project context into each subagent spawn to reduce repeated discovery.`,script:`subagent-context.mjs`,scope:`user`},"pre-compact-save":{id:`pre-compact-save`,event:`PreCompact`,tier:`efficiency`,description:`Persists critical state before context compaction truncates recent session history.`,script:`pre-compact-save.mjs`,scope:`user`},"post-edit-check":{id:`post-edit-check`,event:`PostToolUse`,tier:`nudge`,description:`After repeated file edits, injects a validation reminder so checks are not skipped.`,script:`post-edit-check.mjs`,matcher:[`fileWrite`],scope:`user`},"session-init":{id:`session-init`,event:`SessionStart`,tier:`nudge`,description:`Detects project stack and injects workspace metadata and environment context at startup.`,script:`session-init.mjs`,scope:`user`},"session-observer":{id:`session-observer`,event:`PostToolUse`,tier:`efficiency`,description:`Captures tool usage patterns for autonomous lesson extraction. Writes to session buffer.`,script:`session-observer.mjs`,scope:`user`},"session-learn":{id:`session-learn`,event:`Stop`,tier:`efficiency`,description:`Nudges final pattern analysis on buffered observations at session end.`,script:`session-learn.mjs`,scope:`user`}},qn={PreCompact:3e3,PostToolUse:3e3},Jn={copilot:`hooks.json`,claude:`hooks-settings.json`,copilotCli:`hooks.json`,hermes:`hooks.json`},Yn=Un;function Xn(e){if(!Yn.includes(e))throw Error(`Unknown platform: "${e}". Supported: ${Yn.join(`, `)}. Add it to SUPPORTED_PLATFORMS in exec-hooks.mjs first, then add entries to HOOK_EVENTS, HOOK_TOOL_MATCHERS, and FILE_NAMES.`);for(let[t,n]of Object.entries(Wn))if(!(e in n))throw Error(`Platform "${e}" is missing from HOOK_EVENTS.${t}. Add a "${e}" key to HOOK_EVENTS.${t} in exec-hooks.mjs.`);for(let[t,n]of Object.entries(Gn))if(!(e in n))throw Error(`Platform "${e}" is missing from HOOK_TOOL_MATCHERS.${t}. Add a "${e}" key to HOOK_TOOL_MATCHERS.${t} in exec-hooks.mjs.`);if(!(e in Jn))throw Error(`Platform "${e}" is missing from FILE_NAMES. Add "${e}: '<filename>'" to FILE_NAMES in adapters/hooks.mjs.`)}function Zn(e,t){return(e.matcher||[]).flatMap(e=>{let n=Gn[e];if(!n)throw Error(`Unknown hook matcher: ${e}`);return n[t]||[]})}function Qn(e,t,n,r){let i=`${n}/${e.script}`;return Zn(e,r),r===`copilot`?{event:t,steps:[{type:`command`,command:`node`,args:[i],timeout:qn[e.event]||5e3}]}:r===`claude`?{type:`command`,command:`node ${i}`}:{command:`node`,args:[i]}}function $n(e,t){if(Xn(e),e===`copilot`){let n=Object.values(Kn).map(n=>{let r=Wn[n.event]?.[e];if(!r)throw Error(`Unsupported hook event ${n.event} for ${e}`);return Qn(n,r,t,e)});return[{path:Jn[e],content:JSON.stringify({hooks:n},null,2)}]}let n={};for(let r of Object.values(Kn)){let i=Wn[r.event]?.[e];if(!i)throw Error(`Unsupported hook event ${r.event} for ${e}`);n[i]||=[],n[i].push(Qn(r,i,t,e))}return[{path:Jn[e],content:JSON.stringify({hooks:n},null,2)}]}function er(){return[`_runtime.mjs`,...Object.values(Kn).map(e=>e.script)]}function tr(){let e=nr();if(e)return e;let t={command:b.command,args:b.args?[...b.args]:void 0,type:b.type};if(process.platform!==`win32`){let e=process.env.PATH;e&&(t.env={PATH:e});try{let e=tn(`which`,[`node`],{encoding:`utf-8`,timeout:3e3}).trim();e&&w(e)&&(t.command=e)}catch{}}return t}function nr(){let e=M(z(),`.aikit`,`current-version.json`);if(!w(e))return null;try{let t=JSON.parse(E(e,`utf-8`));if(typeof t.version!=`string`||t.version.length===0)return null;let n=M(z(),`.aikit`,`versions`,`v${t.version}`,`packages`,`server`,`dist`,`bin.js`);if(!w(n))return null;let r={command:process.execPath,args:[n,`serve`],type:`stdio`};return process.platform!==`win32`&&process.env.PATH&&(r.env={PATH:process.env.PATH}),r}catch{return null}}const rr=new Set([`VS Code`,`VS Code Insiders`,`VSCodium`]);function ir(e,t,n){let r=P(z(),`.copilot`,`instructions`,`copilot-instructions.md`);!w(r)||n.has(r)||(T(j(r),{recursive:!0}),A(r,`---\napplyTo: "**"\n---\n\n${e}\n---\n\n${t}`,`utf-8`),n.add(r))}function ar(e,t=!1){if(!rr.has(e.name))return;let n=P(j(e.getConfigPath()),`settings.json`),r={};if(w(n))try{let e=E(n,`utf-8`);r=JSON.parse(e)}catch{console.log(` ${e.name}: skipped settings.json (invalid JSON)`);return}let i=!1;for(let[e,n]of Object.entries(fe))if(typeof n==`object`&&n){let t=typeof r[e]==`object`&&r[e]!==null?r[e]:{},a={...t,...n};JSON.stringify(a)!==JSON.stringify(t)&&(r[e]=a,i=!0)}else (t||!(e in r))&&(r[e]=n,i=!0);i&&(A(n,`${JSON.stringify(r,null,2)}\n`,`utf-8`),console.log(` ${e.name}: updated settings.json`))}async function or(r,o,s,c,l=!1){let u=new Map,d=new Set,f=le(`aikit`,s),p=pe(`aikit`,s);for(let e of o)e.getScaffoldRoot()!==null&&u.set(e.id,e);if(ir(f,p,d),u.size===0){d.size>0?console.log(` Instruction files: ${[...d].join(`, `)}`):console.log(` No IDEs with global scaffold support detected.`);return}let m=await n(r,`copilot`),ee=await n(r,`opencode`),te=await n(r,`hermes-agent`),ne=e=>{let t=new Map;for(let n of e){let e=n.path.indexOf(`/`);if(e===-1)continue;let r=n.path.substring(0,e);if(r===`agents`||r===`prompts`){let i=t.get(r)??[];i.push({path:n.path.substring(e+1),content:n.content}),t.set(r,i)}else if(r===`.opencode`){let r=n.path.indexOf(`/`,e+1);if(r!==-1&&n.path.substring(e+1,r)===`agents`){let e=t.get(`agents`)??[];e.push({path:n.path.substring(r+1),content:n.content}),t.set(`agents`,e)}}}return t},re=ne(m),ie=ne(ee),h=ne(te),ae=await n(r,`skills`),g=new Set;for(let e of ae){let t=e.path.indexOf(`/`);t!==-1&&g.add(e.path.substring(0,t))}let _=await n(r,`flows`),v=new Set;for(let e of _){let t=e.path.indexOf(`/`);t!==-1&&v.add(e.path.substring(0,t))}let y=await n(r,`claude-code`),oe=P(r,`scaffold`,`general`,`hooks`,`scripts`),b=w(oe)?oe:P(import.meta.dirname,`../../../../../scaffold/general/hooks/scripts`),se=er(),x=new Set,ce=new Set,S=new Set,ue=(n,r,o,s)=>{let u=s.get(o);if(!n||!r||!u||u.length===0)return;let d=`${o}:${r}:${n}`;if(x.has(d))return;x.add(d);let f=e(r)??a(c);f.version=c,i(u,n,f,o,l),t(r,f),S.add(j(r))},C=(n,r,o,s)=>{if(!n||!r||s.length===0)return;let u=`${o}:${r}:${n}`;if(x.has(u))return;if(x.add(u),o===`flows`&&!ce.has(n)){for(let e of v){let t=P(n,e,`skills`);w(t)&&(k(t,{recursive:!0,force:!0}),console.log(` ${j(r)}: migrated ${e} flow to steps/ layout`))}ce.add(n)}let d=e(r)??a(c);d.version=c,i(s,n,d,o,l),t(r,d),S.add(j(r))},de=(e,t,n)=>{!e||!t||C(e,t,`hooks`,[...$n(n,P(e,`scripts`).replace(/\\/g,`/`)),...se.map(e=>({path:`scripts/${e}`,content:E(P(b,e),`utf-8`)}))])};for(let e of u.values()){let t=e.getScaffoldPaths(),n=e.family===`opencode`?ie:e.family===`hermes`?h:re;ue(t.agents,t.manifest,`agents`,n),ue(t.prompts,t.manifest,`prompts`,n),C(t.skills,t.manifest,`skills`,ae),C(t.flows,t.manifest,`flows`,_),C(t.commands,t.manifest,`commands`,y),de(t.hooks,t.manifest,e.family===`claude`?`claude`:`copilot`)}for(let e of S)console.log(` ${e}: scaffold updated (${g.size} skills)`);for(let e of u.values()){let t=e.getScaffoldPaths().instructions;!t||d.has(t)||(T(j(t),{recursive:!0}),A(t,e.buildInstructionContent(f,p),`utf-8`),d.add(t))}d.size>0&&console.log(` Instruction files: ${[...d].join(`, `)}`)}function sr(e){let t=[];for(let n of e){let e=n.getScaffoldRoot();if(e)if(rr.has(n.name)){let r=n.getInstructionsRoot()??e;t.push(P(r,`kb.instructions.md`)),t.push(P(r,`aikit.instructions.md`))}else n.name===`Cursor`||n.name===`Cursor Nightly`?t.push(P(e,`rules`,`kb.mdc`)):n.name===`Windsurf`&&t.push(P(e,`rules`,`kb.md`))}for(let e of t)w(e)&&(xe(e),console.log(` Removed legacy file: ${e}`))}async function cr(e){let t=h,n=S(),r=JSON.parse(E(P(n,`package.json`),`utf-8`)).version;console.log(`Initializing @vpxa/aikit v${r}...\n`);let i=Oe();T(i,{recursive:!0}),console.log(` Global data store: ${i}`),Ne({version:1,workspaces:{}}),console.log(` Created registry.json`);let a=await Hn({scope:`user`});if(a.length===0)console.log(`
18
+ No supported IDEs detected. You can manually add the MCP server config.`);else{console.log(`\n Detected ${a.length} IDE(s):`);let n=tr();for(let e of a)try{await e.registerMcp(t,n),console.log(` ${e.name}: configured ${t}`)}catch(t){console.log(` ${e.name}: failed to configure (${t.message})`)}for(let t of a)ar(t,e.force)}console.log(`
19
+ Installing scaffold files:`),await or(n,a,t,r,e.force),sr(a),console.log(`
20
20
  User-level AI Kit installation complete!`),console.log(`
21
- Next steps:`),console.log(` 1. Open any workspace in your IDE`),console.log(` 2. The AI Kit server will auto-start and index the workspace`),console.log(` 3. Agents, prompts, skills & instructions are available globally`),console.log(` 4. No per-workspace init needed — just open a project and start coding`)}const or=[{directory:`.github/copilot/agents`,suffix:`.agent.md`},{directory:`.github/copilot/prompts`,suffix:`.prompt.md`},{directory:`.copilot/skills`,suffix:`/SKILL.md`},{directory:`.agents/skills`,suffix:`/SKILL.md`}],sr=[`.copilot/skills`,`.agents/skills`],cr=/^(?:mcp_)?aikit_[a-z0-9_]+$/;function lr(e,t){return(Ce(e,t)||t).split(`\\`).join(`/`)}function ur(e){let t=new Set;for(let n of or){let r=M(e,n.directory);if(w(r))try{for(let e of D(r,{withFileTypes:!0})){if(n.suffix===`/SKILL.md`){if(e.isDirectory()){let n=M(r,e.name,`SKILL.md`);w(n)&&t.add(n)}continue}e.isFile()&&e.name.endsWith(n.suffix)&&t.add(M(r,e.name))}}catch{}}return[...t].sort()}function dr(e){let t=new Set;for(let n of sr){let r=M(e,n);if(w(r))try{for(let e of D(r,{withFileTypes:!0}))e.isDirectory()&&t.add(e.name.toLowerCase())}catch{}}return t}function fr(e){if(!e.startsWith(`---`))return null;let t=e.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);return t?t[1]:null}function pr(e){let t=e.trim();if(!t)return[];let n=t.startsWith(`[`)&&t.endsWith(`]`)?t.slice(1,-1):t,r=[],i=``,a=null;for(let e of n){if((e===`"`||e===`'`)&&a===null){a=e,i+=e;continue}if(e===a){a=null,i+=e;continue}if(e===`,`&&a===null){let e=mr(i);e&&r.push(e),i=``;continue}i+=e}let o=mr(i);return o&&r.push(o),r}function mr(e){let t=e.trim();return t.startsWith(`"`)&&t.endsWith(`"`)||t.startsWith(`'`)&&t.endsWith(`'`)?t.slice(1,-1).trim():t}function hr(e){let t=e.trim();if(!t)return;if(t.startsWith(`[`)!==t.endsWith(`]`))return`inline array is missing a closing bracket`;if(!t.startsWith(`[`))return;let n=null;for(let e=1;e<t.length-1;e+=1){let r=t[e];if((r===`"`||r===`'`)&&n===null){n=r;continue}r===n&&(n=null)}if(n!==null)return`inline array has an unterminated quoted value`}function gr(e){if(!e.startsWith(`---`))return;let t=fr(e);if(t===null)return`frontmatter is missing a closing --- delimiter`;let n=!1;for(let e of t.split(/\r?\n/)){let t=e.trim();if(!t||t.startsWith(`#`))continue;if(n){if(/^\s{2,}[A-Za-z0-9_-]+:\s*.*$/.test(e))return hr(e.replace(/^\s{2,}[A-Za-z0-9_-]+:\s*/,``));n=!1}let r=e.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);if(!r)return`unsupported frontmatter line: ${t}`;let[,i,a]=r;if(i===`metadata`&&a.trim()===``){n=!0;continue}let o=hr(a);if(o)return o}}function _r(e,t){try{let n=E(t,`utf8`),i=gr(n);return{filePath:t,displayPath:lr(e,t),content:n,parsed:i?null:r(n),yamlError:i}}catch{return null}}function vr(e){return ur(e).map(t=>_r(e,t)).filter(e=>e!==null)}function yr(e){if(!e.parsed)return[];let t=e.parsed.fields.applyTo;return t?pr(t):[]}function br(e){let t=e.trim();if(!t)return`glob pattern is empty`;let n=[],r={"[":`]`,"{":`}`,"(":`)`},i=new Set(Object.values(r));for(let e=0;e<t.length;e+=1){let a=t[e];if(t[e-1]!==`\\`){if(a in r){n.push(r[a]);continue}if(i.has(a)&&n.pop()!==a)return`glob pattern has an unexpected '${a}'`}}if(n.length>0)return`glob pattern is missing '${n[n.length-1]}'`}function xr(e){let t=new Set;for(let n of e.matchAll(/<skill>\s*([a-z][a-z0-9-]*)\s*<\/skill>/gi))t.add(n[1].toLowerCase());let n=e.split(/\r?\n/),r=!1;for(let e of n){if(/^#{1,6}\s+skills\b/i.test(e)){r=!0;continue}if(r&&/^#{1,6}\s+/.test(e)&&(r=!1),!r)continue;let n=e.match(/^\|\s*([a-z][a-z0-9-]*)\s*\|/i);if(n){let e=n[1].toLowerCase();e!==`skill`&&t.add(e)}for(let n of e.matchAll(/`([a-z][a-z0-9-]*)`/gi))t.add(n[1].toLowerCase())}return[...t]}const Sr={name:`yaml-parse`,run:e=>{try{return vr(e).filter(e=>e.yamlError).map(e=>({severity:`error`,file:e.displayPath,message:`invalid YAML frontmatter: ${e.yamlError}`,code:`yaml-parse-error`}))}catch{return[]}}},Cr={name:`skill-refs`,run:e=>{try{let t=dr(e);if(t.size===0)return[];let n=[];for(let r of vr(e))if(r.filePath.endsWith(`.agent.md`))for(let e of xr(r.content))t.has(e)||n.push({severity:`warning`,file:r.displayPath,message:`referenced skill '${e}' was not found in .copilot/skills or .agents/skills`,code:`skill-ref-missing`});return n}catch{return[]}}},wr={name:`tool-names`,run:e=>{try{let t=[];for(let n of vr(e))if(n.parsed)for(let e of n.parsed.tools.map(mr))e&&!cr.test(e)&&t.push({severity:`warning`,file:n.displayPath,message:`tool '${e}' should use an aikit-prefixed name`,code:`tool-name-invalid`});return t}catch{return[]}}},Tr={name:`glob-patterns`,run:e=>{try{let t=[];for(let n of vr(e))if(n.parsed)for(let e of yr(n)){let r=br(e);r&&t.push({severity:`warning`,file:n.displayPath,message:`applyTo pattern '${e}' is invalid: ${r}`,code:`glob-pattern-invalid`})}return t}catch{return[]}}};async function K(e){let t=console.log;console.log=()=>{};try{return await e()}finally{console.log=t}}async function Er(e){let t=e.reset??!1,n=e.silent??!1,r=[],i=0,a=0,o=await Hn({scope:`user`}),s=Qn(),c=S(),l=oe(),u=e=>{r.push(e),a+=1,n||console.log(`- ${e}`)};for(let e of o){let n=e.getConfigPath();if(i+=1,!w(n)){T(j(n),{recursive:!0}),await K(()=>e.registerMcp(h,s)),u(`Fixed: ${e.name} — MCP config was missing, recreated`);continue}try{if(!(await e.readConfig())[e.configKey]?.aikit){T(j(n),{recursive:!0}),await K(()=>e.registerMcp(h,s)),u(`Fixed: ${e.name} — MCP entry was missing, added`);continue}t&&(T(j(n),{recursive:!0}),await K(()=>e.registerMcp(h,s)),u(`Reset: ${e.name} — MCP config restored to factory defaults`))}catch{ye(n,`${n}.bak`),T(j(n),{recursive:!0}),await K(()=>e.registerMcp(h,s)),u(`Fixed: ${e.name} — MCP config was corrupt, backed up and recreated`)}}await K(async()=>{for(let e of o)nr(e,t)}),await K(()=>rr(c,o,h,l??`0.0.0`,t));let d=[Sr,Cr,wr,Tr];for(let e of d)try{let t=e.run(process.cwd());for(let e of t)(e.severity===`error`||e.severity===`warning`)&&(n||console.warn(`[doctor:${e.code}] ${e.file}: ${e.message}`))}catch{}if(n){if(r.length>0)for(let e of r)console.error(`[doctor] ${e}`)}else r.length===0&&console.log(`- No MCP config issues found.`);return{checked:i,fixed:a,issues:r}}const Dr=[{name:`doctor`,description:`Check and repair AI Kit configuration files`,usage:`aikit doctor [--reset]`,run:async e=>{let t=e.includes(`--reset`);console.log(t?`Resetting AI Kit to factory defaults...
21
+ Next steps:`),console.log(` 1. Open any workspace in your IDE`),console.log(` 2. The AI Kit server will auto-start and index the workspace`),console.log(` 3. Agents, prompts, skills & instructions are available globally`),console.log(` 4. No per-workspace init needed — just open a project and start coding`)}const lr=[{directory:`.github/copilot/agents`,suffix:`.agent.md`},{directory:`.github/copilot/prompts`,suffix:`.prompt.md`},{directory:`.copilot/skills`,suffix:`/SKILL.md`},{directory:`.agents/skills`,suffix:`/SKILL.md`}],ur=[`.copilot/skills`,`.agents/skills`],dr=/^(?:mcp_)?aikit_[a-z0-9_]+$/;function fr(e,t){return(Ce(e,t)||t).split(`\\`).join(`/`)}function pr(e){let t=new Set;for(let n of lr){let r=M(e,n.directory);if(w(r))try{for(let e of D(r,{withFileTypes:!0})){if(n.suffix===`/SKILL.md`){if(e.isDirectory()){let n=M(r,e.name,`SKILL.md`);w(n)&&t.add(n)}continue}e.isFile()&&e.name.endsWith(n.suffix)&&t.add(M(r,e.name))}}catch{}}return[...t].sort()}function mr(e){let t=new Set;for(let n of ur){let r=M(e,n);if(w(r))try{for(let e of D(r,{withFileTypes:!0}))e.isDirectory()&&t.add(e.name.toLowerCase())}catch{}}return t}function hr(e){if(!e.startsWith(`---`))return null;let t=e.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);return t?t[1]:null}function gr(e){let t=e.trim();if(!t)return[];let n=t.startsWith(`[`)&&t.endsWith(`]`)?t.slice(1,-1):t,r=[],i=``,a=null;for(let e of n){if((e===`"`||e===`'`)&&a===null){a=e,i+=e;continue}if(e===a){a=null,i+=e;continue}if(e===`,`&&a===null){let e=_r(i);e&&r.push(e),i=``;continue}i+=e}let o=_r(i);return o&&r.push(o),r}function _r(e){let t=e.trim();return t.startsWith(`"`)&&t.endsWith(`"`)||t.startsWith(`'`)&&t.endsWith(`'`)?t.slice(1,-1).trim():t}function vr(e){let t=e.trim();if(!t)return;if(t.startsWith(`[`)!==t.endsWith(`]`))return`inline array is missing a closing bracket`;if(!t.startsWith(`[`))return;let n=null;for(let e=1;e<t.length-1;e+=1){let r=t[e];if((r===`"`||r===`'`)&&n===null){n=r;continue}r===n&&(n=null)}if(n!==null)return`inline array has an unterminated quoted value`}function yr(e){if(!e.startsWith(`---`))return;let t=hr(e);if(t===null)return`frontmatter is missing a closing --- delimiter`;let n=!1;for(let e of t.split(/\r?\n/)){let t=e.trim();if(!t||t.startsWith(`#`))continue;if(n){if(/^\s{2,}[A-Za-z0-9_-]+:\s*.*$/.test(e))return vr(e.replace(/^\s{2,}[A-Za-z0-9_-]+:\s*/,``));n=!1}let r=e.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);if(!r)return`unsupported frontmatter line: ${t}`;let[,i,a]=r;if(i===`metadata`&&a.trim()===``){n=!0;continue}let o=vr(a);if(o)return o}}function br(e,t){try{let n=E(t,`utf8`),i=yr(n);return{filePath:t,displayPath:fr(e,t),content:n,parsed:i?null:r(n),yamlError:i}}catch{return null}}function xr(e){return pr(e).map(t=>br(e,t)).filter(e=>e!==null)}function Sr(e){if(!e.parsed)return[];let t=e.parsed.fields.applyTo;return t?gr(t):[]}function Cr(e){let t=e.trim();if(!t)return`glob pattern is empty`;let n=[],r={"[":`]`,"{":`}`,"(":`)`},i=new Set(Object.values(r));for(let e=0;e<t.length;e+=1){let a=t[e];if(t[e-1]!==`\\`){if(a in r){n.push(r[a]);continue}if(i.has(a)&&n.pop()!==a)return`glob pattern has an unexpected '${a}'`}}if(n.length>0)return`glob pattern is missing '${n[n.length-1]}'`}function wr(e){let t=new Set;for(let n of e.matchAll(/<skill>\s*([a-z][a-z0-9-]*)\s*<\/skill>/gi))t.add(n[1].toLowerCase());let n=e.split(/\r?\n/),r=!1;for(let e of n){if(/^#{1,6}\s+skills\b/i.test(e)){r=!0;continue}if(r&&/^#{1,6}\s+/.test(e)&&(r=!1),!r)continue;let n=e.match(/^\|\s*([a-z][a-z0-9-]*)\s*\|/i);if(n){let e=n[1].toLowerCase();e!==`skill`&&t.add(e)}for(let n of e.matchAll(/`([a-z][a-z0-9-]*)`/gi))t.add(n[1].toLowerCase())}return[...t]}const Tr={name:`yaml-parse`,run:e=>{try{return xr(e).filter(e=>e.yamlError).map(e=>({severity:`error`,file:e.displayPath,message:`invalid YAML frontmatter: ${e.yamlError}`,code:`yaml-parse-error`}))}catch{return[]}}},Er={name:`skill-refs`,run:e=>{try{let t=mr(e);if(t.size===0)return[];let n=[];for(let r of xr(e))if(r.filePath.endsWith(`.agent.md`))for(let e of wr(r.content))t.has(e)||n.push({severity:`warning`,file:r.displayPath,message:`referenced skill '${e}' was not found in .copilot/skills or .agents/skills`,code:`skill-ref-missing`});return n}catch{return[]}}},Dr={name:`tool-names`,run:e=>{try{let t=[];for(let n of xr(e))if(n.parsed)for(let e of n.parsed.tools.map(_r))e&&!dr.test(e)&&t.push({severity:`warning`,file:n.displayPath,message:`tool '${e}' should use an aikit-prefixed name`,code:`tool-name-invalid`});return t}catch{return[]}}},Or={name:`glob-patterns`,run:e=>{try{let t=[];for(let n of xr(e))if(n.parsed)for(let e of Sr(n)){let r=Cr(e);r&&t.push({severity:`warning`,file:n.displayPath,message:`applyTo pattern '${e}' is invalid: ${r}`,code:`glob-pattern-invalid`})}return t}catch{return[]}}};async function K(e){let t=console.log;console.log=()=>{};try{return await e()}finally{console.log=t}}async function kr(e){let t=e.reset??!1,n=e.silent??!1,r=[],i=0,a=0,o=await Hn({scope:`user`}),s=tr(),c=S(),l=oe(),u=e=>{r.push(e),a+=1,n||console.log(`- ${e}`)};for(let e of o){let n=e.getConfigPath();if(i+=1,!w(n)){T(j(n),{recursive:!0}),await K(()=>e.registerMcp(h,s)),u(`Fixed: ${e.name} — MCP config was missing, recreated`);continue}try{if(!(await e.readConfig())[e.configKey]?.aikit){T(j(n),{recursive:!0}),await K(()=>e.registerMcp(h,s)),u(`Fixed: ${e.name} — MCP entry was missing, added`);continue}t&&(T(j(n),{recursive:!0}),await K(()=>e.registerMcp(h,s)),u(`Reset: ${e.name} — MCP config restored to factory defaults`))}catch{ye(n,`${n}.bak`),T(j(n),{recursive:!0}),await K(()=>e.registerMcp(h,s)),u(`Fixed: ${e.name} — MCP config was corrupt, backed up and recreated`)}}await K(async()=>{for(let e of o)ar(e,t)}),await K(()=>or(c,o,h,l??`0.0.0`,t));let d=[Tr,Er,Dr,Or];for(let e of d)try{let t=e.run(process.cwd());for(let e of t)(e.severity===`error`||e.severity===`warning`)&&(n||console.warn(`[doctor:${e.code}] ${e.file}: ${e.message}`))}catch{}if(n){if(r.length>0)for(let e of r)console.error(`[doctor] ${e}`)}else r.length===0&&console.log(`- No MCP config issues found.`);return{checked:i,fixed:a,issues:r}}const Ar=[{name:`doctor`,description:`Check and repair AI Kit configuration files`,usage:`aikit doctor [--reset]`,run:async e=>{let t=e.includes(`--reset`);console.log(t?`Resetting AI Kit to factory defaults...
22
22
  `:`Running AI Kit doctor...
23
- `);let n=await Er({reset:t,silent:!1});if(console.log(`\nDone: ${n.checked} checked, ${n.fixed} fixed.`),n.issues.length>0){console.log(`
24
- Issues found:`);for(let e of n.issues)console.log(` - ${e}`)}}}],Or=[{name:`proc`,description:`Manage in-memory child processes`,usage:`aikit proc <start|stop|status|list|logs> ...`,run:async e=>{let t=e.shift()?.trim()??``;switch(t){case`start`:{let t=e.shift()?.trim(),n=e.shift()?.trim();(!t||!n)&&(console.error(`Usage: aikit proc start <id> <command> [args...]`),process.exit(1)),c(Tt(t,n,e));return}case`stop`:{let t=e.shift()?.trim();t||(console.error(`Usage: aikit proc stop <id>`),process.exit(1));let n=Dt(t);if(!n){console.log(`No managed process found: ${t}`);return}c(n);return}case`status`:{let t=e.shift()?.trim();t||(console.error(`Usage: aikit proc status <id>`),process.exit(1));let n=Et(t);if(!n){console.log(`No managed process found: ${t}`);return}c(n);return}case`list`:{let e=Ct();if(e.length===0){console.log(`No managed processes.`);return}for(let t of e)c(t),console.log(``);return}case`logs`:{let t=_(e,`--tail`,50),n=e.shift()?.trim();n||(console.error(`Usage: aikit proc logs <id> [--tail N]`),process.exit(1));let r=wt(n,t);if(r.length===0){console.log(`No logs found for process: ${n}`);return}for(let e of r)console.log(e);return}default:console.error(`Unknown proc action: ${t}`),console.error(`Actions: start, stop, status, list, logs`),process.exit(1)}}},{name:`watch`,description:`Manage in-memory filesystem watchers`,usage:`aikit watch <start|stop|list> ...`,run:async e=>{let t=e.shift()?.trim()??``;switch(t){case`start`:{let t=e.shift()?.trim();t||(console.error(`Usage: aikit watch start <path>`),process.exit(1));let n=$t({path:P(t)});console.log(`Started watcher: ${n.id}`),console.log(` Path: ${n.path}`),console.log(` Status: ${n.status}`);return}case`stop`:{let t=e.shift()?.trim();t||(console.error(`Usage: aikit watch stop <id>`),process.exit(1));let n=en(t);console.log(n?`Stopped watcher: ${t}`:`Watcher not found: ${t}`);return}case`list`:{let e=Qt();if(e.length===0){console.log(`No active watchers.`);return}for(let t of e)console.log(`${t.id}`),console.log(` Path: ${t.path}`),console.log(` Status: ${t.status}`),console.log(` Events: ${t.eventCount}`);return}default:console.error(`Unknown watch action: ${t}`),console.error(`Actions: start, stop, list`),process.exit(1)}}},{name:`delegate`,description:`Delegate a task to a local Ollama model`,usage:`aikit delegate [--model name] [--system prompt] [--temp 0.3] <prompt | --stdin>`,run:async e=>{if((e[0]===`models`?e.shift():void 0)===`models`){try{let e=await nt();if(e.length===0){console.log(`No Ollama models available. Pull one with: ollama pull gemma4:e2b`);return}for(let t of e)console.log(t)}catch{console.error(`Ollama is not running. Start it with: ollama serve`),process.exit(1)}return}let t=v(e,`--model`,``),n=v(e,`--system`,``),r=_(e,`--temp`,.3),i=v(e,`--context`,``),a=e.join(` `);a||=await m(),a||(console.error(`Usage: aikit delegate [--model name] <prompt>`),process.exit(1));let o;i&&(o=await Be(P(i),`utf-8`));let s=await tt({prompt:a,model:t||void 0,system:n||void 0,context:o,temperature:r});s.error&&(console.error(`Error: ${s.error}`),process.exit(1)),console.log(s.response),console.error(`\n(${s.model}, ${s.durationMs}ms, ${s.tokenCount??`?`} tokens)`)}}],kr=[{name:`eval`,description:`Evaluate JavaScript or TypeScript in a constrained VM sandbox`,usage:`aikit eval [code] [--lang js|ts] [--timeout ms]`,run:async e=>{let t=v(e,`--lang`,`js`),n=_(e,`--timeout`,5e3),r=e.join(` `),i=r.trim()?``:await m(),a=r||i;if(!a.trim())throw new g(`Usage: aikit eval [code] [--lang js|ts] [--timeout ms]`);let o=await at({code:a,lang:t===`ts`?`ts`:`js`,timeout:n});if(!o.success){console.error(`Eval failed in ${o.durationMs}ms: ${o.error}`),process.exitCode=1;return}console.log(`Eval succeeded in ${o.durationMs}ms`),console.log(`─`.repeat(60)),console.log(o.output)}},{name:`proxy`,description:`Run stdio-to-HTTP proxy for IDE MCP integration`,usage:`aikit proxy [--port port] [--no-auto-start]`,run:async e=>{let t=_(e,`--port`,3210),n=!me(e,`--no-auto-start`),{runProxy:r}=await import(`../../server/dist/proxy.js`);await r({port:t,autoStart:n})}},{name:`test`,description:`Run Vitest for all tests or a specific subset`,usage:`aikit test [files...] [--grep pattern] [--cwd path] [--timeout ms]`,run:async e=>{let t=v(e,`--grep`,``).trim()||void 0,n=v(e,`--cwd`,``).trim()||void 0,r=_(e,`--timeout`,6e4),i=e.filter(Boolean),a=await Xt({files:i.length>0?i:void 0,grep:t,cwd:n,timeout:r});o(a),a.passed||(process.exitCode=1)}},{name:`rename`,description:`Rename a symbol across files using whole-word regex matching`,usage:`aikit rename <old> <new> <path> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]`,run:async e=>{let t=e.shift()?.trim()??``,n=e.shift()?.trim()??``,r=e.shift()?.trim()??``;if(!t||!n||!r)throw new g(`Usage: aikit rename <old> <new> <path> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]`);let i=d(v(e,`--extensions`,``)),a=d(v(e,`--exclude`,``)),o=await Rt({oldName:t,newName:n,rootPath:P(r),extensions:i.length>0?i:void 0,exclude:a.length>0?a:void 0,dryRun:me(e,`--dry-run`)});console.log(JSON.stringify(o,null,2))}},{name:`codemod`,description:`Apply regex-based codemod rules from a JSON file across a path`,usage:`aikit codemod <path> --rules <file.json> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]`,run:async e=>{let t=e.shift()?.trim()??``,n=v(e,`--rules`,``).trim();if(!t||!n)throw new g(`Usage: aikit codemod <path> --rules <file.json> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]`);let r=await Be(P(n),`utf-8`),i;try{i=JSON.parse(r)}catch{throw Error(`Failed to parse rules file as JSON: ${n}`)}if(!Array.isArray(i))throw Error(`Codemod rules file must contain a JSON array.`);let a=d(v(e,`--extensions`,``)),o=d(v(e,`--exclude`,``)),s=await Qe({rootPath:P(t),rules:i,extensions:a.length>0?a:void 0,exclude:o.length>0?o:void 0,dryRun:me(e,`--dry-run`)});console.log(JSON.stringify(s,null,2))}},{name:`transform`,description:`Apply jq-like transforms to JSON from stdin`,usage:`cat data.json | aikit transform <expression>`,run:async e=>{let t=e.join(` `).trim(),n=await m();if(!t||!n.trim())throw new g(`Usage: cat data.json | aikit transform <expression>`);let r=et({input:n,expression:t});console.log(r.outputString)}}];async function Ar(){let e=await import(`../../flows/dist/index.js`),{FlowLoader:t,FlowRegistryManager:n,FlowStateMachine:r,GitInstaller:i}=e,a=typeof e.getBuiltinFlows==`function`?e.getBuiltinFlows:void 0,o=un(),s=o.stateDir;if(!s)throw Error(`stateDir not configured`);let c=M(s,`flows`,`installed`),l=M(Oe(),`flows`);T(l,{recursive:!0});let u=M(l,`registry.json`),d=o.sources[0].path,f=M(d,`.flows`);return{loader:new t,registry:new n(u),stateMachine:new r(f,{before:[],after:[{id:`_docs-sync`,description:`Synchronize project documentation — update docs/ folder based on changes made during the flow.`,position:`after`,skills:[`docs`]}]}),git:new i(c),getBuiltinFlows:a,cwd:d}}const jr=[e=>M(`skills`,e,`SKILL.md`),e=>M(`skills`,e,`README.md`),e=>M(e,`SKILL.md`),e=>M(e,`README.md`)];function Mr(e,t){for(let n of t.steps){let t=M(e,n.instruction);if(w(t))continue;let r=!1;for(let i of jr){let a=M(e,i(n.id));if(w(a)){let e=j(t);w(e)||T(e,{recursive:!0}),ye(a,t),r=!0;break}}r||console.warn(`Warning: instruction file for step "${n.id}" not found.\n Expected: ${n.instruction}\n Searched: ${jr.map(e=>e(n.id)).join(`, `)}`)}}const Nr=[{name:`flow`,description:`Manage pluggable development flows`,usage:`flow <add|remove|list|info|use|update|status|start|reset> [args]`,run:async e=>{let t=e[0];if(!t){console.log(`Usage: aikit flow <add|remove|list|info|use|update|status|start|reset|runs>`),console.log(``),console.log(`Commands:`),console.log(` add <source> Install a flow from git URL or local path`),console.log(` remove <name> Remove an installed flow`),console.log(` list List all installed flows`),console.log(` info <name> Show details of a flow`),console.log(` use <name> Set active flow (start it)`),console.log(` update <name> Update a flow from its source`),console.log(` status Show current flow execution status`),console.log(` start [name] Start a flow (or resume)`),console.log(` reset Reset the active flow`),console.log(` runs List all flow runs`);return}let n=await Ar();switch(t){case`add`:{let t=e[1];if(!t){console.error(`Usage: aikit flow add <source>`),console.error(` source: git URL (https://...) or local path`);return}let r=t.startsWith(`http`)||t.startsWith(`git@`)||t.endsWith(`.git`),i=P(t),a=w(i);if(!r&&!a){console.error(`Source not found: ${t}`),console.error(`Provide a git URL or existing local path.`);return}let o,s;if(r){console.log(`Cloning ${t}...`);let e=n.git.clone(t);if(!e.success||!e.data){console.error(e.error??`Failed to clone flow`);return}o=e.data,s=`git`}else{let r=e[2]||Se(i);console.log(`Copying local flow from ${t}...`);let a=n.git.copyLocal(i,r);if(!a.success||!a.data){console.error(a.error??`Failed to copy local flow`);return}o=a.data,s=`local`}let c=await n.loader.load(o);if(!c.success||!c.data){console.error(c.error??`Failed to load flow`),n.git.remove(o);return}let{manifest:l,format:u}=c.data;if(Mr(o,l),l.install.length>0){console.log(`Installing ${l.install.length} dependencies...`);let e=n.git.runInstallDeps(l.install);if(!e.success){console.error(`Dependency install failed: ${e.error}`),n.git.remove(o);return}}let d=new Date().toISOString(),f=n.registry.register({name:l.name,version:l.version,source:t,sourceType:s,installPath:o,format:u,registeredAt:d,updatedAt:d,manifest:l});if(!f.success){console.error(f.error??`Failed to register flow`),n.git.remove(o);return}console.log(`✓ Flow "${l.name}" v${l.version} installed (${u} format)`),console.log(` Steps: ${l.steps.map(e=>e.id).join(` → `)}`);break}case`remove`:{let t=e[1];if(!t){console.error(`Usage: aikit flow remove <name>`);return}let r=n.registry.get(t);if(!r){console.error(`Flow "${t}" not found`);return}let i=n.git.remove(r.installPath);if(!i.success){console.error(i.error??`Failed to remove flow files`);return}let a=n.registry.unregister(t);if(!a.success){console.error(a.error??`Failed to unregister flow`);return}console.log(`✓ Flow "${t}" removed`);break}case`list`:{let e=n.registry.list();if(e.length===0){console.log("No flows installed. Use `aikit flow add <source>` to install one.");return}console.log(`Installed Flows:`),console.log(`─`.repeat(60));for(let t of e){let e=t.manifest.steps.map(e=>e.id).join(` → `);console.log(` ${t.name} v${t.version} (${t.sourceType}, ${t.format})`),console.log(` Steps: ${e}`)}let t=n.stateMachine.getStatus();t.success&&t.data&&(console.log(``),console.log(`Active: ${t.data.flow} (${t.data.status}, step: ${t.data.currentStep??`done`})`));break}case`info`:{let t=e[1];if(!t){console.error(`Usage: aikit flow info <name>`);return}let r=n.registry.get(t);if(!r){console.error(`Flow "${t}" not found`);return}console.log(`Flow: ${r.name}`),console.log(`Version: ${r.version}`),console.log(`Source: ${r.source} (${r.sourceType})`),console.log(`Format: ${r.format}`),console.log(`Path: ${r.installPath}`),console.log(`Registered: ${r.registeredAt}`),console.log(`Updated: ${r.updatedAt}`),console.log(``),console.log(`Steps:`);for(let e of r.manifest.steps){let t=e.requires.length?` (requires: ${e.requires.join(`, `)})`:``;console.log(` ${e.id}: ${e.name}${t}`),console.log(` Skill: ${e.skill}`),console.log(` Produces: ${e.produces.join(`, `)}`)}if(r.manifest.install.length>0){console.log(``),console.log(`Dependencies:`);for(let e of r.manifest.install)console.log(` ${e}`)}break}case`use`:case`start`:{let r=e[1],i=r?n.registry.get(r):null;if(t===`use`&&!r){console.error(`Usage: aikit flow use <name>`);return}if(t===`start`&&!r){let e=n.stateMachine.getStatus();if(e.success&&e.data&&e.data.status===`active`){console.log(`Resuming flow: ${e.data.flow}`),console.log(`Current step: ${e.data.currentStep}`),console.log(`Completed: ${e.data.completedSteps.join(`, `)||`none`}`);return}console.error("No active flow. Use `aikit flow start <name>` to begin one.");return}if(!i){console.error(`Flow "${r}" not found. Use \`aikit flow list\` to see installed flows.`);return}let a=e[2],o=n.stateMachine.start(i.name,i.manifest,a);if(!o.success||!o.data){console.error(o.error??`Failed to start flow`);return}let s=o.data;console.log(`✓ Flow "${i.name}" started`),console.log(` Topic: ${s.topic}`),console.log(` Run directory: ${s.runDir}`),console.log(` Current step: ${s.currentStep}`),console.log(` Steps: ${i.manifest.steps.map(e=>e.id).join(` → `)}`);break}case`update`:{let t=e[1];if(!t){console.error(`Usage: aikit flow update <name>`);return}let r=n.registry.get(t);if(!r){console.error(`Flow "${t}" not found`);return}if(r.sourceType!==`git`){console.error(`Flow "${t}" is ${r.sourceType}, not updatable via git`);return}console.log(`Updating ${t}...`);let i=n.git.update(r.installPath);if(!i.success){console.error(i.error??`Failed to update flow`);return}let a=await n.loader.load(r.installPath);if(a.success&&a.data){let e=new Date().toISOString(),t=n.registry.register({...r,version:a.data.manifest.version,format:a.data.format,manifest:a.data.manifest,updatedAt:e});if(!t.success){console.error(t.error??`Failed to refresh flow registry entry`);return}}console.log(`✓ Flow "${t}" updated`);break}case`status`:{let e=n.stateMachine.getStatus();if(!e.success||!e.data){console.log(`No active flow.`);return}let t=e.data;if(console.log(`Flow: ${t.flow}`),console.log(`Topic: ${t.topic}`),console.log(`Slug: ${t.slug}`),console.log(`Run Dir: ${t.runDir}`),console.log(`Status: ${t.status}`),console.log(`Current Step: ${t.currentStep??`(completed)`}`),console.log(`Completed: ${t.completedSteps.join(`, `)||`none`}`),t.skippedSteps.length>0&&console.log(`Skipped: ${t.skippedSteps.join(`, `)}`),console.log(`Started: ${t.startedAt}`),console.log(`Updated: ${t.updatedAt}`),Object.keys(t.artifacts).length>0){console.log(`Artifacts:`);for(let[e,n]of Object.entries(t.artifacts))console.log(` ${e}: ${n}`)}break}case`reset`:{let e=n.stateMachine.reset();if(!e.success){console.error(e.error??`Failed to reset flow state`);return}console.log(`✓ Flow abandoned`);break}case`runs`:{let t=e[1],r=e[2],i=n.stateMachine.listRuns({flow:t,status:r});if(i.length===0){console.log(`No flow runs found.`);return}console.log(`Flow Runs:`),console.log(`─`.repeat(80));for(let e of i){let t=e.currentStep?` → ${e.currentStep}`:``;console.log(` ${e.id} [${e.status}] ${e.flow}${t}`),console.log(` Topic: ${e.topic}`),console.log(` Started: ${e.startedAt} | Updated: ${e.updatedAt}`)}break}default:console.error(`Unknown flow command: ${t}`),console.log("Use `aikit flow` for help.")}}}],q=L(`cli:gc`),Pr=M(z(),`.aikit`,`versions`),Fr=M(z(),`.aikit`,`current-version.json`);function Ir(e){let t=e.match(/^v(\d+)\.(\d+)\.(\d+)$/);return t?{major:Number.parseInt(t[1],10),minor:Number.parseInt(t[2],10),patch:Number.parseInt(t[3],10)}:null}function Lr(e,t){return e.major===t.major?e.minor===t.minor?t.patch-e.patch:t.minor-e.minor:t.major-e.major}function Rr(){try{return w(Fr)?JSON.parse(E(Fr,`utf-8`)).version??null:null}catch{return null}}const zr=[{name:`gc`,description:`Free disk space by removing old AI Kit versions (keeps current + last N)`,usage:`aikit gc [--keep N]`,run:async e=>{if(!w(Pr)){q.info(`No version directories found.`);return}let t=_(e,`--keep`,2),n=Rr(),r=D(Pr,{withFileTypes:!0}),i=new Set(r.filter(e=>e.isDirectory()&&(e.name.includes(`-staging`)||e.name.startsWith(`_offline-detect-`)||e.name.startsWith(`_aikit-tarball-staging-`))).map(e=>e.name));for(let e of i)await He(M(Pr,e),{recursive:!0,force:!0}),q.debug(`Removed ${e}`);let a=r.filter(e=>e.isDirectory()&&!i.has(e.name)).map(e=>({name:e.name,semver:Ir(e.name)})).filter(e=>e.semver!==null).sort((e,t)=>Lr(e.semver,t.semver));if(a.length===0){q.info(`No version directories found.`);return}let o=new Set;n&&o.add(`v${n}`);for(let e of a){if(o.size>=t+ +!!n)break;o.add(e.name)}let s=a.filter(e=>!o.has(e.name));if(s.length===0){q.info(`No versions to clean`);return}for(let e of s)await He(M(Pr,e.name),{recursive:!0,force:!0}),q.debug(`Removed ${e.name}`);q.info(`Removed ${s.length} versions`)}}];let Br=null;async function J(){return Br||=await pn(),Br}function Vr(){return Br}const Hr=[{name:`graph`,description:`Query the knowledge graph`,usage:`aikit graph <action> [options]
23
+ `);let n=await kr({reset:t,silent:!1});if(console.log(`\nDone: ${n.checked} checked, ${n.fixed} fixed.`),n.issues.length>0){console.log(`
24
+ Issues found:`);for(let e of n.issues)console.log(` - ${e}`)}}}],jr=[{name:`proc`,description:`Manage in-memory child processes`,usage:`aikit proc <start|stop|status|list|logs> ...`,run:async e=>{let t=e.shift()?.trim()??``;switch(t){case`start`:{let t=e.shift()?.trim(),n=e.shift()?.trim();(!t||!n)&&(console.error(`Usage: aikit proc start <id> <command> [args...]`),process.exit(1)),c(Tt(t,n,e));return}case`stop`:{let t=e.shift()?.trim();t||(console.error(`Usage: aikit proc stop <id>`),process.exit(1));let n=Dt(t);if(!n){console.log(`No managed process found: ${t}`);return}c(n);return}case`status`:{let t=e.shift()?.trim();t||(console.error(`Usage: aikit proc status <id>`),process.exit(1));let n=Et(t);if(!n){console.log(`No managed process found: ${t}`);return}c(n);return}case`list`:{let e=Ct();if(e.length===0){console.log(`No managed processes.`);return}for(let t of e)c(t),console.log(``);return}case`logs`:{let t=_(e,`--tail`,50),n=e.shift()?.trim();n||(console.error(`Usage: aikit proc logs <id> [--tail N]`),process.exit(1));let r=wt(n,t);if(r.length===0){console.log(`No logs found for process: ${n}`);return}for(let e of r)console.log(e);return}default:console.error(`Unknown proc action: ${t}`),console.error(`Actions: start, stop, status, list, logs`),process.exit(1)}}},{name:`watch`,description:`Manage in-memory filesystem watchers`,usage:`aikit watch <start|stop|list> ...`,run:async e=>{let t=e.shift()?.trim()??``;switch(t){case`start`:{let t=e.shift()?.trim();t||(console.error(`Usage: aikit watch start <path>`),process.exit(1));let n=$t({path:P(t)});console.log(`Started watcher: ${n.id}`),console.log(` Path: ${n.path}`),console.log(` Status: ${n.status}`);return}case`stop`:{let t=e.shift()?.trim();t||(console.error(`Usage: aikit watch stop <id>`),process.exit(1));let n=en(t);console.log(n?`Stopped watcher: ${t}`:`Watcher not found: ${t}`);return}case`list`:{let e=Qt();if(e.length===0){console.log(`No active watchers.`);return}for(let t of e)console.log(`${t.id}`),console.log(` Path: ${t.path}`),console.log(` Status: ${t.status}`),console.log(` Events: ${t.eventCount}`);return}default:console.error(`Unknown watch action: ${t}`),console.error(`Actions: start, stop, list`),process.exit(1)}}},{name:`delegate`,description:`Delegate a task to a local Ollama model`,usage:`aikit delegate [--model name] [--system prompt] [--temp 0.3] <prompt | --stdin>`,run:async e=>{if((e[0]===`models`?e.shift():void 0)===`models`){try{let e=await nt();if(e.length===0){console.log(`No Ollama models available. Pull one with: ollama pull gemma4:e2b`);return}for(let t of e)console.log(t)}catch{console.error(`Ollama is not running. Start it with: ollama serve`),process.exit(1)}return}let t=v(e,`--model`,``),n=v(e,`--system`,``),r=_(e,`--temp`,.3),i=v(e,`--context`,``),a=e.join(` `);a||=await m(),a||(console.error(`Usage: aikit delegate [--model name] <prompt>`),process.exit(1));let o;i&&(o=await Be(P(i),`utf-8`));let s=await tt({prompt:a,model:t||void 0,system:n||void 0,context:o,temperature:r});s.error&&(console.error(`Error: ${s.error}`),process.exit(1)),console.log(s.response),console.error(`\n(${s.model}, ${s.durationMs}ms, ${s.tokenCount??`?`} tokens)`)}}],Mr=[{name:`eval`,description:`Evaluate JavaScript or TypeScript in a constrained VM sandbox`,usage:`aikit eval [code] [--lang js|ts] [--timeout ms]`,run:async e=>{let t=v(e,`--lang`,`js`),n=_(e,`--timeout`,5e3),r=e.join(` `),i=r.trim()?``:await m(),a=r||i;if(!a.trim())throw new g(`Usage: aikit eval [code] [--lang js|ts] [--timeout ms]`);let o=await at({code:a,lang:t===`ts`?`ts`:`js`,timeout:n});if(!o.success){console.error(`Eval failed in ${o.durationMs}ms: ${o.error}`),process.exitCode=1;return}console.log(`Eval succeeded in ${o.durationMs}ms`),console.log(`─`.repeat(60)),console.log(o.output)}},{name:`proxy`,description:`Run stdio-to-HTTP proxy for IDE MCP integration`,usage:`aikit proxy [--port port] [--no-auto-start]`,run:async e=>{let t=_(e,`--port`,3210),n=!me(e,`--no-auto-start`),{runProxy:r}=await import(`../../server/dist/proxy.js`);await r({port:t,autoStart:n})}},{name:`test`,description:`Run Vitest for all tests or a specific subset`,usage:`aikit test [files...] [--grep pattern] [--cwd path] [--timeout ms]`,run:async e=>{let t=v(e,`--grep`,``).trim()||void 0,n=v(e,`--cwd`,``).trim()||void 0,r=_(e,`--timeout`,6e4),i=e.filter(Boolean),a=await Xt({files:i.length>0?i:void 0,grep:t,cwd:n,timeout:r});o(a),a.passed||(process.exitCode=1)}},{name:`rename`,description:`Rename a symbol across files using whole-word regex matching`,usage:`aikit rename <old> <new> <path> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]`,run:async e=>{let t=e.shift()?.trim()??``,n=e.shift()?.trim()??``,r=e.shift()?.trim()??``;if(!t||!n||!r)throw new g(`Usage: aikit rename <old> <new> <path> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]`);let i=d(v(e,`--extensions`,``)),a=d(v(e,`--exclude`,``)),o=await Rt({oldName:t,newName:n,rootPath:P(r),extensions:i.length>0?i:void 0,exclude:a.length>0?a:void 0,dryRun:me(e,`--dry-run`)});console.log(JSON.stringify(o,null,2))}},{name:`codemod`,description:`Apply regex-based codemod rules from a JSON file across a path`,usage:`aikit codemod <path> --rules <file.json> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]`,run:async e=>{let t=e.shift()?.trim()??``,n=v(e,`--rules`,``).trim();if(!t||!n)throw new g(`Usage: aikit codemod <path> --rules <file.json> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]`);let r=await Be(P(n),`utf-8`),i;try{i=JSON.parse(r)}catch{throw Error(`Failed to parse rules file as JSON: ${n}`)}if(!Array.isArray(i))throw Error(`Codemod rules file must contain a JSON array.`);let a=d(v(e,`--extensions`,``)),o=d(v(e,`--exclude`,``)),s=await Qe({rootPath:P(t),rules:i,extensions:a.length>0?a:void 0,exclude:o.length>0?o:void 0,dryRun:me(e,`--dry-run`)});console.log(JSON.stringify(s,null,2))}},{name:`transform`,description:`Apply jq-like transforms to JSON from stdin`,usage:`cat data.json | aikit transform <expression>`,run:async e=>{let t=e.join(` `).trim(),n=await m();if(!t||!n.trim())throw new g(`Usage: cat data.json | aikit transform <expression>`);let r=et({input:n,expression:t});console.log(r.outputString)}}];async function Nr(){let e=await import(`../../flows/dist/index.js`),{FlowLoader:t,FlowRegistryManager:n,FlowStateMachine:r,GitInstaller:i}=e,a=typeof e.getBuiltinFlows==`function`?e.getBuiltinFlows:void 0,o=un(),s=o.stateDir;if(!s)throw Error(`stateDir not configured`);let c=M(s,`flows`,`installed`),l=M(Oe(),`flows`);T(l,{recursive:!0});let u=M(l,`registry.json`),d=o.sources[0].path,f=M(d,`.flows`);return{loader:new t,registry:new n(u),stateMachine:new r(f,{before:[],after:[{id:`_docs-sync`,description:`Synchronize project documentation — update docs/ folder based on changes made during the flow.`,position:`after`,skills:[`docs`]}]}),git:new i(c),getBuiltinFlows:a,cwd:d}}const Pr=[e=>M(`skills`,e,`SKILL.md`),e=>M(`skills`,e,`README.md`),e=>M(e,`SKILL.md`),e=>M(e,`README.md`)];function Fr(e,t){for(let n of t.steps){let t=M(e,n.instruction);if(w(t))continue;let r=!1;for(let i of Pr){let a=M(e,i(n.id));if(w(a)){let e=j(t);w(e)||T(e,{recursive:!0}),ye(a,t),r=!0;break}}r||console.warn(`Warning: instruction file for step "${n.id}" not found.\n Expected: ${n.instruction}\n Searched: ${Pr.map(e=>e(n.id)).join(`, `)}`)}}const Ir=[{name:`flow`,description:`Manage pluggable development flows`,usage:`flow <add|remove|list|info|use|update|status|start|reset> [args]`,run:async e=>{let t=e[0];if(!t){console.log(`Usage: aikit flow <add|remove|list|info|use|update|status|start|reset|runs>`),console.log(``),console.log(`Commands:`),console.log(` add <source> Install a flow from git URL or local path`),console.log(` remove <name> Remove an installed flow`),console.log(` list List all installed flows`),console.log(` info <name> Show details of a flow`),console.log(` use <name> Set active flow (start it)`),console.log(` update <name> Update a flow from its source`),console.log(` status Show current flow execution status`),console.log(` start [name] Start a flow (or resume)`),console.log(` reset Reset the active flow`),console.log(` runs List all flow runs`);return}let n=await Nr();switch(t){case`add`:{let t=e[1];if(!t){console.error(`Usage: aikit flow add <source>`),console.error(` source: git URL (https://...) or local path`);return}let r=t.startsWith(`http`)||t.startsWith(`git@`)||t.endsWith(`.git`),i=P(t),a=w(i);if(!r&&!a){console.error(`Source not found: ${t}`),console.error(`Provide a git URL or existing local path.`);return}let o,s;if(r){console.log(`Cloning ${t}...`);let e=n.git.clone(t);if(!e.success||!e.data){console.error(e.error??`Failed to clone flow`);return}o=e.data,s=`git`}else{let r=e[2]||Se(i);console.log(`Copying local flow from ${t}...`);let a=n.git.copyLocal(i,r);if(!a.success||!a.data){console.error(a.error??`Failed to copy local flow`);return}o=a.data,s=`local`}let c=await n.loader.load(o);if(!c.success||!c.data){console.error(c.error??`Failed to load flow`),n.git.remove(o);return}let{manifest:l,format:u}=c.data;if(Fr(o,l),l.install.length>0){console.log(`Installing ${l.install.length} dependencies...`);let e=n.git.runInstallDeps(l.install);if(!e.success){console.error(`Dependency install failed: ${e.error}`),n.git.remove(o);return}}let d=new Date().toISOString(),f=n.registry.register({name:l.name,version:l.version,source:t,sourceType:s,installPath:o,format:u,registeredAt:d,updatedAt:d,manifest:l});if(!f.success){console.error(f.error??`Failed to register flow`),n.git.remove(o);return}console.log(`✓ Flow "${l.name}" v${l.version} installed (${u} format)`),console.log(` Steps: ${l.steps.map(e=>e.id).join(` → `)}`);break}case`remove`:{let t=e[1];if(!t){console.error(`Usage: aikit flow remove <name>`);return}let r=n.registry.get(t);if(!r){console.error(`Flow "${t}" not found`);return}let i=n.git.remove(r.installPath);if(!i.success){console.error(i.error??`Failed to remove flow files`);return}let a=n.registry.unregister(t);if(!a.success){console.error(a.error??`Failed to unregister flow`);return}console.log(`✓ Flow "${t}" removed`);break}case`list`:{let e=n.registry.list();if(e.length===0){console.log("No flows installed. Use `aikit flow add <source>` to install one.");return}console.log(`Installed Flows:`),console.log(`─`.repeat(60));for(let t of e){let e=t.manifest.steps.map(e=>e.id).join(` → `);console.log(` ${t.name} v${t.version} (${t.sourceType}, ${t.format})`),console.log(` Steps: ${e}`)}let t=n.stateMachine.getStatus();t.success&&t.data&&(console.log(``),console.log(`Active: ${t.data.flow} (${t.data.status}, step: ${t.data.currentStep??`done`})`));break}case`info`:{let t=e[1];if(!t){console.error(`Usage: aikit flow info <name>`);return}let r=n.registry.get(t);if(!r){console.error(`Flow "${t}" not found`);return}console.log(`Flow: ${r.name}`),console.log(`Version: ${r.version}`),console.log(`Source: ${r.source} (${r.sourceType})`),console.log(`Format: ${r.format}`),console.log(`Path: ${r.installPath}`),console.log(`Registered: ${r.registeredAt}`),console.log(`Updated: ${r.updatedAt}`),console.log(``),console.log(`Steps:`);for(let e of r.manifest.steps){let t=e.requires.length?` (requires: ${e.requires.join(`, `)})`:``;console.log(` ${e.id}: ${e.name}${t}`),console.log(` Skill: ${e.skill}`),console.log(` Produces: ${e.produces.join(`, `)}`)}if(r.manifest.install.length>0){console.log(``),console.log(`Dependencies:`);for(let e of r.manifest.install)console.log(` ${e}`)}break}case`use`:case`start`:{let r=e[1],i=r?n.registry.get(r):null;if(t===`use`&&!r){console.error(`Usage: aikit flow use <name>`);return}if(t===`start`&&!r){let e=n.stateMachine.getStatus();if(e.success&&e.data&&e.data.status===`active`){console.log(`Resuming flow: ${e.data.flow}`),console.log(`Current step: ${e.data.currentStep}`),console.log(`Completed: ${e.data.completedSteps.join(`, `)||`none`}`);return}console.error("No active flow. Use `aikit flow start <name>` to begin one.");return}if(!i){console.error(`Flow "${r}" not found. Use \`aikit flow list\` to see installed flows.`);return}let a=e[2],o=n.stateMachine.start(i.name,i.manifest,a);if(!o.success||!o.data){console.error(o.error??`Failed to start flow`);return}let s=o.data;console.log(`✓ Flow "${i.name}" started`),console.log(` Topic: ${s.topic}`),console.log(` Run directory: ${s.runDir}`),console.log(` Current step: ${s.currentStep}`),console.log(` Steps: ${i.manifest.steps.map(e=>e.id).join(` → `)}`);break}case`update`:{let t=e[1];if(!t){console.error(`Usage: aikit flow update <name>`);return}let r=n.registry.get(t);if(!r){console.error(`Flow "${t}" not found`);return}if(r.sourceType!==`git`){console.error(`Flow "${t}" is ${r.sourceType}, not updatable via git`);return}console.log(`Updating ${t}...`);let i=n.git.update(r.installPath);if(!i.success){console.error(i.error??`Failed to update flow`);return}let a=await n.loader.load(r.installPath);if(a.success&&a.data){let e=new Date().toISOString(),t=n.registry.register({...r,version:a.data.manifest.version,format:a.data.format,manifest:a.data.manifest,updatedAt:e});if(!t.success){console.error(t.error??`Failed to refresh flow registry entry`);return}}console.log(`✓ Flow "${t}" updated`);break}case`status`:{let e=n.stateMachine.getStatus();if(!e.success||!e.data){console.log(`No active flow.`);return}let t=e.data;if(console.log(`Flow: ${t.flow}`),console.log(`Topic: ${t.topic}`),console.log(`Slug: ${t.slug}`),console.log(`Run Dir: ${t.runDir}`),console.log(`Status: ${t.status}`),console.log(`Current Step: ${t.currentStep??`(completed)`}`),console.log(`Completed: ${t.completedSteps.join(`, `)||`none`}`),t.skippedSteps.length>0&&console.log(`Skipped: ${t.skippedSteps.join(`, `)}`),console.log(`Started: ${t.startedAt}`),console.log(`Updated: ${t.updatedAt}`),Object.keys(t.artifacts).length>0){console.log(`Artifacts:`);for(let[e,n]of Object.entries(t.artifacts))console.log(` ${e}: ${n}`)}break}case`reset`:{let e=n.stateMachine.reset();if(!e.success){console.error(e.error??`Failed to reset flow state`);return}console.log(`✓ Flow abandoned`);break}case`runs`:{let t=e[1],r=e[2],i=n.stateMachine.listRuns({flow:t,status:r});if(i.length===0){console.log(`No flow runs found.`);return}console.log(`Flow Runs:`),console.log(`─`.repeat(80));for(let e of i){let t=e.currentStep?` → ${e.currentStep}`:``;console.log(` ${e.id} [${e.status}] ${e.flow}${t}`),console.log(` Topic: ${e.topic}`),console.log(` Started: ${e.startedAt} | Updated: ${e.updatedAt}`)}break}default:console.error(`Unknown flow command: ${t}`),console.log("Use `aikit flow` for help.")}}}],q=L(`cli:gc`),Lr=M(z(),`.aikit`,`versions`),Rr=M(z(),`.aikit`,`current-version.json`);function zr(e){let t=e.match(/^v(\d+)\.(\d+)\.(\d+)$/);return t?{major:Number.parseInt(t[1],10),minor:Number.parseInt(t[2],10),patch:Number.parseInt(t[3],10)}:null}function Br(e,t){return e.major===t.major?e.minor===t.minor?t.patch-e.patch:t.minor-e.minor:t.major-e.major}function Vr(){try{return w(Rr)?JSON.parse(E(Rr,`utf-8`)).version??null:null}catch{return null}}const Hr=[{name:`gc`,description:`Free disk space by removing old AI Kit versions (keeps current + last N)`,usage:`aikit gc [--keep N]`,run:async e=>{if(!w(Lr)){q.info(`No version directories found.`);return}let t=_(e,`--keep`,2),n=Vr(),r=D(Lr,{withFileTypes:!0}),i=new Set(r.filter(e=>e.isDirectory()&&(e.name.includes(`-staging`)||e.name.startsWith(`_offline-detect-`)||e.name.startsWith(`_aikit-tarball-staging-`))).map(e=>e.name));for(let e of i)await He(M(Lr,e),{recursive:!0,force:!0}),q.debug(`Removed ${e}`);let a=r.filter(e=>e.isDirectory()&&!i.has(e.name)).map(e=>({name:e.name,semver:zr(e.name)})).filter(e=>e.semver!==null).sort((e,t)=>Br(e.semver,t.semver));if(a.length===0){q.info(`No version directories found.`);return}let o=new Set;n&&o.add(`v${n}`);for(let e of a){if(o.size>=t+ +!!n)break;o.add(e.name)}let s=a.filter(e=>!o.has(e.name));if(s.length===0){q.info(`No versions to clean`);return}for(let e of s)await He(M(Lr,e.name),{recursive:!0,force:!0}),q.debug(`Removed ${e.name}`);q.info(`Removed ${s.length} versions`)}}];let Ur=null;async function J(){return Ur||=await pn(),Ur}function Wr(){return Ur}const Gr=[{name:`graph`,description:`Query the knowledge graph`,usage:`aikit graph <action> [options]
25
25
  Actions: stats, find-nodes, find-edges, neighbors, traverse, delete, clear
26
26
  Options: --type, --name, --node-id, --edge-type, --direction, --depth, --limit, --source-path`,run:async e=>{let t=e.shift()?.trim()??``;if(!t)throw new g(`Usage: aikit graph <action>
27
27
  Actions: stats, find-nodes, find-edges, neighbors, traverse, delete, clear`);let{graphStore:n}=await J(),r=v(e,`--type`,``),i=v(e,`--name`,``),a=v(e,`--node-id`,``),o=v(e,`--edge-type`,``),s=v(e,`--direction`,`both`),c=_(e,`--depth`,2),l=_(e,`--limit`,50),u=v(e,`--source-path`,``),d={stats:`stats`,"find-nodes":`find_nodes`,"find-edges":`find_edges`,neighbors:`neighbors`,traverse:`traverse`,delete:`delete`,clear:`clear`}[t];if(!d)throw new g(`Unknown graph action: ${t}\nActions: stats, find-nodes, find-edges, neighbors, traverse, delete, clear`);let f=await ft(n,{action:d,nodeType:r||void 0,namePattern:i||void 0,sourcePath:u||void 0,nodeId:a||void 0,edgeType:o||void 0,direction:s,maxDepth:c,limit:l});if(console.log(f.summary),f.nodes&&f.nodes.length>0){console.log(`
28
28
  Nodes:`);for(let e of f.nodes){let t=Object.keys(e.properties).length>0?` ${JSON.stringify(e.properties)}`:``;console.log(` ${e.name} (${e.type}, id: ${e.id})${t}`)}}if(f.edges&&f.edges.length>0){console.log(`
29
- Edges:`);for(let e of f.edges){let t=e.weight===1?``:` (weight: ${e.weight})`;console.log(` ${e.fromId} --[${e.type}]--> ${e.toId}${t}`)}}f.stats&&(console.log(`\nNode types: ${JSON.stringify(f.stats.nodeTypes)}`),console.log(`Edge types: ${JSON.stringify(f.stats.edgeTypes)}`)),f.deleted!==void 0&&console.log(`Deleted: ${f.deleted}`)}}],Y=L(`cli:install`),Ur=/^\d+\.\d+\.\d+(-[\w.+]+)?(\+[\w.]+)?$/,X=M(z(),`.aikit`),Z=M(X,`versions`),Wr=M(X,`current-version.json`),Gr=`@vpxa/aikit`,Kr=`Usage:
29
+ Edges:`);for(let e of f.edges){let t=e.weight===1?``:` (weight: ${e.weight})`;console.log(` ${e.fromId} --[${e.type}]--> ${e.toId}${t}`)}}f.stats&&(console.log(`\nNode types: ${JSON.stringify(f.stats.nodeTypes)}`),console.log(`Edge types: ${JSON.stringify(f.stats.edgeTypes)}`)),f.deleted!==void 0&&console.log(`Deleted: ${f.deleted}`)}}],Y=L(`cli:install`),Kr=/^\d+\.\d+\.\d+(-[\w.+]+)?(\+[\w.]+)?$/,X=M(z(),`.aikit`),Z=M(X,`versions`),qr=M(X,`current-version.json`),Jr=`@vpxa/aikit`,Yr=`Usage:
30
30
  aikit install
31
31
  aikit install --version <version>
32
32
  aikit install --offline <path-to-tarball>
@@ -48,12 +48,12 @@ After install, verify with:
48
48
  Options:
49
49
  --version <version> Install a specific version instead of latest
50
50
  --offline <path> Install from a local tarball (no network needed)
51
- --help, -h Show this help`;function qr(e){if(!Ur.test(e))throw Error(`Invalid semver version: ${JSON.stringify(e)}`)}async function Jr(){let e=await fetch(`https://registry.npmjs.org/${Gr}/latest`,{signal:AbortSignal.timeout(1e4)});if(!e.ok)throw Error(`Failed to fetch latest version from npm registry (HTTP ${e.status})`);let t=await e.json();if(!t.version)throw Error(`npm registry response missing "version" field`);return t.version}function Yr(e){let t=M(e,`packages`,`server`,`dist`,`bin.js`);if(!w(t))throw Error(`Server entry point not found at ${t}. The installation may be incomplete or corrupted.`);let n=M(e,`node_modules`);if(!w(n))throw Error(`node_modules not found at ${n}. Production dependencies may not have been installed.`)}function Xr(e){let t=M(e,`package.json`),n=JSON.parse(E(t,`utf-8`));if(!n.version)throw Error(`No "version" field in ${t}`);return n.version}function Zr(e){w(X)||T(X,{recursive:!0});let t=M(X,`current-version.json.tmp`);A(t,`${JSON.stringify({version:e},null,2)}\n`),O(t,Wr)}function Qr(e){let t=D(e).filter(e=>e.endsWith(`.tgz`));return t.length>0?t[0]:null}function $r(e,t){Y.debug(`Extracting...`),R(`tar -xzf "${t}"`,{cwd:e,stdio:`pipe`,timeout:6e4});let n=M(e,`package`);if(!w(n))throw Error(`Expected "package/" directory not found after extraction`);return Y.debug(`Installing production dependencies...`),R(`npm install --production --install-strategy=nested --no-audit --no-fund`,{cwd:n,stdio:`pipe`,timeout:3e5}),n}function ei(e,t){let n=M(Z,`v${t}`);w(Z)||T(Z,{recursive:!0}),w(n)&&(Y.debug(`Removing previous installation...`,{target:n}),k(n,{recursive:!0})),O(e,n),Zr(t),Y.info(`Installation complete`,{package:`${Gr}@${t}`,target:n})}function ti(){let e={win32:`win32`,darwin:`darwin`,linux:`linux`},t={x64:`x64`,arm64:`arm64`},n=e[on()],r=t[an()];return!n||!r?(Y.warn(`Unknown platform, falling back to npm pack`,{platform:on(),arch:an()}),``):`${n}-${r}`}function ni(e){let t=ti();if(!t)return null;let n=`aikit-v${e}-${t}.tar.gz`,r=M(M(X,`cache`,`tarballs`),n);return w(r)?r:null}function ri(e,t){let n=M(Z,`v${t}-staging`);w(n)&&k(n,{recursive:!0}),T(n,{recursive:!0});try{Y.debug(`Extracting prebuilt tarball...`),R(`tar -xzf "${e}"`,{cwd:n,stdio:`pipe`,timeout:6e4});let r=M(n,`aikit-v${t}-${ti()}`);if(!w(r)){let e=M(n,`package`);if(w(e)){Y.debug(`Validating installation...`),Yr(e),ei(e,t);return}throw Error(`Expected directory not found after extracting prebuilt tarball`)}Y.debug(`Validating installation...`),Yr(r),ei(r,t)}finally{w(n)&&k(n,{recursive:!0})}}function ii(e){qr(e);let t=ni(e);if(t){Y.debug(`Found prebuilt tarball`,{path:t}),ri(t,e);return}let n=M(Z,`v${e}-staging`);w(n)&&k(n,{recursive:!0}),T(n,{recursive:!0});try{Y.debug(`Downloading...`,{package:`${Gr}@${e}`}),R(`npm pack ${Gr}@${e}`,{cwd:n,stdio:`pipe`,timeout:12e4});let t=Qr(n);if(!t)throw Error(`No .tgz file found after npm pack`);let r=$r(n,t);Y.debug(`Validating installation...`),Yr(r),ei(r,e)}finally{w(n)&&k(n,{recursive:!0})}}function ai(e){if(!w(e))throw Error(`Tarball not found: ${e}`);let t=M(Z,`_offline-detect-${Date.now()}`);T(t,{recursive:!0});let n;try{R(`tar -xzf "${e}"`,{cwd:t,stdio:`pipe`,timeout:6e4}),n=Xr(M(t,`package`))}finally{w(t)&&k(t,{recursive:!0})}Y.debug(`Installing from local tarball...`,{package:`${Gr}@${n}`});let r=M(Z,`v${n}-staging`);w(r)&&k(r,{recursive:!0}),T(r,{recursive:!0});try{ye(e,M(r,`offline-${n}.tgz`));let t=$r(r,`offline-${n}.tgz`);return Y.debug(`Validating installation...`),Yr(t),ei(t,n),n}finally{w(r)&&k(r,{recursive:!0})}}async function oi(e){try{let t=M(Z,`v${e}`,`packages`,`server`,`dist`,`bin.js`);if(!w(t)){Y.warn(`Server entry not found — skipping MCP registration`,{serverPath:t});return}let n={command:process.execPath,args:[t,`serve`],type:`stdio`};if(process.platform!==`win32`){let e=process.env.PATH;e&&(n.env={PATH:e})}let r=await Hn({scope:`user`});if(r.length===0){Y.info(`No supported IDEs detected for MCP registration`);return}let i=0;for(let e of r)try{await e.registerMcp(h,n),i++}catch(t){Y.warn(`Failed to register MCP for ${e.name}`,{error:t.message})}i>0&&Y.info(`MCP server configured for ${i} IDE(s) — using local install path`)}catch(e){Y.warn(`MCP registration failed`,{error:e.message})}}const si=[{name:`install`,description:`Install AI Kit to ~/.aikit/versions/ (one-time setup for fast local startup)`,usage:Kr,run:async e=>{let t=e.indexOf(`--version`),n=e.indexOf(`--offline`),r=t!==-1&&t+1<e.length,i=n!==-1&&n+1<e.length;if(e.includes(`--help`)||e.includes(`-h`)){console.log(Kr);return}if(i){let t=e[n+1];await oi(ai(t)),Y.info(`Install complete — restart your IDE to use the new version`);return}let a;r?a=e[t+1]:(Y.debug(`Checking npm registry for latest version...`),a=await Jr(),Y.info(`Latest version detected`,{version:a})),ii(a),await oi(a),Y.info(`Install complete — restart your IDE to use the new version`)}}],ci=[{name:`remember`,description:`Store curated knowledge`,usage:`aikit remember <title> --category <cat> [--tags tag1,tag2]`,run:async e=>{let t=v(e,`--category`,``).trim(),n=d(v(e,`--tags`,``)),r=e.shift()?.trim()??``,i=await m(),a=i.trim().length>0?i:e.join(` `).trim();(!r||!t||!a.trim())&&(console.error(`Usage: aikit remember <title> --category <cat> [--tags tag1,tag2]`),process.exit(1));let{curated:o}=await J(),s=await o.remember(r,a,t,n);console.log(`Stored curated entry`),console.log(` Path: ${s.path}`),console.log(` Category: ${t}`),n.length>0&&console.log(` Tags: ${n.join(`, `)}`)}},{name:`forget`,description:`Remove a curated entry`,usage:`aikit forget <path> --reason <reason>`,run:async e=>{let t=v(e,`--reason`,``).trim(),n=e.shift()?.trim()??``;(!n||!t)&&(console.error(`Usage: aikit forget <path> --reason <reason>`),process.exit(1));let{curated:r}=await J(),i=await r.forget(n,t);console.log(`Removed curated entry: ${i.path}`)}},{name:`read`,description:`Read a curated entry`,usage:`aikit read <path>`,run:async e=>{let t=e.shift()?.trim()??``;t||(console.error(`Usage: aikit read <path>`),process.exit(1));let{curated:n}=await J(),r=await n.read(t);console.log(r.title),console.log(`─`.repeat(60)),console.log(`Path: ${r.path}`),console.log(`Category: ${r.category}`),console.log(`Version: ${r.version}`),console.log(`Tags: ${r.tags.length>0?r.tags.join(`, `):`None`}`),console.log(``),console.log(r.content)}},{name:`list`,description:`List curated entries`,usage:`aikit list [--category <cat>] [--tag <tag>]`,run:async e=>{let t=v(e,`--category`,``).trim()||void 0,n=v(e,`--tag`,``).trim()||void 0,{curated:r}=await J(),i=await r.list({category:t,tag:n});if(i.length===0){console.log(`No curated entries found.`);return}console.log(`Curated entries (${i.length})`),console.log(`─`.repeat(60));for(let e of i){console.log(e.path),console.log(` ${e.title}`),console.log(` Category: ${e.category} | Version: ${e.version}`),console.log(` Tags: ${e.tags.length>0?e.tags.join(`, `):`None`}`);let t=e.contentPreview.replace(/\s+/g,` `).trim();t&&console.log(` Preview: ${t}`),console.log(``)}}},{name:`update`,description:`Update a curated entry`,usage:`aikit update <path> --reason <reason>`,run:async e=>{let t=v(e,`--reason`,``).trim(),n=e.shift()?.trim()??``,r=await m();(!n||!t||!r.trim())&&(console.error(`Usage: aikit update <path> --reason <reason>`),process.exit(1));let{curated:i}=await J(),a=await i.update(n,r,t);console.log(`Updated curated entry`),console.log(` Path: ${a.path}`),console.log(` Version: ${a.version}`)}},{name:`compact`,description:`Compress text for context`,usage:`aikit compact <query> [--path <file>] [--max-chars N] [--segmentation paragraph|sentence|line]`,run:async e=>{let t=_(e,`--max-chars`,3e3),n=v(e,`--path`,``).trim()||void 0,r=v(e,`--segmentation`,`paragraph`),i=e.join(` `).trim(),a=n?void 0:await m();(!i||!n&&!a?.trim())&&(console.error(`Usage: aikit compact <query> --path <file> OR cat file | aikit compact <query>`),process.exit(1));let{embedder:o}=await J(),s=n?await $e(o,{path:n,query:i,maxChars:t,segmentation:r}):await $e(o,{text:a??``,query:i,maxChars:t,segmentation:r});console.log(`Compressed ${s.originalChars} chars to ${s.compressedChars} chars`),console.log(`Ratio: ${(s.ratio*100).toFixed(1)}% | Segments: ${s.segmentsKept}/${s.segmentsTotal}`),console.log(``),console.log(s.text)}}],Q=L(`cli:rollback`),li=M(z(),`.aikit`,`versions`),ui=M(z(),`.aikit`,`current-version.json`),di=[{name:`rollback`,description:`Rollback to a previous AI Kit version (see "aikit versions" for available)`,usage:`aikit rollback <version>`,run:async e=>{let t=e[0];t||(console.error(`Usage: aikit rollback <version>`),console.error(`Example: aikit rollback 0.1.280`),process.exit(1)),Q.debug(`Validating version directory for v${t}...`);let n=M(li,`v${t}`);w(n)||(Q.warn(`Version v${t} not found`),process.exit(1)),Q.debug(`Validating version dir...`);let r=M(n,`package.json`);w(r)||(Q.error(`Version v${t} is missing package.json`),process.exit(1));try{JSON.parse(E(r,`utf-8`)).version||(Q.error(`Version v${t} has invalid package.json (missing version field)`),process.exit(1))}catch{Q.error(`Version v${t} has invalid package.json`),process.exit(1)}let i=M(li,`current-version.json.tmp`);await We(i,JSON.stringify({version:t},null,2),`utf-8`),await Ve(i,ui),Q.info(`Switched to v${t}`)}}],fi=[{name:`search`,description:`Search the AI Kit index`,usage:`aikit search <query> [--limit N] [--mode hybrid|semantic|keyword] [--graph-hops 0-3]`,run:async e=>{let t=y(e),n=_(e,`--limit`,5),r=v(e,`--mode`,`hybrid`),i=_(e,`--graph-hops`,0),a=e.join(` `).trim();if(!a)throw new g(`Usage: aikit search <query>`);let{embedder:o,store:s,graphStore:c}=await J(),d=await o.embedQuery(a),f;if(r===`keyword`)f=await s.ftsSearch(a,{limit:n});else if(r===`semantic`)f=await s.search(d,{limit:n});else{let[e,t]=await Promise.all([s.search(d,{limit:n*2}),s.ftsSearch(a,{limit:n*2}).catch(()=>[])]);f=u(e,t).slice(0,n)}if(t){l({query:a,results:f,graphHops:i});return}if(f.length===0){console.log(`No results found.`);return}for(let{record:e,score:t}of f){console.log(`\n${`─`.repeat(60)}`),console.log(`[${(t*100).toFixed(1)}%] ${e.sourcePath}:${e.startLine}-${e.endLine}`),console.log(` Type: ${e.contentType} | Origin: ${e.origin}`),e.tags.length>0&&console.log(` Tags: ${e.tags.join(`, `)}`),console.log(``);let n=e.content.length>500?`${e.content.slice(0,500)}...`:e.content;console.log(n)}if(console.log(`\n${`─`.repeat(60)}`),console.log(`${f.length} result(s) found.`),i>0&&f.length>0)try{let{graphAugmentSearch:e}=await import(`../../tools/dist/index.js`),t=(await e(c,f.map(e=>({recordId:e.record.id,score:e.score,sourcePath:e.record.sourcePath})),{hops:i,maxPerHit:5})).filter(e=>e.graphContext.nodes.length>0);if(t.length>0){console.log(`\nGraph context (${i} hop${i>1?`s`:``}):\n`);for(let e of t){console.log(` ${e.sourcePath}:`);for(let t of e.graphContext.nodes.slice(0,5))console.log(` → ${t.name} (${t.type})`);for(let t of e.graphContext.edges.slice(0,5))console.log(` → ${t.fromId} --[${t.type}]--> ${t.toId}`)}}}catch(e){console.error(`[graph] augmentation failed: ${e.message}`)}}},{name:`find`,description:`Run federated search across indexed content and files`,usage:`aikit find [query] [--glob <pattern>] [--pattern <regex>] [--limit N]`,run:async e=>{let t=y(e),n=_(e,`--limit`,10),r=v(e,`--glob`,``).trim()||void 0,i=v(e,`--pattern`,``).trim()||void 0,a=e.join(` `).trim()||void 0;if(!a&&!r&&!i)throw new g(`Usage: aikit find [query] [--glob <pattern>] [--pattern <regex>] [--limit N]`);let{embedder:o,store:s}=await J(),c=await st(o,s,{query:a,glob:r,pattern:i,limit:n});if(t){l(c);return}if(c.results.length===0){console.log(`No matches found.`);return}console.log(`Strategies: ${c.strategies.join(`, `)}`),console.log(`Results: ${c.results.length} shown (${c.totalFound} total)`);for(let e of c.results){let t=e.lineRange?`:${e.lineRange.start}-${e.lineRange.end}`:``;console.log(`\n[${e.source}] ${e.path}${t}`),console.log(` Score: ${(e.score*100).toFixed(1)}%`),e.preview&&console.log(` ${e.preview.replace(/\s+/g,` `).trim()}`)}}},{name:`scope-map`,description:`Generate a reading plan for a task`,usage:`aikit scope-map <task> [--max-files N]`,run:async e=>{let t=_(e,`--max-files`,15),n=e.join(` `).trim();if(!n)throw new g(`Usage: aikit scope-map <task> [--max-files N]`);let{embedder:r,store:i}=await J(),a=await Ut(r,i,{task:n,maxFiles:t});console.log(`Task: ${a.task}`),console.log(`Files: ${a.files.length}`),console.log(`Estimated tokens: ${a.totalEstimatedTokens}`),console.log(``),console.log(`Reading order:`);for(let e of a.readingOrder)console.log(` ${e}`);for(let[e,t]of a.files.entries())console.log(`\n${e+1}. ${t.path}`),console.log(` Relevance: ${(t.relevance*100).toFixed(1)}% | Tokens: ${t.estimatedTokens}`),console.log(` Why: ${t.reason}`),t.focusRanges.length>0&&console.log(` Focus: ${C(t.focusRanges)}`)}},{name:`symbol`,description:`Resolve a symbol definition, imports, and references`,usage:`aikit symbol <name> [--limit N]`,run:async e=>{let t=_(e,`--limit`,20),n=e.join(` `).trim();if(!n)throw new g(`Usage: aikit symbol <name> [--limit N]`);let{embedder:r,store:i}=await J();x(await Yt(r,i,{name:n,limit:t}))}},{name:`trace`,description:`Trace forward/backward flow for a symbol or file location`,usage:`aikit trace <start> [--direction forward|backward|both] [--max-depth N]`,run:async e=>{let t=v(e,`--direction`,`both`).trim()||`both`,n=_(e,`--max-depth`,3),r=e.join(` `).trim();if(!r||![`forward`,`backward`,`both`].includes(t))throw new g(`Usage: aikit trace <start> [--direction forward|backward|both] [--max-depth N]`);let{embedder:i,store:a}=await J();se(await Zt(i,a,{start:r,direction:t,maxDepth:n}))}},{name:`examples`,description:`Find real code examples of a symbol or pattern`,usage:`aikit examples <query> [--limit N] [--content-type type]`,run:async e=>{let t=_(e,`--limit`,5),n=v(e,`--content-type`,``).trim()||void 0,r=e.join(` `).trim();if(!r)throw new g(`Usage: aikit examples <query> [--limit N] [--content-type type]`);let{embedder:i,store:a}=await J();s(await lt(i,a,{query:r,limit:t,contentType:n}))}},{name:`dead-symbols`,description:`Find exported symbols that appear to be unused`,usage:`aikit dead-symbols [--limit N]`,run:async e=>{let t=_(e,`--limit`,100),{embedder:n,store:r}=await J();_e(await ct(n,r,{limit:t}))}},{name:`lookup`,description:`Look up indexed content by record ID or source path`,usage:`aikit lookup <id>`,run:async e=>{let t=e.join(` `).trim();if(!t)throw new g(`Usage: aikit lookup <id>`);let{store:n}=await J(),r=await n.getById(t);if(r){console.log(r.id),console.log(`─`.repeat(60)),console.log(`Path: ${r.sourcePath}`),console.log(`Chunk: ${r.chunkIndex+1}/${r.totalChunks}`),console.log(`Lines: ${r.startLine}-${r.endLine}`),console.log(`Type: ${r.contentType} | Origin: ${r.origin}`),r.tags.length>0&&console.log(`Tags: ${r.tags.join(`, `)}`),console.log(``),console.log(r.content);return}let i=await n.getBySourcePath(t);if(i.length===0){console.log(`No indexed content found for: ${t}`);return}i.sort((e,t)=>e.chunkIndex-t.chunkIndex),console.log(t),console.log(`─`.repeat(60)),console.log(`Chunks: ${i.length} | Type: ${i[0].contentType}`);for(let e of i){let t=e.startLine?` (lines ${e.startLine}-${e.endLine})`:``;console.log(`\nChunk ${e.chunkIndex+1}/${e.totalChunks}${t}`),console.log(e.content)}}}];async function pi(e){let{port:t,noOpen:n,urlPath:r,commandName:i}=e;console.log(`Starting AI Kit server on port ${t}...`);let{spawn:a}=await import(`node:child_process`),{platform:o}=await import(`node:os`),s=te(),c=a(process.execPath,[s,`--transport`,`http`,`--port`,String(t)],{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env,NODE_OPTIONS:f(process.env.NODE_OPTIONS),AIKIT_TRANSPORT:`http`,AIKIT_PORT:String(t)}}),l=`http://localhost:${t}${r}`,u=`http://localhost:${t}/health`,d=!1;for(let e=0;e<30;e+=1){try{if((await fetch(u)).ok){d=!0;break}}catch{}await new Promise(e=>setTimeout(e,1e3))}if(!d)throw c.kill(),new g(`Server failed to start within 30 seconds.`);let p=i.charAt(0).toUpperCase()+i.slice(1);if(console.log(`AI Kit ${p}: ${l}`),console.log(`Press Ctrl+C to stop.`),!n){let e=o();e===`win32`?a(`cmd`,[`/c`,`start`,``,l],{stdio:`ignore`,detached:!0}).unref():a(e===`darwin`?`open`:`xdg-open`,[l],{stdio:`ignore`,detached:!0}).unref()}let m=()=>{c.kill(),process.exit(0)};process.on(`SIGINT`,m),process.on(`SIGTERM`,m),await new Promise(e=>{c.on(`exit`,()=>e())})}const mi=[{name:`status`,description:`Show AI Kit index status and statistics`,run:async e=>{let t=y(e),{AIKIT_PATHS:n,computePartitionKey:r,getPartitionDir:i,isUserInstalled:a,listWorkspaces:o}=await import(`../../core/dist/index.js`),{existsSync:s}=await import(`node:fs`),c=process.cwd(),u=a(),d=s(P(c,`.vscode`,`mcp.json`)),f={mode:void 0,dataPath:void 0};if(u&&d)f.mode=`workspace (overrides user-level for this workspace)`,f.dataPath=P(c,n.data);else if(u){let e=r(c);f.mode=s(P(c,`AGENTS.md`))?`user (workspace scaffolded)`:`user (workspace not scaffolded)`,f.dataPath=i(e)}else f.mode=`workspace`,f.dataPath=P(c,n.data);u&&!d&&(f.workspaces=o().length);try{let{store:e}=await J(),t=await e.getStats(),n=await e.listSourcePaths();f.records=t.totalRecords,f.files=t.totalFiles,f.lastIndexed=t.lastIndexedAt??null,f.backend=t.storeBackend,f.model=t.embeddingModel,f.contentTypeBreakdown=t.contentTypeBreakdown,f.sourcePaths=n.slice(0,20),f.sourcePathTotal=n.length}catch{f.indexAvailable=!1}if(t){l(f);return}if(console.log(`AI Kit Status`),console.log(`─`.repeat(40)),console.log(` Mode: ${f.mode}`),console.log(` Data: ${f.dataPath}`),u&&!d){let e=o();console.log(` Registry: ${e.length} workspace(s) enrolled`)}if(f.records!==void 0){console.log(` Records: ${f.records}`),console.log(` Files: ${f.files}`),console.log(` Indexed: ${f.lastIndexed??`Never`}`),console.log(` Backend: ${f.backend}`),console.log(` Model: ${f.model}`),console.log(``),console.log(`Content Types:`);for(let[e,t]of Object.entries(f.contentTypeBreakdown))console.log(` ${e}: ${t}`);let e=f.sourcePaths;if(e.length>0){console.log(``),console.log(`Files (${f.sourcePathTotal} total):`);for(let t of e.slice(0,20))console.log(` ${t}`);f.sourcePathTotal>20&&console.log(` ... and ${f.sourcePathTotal-20} more`)}}else console.log(``),console.log(" Index not available — run `aikit reindex` to index this workspace.");u&&!d&&!s(P(c,`AGENTS.md`))&&(console.log(``),console.log(" Action: Run `npx @vpxa/aikit init` to add AGENTS.md and copilot-instructions.md"))}},{name:`reindex`,description:`Re-index the AI Kit index from configured sources`,usage:`aikit reindex [--full]`,run:async e=>{let t=e.includes(`--full`),{store:n,indexer:r,curated:i,config:a}=await J();console.log(`Indexing sources...`);let o=e=>{e.phase===`chunking`&&e.currentFile&&process.stdout.write(`\r [${e.filesProcessed+1}/${e.filesTotal}] ${e.currentFile}`),e.phase===`done`&&process.stdout.write(`
52
- `)},s;t?(console.log(`Dropping existing index for full reindex...`),s=await r.reindexAll(a,o)):s=await r.index(a,o),console.log(`Done: ${s.filesProcessed} files, ${s.chunksCreated} chunks in ${(s.durationMs/1e3).toFixed(1)}s`),console.log(`Building FTS index...`),await n.createFtsIndex(),console.log(`Re-indexing curated entries...`);let c=await i.reindexAll();console.log(`Curated: ${c.indexed} entries restored`)}},{name:`serve`,description:`Start the MCP server. Default: direct stdio (one server per workspace). Use --daemon to share a single HTTP daemon across multiple clients.`,usage:`aikit serve [--transport stdio|http] [--port N] [--daemon]`,run:async e=>{let t=v(e,`--transport`,`stdio`),n=v(e,`--port`,`3210`),r=me(e,`--daemon`);try{await Er({silent:!0})}catch{}if(t===`stdio`&&r){let{runProxy:e}=await import(`../../server/dist/proxy.js`);try{let t=`http://127.0.0.1:${n}/health`;if((await fetch(t,{signal:AbortSignal.timeout(2e3)})).ok){await e({port:Number(n),autoStart:!1});return}}catch{}await e({port:Number(n),autoStart:!0});return}let i=nn(te(),[],{stdio:t===`stdio`?[`pipe`,`pipe`,`inherit`,`ipc`]:`inherit`,env:{...process.env,NODE_OPTIONS:f(process.env.NODE_OPTIONS),AIKIT_TRANSPORT:t,AIKIT_PORT:n}});t===`stdio`&&i.stdin&&i.stdout&&(process.stdin.pipe(i.stdin),i.stdout.pipe(process.stdout)),i.on(`exit`,e=>process.exit(e??0)),process.on(`SIGINT`,()=>i.kill(`SIGINT`)),process.on(`SIGTERM`,()=>i.kill(`SIGTERM`)),await new Promise(()=>{})}},{name:`init`,description:`Initialize AI Kit in the current directory`,usage:`aikit init [--workspace] [--smart] [--force] [--guide]`,run:async e=>{let t=e.includes(`--user`),n=e.includes(`--workspace`),r=e.includes(`--smart`),i=e.includes(`--guide`),a=e.includes(`--force`);if(t&&n)throw new g(`Cannot use --user and --workspace together.`);if(i){let{guideProject:e}=await import(`./init-CyjUXjQw.js`);await e();return}if(r){let{initSmart:e}=await import(`./init-CyjUXjQw.js`);await e({force:a})}else if(t)await ar({force:a});else if(n){let{initProject:e}=await import(`./init-CyjUXjQw.js`);await e({force:a})}else await ar({force:a})}},{name:`check`,description:`Run incremental typecheck and lint`,usage:`aikit check [--cwd <dir>] [--files f1,f2] [--skip-types] [--skip-lint] [--detail efficient|normal|full]`,run:async e=>{let t=v(e,`--cwd`,``).trim()||void 0,n=v(e,`--files`,``),r=v(e,`--detail`,`full`)||`full`,i=n.split(`,`).map(e=>e.trim()).filter(Boolean),a=!1;e.includes(`--skip-types`)&&(e.splice(e.indexOf(`--skip-types`),1),a=!0);let o=!1;e.includes(`--skip-lint`)&&(e.splice(e.indexOf(`--skip-lint`),1),o=!0);let s=await qe({cwd:t,files:i.length>0?i:void 0,skipTypes:a,skipLint:o,detail:r});ve(s),s.passed||(process.exitCode=1)}},{name:`health`,description:`Run project health checks on the current directory`,usage:`aikit health [path]`,run:async e=>{let t=y(e),n=mt(e.shift());if(t){l(n);return}console.log(`Project Health: ${n.path}`),console.log(`─`.repeat(50));for(let e of n.checks){let t=e.status===`pass`?`+`:e.status===`warn`?`~`:`X`;console.log(` [${t}] ${e.name}: ${e.message}`)}console.log(`─`.repeat(50)),console.log(`Score: ${n.score}% — ${n.summary}`)}},{name:`prune`,description:`Clean up orphaned storage, legacy data, and stale partitions`,usage:`aikit prune [--dry-run] [--max-age-days=90] [--force]`,run:async e=>{let{prune:t,formatBytes:n,markPruneRun:r}=await import(`../../tools/dist/index.js`),i=e.includes(`--dry-run`),a=e.includes(`--force`),o=e.find(e=>e.startsWith(`--max-age-days=`)),s=o?Number.parseInt(o.split(`=`)[1]??``,10):90;if(!i&&!a){console.log(`⚠️ This will permanently delete data. Use --dry-run to preview, or --force to execute.`);return}console.log(i?`🔍 Dry run — no files will be deleted
51
+ --help, -h Show this help`;function Xr(e){if(!Kr.test(e))throw Error(`Invalid semver version: ${JSON.stringify(e)}`)}async function Zr(){let e=await fetch(`https://registry.npmjs.org/${Jr}/latest`,{signal:AbortSignal.timeout(1e4)});if(!e.ok)throw Error(`Failed to fetch latest version from npm registry (HTTP ${e.status})`);let t=await e.json();if(!t.version)throw Error(`npm registry response missing "version" field`);return t.version}function Qr(e){let t=M(e,`packages`,`server`,`dist`,`bin.js`);if(!w(t))throw Error(`Server entry point not found at ${t}. The installation may be incomplete or corrupted.`);let n=M(e,`node_modules`);if(!w(n))throw Error(`node_modules not found at ${n}. Production dependencies may not have been installed.`)}function $r(e){let t=M(e,`package.json`),n=JSON.parse(E(t,`utf-8`));if(!n.version)throw Error(`No "version" field in ${t}`);return n.version}function ei(e){w(X)||T(X,{recursive:!0});let t=M(X,`current-version.json.tmp`);A(t,`${JSON.stringify({version:e},null,2)}\n`),O(t,qr)}function ti(e){let t=D(e).filter(e=>e.endsWith(`.tgz`));return t.length>0?t[0]:null}function ni(e,t){Y.debug(`Extracting...`),R(`tar -xzf "${t}"`,{cwd:e,stdio:`pipe`,timeout:6e4});let n=M(e,`package`);if(!w(n))throw Error(`Expected "package/" directory not found after extraction`);return Y.debug(`Installing production dependencies...`),R(`npm install --production --install-strategy=nested --no-audit --no-fund`,{cwd:n,stdio:`pipe`,timeout:3e5}),n}function ri(e,t){let n=M(Z,`v${t}`);w(Z)||T(Z,{recursive:!0}),w(n)&&(Y.debug(`Removing previous installation...`,{target:n}),k(n,{recursive:!0})),O(e,n),ei(t),Y.info(`Installation complete`,{package:`${Jr}@${t}`,target:n})}function ii(){let e={win32:`win32`,darwin:`darwin`,linux:`linux`},t={x64:`x64`,arm64:`arm64`},n=e[on()],r=t[an()];return!n||!r?(Y.warn(`Unknown platform, falling back to npm pack`,{platform:on(),arch:an()}),``):`${n}-${r}`}function ai(e){let t=ii();if(!t)return null;let n=`aikit-v${e}-${t}.tar.gz`,r=M(M(X,`cache`,`tarballs`),n);return w(r)?r:null}function oi(e,t){let n=M(Z,`v${t}-staging`);w(n)&&k(n,{recursive:!0}),T(n,{recursive:!0});try{Y.debug(`Extracting prebuilt tarball...`),R(`tar -xzf "${e}"`,{cwd:n,stdio:`pipe`,timeout:6e4});let r=M(n,`aikit-v${t}-${ii()}`);if(!w(r)){let e=M(n,`package`);if(w(e)){Y.debug(`Validating installation...`),Qr(e),ri(e,t);return}throw Error(`Expected directory not found after extracting prebuilt tarball`)}Y.debug(`Validating installation...`),Qr(r),ri(r,t)}finally{w(n)&&k(n,{recursive:!0})}}function si(e){Xr(e);let t=ai(e);if(t){Y.debug(`Found prebuilt tarball`,{path:t}),oi(t,e);return}let n=M(Z,`v${e}-staging`);w(n)&&k(n,{recursive:!0}),T(n,{recursive:!0});try{Y.debug(`Downloading...`,{package:`${Jr}@${e}`}),R(`npm pack ${Jr}@${e}`,{cwd:n,stdio:`pipe`,timeout:12e4});let t=ti(n);if(!t)throw Error(`No .tgz file found after npm pack`);let r=ni(n,t);Y.debug(`Validating installation...`),Qr(r),ri(r,e)}finally{w(n)&&k(n,{recursive:!0})}}function ci(e){if(!w(e))throw Error(`Tarball not found: ${e}`);let t=M(Z,`_offline-detect-${Date.now()}`);T(t,{recursive:!0});let n;try{R(`tar -xzf "${e}"`,{cwd:t,stdio:`pipe`,timeout:6e4}),n=$r(M(t,`package`))}finally{w(t)&&k(t,{recursive:!0})}Y.debug(`Installing from local tarball...`,{package:`${Jr}@${n}`});let r=M(Z,`v${n}-staging`);w(r)&&k(r,{recursive:!0}),T(r,{recursive:!0});try{ye(e,M(r,`offline-${n}.tgz`));let t=ni(r,`offline-${n}.tgz`);return Y.debug(`Validating installation...`),Qr(t),ri(t,n),n}finally{w(r)&&k(r,{recursive:!0})}}async function li(e){try{let t=M(Z,`v${e}`,`packages`,`server`,`dist`,`bin.js`);if(!w(t)){Y.warn(`Server entry not found — skipping MCP registration`,{serverPath:t});return}let n={command:process.execPath,args:[t,`serve`],type:`stdio`};if(process.platform!==`win32`){let e=process.env.PATH;e&&(n.env={PATH:e})}let r=await Hn({scope:`user`});if(r.length===0){Y.info(`No supported IDEs detected for MCP registration`);return}let i=0;for(let e of r)try{await e.registerMcp(h,n),i++}catch(t){Y.warn(`Failed to register MCP for ${e.name}`,{error:t.message})}i>0&&Y.info(`MCP server configured for ${i} IDE(s) — using local install path`)}catch(e){Y.warn(`MCP registration failed`,{error:e.message})}}const ui=[{name:`install`,description:`Install AI Kit to ~/.aikit/versions/ (one-time setup for fast local startup)`,usage:Yr,run:async e=>{let t=e.indexOf(`--version`),n=e.indexOf(`--offline`),r=t!==-1&&t+1<e.length,i=n!==-1&&n+1<e.length;if(e.includes(`--help`)||e.includes(`-h`)){console.log(Yr);return}if(i){let t=e[n+1];await li(ci(t)),Y.info(`Install complete — restart your IDE to use the new version`);return}let a;r?a=e[t+1]:(Y.debug(`Checking npm registry for latest version...`),a=await Zr(),Y.info(`Latest version detected`,{version:a})),si(a),await li(a),Y.info(`Install complete — restart your IDE to use the new version`)}}],di=[{name:`remember`,description:`Store curated knowledge`,usage:`aikit remember <title> --category <cat> [--tags tag1,tag2]`,run:async e=>{let t=v(e,`--category`,``).trim(),n=d(v(e,`--tags`,``)),r=e.shift()?.trim()??``,i=await m(),a=i.trim().length>0?i:e.join(` `).trim();(!r||!t||!a.trim())&&(console.error(`Usage: aikit remember <title> --category <cat> [--tags tag1,tag2]`),process.exit(1));let{curated:o}=await J(),s=await o.remember(r,a,t,n);console.log(`Stored curated entry`),console.log(` Path: ${s.path}`),console.log(` Category: ${t}`),n.length>0&&console.log(` Tags: ${n.join(`, `)}`)}},{name:`forget`,description:`Remove a curated entry`,usage:`aikit forget <path> --reason <reason>`,run:async e=>{let t=v(e,`--reason`,``).trim(),n=e.shift()?.trim()??``;(!n||!t)&&(console.error(`Usage: aikit forget <path> --reason <reason>`),process.exit(1));let{curated:r}=await J(),i=await r.forget(n,t);console.log(`Removed curated entry: ${i.path}`)}},{name:`read`,description:`Read a curated entry`,usage:`aikit read <path>`,run:async e=>{let t=e.shift()?.trim()??``;t||(console.error(`Usage: aikit read <path>`),process.exit(1));let{curated:n}=await J(),r=await n.read(t);console.log(r.title),console.log(`─`.repeat(60)),console.log(`Path: ${r.path}`),console.log(`Category: ${r.category}`),console.log(`Version: ${r.version}`),console.log(`Tags: ${r.tags.length>0?r.tags.join(`, `):`None`}`),console.log(``),console.log(r.content)}},{name:`list`,description:`List curated entries`,usage:`aikit list [--category <cat>] [--tag <tag>]`,run:async e=>{let t=v(e,`--category`,``).trim()||void 0,n=v(e,`--tag`,``).trim()||void 0,{curated:r}=await J(),i=await r.list({category:t,tag:n});if(i.length===0){console.log(`No curated entries found.`);return}console.log(`Curated entries (${i.length})`),console.log(`─`.repeat(60));for(let e of i){console.log(e.path),console.log(` ${e.title}`),console.log(` Category: ${e.category} | Version: ${e.version}`),console.log(` Tags: ${e.tags.length>0?e.tags.join(`, `):`None`}`);let t=e.contentPreview.replace(/\s+/g,` `).trim();t&&console.log(` Preview: ${t}`),console.log(``)}}},{name:`update`,description:`Update a curated entry`,usage:`aikit update <path> --reason <reason>`,run:async e=>{let t=v(e,`--reason`,``).trim(),n=e.shift()?.trim()??``,r=await m();(!n||!t||!r.trim())&&(console.error(`Usage: aikit update <path> --reason <reason>`),process.exit(1));let{curated:i}=await J(),a=await i.update(n,r,t);console.log(`Updated curated entry`),console.log(` Path: ${a.path}`),console.log(` Version: ${a.version}`)}},{name:`compact`,description:`Compress text for context`,usage:`aikit compact <query> [--path <file>] [--max-chars N] [--segmentation paragraph|sentence|line]`,run:async e=>{let t=_(e,`--max-chars`,3e3),n=v(e,`--path`,``).trim()||void 0,r=v(e,`--segmentation`,`paragraph`),i=e.join(` `).trim(),a=n?void 0:await m();(!i||!n&&!a?.trim())&&(console.error(`Usage: aikit compact <query> --path <file> OR cat file | aikit compact <query>`),process.exit(1));let{embedder:o}=await J(),s=n?await $e(o,{path:n,query:i,maxChars:t,segmentation:r}):await $e(o,{text:a??``,query:i,maxChars:t,segmentation:r});console.log(`Compressed ${s.originalChars} chars to ${s.compressedChars} chars`),console.log(`Ratio: ${(s.ratio*100).toFixed(1)}% | Segments: ${s.segmentsKept}/${s.segmentsTotal}`),console.log(``),console.log(s.text)}}],Q=L(`cli:rollback`),fi=M(z(),`.aikit`,`versions`),pi=M(z(),`.aikit`,`current-version.json`),mi=[{name:`rollback`,description:`Rollback to a previous AI Kit version (see "aikit versions" for available)`,usage:`aikit rollback <version>`,run:async e=>{let t=e[0];t||(console.error(`Usage: aikit rollback <version>`),console.error(`Example: aikit rollback 0.1.280`),process.exit(1)),Q.debug(`Validating version directory for v${t}...`);let n=M(fi,`v${t}`);w(n)||(Q.warn(`Version v${t} not found`),process.exit(1)),Q.debug(`Validating version dir...`);let r=M(n,`package.json`);w(r)||(Q.error(`Version v${t} is missing package.json`),process.exit(1));try{JSON.parse(E(r,`utf-8`)).version||(Q.error(`Version v${t} has invalid package.json (missing version field)`),process.exit(1))}catch{Q.error(`Version v${t} has invalid package.json`),process.exit(1)}let i=M(fi,`current-version.json.tmp`);await We(i,JSON.stringify({version:t},null,2),`utf-8`),await Ve(i,pi),Q.info(`Switched to v${t}`)}}],hi=[{name:`search`,description:`Search the AI Kit index`,usage:`aikit search <query> [--limit N] [--mode hybrid|semantic|keyword] [--graph-hops 0-3]`,run:async e=>{let t=y(e),n=_(e,`--limit`,5),r=v(e,`--mode`,`hybrid`),i=_(e,`--graph-hops`,0),a=e.join(` `).trim();if(!a)throw new g(`Usage: aikit search <query>`);let{embedder:o,store:s,graphStore:c}=await J(),d=await o.embedQuery(a),f;if(r===`keyword`)f=await s.ftsSearch(a,{limit:n});else if(r===`semantic`)f=await s.search(d,{limit:n});else{let[e,t]=await Promise.all([s.search(d,{limit:n*2}),s.ftsSearch(a,{limit:n*2}).catch(()=>[])]);f=u(e,t).slice(0,n)}if(t){l({query:a,results:f,graphHops:i});return}if(f.length===0){console.log(`No results found.`);return}for(let{record:e,score:t}of f){console.log(`\n${`─`.repeat(60)}`),console.log(`[${(t*100).toFixed(1)}%] ${e.sourcePath}:${e.startLine}-${e.endLine}`),console.log(` Type: ${e.contentType} | Origin: ${e.origin}`),e.tags.length>0&&console.log(` Tags: ${e.tags.join(`, `)}`),console.log(``);let n=e.content.length>500?`${e.content.slice(0,500)}...`:e.content;console.log(n)}if(console.log(`\n${`─`.repeat(60)}`),console.log(`${f.length} result(s) found.`),i>0&&f.length>0)try{let{graphAugmentSearch:e}=await import(`../../tools/dist/index.js`),t=(await e(c,f.map(e=>({recordId:e.record.id,score:e.score,sourcePath:e.record.sourcePath})),{hops:i,maxPerHit:5})).filter(e=>e.graphContext.nodes.length>0);if(t.length>0){console.log(`\nGraph context (${i} hop${i>1?`s`:``}):\n`);for(let e of t){console.log(` ${e.sourcePath}:`);for(let t of e.graphContext.nodes.slice(0,5))console.log(` → ${t.name} (${t.type})`);for(let t of e.graphContext.edges.slice(0,5))console.log(` → ${t.fromId} --[${t.type}]--> ${t.toId}`)}}}catch(e){console.error(`[graph] augmentation failed: ${e.message}`)}}},{name:`find`,description:`Run federated search across indexed content and files`,usage:`aikit find [query] [--glob <pattern>] [--pattern <regex>] [--limit N]`,run:async e=>{let t=y(e),n=_(e,`--limit`,10),r=v(e,`--glob`,``).trim()||void 0,i=v(e,`--pattern`,``).trim()||void 0,a=e.join(` `).trim()||void 0;if(!a&&!r&&!i)throw new g(`Usage: aikit find [query] [--glob <pattern>] [--pattern <regex>] [--limit N]`);let{embedder:o,store:s}=await J(),c=await st(o,s,{query:a,glob:r,pattern:i,limit:n});if(t){l(c);return}if(c.results.length===0){console.log(`No matches found.`);return}console.log(`Strategies: ${c.strategies.join(`, `)}`),console.log(`Results: ${c.results.length} shown (${c.totalFound} total)`);for(let e of c.results){let t=e.lineRange?`:${e.lineRange.start}-${e.lineRange.end}`:``;console.log(`\n[${e.source}] ${e.path}${t}`),console.log(` Score: ${(e.score*100).toFixed(1)}%`),e.preview&&console.log(` ${e.preview.replace(/\s+/g,` `).trim()}`)}}},{name:`scope-map`,description:`Generate a reading plan for a task`,usage:`aikit scope-map <task> [--max-files N]`,run:async e=>{let t=_(e,`--max-files`,15),n=e.join(` `).trim();if(!n)throw new g(`Usage: aikit scope-map <task> [--max-files N]`);let{embedder:r,store:i}=await J(),a=await Ut(r,i,{task:n,maxFiles:t});console.log(`Task: ${a.task}`),console.log(`Files: ${a.files.length}`),console.log(`Estimated tokens: ${a.totalEstimatedTokens}`),console.log(``),console.log(`Reading order:`);for(let e of a.readingOrder)console.log(` ${e}`);for(let[e,t]of a.files.entries())console.log(`\n${e+1}. ${t.path}`),console.log(` Relevance: ${(t.relevance*100).toFixed(1)}% | Tokens: ${t.estimatedTokens}`),console.log(` Why: ${t.reason}`),t.focusRanges.length>0&&console.log(` Focus: ${C(t.focusRanges)}`)}},{name:`symbol`,description:`Resolve a symbol definition, imports, and references`,usage:`aikit symbol <name> [--limit N]`,run:async e=>{let t=_(e,`--limit`,20),n=e.join(` `).trim();if(!n)throw new g(`Usage: aikit symbol <name> [--limit N]`);let{embedder:r,store:i}=await J();x(await Yt(r,i,{name:n,limit:t}))}},{name:`trace`,description:`Trace forward/backward flow for a symbol or file location`,usage:`aikit trace <start> [--direction forward|backward|both] [--max-depth N]`,run:async e=>{let t=v(e,`--direction`,`both`).trim()||`both`,n=_(e,`--max-depth`,3),r=e.join(` `).trim();if(!r||![`forward`,`backward`,`both`].includes(t))throw new g(`Usage: aikit trace <start> [--direction forward|backward|both] [--max-depth N]`);let{embedder:i,store:a}=await J();se(await Zt(i,a,{start:r,direction:t,maxDepth:n}))}},{name:`examples`,description:`Find real code examples of a symbol or pattern`,usage:`aikit examples <query> [--limit N] [--content-type type]`,run:async e=>{let t=_(e,`--limit`,5),n=v(e,`--content-type`,``).trim()||void 0,r=e.join(` `).trim();if(!r)throw new g(`Usage: aikit examples <query> [--limit N] [--content-type type]`);let{embedder:i,store:a}=await J();s(await lt(i,a,{query:r,limit:t,contentType:n}))}},{name:`dead-symbols`,description:`Find exported symbols that appear to be unused`,usage:`aikit dead-symbols [--limit N]`,run:async e=>{let t=_(e,`--limit`,100),{embedder:n,store:r}=await J();_e(await ct(n,r,{limit:t}))}},{name:`lookup`,description:`Look up indexed content by record ID or source path`,usage:`aikit lookup <id>`,run:async e=>{let t=e.join(` `).trim();if(!t)throw new g(`Usage: aikit lookup <id>`);let{store:n}=await J(),r=await n.getById(t);if(r){console.log(r.id),console.log(`─`.repeat(60)),console.log(`Path: ${r.sourcePath}`),console.log(`Chunk: ${r.chunkIndex+1}/${r.totalChunks}`),console.log(`Lines: ${r.startLine}-${r.endLine}`),console.log(`Type: ${r.contentType} | Origin: ${r.origin}`),r.tags.length>0&&console.log(`Tags: ${r.tags.join(`, `)}`),console.log(``),console.log(r.content);return}let i=await n.getBySourcePath(t);if(i.length===0){console.log(`No indexed content found for: ${t}`);return}i.sort((e,t)=>e.chunkIndex-t.chunkIndex),console.log(t),console.log(`─`.repeat(60)),console.log(`Chunks: ${i.length} | Type: ${i[0].contentType}`);for(let e of i){let t=e.startLine?` (lines ${e.startLine}-${e.endLine})`:``;console.log(`\nChunk ${e.chunkIndex+1}/${e.totalChunks}${t}`),console.log(e.content)}}}];async function gi(e){let{port:t,noOpen:n,urlPath:r,commandName:i}=e;console.log(`Starting AI Kit server on port ${t}...`);let{spawn:a}=await import(`node:child_process`),{platform:o}=await import(`node:os`),s=te(),c=a(process.execPath,[s,`--transport`,`http`,`--port`,String(t)],{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env,NODE_OPTIONS:f(process.env.NODE_OPTIONS),AIKIT_TRANSPORT:`http`,AIKIT_PORT:String(t)}}),l=`http://localhost:${t}${r}`,u=`http://localhost:${t}/health`,d=!1;for(let e=0;e<30;e+=1){try{if((await fetch(u)).ok){d=!0;break}}catch{}await new Promise(e=>setTimeout(e,1e3))}if(!d)throw c.kill(),new g(`Server failed to start within 30 seconds.`);let p=i.charAt(0).toUpperCase()+i.slice(1);if(console.log(`AI Kit ${p}: ${l}`),console.log(`Press Ctrl+C to stop.`),!n){let e=o();e===`win32`?a(`cmd`,[`/c`,`start`,``,l],{stdio:`ignore`,detached:!0}).unref():a(e===`darwin`?`open`:`xdg-open`,[l],{stdio:`ignore`,detached:!0}).unref()}let m=()=>{c.kill(),process.exit(0)};process.on(`SIGINT`,m),process.on(`SIGTERM`,m),await new Promise(e=>{c.on(`exit`,()=>e())})}const _i=[{name:`status`,description:`Show AI Kit index status and statistics`,run:async e=>{let t=y(e),{AIKIT_PATHS:n,computePartitionKey:r,getPartitionDir:i,isUserInstalled:a,listWorkspaces:o}=await import(`../../core/dist/index.js`),{existsSync:s}=await import(`node:fs`),c=process.cwd(),u=a(),d=s(P(c,`.vscode`,`mcp.json`)),f={mode:void 0,dataPath:void 0};if(u&&d)f.mode=`workspace (overrides user-level for this workspace)`,f.dataPath=P(c,n.data);else if(u){let e=r(c);f.mode=s(P(c,`AGENTS.md`))?`user (workspace scaffolded)`:`user (workspace not scaffolded)`,f.dataPath=i(e)}else f.mode=`workspace`,f.dataPath=P(c,n.data);u&&!d&&(f.workspaces=o().length);try{let{store:e}=await J(),t=await e.getStats(),n=await e.listSourcePaths();f.records=t.totalRecords,f.files=t.totalFiles,f.lastIndexed=t.lastIndexedAt??null,f.backend=t.storeBackend,f.model=t.embeddingModel,f.contentTypeBreakdown=t.contentTypeBreakdown,f.sourcePaths=n.slice(0,20),f.sourcePathTotal=n.length}catch{f.indexAvailable=!1}if(t){l(f);return}if(console.log(`AI Kit Status`),console.log(`─`.repeat(40)),console.log(` Mode: ${f.mode}`),console.log(` Data: ${f.dataPath}`),u&&!d){let e=o();console.log(` Registry: ${e.length} workspace(s) enrolled`)}if(f.records!==void 0){console.log(` Records: ${f.records}`),console.log(` Files: ${f.files}`),console.log(` Indexed: ${f.lastIndexed??`Never`}`),console.log(` Backend: ${f.backend}`),console.log(` Model: ${f.model}`),console.log(``),console.log(`Content Types:`);for(let[e,t]of Object.entries(f.contentTypeBreakdown))console.log(` ${e}: ${t}`);let e=f.sourcePaths;if(e.length>0){console.log(``),console.log(`Files (${f.sourcePathTotal} total):`);for(let t of e.slice(0,20))console.log(` ${t}`);f.sourcePathTotal>20&&console.log(` ... and ${f.sourcePathTotal-20} more`)}}else console.log(``),console.log(" Index not available — run `aikit reindex` to index this workspace.");u&&!d&&!s(P(c,`AGENTS.md`))&&(console.log(``),console.log(" Action: Run `npx @vpxa/aikit init` to add AGENTS.md and copilot-instructions.md"))}},{name:`reindex`,description:`Re-index the AI Kit index from configured sources`,usage:`aikit reindex [--full]`,run:async e=>{let t=e.includes(`--full`),{store:n,indexer:r,curated:i,config:a}=await J();console.log(`Indexing sources...`);let o=e=>{e.phase===`chunking`&&e.currentFile&&process.stdout.write(`\r [${e.filesProcessed+1}/${e.filesTotal}] ${e.currentFile}`),e.phase===`done`&&process.stdout.write(`
52
+ `)},s;t?(console.log(`Dropping existing index for full reindex...`),s=await r.reindexAll(a,o)):s=await r.index(a,o),console.log(`Done: ${s.filesProcessed} files, ${s.chunksCreated} chunks in ${(s.durationMs/1e3).toFixed(1)}s`),console.log(`Building FTS index...`),await n.createFtsIndex(),console.log(`Re-indexing curated entries...`);let c=await i.reindexAll();console.log(`Curated: ${c.indexed} entries restored`)}},{name:`serve`,description:`Start the MCP server. Default: direct stdio (one server per workspace). Use --daemon to share a single HTTP daemon across multiple clients.`,usage:`aikit serve [--transport stdio|http] [--port N] [--daemon]`,run:async e=>{let t=v(e,`--transport`,`stdio`),n=v(e,`--port`,`3210`),r=me(e,`--daemon`);try{await kr({silent:!0})}catch{}if(t===`stdio`&&r){let{runProxy:e}=await import(`../../server/dist/proxy.js`);try{let t=`http://127.0.0.1:${n}/health`;if((await fetch(t,{signal:AbortSignal.timeout(2e3)})).ok){await e({port:Number(n),autoStart:!1});return}}catch{}await e({port:Number(n),autoStart:!0});return}let i=nn(te(),[],{stdio:t===`stdio`?[`pipe`,`pipe`,`inherit`,`ipc`]:`inherit`,env:{...process.env,NODE_OPTIONS:f(process.env.NODE_OPTIONS),AIKIT_TRANSPORT:t,AIKIT_PORT:n}});t===`stdio`&&i.stdin&&i.stdout&&(process.stdin.pipe(i.stdin),i.stdout.pipe(process.stdout)),i.on(`exit`,e=>process.exit(e??0)),process.on(`SIGINT`,()=>i.kill(`SIGINT`)),process.on(`SIGTERM`,()=>i.kill(`SIGTERM`)),await new Promise(()=>{})}},{name:`init`,description:`Initialize AI Kit in the current directory`,usage:`aikit init [--workspace] [--smart] [--force] [--guide]`,run:async e=>{let t=e.includes(`--user`),n=e.includes(`--workspace`),r=e.includes(`--smart`),i=e.includes(`--guide`),a=e.includes(`--force`);if(t&&n)throw new g(`Cannot use --user and --workspace together.`);if(i){let{guideProject:e}=await import(`./init-CyjUXjQw.js`);await e();return}if(r){let{initSmart:e}=await import(`./init-CyjUXjQw.js`);await e({force:a})}else if(t)await cr({force:a});else if(n){let{initProject:e}=await import(`./init-CyjUXjQw.js`);await e({force:a})}else await cr({force:a})}},{name:`check`,description:`Run incremental typecheck and lint`,usage:`aikit check [--cwd <dir>] [--files f1,f2] [--skip-types] [--skip-lint] [--detail efficient|normal|full]`,run:async e=>{let t=v(e,`--cwd`,``).trim()||void 0,n=v(e,`--files`,``),r=v(e,`--detail`,`full`)||`full`,i=n.split(`,`).map(e=>e.trim()).filter(Boolean),a=!1;e.includes(`--skip-types`)&&(e.splice(e.indexOf(`--skip-types`),1),a=!0);let o=!1;e.includes(`--skip-lint`)&&(e.splice(e.indexOf(`--skip-lint`),1),o=!0);let s=await qe({cwd:t,files:i.length>0?i:void 0,skipTypes:a,skipLint:o,detail:r});ve(s),s.passed||(process.exitCode=1)}},{name:`health`,description:`Run project health checks on the current directory`,usage:`aikit health [path]`,run:async e=>{let t=y(e),n=mt(e.shift());if(t){l(n);return}console.log(`Project Health: ${n.path}`),console.log(`─`.repeat(50));for(let e of n.checks){let t=e.status===`pass`?`+`:e.status===`warn`?`~`:`X`;console.log(` [${t}] ${e.name}: ${e.message}`)}console.log(`─`.repeat(50)),console.log(`Score: ${n.score}% — ${n.summary}`)}},{name:`prune`,description:`Clean up orphaned storage, legacy data, and stale partitions`,usage:`aikit prune [--dry-run] [--max-age-days=90] [--force]`,run:async e=>{let{prune:t,formatBytes:n,markPruneRun:r}=await import(`../../tools/dist/index.js`),i=e.includes(`--dry-run`),a=e.includes(`--force`),o=e.find(e=>e.startsWith(`--max-age-days=`)),s=o?Number.parseInt(o.split(`=`)[1]??``,10):90;if(!i&&!a){console.log(`⚠️ This will permanently delete data. Use --dry-run to preview, or --force to execute.`);return}console.log(i?`🔍 Dry run — no files will be deleted
53
53
  `:`🧹 Pruning storage...
54
54
  `);let c=await t({dryRun:i,maxAgeDays:s});console.log(`Results:`),console.log(` Forge-ground orphans: ${c.forgeGroundOrphans.count} dirs (${n(c.forgeGroundOrphans.bytesFreed)})`),console.log(` Legacy LanceDB: ${c.legacyLance.count} dirs (${n(c.legacyLance.bytesFreed)})`),console.log(` Empty ephemeral dirs: ${c.emptyEphemeral.count} dirs`),console.log(` Stale partitions: ${c.stalePartitions.count} dirs (${n(c.stalePartitions.bytesFreed)})`),console.log(` Browser profiles: ${c.browserProfiles.count} dirs (${n(c.browserProfiles.bytesFreed)})`),console.log(`\n Total freed: ${n(c.totalBytesFreed)}`),i||(r(),console.log(`
55
55
  ✅ Cleanup complete.`))}},{name:`audit`,description:`Run a unified project audit (structure, deps, patterns, health, dead symbols, check)`,usage:`aikit audit [path] [--checks structure,dependencies,patterns,health,dead_symbols,check,entry_points] [--detail efficient|normal|full]`,run:async e=>{let{store:t,embedder:n}=await J(),r=v(e,`--detail`,`efficient`)||`efficient`,i=v(e,`--checks`,``),a=i?i.split(`,`).map(e=>e.trim()):void 0,o=await Ke(t,n,{path:e.shift()||`.`,checks:a,detail:r});if(o.ok){if(console.log(o.summary),o.next&&o.next.length>0){console.log(`
56
56
  Suggested next steps:`);for(let e of o.next)console.log(` → ${e.tool}: ${e.reason}`)}}else console.error(o.error?.message??`Audit failed`),process.exitCode=1}},{name:`guide`,description:`Tool discovery — recommend AI Kit tools for a given goal`,usage:`aikit guide <goal> [--max N]`,run:async e=>{let t=e.indexOf(`--max`),n=5;t!==-1&&t+1<e.length&&(n=Number.parseInt(e.splice(t,2)[1],10)||5);let r=e.join(` `).trim();if(!r)throw new g(`Usage: aikit guide <goal> [--max N]
57
- Example: aikit guide "audit this project"`);let i=pt(r,n);console.log(`Workflow: ${i.workflow}`),console.log(` ${i.description}\n`),console.log(`Recommended tools:`);for(let e of i.tools){let t=e.suggestedArgs?` ${JSON.stringify(e.suggestedArgs)}`:``;console.log(` ${e.order}. ${e.tool} — ${e.reason}${t}`)}i.alternativeWorkflows.length>0&&console.log(`\nAlternatives: ${i.alternativeWorkflows.join(`, `)}`)}},{name:`replay`,description:`Show recent tool invocation audit trail`,usage:`aikit replay [--last N] [--tool <name>] [--source mcp|cli]`,run:async e=>{let t=Bt({last:Number.parseInt(e[e.indexOf(`--last`)+1],10)||20,tool:e.includes(`--tool`)?e[e.indexOf(`--tool`)+1]:void 0,source:e.includes(`--source`)?e[e.indexOf(`--source`)+1]:void 0});if(t.length===0){console.log(`No replay entries. Activity is logged when tools are invoked.`);return}console.log(`Replay Log (${t.length} entries)\n`);for(let e of t){let t=e.ts.split(`T`)[1]?.split(`.`)[0]??e.ts,n=e.status===`ok`?`✓`:`✗`;console.log(`${t} ${n} ${e.tool} (${e.durationMs}ms) [${e.source}]`),console.log(` in: ${e.input}`),console.log(` out: ${e.output}`)}Vt().catch(()=>{})}},{name:`replay-clear`,description:`Clear the replay audit trail`,run:async()=>{zt(),console.log(`Replay log cleared.`)}},{name:`dashboard`,description:`Launch web dashboard for knowledge graph visualization`,usage:`aikit dashboard [--port <port>] [--no-open]`,run:async e=>{let t=e.indexOf(`--port`),n=t!==-1&&e[t+1]?Number.parseInt(e[t+1],10):3210;await pi({port:Number.isFinite(n)?n:3210,noOpen:e.includes(`--no-open`),urlPath:`/_dashboard/`,commandName:`dashboard`})}},{name:`settings`,description:`Launch web UI to manage AI Kit configuration and environment variables`,usage:`aikit settings [--port <port>] [--no-open]`,run:async e=>{let t=e.indexOf(`--port`),n=t!==-1&&e[t+1]?Number.parseInt(e[t+1],10):3210;await pi({port:Number.isFinite(n)?n:3210,noOpen:e.includes(`--no-open`),urlPath:`/settings/`,commandName:`settings`})}}],$=L(`cli:update`),hi=M(z(),`.aikit`),gi=M(hi,`versions`),_i=M(hi,`current-version.json`);function vi(){if(!w(_i))return null;try{let e=E(_i,`utf-8`);return JSON.parse(e)}catch{return null}}function yi(e){w(hi)||T(hi,{recursive:!0});let t=`${_i}.tmp`;A(t,`${JSON.stringify({version:e,installedAt:new Date().toISOString()},null,2)}\n`),O(t,_i)}function bi(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){let t=n[e]??0,i=r[e]??0;if(t>i)return!0;if(t<i)return!1}return!1}async function xi(){let e=await fetch(`https://registry.npmjs.org/@vpxa%2faikit/latest`);if(!e.ok)throw Error(`npm registry responded ${e.status}: ${e.statusText}`);let t=await e.json(),n=Array.isArray(t)?t[0]:t;return n.version??n[`dist-tags`]?.latest??`0.0.0`}const Si=[{name:`version-update`,description:`Update AI Kit to the latest version from npm (auto-detects and installs newer release)`,usage:`aikit version-update`,run:async()=>{let e=vi();if(!e){$.debug("No installed version found. Run `aikit install` first.");return}$.debug(`Current version: ${e.version}`);let t;try{t=await xi()}catch(e){let t=e instanceof Error?e.message:String(e);$.error(`Failed to check for updates: ${t}`);return}if($.debug(`Latest version: ${t}`),!bi(t,e.version)){$.info(`Already latest version.`);return}$.debug(`Updating to ${t}...`);try{let e=`https://registry.npmjs.org/@vpxa/aikit/-/aikit-${t}.tgz`,n=await fetch(e);if(!n.ok)throw Error(`Download failed: ${n.status} ${n.statusText}`);let r=Buffer.from(await n.arrayBuffer()),i=M(gi,`v${t}-staging`);w(i)&&k(i,{recursive:!0,force:!0}),T(i,{recursive:!0});try{let e=M(i,`aikit-${t}.tgz`);A(e,r),$.debug(`Extracting...`),R(`tar -xzf "${e}"`,{cwd:i,stdio:`pipe`,timeout:6e4});let n=M(i,`package`);if(!w(n))throw Error(`Expected "package/" directory not found after extraction`);$.debug(`Installing production dependencies...`),R(`npm install --production --install-strategy=nested --no-audit --no-fund`,{cwd:n,stdio:`pipe`,timeout:3e5});let a=M(n,`packages`,`server`,`dist`,`bin.js`);if(!w(a))throw Error(`Server entry not found at ${a}`);let o=M(gi,`v${t}`);w(gi)||T(gi,{recursive:!0}),w(o)&&($.debug(`Removing previous installation at ${o}...`),k(o,{recursive:!0,force:!0})),O(n,o),yi(t),$.info(`Updated to ${t}`)}finally{w(i)&&k(i,{recursive:!0,force:!0})}}catch(e){let t=e instanceof Error?e.message:String(e);$.error(`Update failed: ${t}`)}}}],Ci=[{name:`upgrade`,description:`Upgrade AI Kit agents, prompts, and skills to the latest version (user-level and workspace-level)`,usage:`aikit upgrade`,run:async()=>{await ar({force:!0});let e=process.cwd();if(w(P(e,`.github`,`.aikit-scaffold.json`))){let{initScaffoldOnly:e}=await import(`./init-CyjUXjQw.js`);await e({force:!0})}if(w(P(e,`.github`,`skills`))){let{smartCopySkills:t}=await import(`./scaffold-BNPHP-QC.js`).then(e=>e.a),n=S(),r=oe();await t(e,n,[...ue],r,!0);let{smartCopyFlows:i}=await import(`./scaffold-BNPHP-QC.js`).then(e=>e.a);await i(e,n,[...de],r,!0)}let{homedir:t}=await import(`node:os`),{rmSync:n}=await import(`node:fs`),r=M(t(),`.aikit`,`cache`,`wasm`);if(w(r))try{n(r,{recursive:!0,force:!0}),console.log(`✓ WASM cache cleared (will re-resolve on next start)`)}catch{console.warn(`⚠ Could not clear WASM cache at`,r)}}}],wi=L(`cli:versions`),Ti=M(z(),`.aikit`,`versions`),Ei=M(z(),`.aikit`,`current-version.json`);function Di(){try{return w(Ei)?JSON.parse(E(Ei,`utf-8`)).version??null:null}catch{return null}}const Oi=[{name:`versions`,description:`List installed AI Kit versions (shows current, date, and available rollbacks)`,usage:`aikit versions`,run:async()=>{if(!w(Ti)){wi.warn(`No versions installed.`);return}let e=Di(),t=D(Ti,{withFileTypes:!0}).filter(e=>e.isDirectory()&&/^v\d+\.\d+\.\d+$/.test(e.name)).map(e=>{let t=be(M(Ti,e.name));return{name:e.name,ver:e.name.slice(1),mtime:t.mtime}}).sort((e,t)=>t.mtime.getTime()-e.mtime.getTime());if(t.length===0){wi.warn(`No versions installed.`);return}for(let n of t){let t=n.ver===e,r=n.mtime.toISOString().split(`T`)[0],i=t?`(current)`:`(older)`,a=t?` ←`:``;console.log(`${n.name} - ${r} ${i}${a}`)}}}],ki=[{name:`workset`,description:`Manage saved file sets`,usage:`aikit workset <action> [name] [--files f1,f2] [--description desc]`,run:async e=>{let t=e.shift()?.trim(),n=d(v(e,`--files`,``)),r=v(e,`--description`,``).trim()||void 0,i=e.shift()?.trim();switch(t||(console.error(`Usage: aikit workset <action> [name] [--files f1,f2] [--description desc]`),console.error(`Actions: save, get, list, delete, add, remove`),process.exit(1)),t){case`save`:{(!i||n.length===0)&&(console.error(`Usage: aikit workset save <name> --files f1,f2 [--description desc]`),process.exit(1));let e=Ht(i,n,{description:r});console.log(`Saved workset: ${e.name}`),p(e);return}case`get`:{i||(console.error(`Usage: aikit workset get <name>`),process.exit(1));let e=ut(i);if(!e){console.log(`No workset found: ${i}`);return}p(e);return}case`list`:{let e=xt();if(e.length===0){console.log(`No worksets saved.`);return}console.log(`Worksets (${e.length})`),console.log(`─`.repeat(60));for(let t of e)p(t),console.log(``);return}case`delete`:{i||(console.error(`Usage: aikit workset delete <name>`),process.exit(1));let e=rt(i);console.log(e?`Deleted workset: ${i}`:`No workset found: ${i}`);return}case`add`:{(!i||n.length===0)&&(console.error(`Usage: aikit workset add <name> --files f1,f2`),process.exit(1));let e=Ge(i,n);console.log(`Updated workset: ${e.name}`),p(e);return}case`remove`:{(!i||n.length===0)&&(console.error(`Usage: aikit workset remove <name> --files f1,f2`),process.exit(1));let e=Lt(i,n);if(!e){console.log(`No workset found: ${i}`);return}console.log(`Updated workset: ${e.name}`),p(e);return}default:console.error(`Unknown workset action: ${t}`),console.error(`Actions: save, get, list, delete, add, remove`),process.exit(1)}}},{name:`stash`,description:`Persist and retrieve named intermediate values`,usage:`aikit stash <set|get|list|delete|clear> [key] [value]`,run:async e=>{let t=e.shift()?.trim(),n=e.shift()?.trim();t||(console.error(`Usage: aikit stash <set|get|list|delete|clear> [key] [value]`),process.exit(1));let r=await ce();switch(t){case`set`:{n||(console.error(`Usage: aikit stash set <key> <value>`),process.exit(1));let t=e.join(` `),i=t.trim()?``:await m(),a=Jt(r,n,ie(t||i));console.log(`Stored stash entry: ${a.key}`),console.log(` Type: ${a.type}`),console.log(` Stored: ${a.storedAt}`);return}case`get`:{n||(console.error(`Usage: aikit stash get <key>`),process.exit(1));let e=Kt(r,n);if(!e){console.log(`No stash entry found: ${n}`);return}console.log(JSON.stringify(e,null,2));return}case`list`:{let e=qt(r);if(e.length===0){console.log(`No stash entries saved.`);return}console.log(`Stash entries (${e.length})`),console.log(`─`.repeat(60));for(let t of e)console.log(`${t.key} (${t.type})`),console.log(` Stored: ${t.storedAt}`);return}case`delete`:{n||(console.error(`Usage: aikit stash delete <key>`),process.exit(1));let e=Gt(r,n);console.log(e?`Deleted stash entry: ${n}`:`No stash entry found: ${n}`);return}case`clear`:{let e=Wt(r);console.log(`Cleared ${e} stash entr${e===1?`y`:`ies`}.`);return}default:console.error(`Unknown stash action: ${t}`),console.error(`Actions: set, get, list, delete, clear`),process.exit(1)}}},{name:`lane`,description:`Manage verified lanes — isolated file copies for parallel exploration`,usage:`aikit lane <create|list|status|diff|merge|discard> [name] [--files f1,f2]`,run:async e=>{let t=e.shift();if((!t||![`create`,`list`,`status`,`diff`,`merge`,`discard`].includes(t))&&(console.error(`Usage: aikit lane <create|list|status|diff|merge|discard> [name] [--files f1,f2]`),process.exit(1)),t===`list`){let e=vt();if(e.length===0){console.log(`No active lanes.`);return}for(let t of e)console.log(`${t.name} (${t.sourceFiles.length} files, created ${t.createdAt})`);return}let n=e.shift();switch(n||(console.error(`Lane name is required for "${t}".`),process.exit(1)),t){case`create`:{let t=v(e,`--files`,``);t||(console.error(`Usage: aikit lane create <name> --files file1.ts,file2.ts`),process.exit(1));let r=ht(n,t.split(`,`).map(e=>e.trim()));console.log(`Lane "${r.name}" created with ${r.sourceFiles.length} files.`);break}case`status`:{let e=bt(n);console.log(`Lane: ${e.name}`),console.log(`Modified: ${e.modified} | Added: ${e.added} | Deleted: ${e.deleted}`);for(let t of e.entries)console.log(` ${t.status.padEnd(10)} ${t.file}`);break}case`diff`:{let e=gt(n);console.log(`Lane: ${e.name} — ${e.modified} modified, ${e.added} added, ${e.deleted} deleted`);for(let t of e.entries)t.diff&&(console.log(`\n--- ${t.file} (${t.status})`),console.log(t.diff));break}case`merge`:{let e=yt(n);console.log(`Merged ${e.filesMerged} files from lane "${e.name}".`);for(let t of e.files)console.log(` ${t}`);break}case`discard`:{let e=_t(n);console.log(e?`Lane "${n}" discarded.`:`Lane "${n}" not found.`);break}}}},{name:`queue`,description:`Manage task queues for sequential agent operations`,usage:`aikit queue <create|push|next|done|fail|get|list|clear|delete> [name] [args]`,run:async e=>{let t=e.shift();if((!t||![`create`,`push`,`next`,`done`,`fail`,`get`,`list`,`clear`,`delete`].includes(t))&&(console.error(`Usage: aikit queue <create|push|next|done|fail|get|list|clear|delete> [name] [args]`),process.exit(1)),t===`list`){let e=Pt();if(e.length===0){console.log(`No queues.`);return}for(let t of e)console.log(`${t.name} pending:${t.pending} done:${t.done} failed:${t.failed} total:${t.total}`);return}let n=e.shift();switch(n||(console.error(`Queue name is required for "${t}".`),process.exit(1)),t){case`create`:{let e=kt(n);console.log(`Queue "${e.name}" created.`);break}case`push`:{let t=It(n,e.join(` `)||`Untitled task`);console.log(`Pushed "${t.title}" (${t.id}) to queue "${n}".`);break}case`next`:{let e=Ft(n);console.log(e?`Next: ${e.title} (${e.id})`:`No pending items in queue "${n}".`);break}case`done`:{let t=e.shift();t||(console.error(`Usage: aikit queue done <name> <id>`),process.exit(1));let r=jt(n,t);console.log(`Marked "${r.item.title}" as done.`);break}case`fail`:{let t=e.shift(),r=e.join(` `)||`Unknown error`;t||(console.error(`Usage: aikit queue fail <name> <id> [error message]`),process.exit(1));let i=Mt(n,t,r);console.log(`Marked "${i.title}" as failed: ${r}`);break}case`get`:{let e=Nt(n);if(!e){console.log(`Queue "${n}" not found.`);return}console.log(`Queue: ${e.name} (${e.items.length} items)`);for(let t of e.items){let e=t.error?` — ${t.error}`:``;console.log(` ${t.status.padEnd(12)} ${t.id} ${t.title}${e}`)}break}case`clear`:{let e=Ot(n);console.log(`Cleared ${e} completed/failed items from queue "${n}".`);break}case`delete`:{let e=At(n);console.log(e?`Queue "${n}" deleted.`:`Queue "${n}" not found.`);break}}}}],Ai=[...fi,...ci,...mn,...Hr,...si,...mi,...kr,...hn,...wn,...ki,...Or,...Si,...Ci,...Nr,...Dr,...Oi,...di,...zr];Ai.push({name:`help`,description:`Show available commands`,run:async()=>{Mi()}});async function ji(e){let t=[...e],n=t.shift();if(!n||n===`--help`||n===`-h`){Mi();return}if(n===`--version`||n===`-v`){let e=P(j(we(import.meta.url)),`..`,`..`,`..`,`package.json`),t=JSON.parse(E(e,`utf-8`));console.log(t.version);return}if(n&&new Set([`--user`,`--workspace`,`--guide`,`--smart`]).has(n)){let e=Ai.find(e=>e.name===`init`);if(e){await e.run([n,...t]);return}}let r=Ai.find(e=>e.name===n);r||(console.error(`Unknown command: ${n}`),Mi(),process.exit(1));try{await r.run(t)}catch(e){throw e instanceof g&&(console.error(e.message),process.exit(e.exitCode)),e}finally{let e=Vr();e&&await e.store.close()}}function Mi(){console.log(`@vpxa/aikit — Local-first AI developer toolkit
57
+ Example: aikit guide "audit this project"`);let i=pt(r,n);console.log(`Workflow: ${i.workflow}`),console.log(` ${i.description}\n`),console.log(`Recommended tools:`);for(let e of i.tools){let t=e.suggestedArgs?` ${JSON.stringify(e.suggestedArgs)}`:``;console.log(` ${e.order}. ${e.tool} — ${e.reason}${t}`)}i.alternativeWorkflows.length>0&&console.log(`\nAlternatives: ${i.alternativeWorkflows.join(`, `)}`)}},{name:`replay`,description:`Show recent tool invocation audit trail`,usage:`aikit replay [--last N] [--tool <name>] [--source mcp|cli]`,run:async e=>{let t=Bt({last:Number.parseInt(e[e.indexOf(`--last`)+1],10)||20,tool:e.includes(`--tool`)?e[e.indexOf(`--tool`)+1]:void 0,source:e.includes(`--source`)?e[e.indexOf(`--source`)+1]:void 0});if(t.length===0){console.log(`No replay entries. Activity is logged when tools are invoked.`);return}console.log(`Replay Log (${t.length} entries)\n`);for(let e of t){let t=e.ts.split(`T`)[1]?.split(`.`)[0]??e.ts,n=e.status===`ok`?`✓`:`✗`;console.log(`${t} ${n} ${e.tool} (${e.durationMs}ms) [${e.source}]`),console.log(` in: ${e.input}`),console.log(` out: ${e.output}`)}Vt().catch(()=>{})}},{name:`replay-clear`,description:`Clear the replay audit trail`,run:async()=>{zt(),console.log(`Replay log cleared.`)}},{name:`dashboard`,description:`Launch web dashboard for knowledge graph visualization`,usage:`aikit dashboard [--port <port>] [--no-open]`,run:async e=>{let t=e.indexOf(`--port`),n=t!==-1&&e[t+1]?Number.parseInt(e[t+1],10):3210;await gi({port:Number.isFinite(n)?n:3210,noOpen:e.includes(`--no-open`),urlPath:`/_dashboard/`,commandName:`dashboard`})}},{name:`settings`,description:`Launch web UI to manage AI Kit configuration and environment variables`,usage:`aikit settings [--port <port>] [--no-open]`,run:async e=>{let t=e.indexOf(`--port`),n=t!==-1&&e[t+1]?Number.parseInt(e[t+1],10):3210;await gi({port:Number.isFinite(n)?n:3210,noOpen:e.includes(`--no-open`),urlPath:`/settings/`,commandName:`settings`})}}],$=L(`cli:update`),vi=M(z(),`.aikit`),yi=M(vi,`versions`),bi=M(vi,`current-version.json`);function xi(){if(!w(bi))return null;try{let e=E(bi,`utf-8`);return JSON.parse(e)}catch{return null}}function Si(e){w(vi)||T(vi,{recursive:!0});let t=`${bi}.tmp`;A(t,`${JSON.stringify({version:e,installedAt:new Date().toISOString()},null,2)}\n`),O(t,bi)}function Ci(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){let t=n[e]??0,i=r[e]??0;if(t>i)return!0;if(t<i)return!1}return!1}async function wi(){let e=await fetch(`https://registry.npmjs.org/@vpxa%2faikit/latest`);if(!e.ok)throw Error(`npm registry responded ${e.status}: ${e.statusText}`);let t=await e.json(),n=Array.isArray(t)?t[0]:t;return n.version??n[`dist-tags`]?.latest??`0.0.0`}const Ti=[{name:`version-update`,description:`Update AI Kit to the latest version from npm (auto-detects and installs newer release)`,usage:`aikit version-update`,run:async()=>{let e=xi();if(!e){$.debug("No installed version found. Run `aikit install` first.");return}$.debug(`Current version: ${e.version}`);let t;try{t=await wi()}catch(e){let t=e instanceof Error?e.message:String(e);$.error(`Failed to check for updates: ${t}`);return}if($.debug(`Latest version: ${t}`),!Ci(t,e.version)){$.info(`Already latest version.`);return}$.debug(`Updating to ${t}...`);try{let e=`https://registry.npmjs.org/@vpxa/aikit/-/aikit-${t}.tgz`,n=await fetch(e);if(!n.ok)throw Error(`Download failed: ${n.status} ${n.statusText}`);let r=Buffer.from(await n.arrayBuffer()),i=M(yi,`v${t}-staging`);w(i)&&k(i,{recursive:!0,force:!0}),T(i,{recursive:!0});try{let e=M(i,`aikit-${t}.tgz`);A(e,r),$.debug(`Extracting...`),R(`tar -xzf "${e}"`,{cwd:i,stdio:`pipe`,timeout:6e4});let n=M(i,`package`);if(!w(n))throw Error(`Expected "package/" directory not found after extraction`);$.debug(`Installing production dependencies...`),R(`npm install --production --install-strategy=nested --no-audit --no-fund`,{cwd:n,stdio:`pipe`,timeout:3e5});let a=M(n,`packages`,`server`,`dist`,`bin.js`);if(!w(a))throw Error(`Server entry not found at ${a}`);let o=M(yi,`v${t}`);w(yi)||T(yi,{recursive:!0}),w(o)&&($.debug(`Removing previous installation at ${o}...`),k(o,{recursive:!0,force:!0})),O(n,o),Si(t),$.info(`Updated to ${t}`)}finally{w(i)&&k(i,{recursive:!0,force:!0})}}catch(e){let t=e instanceof Error?e.message:String(e);$.error(`Update failed: ${t}`)}}}],Ei=[{name:`upgrade`,description:`Upgrade AI Kit agents, prompts, and skills to the latest version (user-level and workspace-level)`,usage:`aikit upgrade`,run:async()=>{await cr({force:!0});let e=process.cwd();if(w(P(e,`.github`,`.aikit-scaffold.json`))){let{initScaffoldOnly:e}=await import(`./init-CyjUXjQw.js`);await e({force:!0})}if(w(P(e,`.github`,`skills`))){let{smartCopySkills:t}=await import(`./scaffold-BNPHP-QC.js`).then(e=>e.a),n=S(),r=oe();await t(e,n,[...ue],r,!0);let{smartCopyFlows:i}=await import(`./scaffold-BNPHP-QC.js`).then(e=>e.a);await i(e,n,[...de],r,!0)}let{homedir:t}=await import(`node:os`),{rmSync:n}=await import(`node:fs`),r=M(t(),`.aikit`,`cache`,`wasm`);if(w(r))try{n(r,{recursive:!0,force:!0}),console.log(`✓ WASM cache cleared (will re-resolve on next start)`)}catch{console.warn(`⚠ Could not clear WASM cache at`,r)}}}],Di=L(`cli:versions`),Oi=M(z(),`.aikit`,`versions`),ki=M(z(),`.aikit`,`current-version.json`);function Ai(){try{return w(ki)?JSON.parse(E(ki,`utf-8`)).version??null:null}catch{return null}}const ji=[{name:`versions`,description:`List installed AI Kit versions (shows current, date, and available rollbacks)`,usage:`aikit versions`,run:async()=>{if(!w(Oi)){Di.warn(`No versions installed.`);return}let e=Ai(),t=D(Oi,{withFileTypes:!0}).filter(e=>e.isDirectory()&&/^v\d+\.\d+\.\d+$/.test(e.name)).map(e=>{let t=be(M(Oi,e.name));return{name:e.name,ver:e.name.slice(1),mtime:t.mtime}}).sort((e,t)=>t.mtime.getTime()-e.mtime.getTime());if(t.length===0){Di.warn(`No versions installed.`);return}for(let n of t){let t=n.ver===e,r=n.mtime.toISOString().split(`T`)[0],i=t?`(current)`:`(older)`,a=t?` ←`:``;console.log(`${n.name} - ${r} ${i}${a}`)}}}],Mi=[{name:`workset`,description:`Manage saved file sets`,usage:`aikit workset <action> [name] [--files f1,f2] [--description desc]`,run:async e=>{let t=e.shift()?.trim(),n=d(v(e,`--files`,``)),r=v(e,`--description`,``).trim()||void 0,i=e.shift()?.trim();switch(t||(console.error(`Usage: aikit workset <action> [name] [--files f1,f2] [--description desc]`),console.error(`Actions: save, get, list, delete, add, remove`),process.exit(1)),t){case`save`:{(!i||n.length===0)&&(console.error(`Usage: aikit workset save <name> --files f1,f2 [--description desc]`),process.exit(1));let e=Ht(i,n,{description:r});console.log(`Saved workset: ${e.name}`),p(e);return}case`get`:{i||(console.error(`Usage: aikit workset get <name>`),process.exit(1));let e=ut(i);if(!e){console.log(`No workset found: ${i}`);return}p(e);return}case`list`:{let e=xt();if(e.length===0){console.log(`No worksets saved.`);return}console.log(`Worksets (${e.length})`),console.log(`─`.repeat(60));for(let t of e)p(t),console.log(``);return}case`delete`:{i||(console.error(`Usage: aikit workset delete <name>`),process.exit(1));let e=rt(i);console.log(e?`Deleted workset: ${i}`:`No workset found: ${i}`);return}case`add`:{(!i||n.length===0)&&(console.error(`Usage: aikit workset add <name> --files f1,f2`),process.exit(1));let e=Ge(i,n);console.log(`Updated workset: ${e.name}`),p(e);return}case`remove`:{(!i||n.length===0)&&(console.error(`Usage: aikit workset remove <name> --files f1,f2`),process.exit(1));let e=Lt(i,n);if(!e){console.log(`No workset found: ${i}`);return}console.log(`Updated workset: ${e.name}`),p(e);return}default:console.error(`Unknown workset action: ${t}`),console.error(`Actions: save, get, list, delete, add, remove`),process.exit(1)}}},{name:`stash`,description:`Persist and retrieve named intermediate values`,usage:`aikit stash <set|get|list|delete|clear> [key] [value]`,run:async e=>{let t=e.shift()?.trim(),n=e.shift()?.trim();t||(console.error(`Usage: aikit stash <set|get|list|delete|clear> [key] [value]`),process.exit(1));let r=await ce();switch(t){case`set`:{n||(console.error(`Usage: aikit stash set <key> <value>`),process.exit(1));let t=e.join(` `),i=t.trim()?``:await m(),a=Jt(r,n,ie(t||i));console.log(`Stored stash entry: ${a.key}`),console.log(` Type: ${a.type}`),console.log(` Stored: ${a.storedAt}`);return}case`get`:{n||(console.error(`Usage: aikit stash get <key>`),process.exit(1));let e=Kt(r,n);if(!e){console.log(`No stash entry found: ${n}`);return}console.log(JSON.stringify(e,null,2));return}case`list`:{let e=qt(r);if(e.length===0){console.log(`No stash entries saved.`);return}console.log(`Stash entries (${e.length})`),console.log(`─`.repeat(60));for(let t of e)console.log(`${t.key} (${t.type})`),console.log(` Stored: ${t.storedAt}`);return}case`delete`:{n||(console.error(`Usage: aikit stash delete <key>`),process.exit(1));let e=Gt(r,n);console.log(e?`Deleted stash entry: ${n}`:`No stash entry found: ${n}`);return}case`clear`:{let e=Wt(r);console.log(`Cleared ${e} stash entr${e===1?`y`:`ies`}.`);return}default:console.error(`Unknown stash action: ${t}`),console.error(`Actions: set, get, list, delete, clear`),process.exit(1)}}},{name:`lane`,description:`Manage verified lanes — isolated file copies for parallel exploration`,usage:`aikit lane <create|list|status|diff|merge|discard> [name] [--files f1,f2]`,run:async e=>{let t=e.shift();if((!t||![`create`,`list`,`status`,`diff`,`merge`,`discard`].includes(t))&&(console.error(`Usage: aikit lane <create|list|status|diff|merge|discard> [name] [--files f1,f2]`),process.exit(1)),t===`list`){let e=vt();if(e.length===0){console.log(`No active lanes.`);return}for(let t of e)console.log(`${t.name} (${t.sourceFiles.length} files, created ${t.createdAt})`);return}let n=e.shift();switch(n||(console.error(`Lane name is required for "${t}".`),process.exit(1)),t){case`create`:{let t=v(e,`--files`,``);t||(console.error(`Usage: aikit lane create <name> --files file1.ts,file2.ts`),process.exit(1));let r=ht(n,t.split(`,`).map(e=>e.trim()));console.log(`Lane "${r.name}" created with ${r.sourceFiles.length} files.`);break}case`status`:{let e=bt(n);console.log(`Lane: ${e.name}`),console.log(`Modified: ${e.modified} | Added: ${e.added} | Deleted: ${e.deleted}`);for(let t of e.entries)console.log(` ${t.status.padEnd(10)} ${t.file}`);break}case`diff`:{let e=gt(n);console.log(`Lane: ${e.name} — ${e.modified} modified, ${e.added} added, ${e.deleted} deleted`);for(let t of e.entries)t.diff&&(console.log(`\n--- ${t.file} (${t.status})`),console.log(t.diff));break}case`merge`:{let e=yt(n);console.log(`Merged ${e.filesMerged} files from lane "${e.name}".`);for(let t of e.files)console.log(` ${t}`);break}case`discard`:{let e=_t(n);console.log(e?`Lane "${n}" discarded.`:`Lane "${n}" not found.`);break}}}},{name:`queue`,description:`Manage task queues for sequential agent operations`,usage:`aikit queue <create|push|next|done|fail|get|list|clear|delete> [name] [args]`,run:async e=>{let t=e.shift();if((!t||![`create`,`push`,`next`,`done`,`fail`,`get`,`list`,`clear`,`delete`].includes(t))&&(console.error(`Usage: aikit queue <create|push|next|done|fail|get|list|clear|delete> [name] [args]`),process.exit(1)),t===`list`){let e=Pt();if(e.length===0){console.log(`No queues.`);return}for(let t of e)console.log(`${t.name} pending:${t.pending} done:${t.done} failed:${t.failed} total:${t.total}`);return}let n=e.shift();switch(n||(console.error(`Queue name is required for "${t}".`),process.exit(1)),t){case`create`:{let e=kt(n);console.log(`Queue "${e.name}" created.`);break}case`push`:{let t=It(n,e.join(` `)||`Untitled task`);console.log(`Pushed "${t.title}" (${t.id}) to queue "${n}".`);break}case`next`:{let e=Ft(n);console.log(e?`Next: ${e.title} (${e.id})`:`No pending items in queue "${n}".`);break}case`done`:{let t=e.shift();t||(console.error(`Usage: aikit queue done <name> <id>`),process.exit(1));let r=jt(n,t);console.log(`Marked "${r.item.title}" as done.`);break}case`fail`:{let t=e.shift(),r=e.join(` `)||`Unknown error`;t||(console.error(`Usage: aikit queue fail <name> <id> [error message]`),process.exit(1));let i=Mt(n,t,r);console.log(`Marked "${i.title}" as failed: ${r}`);break}case`get`:{let e=Nt(n);if(!e){console.log(`Queue "${n}" not found.`);return}console.log(`Queue: ${e.name} (${e.items.length} items)`);for(let t of e.items){let e=t.error?` — ${t.error}`:``;console.log(` ${t.status.padEnd(12)} ${t.id} ${t.title}${e}`)}break}case`clear`:{let e=Ot(n);console.log(`Cleared ${e} completed/failed items from queue "${n}".`);break}case`delete`:{let e=At(n);console.log(e?`Queue "${n}" deleted.`:`Queue "${n}" not found.`);break}}}}],Ni=[...hi,...di,...mn,...Gr,...ui,..._i,...Mr,...hn,...wn,...Mi,...jr,...Ti,...Ei,...Ir,...Ar,...ji,...mi,...Hr];Ni.push({name:`help`,description:`Show available commands`,run:async()=>{Fi()}});async function Pi(e){let t=[...e],n=t.shift();if(!n||n===`--help`||n===`-h`){Fi();return}if(n===`--version`||n===`-v`){let e=P(j(we(import.meta.url)),`..`,`..`,`..`,`package.json`),t=JSON.parse(E(e,`utf-8`));console.log(t.version);return}if(n&&new Set([`--user`,`--workspace`,`--guide`,`--smart`]).has(n)){let e=Ni.find(e=>e.name===`init`);if(e){await e.run([n,...t]);return}}let r=Ni.find(e=>e.name===n);r||(console.error(`Unknown command: ${n}`),Fi(),process.exit(1));try{await r.run(t)}catch(e){throw e instanceof g&&(console.error(e.message),process.exit(e.exitCode)),e}finally{let e=Wr();e&&await e.store.close()}}function Fi(){console.log(`@vpxa/aikit — Local-first AI developer toolkit
58
58
  `),console.log(`Usage: aikit <command> [options]
59
- `),console.log(`Commands:`);let e=Math.max(...Ai.map(e=>e.name.length));for(let t of Ai)console.log(` ${t.name.padEnd(e+2)}${t.description}`);console.log(``),console.log(`Options:`),console.log(` --help, -h Show this help`),console.log(` --version, -v Show version`)}export{ji as run};
59
+ `),console.log(`Commands:`);let e=Math.max(...Ni.map(e=>e.name.length));for(let t of Ni)console.log(` ${t.name.padEnd(e+2)}${t.description}`);console.log(``),console.log(`Options:`),console.log(` --help, -h Show this help`),console.log(` --version, -v Show version`)}export{Pi as run};
@@ -1 +1 @@
1
- import{EXEC_HOOKS as e,HOOK_EVENTS as t,HOOK_TOOL_MATCHERS as n}from"../definitions/exec-hooks.mjs";const r={PreCompact:3e3,PostToolUse:3e3},i={copilot:`hooks.json`,claude:`hooks-settings.json`,copilotCli:`hooks.json`};function a(e,t){return(e.matcher||[]).flatMap(e=>{let r=n[e];if(!r)throw Error(`Unknown hook matcher: ${e}`);return r[t]||[]})}function o(e,t,n,i){let o=`${n}/${e.script}`;return a(e,i),i===`copilot`?{event:t,steps:[{type:`command`,command:`node`,args:[o],timeout:r[e.event]||5e3}]}:i===`claude`?{type:`command`,command:`node ${o}`}:{command:`node`,args:[o]}}function s(n,r){if(n===`copilot`){let a=Object.values(e).map(e=>{let i=t[e.event]?.[n];if(!i)throw Error(`Unsupported hook event ${e.event} for ${n}`);return o(e,i,r,n)});return[{path:i[n],content:JSON.stringify({hooks:a},null,2)}]}let a={};for(let i of Object.values(e)){let e=t[i.event]?.[n];if(!e)throw Error(`Unsupported hook event ${i.event} for ${n}`);a[e]||=[],a[e].push(o(i,e,r,n))}return[{path:i[n],content:JSON.stringify({hooks:a},null,2)}]}function c(){return[`_runtime.mjs`,...Object.values(e).map(e=>e.script)]}export{s as generateHooks,c as getHookScriptFiles};
1
+ import{EXEC_HOOKS as e,HOOK_EVENTS as t,HOOK_TOOL_MATCHERS as n,SUPPORTED_PLATFORMS as r}from"../definitions/exec-hooks.mjs";const i={PreCompact:3e3,PostToolUse:3e3},a={copilot:`hooks.json`,claude:`hooks-settings.json`,copilotCli:`hooks.json`,hermes:`hooks.json`},o=r;function s(e){if(!o.includes(e))throw Error(`Unknown platform: "${e}". Supported: ${o.join(`, `)}. Add it to SUPPORTED_PLATFORMS in exec-hooks.mjs first, then add entries to HOOK_EVENTS, HOOK_TOOL_MATCHERS, and FILE_NAMES.`);for(let[n,r]of Object.entries(t))if(!(e in r))throw Error(`Platform "${e}" is missing from HOOK_EVENTS.${n}. Add a "${e}" key to HOOK_EVENTS.${n} in exec-hooks.mjs.`);for(let[t,r]of Object.entries(n))if(!(e in r))throw Error(`Platform "${e}" is missing from HOOK_TOOL_MATCHERS.${t}. Add a "${e}" key to HOOK_TOOL_MATCHERS.${t} in exec-hooks.mjs.`);if(!(e in a))throw Error(`Platform "${e}" is missing from FILE_NAMES. Add "${e}: '<filename>'" to FILE_NAMES in adapters/hooks.mjs.`)}function c(e,t){return(e.matcher||[]).flatMap(e=>{let r=n[e];if(!r)throw Error(`Unknown hook matcher: ${e}`);return r[t]||[]})}function l(e,t,n,r){let a=`${n}/${e.script}`;return c(e,r),r===`copilot`?{event:t,steps:[{type:`command`,command:`node`,args:[a],timeout:i[e.event]||5e3}]}:r===`claude`?{type:`command`,command:`node ${a}`}:{command:`node`,args:[a]}}function u(n,r){if(s(n),n===`copilot`){let i=Object.values(e).map(e=>{let i=t[e.event]?.[n];if(!i)throw Error(`Unsupported hook event ${e.event} for ${n}`);return l(e,i,r,n)});return[{path:a[n],content:JSON.stringify({hooks:i},null,2)}]}let i={};for(let a of Object.values(e)){let e=t[a.event]?.[n];if(!e)throw Error(`Unsupported hook event ${a.event} for ${n}`);i[e]||=[],i[e].push(l(a,e,r,n))}return[{path:a[n],content:JSON.stringify({hooks:i},null,2)}]}function d(){return[`_runtime.mjs`,...Object.values(e).map(e=>e.script)]}export{u as generateHooks,d as getHookScriptFiles};
@@ -1 +1 @@
1
- const e={SessionStart:{copilot:`SessionStart`,claude:`PreToolCall`,copilotCli:`sessionStart`},PreToolUse:{copilot:`PreToolUse`,claude:`PreToolCall`,copilotCli:`preToolUse`},PostToolUse:{copilot:`PostToolUse`,claude:`PostToolCall`,copilotCli:`postToolUse`},SubagentStart:{copilot:`SubagentStart`,claude:`PreToolCall`,copilotCli:`subagentStart`},PreCompact:{copilot:`PreCompact`,claude:`PreToolCall`,copilotCli:`preCompact`},Stop:{copilot:`Stop`,claude:`PostToolCall`,copilotCli:`stop`}},t={fileRead:{copilot:[`read_file`,`readFile`],claude:[`Read`],copilotCli:[`read_file`]},fileWrite:{copilot:[`editFiles`,`replace_string_in_file`,`create_file`],claude:[`Write`,`Edit`],copilotCli:[`editFiles`,`replace_string_in_file`]},fileSearch:{copilot:[`grep_search`,`semantic_search`,`find`],claude:[`Bash`],copilotCli:[`grep_search`]}},n={"privacy-guard":{id:`privacy-guard`,event:`PreToolUse`,tier:`safety`,description:`Blocks reads of secret-bearing env files, key material, SSH paths, and credential artifacts.`,script:`privacy-guard.mjs`,matcher:[`fileRead`],scope:`user`,patterns:[`.env`,`*.pem`,`*.key`,`id_rsa*`,`.ssh/*`,`*credentials*`,`*.secret`]},"scout-guard":{id:`scout-guard`,event:`PreToolUse`,tier:`safety`,description:`Blocks reads and searches inside generated, dependency, and git object directories.`,script:`scout-guard.mjs`,matcher:[`fileRead`,`fileSearch`],scope:`user`,patterns:[`node_modules/`,`dist/`,`.git/objects/`,`vendor/`,`build/`]},"subagent-context":{id:`subagent-context`,event:`SubagentStart`,tier:`efficiency`,description:`Injects compact project context into each subagent spawn to reduce repeated discovery.`,script:`subagent-context.mjs`,scope:`user`},"pre-compact-save":{id:`pre-compact-save`,event:`PreCompact`,tier:`efficiency`,description:`Persists critical state before context compaction truncates recent session history.`,script:`pre-compact-save.mjs`,scope:`user`},"post-edit-check":{id:`post-edit-check`,event:`PostToolUse`,tier:`nudge`,description:`After repeated file edits, injects a validation reminder so checks are not skipped.`,script:`post-edit-check.mjs`,matcher:[`fileWrite`],scope:`user`},"session-init":{id:`session-init`,event:`SessionStart`,tier:`nudge`,description:`Detects project stack and injects workspace metadata and environment context at startup.`,script:`session-init.mjs`,scope:`user`},"session-observer":{id:`session-observer`,event:`PostToolUse`,tier:`efficiency`,description:`Captures tool usage patterns for autonomous lesson extraction. Writes to session buffer.`,script:`session-observer.mjs`,scope:`user`},"session-learn":{id:`session-learn`,event:`Stop`,tier:`efficiency`,description:`Nudges final pattern analysis on buffered observations at session end.`,script:`session-learn.mjs`,scope:`user`}};export{n as EXEC_HOOKS,e as HOOK_EVENTS,t as HOOK_TOOL_MATCHERS};
1
+ const e=[`copilot`,`claude`,`copilotCli`,`hermes`],t={SessionStart:{copilot:`SessionStart`,claude:`PreToolCall`,copilotCli:`sessionStart`,hermes:`SessionStart`},PreToolUse:{copilot:`PreToolUse`,claude:`PreToolCall`,copilotCli:`preToolUse`,hermes:`PreToolUse`},PostToolUse:{copilot:`PostToolUse`,claude:`PostToolCall`,copilotCli:`postToolUse`,hermes:`PostToolUse`},SubagentStart:{copilot:`SubagentStart`,claude:`PreToolCall`,copilotCli:`subagentStart`,hermes:`SubagentStart`},PreCompact:{copilot:`PreCompact`,claude:`PreToolCall`,copilotCli:`preCompact`,hermes:`PreCompact`},Stop:{copilot:`Stop`,claude:`PostToolCall`,copilotCli:`stop`,hermes:`Stop`}},n={fileRead:{copilot:[`read_file`,`readFile`],claude:[`Read`],copilotCli:[`read_file`],hermes:[`read_file`]},fileWrite:{copilot:[`editFiles`,`replace_string_in_file`,`create_file`],claude:[`Write`,`Edit`],copilotCli:[`editFiles`,`replace_string_in_file`],hermes:[`write_file`,`patch`]},fileSearch:{copilot:[`grep_search`,`semantic_search`,`find`],claude:[`Bash`],copilotCli:[`grep_search`],hermes:[`search_files`]}},r={"privacy-guard":{id:`privacy-guard`,event:`PreToolUse`,tier:`safety`,description:`Blocks reads of secret-bearing env files, key material, SSH paths, and credential artifacts.`,script:`privacy-guard.mjs`,matcher:[`fileRead`],scope:`user`,patterns:[`.env`,`*.pem`,`*.key`,`id_rsa*`,`.ssh/*`,`*credentials*`,`*.secret`]},"scout-guard":{id:`scout-guard`,event:`PreToolUse`,tier:`safety`,description:`Blocks reads and searches inside generated, dependency, and git object directories.`,script:`scout-guard.mjs`,matcher:[`fileRead`,`fileSearch`],scope:`user`,patterns:[`node_modules/`,`dist/`,`.git/objects/`,`vendor/`,`build/`]},"subagent-context":{id:`subagent-context`,event:`SubagentStart`,tier:`efficiency`,description:`Injects compact project context into each subagent spawn to reduce repeated discovery.`,script:`subagent-context.mjs`,scope:`user`},"pre-compact-save":{id:`pre-compact-save`,event:`PreCompact`,tier:`efficiency`,description:`Persists critical state before context compaction truncates recent session history.`,script:`pre-compact-save.mjs`,scope:`user`},"post-edit-check":{id:`post-edit-check`,event:`PostToolUse`,tier:`nudge`,description:`After repeated file edits, injects a validation reminder so checks are not skipped.`,script:`post-edit-check.mjs`,matcher:[`fileWrite`],scope:`user`},"session-init":{id:`session-init`,event:`SessionStart`,tier:`nudge`,description:`Detects project stack and injects workspace metadata and environment context at startup.`,script:`session-init.mjs`,scope:`user`},"session-observer":{id:`session-observer`,event:`PostToolUse`,tier:`efficiency`,description:`Captures tool usage patterns for autonomous lesson extraction. Writes to session buffer.`,script:`session-observer.mjs`,scope:`user`},"session-learn":{id:`session-learn`,event:`Stop`,tier:`efficiency`,description:`Nudges final pattern analysis on buffered observations at session end.`,script:`session-learn.mjs`,scope:`user`}};function i(r){let i=[{name:`HOOK_EVENTS`,entries:Object.values(t)},{name:`HOOK_TOOL_MATCHERS`,entries:Object.values(n)}];for(let t of e){for(let e of i)for(let n of e.entries)if(!(t in n))throw Error(`Registration drift: platform "${t}" is missing from ${e.name} (entry has keys: ${Object.keys(n).join(`, `)}). Add a "${t}" key to all entries in ${e.name} in exec-hooks.mjs.`);if(r){for(let[e,n]of Object.entries(r))if(!(t in n))throw Error(`Registration drift: platform "${t}" is missing from ${e} (has keys: ${Object.keys(n).join(`, `)}). Add "${t}: '...'" to ${e}.`)}}}export{r as EXEC_HOOKS,t as HOOK_EVENTS,n as HOOK_TOOL_MATCHERS,e as SUPPORTED_PLATFORMS,i as validateAllPlatformRegistries};