@vpxa/aikit 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packages/cli/dist/aikit-init.js +1 -1
- package/packages/cli/dist/commands/init/constants.d.ts +1 -1
- package/packages/cli/dist/commands/init/constants.js +1 -1
- package/packages/cli/dist/commands/init/user.js +1 -1
- package/packages/core/dist/index.d.ts +2 -2
- package/packages/core/dist/index.js +1 -1
- package/packages/core/dist/types.d.ts +12 -2
- package/packages/core/dist/types.js +1 -1
- package/packages/indexer/dist/incremental-indexer.d.ts +16 -0
- package/packages/indexer/dist/incremental-indexer.js +1 -1
- package/packages/indexer/dist/index.d.ts +2 -1
- package/packages/indexer/dist/index.js +1 -1
- package/packages/indexer/dist/smart-index-scheduler.d.ts +36 -0
- package/packages/indexer/dist/smart-index-scheduler.js +1 -0
- package/packages/server/dist/config.d.ts +3 -1
- package/packages/server/dist/config.js +1 -1
- package/packages/server/dist/index.js +1 -1
- package/packages/server/dist/server.d.ts +6 -2
- package/packages/server/dist/server.js +2 -2
- package/packages/server/dist/tools/context.tools.d.ts +1 -1
- package/packages/server/dist/tools/context.tools.js +2 -2
- package/packages/server/dist/tools/graph.tool.js +7 -2
- package/packages/store/dist/graph-store.interface.d.ts +42 -1
- package/packages/store/dist/index.d.ts +2 -2
- package/packages/store/dist/sqlite-graph-store.d.ts +10 -1
- package/packages/store/dist/sqlite-graph-store.js +49 -17
- package/packages/tools/dist/graph-query.d.ts +14 -2
- package/packages/tools/dist/graph-query.js +1 -1
- package/packages/tools/dist/trace.d.ts +16 -2
- package/packages/tools/dist/trace.js +2 -2
- package/scaffold/definitions/bodies.mjs +24 -0
- package/scaffold/definitions/prompts.mjs +22 -3
- package/scaffold/definitions/protocols.mjs +22 -0
- package/scaffold/general/agents/Architect-Reviewer-Alpha.agent.md +6 -0
- package/scaffold/general/agents/Architect-Reviewer-Beta.agent.md +6 -0
- package/scaffold/general/agents/Code-Reviewer-Alpha.agent.md +6 -0
- package/scaffold/general/agents/Code-Reviewer-Beta.agent.md +6 -0
- package/scaffold/general/agents/Debugger.agent.md +6 -0
- package/scaffold/general/agents/Documenter.agent.md +6 -0
- package/scaffold/general/agents/Explorer.agent.md +6 -0
- package/scaffold/general/agents/Frontend.agent.md +6 -0
- package/scaffold/general/agents/Implementer.agent.md +6 -0
- package/scaffold/general/agents/Orchestrator.agent.md +69 -0
- package/scaffold/general/agents/Planner.agent.md +18 -0
- package/scaffold/general/agents/Refactor.agent.md +6 -0
- package/scaffold/general/agents/Researcher-Alpha.agent.md +6 -0
- package/scaffold/general/agents/Researcher-Beta.agent.md +6 -0
- package/scaffold/general/agents/Researcher-Delta.agent.md +6 -0
- package/scaffold/general/agents/Researcher-Gamma.agent.md +6 -0
- package/scaffold/general/agents/Security.agent.md +6 -0
- package/scaffold/general/agents/_shared/code-agent-base.md +22 -0
- package/scaffold/general/prompts/ask.prompt.md +1 -1
- package/scaffold/general/prompts/debug.prompt.md +1 -0
- package/scaffold/general/prompts/implement.prompt.md +1 -0
- package/scaffold/general/prompts/plan.prompt.md +1 -1
- package/scaffold/general/prompts/review.prompt.md +1 -1
- package/scaffold/general/skills/frontend-design/SKILL.md +225 -0
- package/scaffold/general/skills/react/SKILL.md +297 -0
- package/scaffold/general/skills/typescript/SKILL.md +393 -0
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as e,readFileSync as t}from"node:fs";import{dirname as n,resolve as r}from"node:path";import{initializeWasm as i}from"../../chunker/dist/index.js";import{AIKIT_PATHS as a,getPartitionDir as o,isUserInstalled as s,registerWorkspace as c}from"../../core/dist/index.js";import{OnnxEmbedder as l}from"../../embeddings/dist/index.js";import{IncrementalIndexer as u}from"../../indexer/dist/index.js";import{SqliteGraphStore as d,createStore as f}from"../../store/dist/index.js";function p(){let i=process.env.AIKIT_CONFIG_PATH??(e(r(process.cwd(),`aikit.config.json`))?r(process.cwd(),`aikit.config.json`):null);if(!i)return m();let a=t(i,`utf-8`),o;try{o=JSON.parse(a)}catch{console.error(`Failed to parse ${i} as JSON. Ensure the file contains valid JSON.`),process.exit(1)}let s=n(i);return o.sources=o.sources.map(e=>({...e,path:r(s,e.path)})),o.store.path=r(s,o.store.path),o.curated=o.curated??{path:`curated`},o.curated.path=r(s,o.curated.path),h(o,s),o}function m(){let e=process.env.AIKIT_WORKSPACE_ROOT??process.cwd(),t={sources:[{path:e,excludePatterns:[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],serverName:`aikit`,indexing:{chunkSize:1500,chunkOverlap:200,minChunkSize:100},embedding:{model:`mixedbread-ai/mxbai-embed-large-v1`,dimensions:1024},store:{backend:`lancedb`,path:r(e,a.data)},curated:{path:r(e,a.aiCurated)},stateDir:r(e,a.state)};return h(t,e),t}function h(e,t){if(!s())return;let n=c(t);e.store.path=r(o(n.partition)),e.stateDir=r(o(n.partition),`state`),e.curated||={path:r(t,a.aiCurated)}}async function g(){let e=p(),t=new l({model:e.embedding.model,dimensions:e.embedding.dimensions});await t.initialize();let n=await f({backend:e.store.backend,path:e.store.path});await n.initialize();let r=new u(t,n),{CuratedKnowledgeManager:a}=await import(`../../server/dist/curated-manager.js`),o=new a(e.curated.path,n,t),s;try{let t=new d({path:e.store.path});await t.initialize(),s=t,r.setGraphStore(s)}catch(e){console.error(`[aikit] Graph store init failed (non-fatal): ${e.message}`),s={initialize:async()=>{},upsertNode:async()=>{},upsertEdge:async()=>{},upsertNodes:async()=>{},upsertEdges:async()=>{},getNode:async()=>null,getNeighbors:async()=>({nodes:[],edges:[]}),traverse:async()=>({nodes:[],edges:[]}),findNodes:async()=>[],findEdges:async()=>[],deleteNode:async()=>{},deleteBySourcePath:async()=>0,clear:async()=>{},getStats:async()=>({nodeCount:0,edgeCount:0,nodeTypes:{},edgeTypes:{}}),validate:async()=>({valid:!0,orphanNodes:[],danglingEdges:[],stats:{nodeCount:0,edgeCount:0,nodeTypes:{},edgeTypes:{}}}),close:async()=>{}}}return await i().catch(()=>{}),{config:e,embedder:t,store:n,graphStore:s,indexer:r,curated:o}}export{g as initKB};
|
|
1
|
+
import{existsSync as e,readFileSync as t}from"node:fs";import{dirname as n,resolve as r}from"node:path";import{initializeWasm as i}from"../../chunker/dist/index.js";import{AIKIT_PATHS as a,getPartitionDir as o,isUserInstalled as s,registerWorkspace as c}from"../../core/dist/index.js";import{OnnxEmbedder as l}from"../../embeddings/dist/index.js";import{IncrementalIndexer as u}from"../../indexer/dist/index.js";import{SqliteGraphStore as d,createStore as f}from"../../store/dist/index.js";function p(){let i=process.env.AIKIT_CONFIG_PATH??(e(r(process.cwd(),`aikit.config.json`))?r(process.cwd(),`aikit.config.json`):null);if(!i)return m();let a=t(i,`utf-8`),o;try{o=JSON.parse(a)}catch{console.error(`Failed to parse ${i} as JSON. Ensure the file contains valid JSON.`),process.exit(1)}let s=n(i);return o.sources=o.sources.map(e=>({...e,path:r(s,e.path)})),o.store.path=r(s,o.store.path),o.curated=o.curated??{path:`curated`},o.curated.path=r(s,o.curated.path),h(o,s),o}function m(){let e=process.env.AIKIT_WORKSPACE_ROOT??process.cwd(),t={sources:[{path:e,excludePatterns:[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],serverName:`aikit`,indexing:{chunkSize:1500,chunkOverlap:200,minChunkSize:100},embedding:{model:`mixedbread-ai/mxbai-embed-large-v1`,dimensions:1024},store:{backend:`lancedb`,path:r(e,a.data)},curated:{path:r(e,a.aiCurated)},stateDir:r(e,a.state)};return h(t,e),t}function h(e,t){if(!s())return;let n=c(t);e.store.path=r(o(n.partition)),e.stateDir=r(o(n.partition),`state`),e.curated||={path:r(t,a.aiCurated)}}async function g(){let e=p(),t=new l({model:e.embedding.model,dimensions:e.embedding.dimensions});await t.initialize();let n=await f({backend:e.store.backend,path:e.store.path});await n.initialize();let r=new u(t,n),{CuratedKnowledgeManager:a}=await import(`../../server/dist/curated-manager.js`),o=new a(e.curated.path,n,t),s;try{let t=new d({path:e.store.path});await t.initialize(),s=t,r.setGraphStore(s)}catch(e){console.error(`[aikit] Graph store init failed (non-fatal): ${e.message}`),s={initialize:async()=>{},upsertNode:async()=>{},upsertEdge:async()=>{},upsertNodes:async()=>{},upsertEdges:async()=>{},getNode:async()=>null,getNeighbors:async()=>({nodes:[],edges:[]}),traverse:async()=>({nodes:[],edges:[]}),findNodes:async()=>[],findEdges:async()=>[],deleteNode:async()=>{},deleteBySourcePath:async()=>0,clear:async()=>{},getStats:async()=>({nodeCount:0,edgeCount:0,nodeTypes:{},edgeTypes:{}}),validate:async()=>({valid:!0,orphanNodes:[],danglingEdges:[],stats:{nodeCount:0,edgeCount:0,nodeTypes:{},edgeTypes:{}}}),setNodeCommunity:async()=>{},detectCommunities:async()=>({}),traceProcess:async()=>({id:``,entryNodeId:``,label:``,properties:{},steps:[]}),getProcesses:async()=>[],deleteProcess:async()=>{},depthGroupedTraversal:async()=>({}),getCohesionScore:async()=>0,getSymbol360:async()=>({node:{id:``,type:``,name:``,properties:{}},incoming:[],outgoing:[],community:null,processes:[]}),close:async()=>{}}}return await i().catch(()=>{}),{config:e,embedder:t,store:n,graphStore:s,indexer:r,curated:o}}export{g as initKB};
|
|
@@ -13,7 +13,7 @@ declare const MCP_SERVER_ENTRY: {
|
|
|
13
13
|
readonly args: readonly ["-y", "@vpxa/aikit", "serve"];
|
|
14
14
|
};
|
|
15
15
|
/** Skills shipped with the AI Kit package and installed during init. */
|
|
16
|
-
declare const SKILL_NAMES: readonly ["aikit", "brainstorming", "multi-agents-development", "session-handoff", "requirements-clarity", "lesson-learned", "c4-architecture", "adr-skill", "present"];
|
|
16
|
+
declare const SKILL_NAMES: readonly ["aikit", "brainstorming", "multi-agents-development", "session-handoff", "requirements-clarity", "lesson-learned", "c4-architecture", "adr-skill", "present", "frontend-design", "react", "typescript"];
|
|
17
17
|
/** Built-in flow directories shipped with the package (under scaffold/flows/). */
|
|
18
18
|
declare const FLOW_DIRS: readonly ["aikit-basic", "aikit-advanced"];
|
|
19
19
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=`aikit`,t={type:`stdio`,command:`npx`,args:[`-y`,`@vpxa/aikit`,`serve`]},n=[`aikit`,`brainstorming`,`multi-agents-development`,`session-handoff`,`requirements-clarity`,`lesson-learned`,`c4-architecture`,`adr-skill`,`present`],r=[`aikit-basic`,`aikit-advanced`],i={"chat.agentFilesLocations":{"~/.claude/agents":!1},"github.copilot.chat.copilotMemory.enabled":!0,"chat.customAgentInSubagent.enabled":!0,"chat.useNestedAgentsMdFiles":!0,"chat.useAgentSkills":!0,"github.copilot.chat.switchAgent.enabled":!0,"workbench.browser.enableChatTools":!0,"chat.mcp.apps.enabled":!0};export{r as FLOW_DIRS,t as MCP_SERVER_ENTRY,e as SERVER_NAME,n as SKILL_NAMES,i as VSCODE_SETTINGS};
|
|
1
|
+
const e=`aikit`,t={type:`stdio`,command:`npx`,args:[`-y`,`@vpxa/aikit`,`serve`]},n=[`aikit`,`brainstorming`,`multi-agents-development`,`session-handoff`,`requirements-clarity`,`lesson-learned`,`c4-architecture`,`adr-skill`,`present`,`frontend-design`,`react`,`typescript`],r=[`aikit-basic`,`aikit-advanced`],i={"chat.agentFilesLocations":{"~/.claude/agents":!1},"github.copilot.chat.copilotMemory.enabled":!0,"chat.customAgentInSubagent.enabled":!0,"chat.useNestedAgentsMdFiles":!0,"chat.useAgentSkills":!0,"github.copilot.chat.switchAgent.enabled":!0,"workbench.browser.enableChatTools":!0,"chat.mcp.apps.enabled":!0};export{r as FLOW_DIRS,t as MCP_SERVER_ENTRY,e as SERVER_NAME,n as SKILL_NAMES,i as VSCODE_SETTINGS};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{FLOW_DIRS as e,MCP_SERVER_ENTRY as t,SERVER_NAME as n,SKILL_NAMES as r,VSCODE_SETTINGS as i}from"./constants.js";import{buildAgentsMd as a,buildCopilotInstructions as o}from"./templates.js";import{smartCopySubdir as s}from"./scaffold.js";import{existsSync as c,mkdirSync as l,readFileSync as u,writeFileSync as d}from"node:fs";import{dirname as f,resolve as p}from"node:path";import{fileURLToPath as m}from"node:url";import{getGlobalDataDir as h,saveRegistry as g}from"../../../../core/dist/index.js";import{homedir as _}from"node:os";function v(){let e=_(),t=process.platform,n=[],r=p(e,`.copilot`),i=p(r,`instructions`),a=p(e,`.claude`),o=p(e,`.cursor`),s=p(e,`.windsurf`);if(t===`win32`){let t=process.env.APPDATA??p(e,`AppData`,`Roaming`);n.push({ide:`VS Code`,configDir:p(t,`Code`,`User`),mcpConfigPath:p(t,`Code`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`VS Code Insiders`,configDir:p(t,`Code - Insiders`,`User`),mcpConfigPath:p(t,`Code - Insiders`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`VSCodium`,configDir:p(t,`VSCodium`,`User`),mcpConfigPath:p(t,`VSCodium`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`Cursor`,configDir:p(t,`Cursor`,`User`),mcpConfigPath:p(t,`Cursor`,`User`,`mcp.json`),globalScaffoldRoot:o,instructionsRoot:null},{ide:`Cursor Nightly`,configDir:p(t,`Cursor Nightly`,`User`),mcpConfigPath:p(t,`Cursor Nightly`,`User`,`mcp.json`),globalScaffoldRoot:o,instructionsRoot:null},{ide:`Windsurf`,configDir:p(t,`Windsurf`,`User`),mcpConfigPath:p(t,`Windsurf`,`User`,`mcp.json`),globalScaffoldRoot:s,instructionsRoot:null})}else if(t===`darwin`){let t=p(e,`Library`,`Application Support`);n.push({ide:`VS Code`,configDir:p(t,`Code`,`User`),mcpConfigPath:p(t,`Code`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`VS Code Insiders`,configDir:p(t,`Code - Insiders`,`User`),mcpConfigPath:p(t,`Code - Insiders`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`VSCodium`,configDir:p(t,`VSCodium`,`User`),mcpConfigPath:p(t,`VSCodium`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`Cursor`,configDir:p(t,`Cursor`,`User`),mcpConfigPath:p(t,`Cursor`,`User`,`mcp.json`),globalScaffoldRoot:o,instructionsRoot:null},{ide:`Cursor Nightly`,configDir:p(t,`Cursor Nightly`,`User`),mcpConfigPath:p(t,`Cursor Nightly`,`User`,`mcp.json`),globalScaffoldRoot:o,instructionsRoot:null},{ide:`Windsurf`,configDir:p(t,`Windsurf`,`User`),mcpConfigPath:p(t,`Windsurf`,`User`,`mcp.json`),globalScaffoldRoot:s,instructionsRoot:null})}else{let t=process.env.XDG_CONFIG_HOME??p(e,`.config`);n.push({ide:`VS Code`,configDir:p(t,`Code`,`User`),mcpConfigPath:p(t,`Code`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`VS Code Insiders`,configDir:p(t,`Code - Insiders`,`User`),mcpConfigPath:p(t,`Code - Insiders`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`VSCodium`,configDir:p(t,`VSCodium`,`User`),mcpConfigPath:p(t,`VSCodium`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`Cursor`,configDir:p(t,`Cursor`,`User`),mcpConfigPath:p(t,`Cursor`,`User`,`mcp.json`),globalScaffoldRoot:o,instructionsRoot:null},{ide:`Cursor Nightly`,configDir:p(t,`Cursor Nightly`,`User`),mcpConfigPath:p(t,`Cursor Nightly`,`User`,`mcp.json`),globalScaffoldRoot:o,instructionsRoot:null},{ide:`Windsurf`,configDir:p(t,`Windsurf`,`User`),mcpConfigPath:p(t,`Windsurf`,`User`,`mcp.json`),globalScaffoldRoot:s,instructionsRoot:null})}return n.push({ide:`Claude Code`,configDir:p(e,`.claude`),mcpConfigPath:p(e,`.claude`,`mcp.json`),globalScaffoldRoot:a,instructionsRoot:null}),n.filter(e=>c(e.configDir))}function y(e,n,r=!1){let{mcpConfigPath:i,configDir:a}=e,o={...t},s={};if(c(i)){try{let e=u(i,`utf-8`);s=JSON.parse(e)}catch{let e=`${i}.bak`;d(e,u(i,`utf-8`),`utf-8`),console.log(` Backed up invalid ${i} to ${e}`),s={}}if((s.servers??s.mcpServers??{})[n]&&!r){console.log(` ${e.ide}: ${n} already configured (use --force to update)`);return}}let f=new Set([`VS Code`,`VS Code Insiders`,`VSCodium`,`Windsurf`]).has(e.ide)?`servers`:`mcpServers`,p=s[f]??{};p[n]=o,s[f]=p,l(a,{recursive:!0}),d(i,`${JSON.stringify(s,null,2)}\n`,`utf-8`),console.log(` ${e.ide}: configured ${n} in ${i}`)}const b=new Set([`VS Code`,`VS Code Insiders`,`VSCodium`]);function x(e,t=!1){if(!b.has(e.ide))return;let n=p(e.configDir,`settings.json`),r={};if(c(n))try{let e=u(n,`utf-8`);r=JSON.parse(e)}catch{console.log(` ${e.ide}: skipped settings.json (invalid JSON)`);return}let a=!1;for(let[e,n]of Object.entries(i))if(typeof n==`object`&&n){let t=typeof r[e]==`object`&&r[e]!==null?r[e]:{},i={...t,...n};JSON.stringify(i)!==JSON.stringify(t)&&(r[e]=i,a=!0)}else (t||!(e in r))&&(r[e]=n,a=!0);a&&(d(n,`${JSON.stringify(r,null,2)}\n`,`utf-8`),console.log(` ${e.ide}: updated settings.json`))}function S(t,n,i,u,f=!1){let m=new Set;for(let e of n)e.globalScaffoldRoot&&m.add(e.globalScaffoldRoot);if(m.size===0){console.log(` No IDEs with global scaffold support detected.`);return}let h=p(t,`scaffold`,`general`);for(let n of m){s(h,n,`agents`,u,f),s(h,n,`prompts`,u,f);let i=0;for(let e of r)c(p(h,`skills`,e))&&(s(h,n,`skills/${e}`,u,f),i++);for(let r of e){let e=p(t,`scaffold`,`flows`,r);c(p(e,`skills`))&&s(e,p(n,`flows`,r),`skills`,u,f)}console.log(` ${n}: scaffold updated (${i} skills)`)}let g=new Set,_=o(`aikit`,i),v=a(`aikit`,i);for(let e of n){if(!e.globalScaffoldRoot)continue;let t=e.globalScaffoldRoot;if(e.ide===`Claude Code`){let e=p(t,`CLAUDE.md`);d(e,`${_}\n---\n\n${v}`,`utf-8`),g.add(e)}else if(e.ide===`VS Code`||e.ide===`VS Code Insiders`||e.ide===`VSCodium`){let n=e.instructionsRoot??t;l(n,{recursive:!0});let r=p(n,`
|
|
1
|
+
import{FLOW_DIRS as e,MCP_SERVER_ENTRY as t,SERVER_NAME as n,SKILL_NAMES as r,VSCODE_SETTINGS as i}from"./constants.js";import{buildAgentsMd as a,buildCopilotInstructions as o}from"./templates.js";import{smartCopySubdir as s}from"./scaffold.js";import{existsSync as c,mkdirSync as l,readFileSync as u,writeFileSync as d}from"node:fs";import{dirname as f,resolve as p}from"node:path";import{fileURLToPath as m}from"node:url";import{getGlobalDataDir as h,saveRegistry as g}from"../../../../core/dist/index.js";import{homedir as _}from"node:os";function v(){let e=_(),t=process.platform,n=[],r=p(e,`.copilot`),i=p(r,`instructions`),a=p(e,`.claude`),o=p(e,`.cursor`),s=p(e,`.windsurf`);if(t===`win32`){let t=process.env.APPDATA??p(e,`AppData`,`Roaming`);n.push({ide:`VS Code`,configDir:p(t,`Code`,`User`),mcpConfigPath:p(t,`Code`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`VS Code Insiders`,configDir:p(t,`Code - Insiders`,`User`),mcpConfigPath:p(t,`Code - Insiders`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`VSCodium`,configDir:p(t,`VSCodium`,`User`),mcpConfigPath:p(t,`VSCodium`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`Cursor`,configDir:p(t,`Cursor`,`User`),mcpConfigPath:p(t,`Cursor`,`User`,`mcp.json`),globalScaffoldRoot:o,instructionsRoot:null},{ide:`Cursor Nightly`,configDir:p(t,`Cursor Nightly`,`User`),mcpConfigPath:p(t,`Cursor Nightly`,`User`,`mcp.json`),globalScaffoldRoot:o,instructionsRoot:null},{ide:`Windsurf`,configDir:p(t,`Windsurf`,`User`),mcpConfigPath:p(t,`Windsurf`,`User`,`mcp.json`),globalScaffoldRoot:s,instructionsRoot:null})}else if(t===`darwin`){let t=p(e,`Library`,`Application Support`);n.push({ide:`VS Code`,configDir:p(t,`Code`,`User`),mcpConfigPath:p(t,`Code`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`VS Code Insiders`,configDir:p(t,`Code - Insiders`,`User`),mcpConfigPath:p(t,`Code - Insiders`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`VSCodium`,configDir:p(t,`VSCodium`,`User`),mcpConfigPath:p(t,`VSCodium`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`Cursor`,configDir:p(t,`Cursor`,`User`),mcpConfigPath:p(t,`Cursor`,`User`,`mcp.json`),globalScaffoldRoot:o,instructionsRoot:null},{ide:`Cursor Nightly`,configDir:p(t,`Cursor Nightly`,`User`),mcpConfigPath:p(t,`Cursor Nightly`,`User`,`mcp.json`),globalScaffoldRoot:o,instructionsRoot:null},{ide:`Windsurf`,configDir:p(t,`Windsurf`,`User`),mcpConfigPath:p(t,`Windsurf`,`User`,`mcp.json`),globalScaffoldRoot:s,instructionsRoot:null})}else{let t=process.env.XDG_CONFIG_HOME??p(e,`.config`);n.push({ide:`VS Code`,configDir:p(t,`Code`,`User`),mcpConfigPath:p(t,`Code`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`VS Code Insiders`,configDir:p(t,`Code - Insiders`,`User`),mcpConfigPath:p(t,`Code - Insiders`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`VSCodium`,configDir:p(t,`VSCodium`,`User`),mcpConfigPath:p(t,`VSCodium`,`User`,`mcp.json`),globalScaffoldRoot:r,instructionsRoot:i},{ide:`Cursor`,configDir:p(t,`Cursor`,`User`),mcpConfigPath:p(t,`Cursor`,`User`,`mcp.json`),globalScaffoldRoot:o,instructionsRoot:null},{ide:`Cursor Nightly`,configDir:p(t,`Cursor Nightly`,`User`),mcpConfigPath:p(t,`Cursor Nightly`,`User`,`mcp.json`),globalScaffoldRoot:o,instructionsRoot:null},{ide:`Windsurf`,configDir:p(t,`Windsurf`,`User`),mcpConfigPath:p(t,`Windsurf`,`User`,`mcp.json`),globalScaffoldRoot:s,instructionsRoot:null})}return n.push({ide:`Claude Code`,configDir:p(e,`.claude`),mcpConfigPath:p(e,`.claude`,`mcp.json`),globalScaffoldRoot:a,instructionsRoot:null}),n.filter(e=>c(e.configDir))}function y(e,n,r=!1){let{mcpConfigPath:i,configDir:a}=e,o={...t},s={};if(c(i)){try{let e=u(i,`utf-8`);s=JSON.parse(e)}catch{let e=`${i}.bak`;d(e,u(i,`utf-8`),`utf-8`),console.log(` Backed up invalid ${i} to ${e}`),s={}}if((s.servers??s.mcpServers??{})[n]&&!r){console.log(` ${e.ide}: ${n} already configured (use --force to update)`);return}}let f=new Set([`VS Code`,`VS Code Insiders`,`VSCodium`,`Windsurf`]).has(e.ide)?`servers`:`mcpServers`,p=s[f]??{};p[n]=o,s[f]=p,l(a,{recursive:!0}),d(i,`${JSON.stringify(s,null,2)}\n`,`utf-8`),console.log(` ${e.ide}: configured ${n} in ${i}`)}const b=new Set([`VS Code`,`VS Code Insiders`,`VSCodium`]);function x(e,t=!1){if(!b.has(e.ide))return;let n=p(e.configDir,`settings.json`),r={};if(c(n))try{let e=u(n,`utf-8`);r=JSON.parse(e)}catch{console.log(` ${e.ide}: skipped settings.json (invalid JSON)`);return}let a=!1;for(let[e,n]of Object.entries(i))if(typeof n==`object`&&n){let t=typeof r[e]==`object`&&r[e]!==null?r[e]:{},i={...t,...n};JSON.stringify(i)!==JSON.stringify(t)&&(r[e]=i,a=!0)}else (t||!(e in r))&&(r[e]=n,a=!0);a&&(d(n,`${JSON.stringify(r,null,2)}\n`,`utf-8`),console.log(` ${e.ide}: updated settings.json`))}function S(t,n,i,u,f=!1){let m=new Set;for(let e of n)e.globalScaffoldRoot&&m.add(e.globalScaffoldRoot);if(m.size===0){console.log(` No IDEs with global scaffold support detected.`);return}let h=p(t,`scaffold`,`general`);for(let n of m){s(h,n,`agents`,u,f),s(h,n,`prompts`,u,f);let i=0;for(let e of r)c(p(h,`skills`,e))&&(s(h,n,`skills/${e}`,u,f),i++);for(let r of e){let e=p(t,`scaffold`,`flows`,r);c(p(e,`skills`))&&s(e,p(n,`flows`,r),`skills`,u,f)}console.log(` ${n}: scaffold updated (${i} skills)`)}let g=new Set,_=o(`aikit`,i),v=a(`aikit`,i);for(let e of n){if(!e.globalScaffoldRoot)continue;let t=e.globalScaffoldRoot;if(e.ide===`Claude Code`){let e=p(t,`CLAUDE.md`);d(e,`${_}\n---\n\n${v}`,`utf-8`),g.add(e)}else if(e.ide===`VS Code`||e.ide===`VS Code Insiders`||e.ide===`VSCodium`){let n=e.instructionsRoot??t;l(n,{recursive:!0});let r=p(n,`aikit.instructions.md`);g.has(r)||(d(r,`---\napplyTo: "**"\n---\n\n${_}\n---\n\n${v}`,`utf-8`),g.add(r))}else if(e.ide===`Cursor`||e.ide===`Cursor Nightly`){let e=p(t,`rules`);l(e,{recursive:!0});let n=p(e,`aikit.mdc`);g.has(n)||(d(n,`${_}\n---\n\n${v}`,`utf-8`),g.add(n))}else if(e.ide===`Windsurf`){let e=p(t,`rules`);l(e,{recursive:!0});let n=p(e,`aikit.md`);g.has(n)||(d(n,`${_}\n---\n\n${v}`,`utf-8`),g.add(n))}}g.size>0&&console.log(` Instruction files: ${[...g].join(`, `)}`)}async function C(e){let t=n,r=p(f(m(import.meta.url)),`..`,`..`,`..`,`..`,`..`,`package.json`),i=JSON.parse(u(r,`utf-8`)).version;console.log(`Initializing @vpxa/aikit v${i}...\n`);let a=h();l(a,{recursive:!0}),console.log(` Global data store: ${a}`),g({version:1,workspaces:{}}),console.log(` Created registry.json`);let o=v();if(o.length===0)console.log(`
|
|
2
2
|
No supported IDEs detected. You can manually add the MCP server config.`);else{console.log(`\n Detected ${o.length} IDE(s):`);for(let n of o)y(n,t,e.force),x(n,e.force)}let s=p(f(m(import.meta.url)),`..`,`..`,`..`,`..`,`..`);console.log(`
|
|
3
3
|
Installing scaffold files:`),S(s,o,t,i,e.force),console.log(`
|
|
4
4
|
User-level AI Kit installation complete!`),console.log(`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AIKIT_GLOBAL_PATHS, AIKIT_PATHS, CATEGORY_PATTERN, CHUNK_SIZES, DEFAULT_CATEGORIES, EMBEDDING_DEFAULTS, FILE_LIMITS, SEARCH_DEFAULTS, STORE_DEFAULTS } from "./constants.js";
|
|
2
|
-
import { CONTENT_TYPES, ChunkMetadata, ContentType, IndexStats, KBConfig, KNOWLEDGE_ORIGINS, KnowledgeOrigin, KnowledgeRecord, RawChunk, SOURCE_TYPES, SearchResult, SourceType } from "./types.js";
|
|
2
|
+
import { CONTENT_TYPES, ChunkMetadata, ContentType, INDEX_MODES, IndexMode, IndexStats, KBConfig, KNOWLEDGE_ORIGINS, KnowledgeOrigin, KnowledgeRecord, RawChunk, SOURCE_TYPES, SearchResult, SourceType } from "./types.js";
|
|
3
3
|
import { contentTypeToSourceType, detectContentType, sourceTypeContentTypes } from "./content-detector.js";
|
|
4
4
|
import { ConfigError, EmbeddingError, IndexError, KBError, StoreError } from "./errors.js";
|
|
5
5
|
import { GlobalRegistry, RegistryEntry, computePartitionKey, getGlobalDataDir, getPartitionDir, isUserInstalled, listWorkspaces, loadRegistry, lookupWorkspace, registerWorkspace, resolveStateDir, saveRegistry } from "./global-registry.js";
|
|
6
6
|
import { LogLevel, LogListener, addLogListener, createLogger, getLogLevel, resetLogDir, serializeError, setFileSinkEnabled, setLogLevel } from "./logger.js";
|
|
7
|
-
export { AIKIT_GLOBAL_PATHS, AIKIT_PATHS, CATEGORY_PATTERN, CHUNK_SIZES, CONTENT_TYPES, ChunkMetadata, ConfigError, ContentType, DEFAULT_CATEGORIES, EMBEDDING_DEFAULTS, EmbeddingError, FILE_LIMITS, GlobalRegistry, IndexError, IndexStats, KBConfig, KBError, KNOWLEDGE_ORIGINS, KnowledgeOrigin, KnowledgeRecord, LogLevel, LogListener, RawChunk, RegistryEntry, SEARCH_DEFAULTS, SOURCE_TYPES, STORE_DEFAULTS, SearchResult, SourceType, StoreError, addLogListener, computePartitionKey, contentTypeToSourceType, createLogger, detectContentType, getGlobalDataDir, getLogLevel, getPartitionDir, isUserInstalled, listWorkspaces, loadRegistry, lookupWorkspace, registerWorkspace, resetLogDir, resolveStateDir, saveRegistry, serializeError, setFileSinkEnabled, setLogLevel, sourceTypeContentTypes };
|
|
7
|
+
export { AIKIT_GLOBAL_PATHS, AIKIT_PATHS, CATEGORY_PATTERN, CHUNK_SIZES, CONTENT_TYPES, ChunkMetadata, ConfigError, ContentType, DEFAULT_CATEGORIES, EMBEDDING_DEFAULTS, EmbeddingError, FILE_LIMITS, GlobalRegistry, INDEX_MODES, IndexError, IndexMode, IndexStats, KBConfig, KBError, KNOWLEDGE_ORIGINS, KnowledgeOrigin, KnowledgeRecord, LogLevel, LogListener, RawChunk, RegistryEntry, SEARCH_DEFAULTS, SOURCE_TYPES, STORE_DEFAULTS, SearchResult, SourceType, StoreError, addLogListener, computePartitionKey, contentTypeToSourceType, createLogger, detectContentType, getGlobalDataDir, getLogLevel, getPartitionDir, isUserInstalled, listWorkspaces, loadRegistry, lookupWorkspace, registerWorkspace, resetLogDir, resolveStateDir, saveRegistry, serializeError, setFileSinkEnabled, setLogLevel, sourceTypeContentTypes };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AIKIT_GLOBAL_PATHS as e,AIKIT_PATHS as t,CATEGORY_PATTERN as n,CHUNK_SIZES as r,DEFAULT_CATEGORIES as i,EMBEDDING_DEFAULTS as a,FILE_LIMITS as o,SEARCH_DEFAULTS as s,STORE_DEFAULTS as c}from"./constants.js";import{contentTypeToSourceType as l,detectContentType as u,sourceTypeContentTypes as d}from"./content-detector.js";import{ConfigError as f,EmbeddingError as p,IndexError as m,KBError as h,StoreError as g}from"./errors.js";import{computePartitionKey as _,getGlobalDataDir as v,getPartitionDir as y,isUserInstalled as b,listWorkspaces as x,loadRegistry as S,lookupWorkspace as C,registerWorkspace as w,resolveStateDir as T,saveRegistry as E}from"./global-registry.js";import{addLogListener as D,createLogger as O,getLogLevel as k,resetLogDir as A,serializeError as j,setFileSinkEnabled as M,setLogLevel as N}from"./logger.js";import{CONTENT_TYPES as P,
|
|
1
|
+
import{AIKIT_GLOBAL_PATHS as e,AIKIT_PATHS as t,CATEGORY_PATTERN as n,CHUNK_SIZES as r,DEFAULT_CATEGORIES as i,EMBEDDING_DEFAULTS as a,FILE_LIMITS as o,SEARCH_DEFAULTS as s,STORE_DEFAULTS as c}from"./constants.js";import{contentTypeToSourceType as l,detectContentType as u,sourceTypeContentTypes as d}from"./content-detector.js";import{ConfigError as f,EmbeddingError as p,IndexError as m,KBError as h,StoreError as g}from"./errors.js";import{computePartitionKey as _,getGlobalDataDir as v,getPartitionDir as y,isUserInstalled as b,listWorkspaces as x,loadRegistry as S,lookupWorkspace as C,registerWorkspace as w,resolveStateDir as T,saveRegistry as E}from"./global-registry.js";import{addLogListener as D,createLogger as O,getLogLevel as k,resetLogDir as A,serializeError as j,setFileSinkEnabled as M,setLogLevel as N}from"./logger.js";import{CONTENT_TYPES as P,INDEX_MODES as F,KNOWLEDGE_ORIGINS as I,SOURCE_TYPES as L}from"./types.js";export{e as AIKIT_GLOBAL_PATHS,t as AIKIT_PATHS,n as CATEGORY_PATTERN,r as CHUNK_SIZES,P as CONTENT_TYPES,f as ConfigError,i as DEFAULT_CATEGORIES,a as EMBEDDING_DEFAULTS,p as EmbeddingError,o as FILE_LIMITS,F as INDEX_MODES,m as IndexError,h as KBError,I as KNOWLEDGE_ORIGINS,s as SEARCH_DEFAULTS,L as SOURCE_TYPES,c as STORE_DEFAULTS,g as StoreError,D as addLogListener,_ as computePartitionKey,l as contentTypeToSourceType,O as createLogger,u as detectContentType,v as getGlobalDataDir,k as getLogLevel,y as getPartitionDir,b as isUserInstalled,x as listWorkspaces,S as loadRegistry,C as lookupWorkspace,w as registerWorkspace,A as resetLogDir,T as resolveStateDir,E as saveRegistry,j as serializeError,M as setFileSinkEnabled,N as setLogLevel,d as sourceTypeContentTypes};
|
|
@@ -8,6 +8,9 @@ type KnowledgeOrigin = (typeof KNOWLEDGE_ORIGINS)[number];
|
|
|
8
8
|
/** Coarse source classification derived from ContentType */
|
|
9
9
|
declare const SOURCE_TYPES: readonly ["source", "documentation", "test", "config", "generated"];
|
|
10
10
|
type SourceType = (typeof SOURCE_TYPES)[number];
|
|
11
|
+
/** Indexing mode */
|
|
12
|
+
declare const INDEX_MODES: readonly ["auto", "manual", "smart"];
|
|
13
|
+
type IndexMode = (typeof INDEX_MODES)[number];
|
|
11
14
|
/** Content type classification */
|
|
12
15
|
declare const CONTENT_TYPES: readonly ["documentation", "code-typescript", "code-javascript", "code-python", "code-other", "config-json", "config-yaml", "config-toml", "config-env", "test-code", "cdk-stack", "markdown", "curated-knowledge", "produced-knowledge", "unknown"];
|
|
13
16
|
type ContentType = (typeof CONTENT_TYPES)[number];
|
|
@@ -81,8 +84,15 @@ interface SearchResult {
|
|
|
81
84
|
interface KBConfig {
|
|
82
85
|
/** MCP server name. Defaults to 'kb'. */
|
|
83
86
|
serverName?: string;
|
|
84
|
-
/**
|
|
87
|
+
/** @deprecated Use `indexMode` instead. Maps true→'auto', false→'manual'. */
|
|
85
88
|
autoIndex?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Indexing mode:
|
|
91
|
+
* - `auto`: Full index on startup (same as autoIndex=true)
|
|
92
|
+
* - `manual`: Only index via tool calls (same as autoIndex=false)
|
|
93
|
+
* - `smart`: On-demand + idle indexing (default)
|
|
94
|
+
*/
|
|
95
|
+
indexMode?: IndexMode;
|
|
86
96
|
/**
|
|
87
97
|
* Prefix prepended to every MCP tool name to avoid collisions with other
|
|
88
98
|
* MCP servers. E.g. `"aikit_"` turns `search` → `aikit_search`.
|
|
@@ -134,4 +144,4 @@ interface IndexStats {
|
|
|
134
144
|
embeddingModel: string;
|
|
135
145
|
}
|
|
136
146
|
//#endregion
|
|
137
|
-
export { CONTENT_TYPES, ChunkMetadata, ContentType, IndexStats, KBConfig, KNOWLEDGE_ORIGINS, KnowledgeOrigin, KnowledgeRecord, RawChunk, SOURCE_TYPES, SearchResult, SourceType };
|
|
147
|
+
export { CONTENT_TYPES, ChunkMetadata, ContentType, INDEX_MODES, IndexMode, IndexStats, KBConfig, KNOWLEDGE_ORIGINS, KnowledgeOrigin, KnowledgeRecord, RawChunk, SOURCE_TYPES, SearchResult, SourceType };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=[`indexed`,`curated`,`produced`],t=[`source`,`documentation`,`test`,`config`,`generated`],n=[`documentation`,`code-typescript`,`code-javascript`,`code-python`,`code-other`,`config-json`,`config-yaml`,`config-toml`,`config-env`,`test-code`,`cdk-stack`,`markdown`,`curated-knowledge`,`produced-knowledge`,`unknown`];export{
|
|
1
|
+
const e=[`indexed`,`curated`,`produced`],t=[`source`,`documentation`,`test`,`config`,`generated`],n=[`auto`,`manual`,`smart`],r=[`documentation`,`code-typescript`,`code-javascript`,`code-python`,`code-other`,`config-json`,`config-yaml`,`config-toml`,`config-env`,`test-code`,`cdk-stack`,`markdown`,`curated-knowledge`,`produced-knowledge`,`unknown`];export{r as CONTENT_TYPES,n as INDEX_MODES,e as KNOWLEDGE_ORIGINS,t as SOURCE_TYPES};
|
|
@@ -41,7 +41,23 @@ declare class IncrementalIndexer {
|
|
|
41
41
|
* up to `config.indexing.concurrency` (default: 50% of CPU cores, minimum 2, maximum 4).
|
|
42
42
|
*/
|
|
43
43
|
index(config: KBConfig, onProgress?: ProgressCallback): Promise<IndexResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Crawl sources and return file paths whose content has changed since the last index.
|
|
46
|
+
* This performs a read-only scan and does not modify the store.
|
|
47
|
+
*/
|
|
48
|
+
getChangedFiles(config: KBConfig): Promise<string[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Index only the specified file paths.
|
|
51
|
+
* Files that have not changed are skipped.
|
|
52
|
+
*/
|
|
53
|
+
indexFiles(config: KBConfig, paths: string[], onProgress?: ProgressCallback): Promise<IndexResult>;
|
|
44
54
|
private doIndex;
|
|
55
|
+
private doIndexFiles;
|
|
56
|
+
private crawlSources;
|
|
57
|
+
private planIndexWork;
|
|
58
|
+
private getPathsToRemove;
|
|
59
|
+
private processFiles;
|
|
60
|
+
private cleanupRemovedFiles;
|
|
45
61
|
/**
|
|
46
62
|
* Force re-index all files (ignoring hashes).
|
|
47
63
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{generateRecordId as e,hashContent as t}from"./file-hasher.js";import{FilesystemCrawler as n}from"./filesystem-crawler.js";import{extractGraph as r}from"./graph-extractor.js";import{AIKIT_PATHS as i,createLogger as a,detectContentType as o,serializeError as s}from"../../core/dist/index.js";import{availableParallelism as c,loadavg as l}from"node:os";import{createChunkerSync as u}from"../../chunker/dist/index.js";const d=a(`indexer`),f=()=>new Promise(e=>setImmediate(e));async function p(e,t,n,r){let i=0;async function a(){for(;i<e.length;){let n=i++;try{await t(e[n])}catch(t){r?.(e[n],t)}n%10==0&&await f()}}await Promise.all(Array.from({length:Math.min(n,e.length)},()=>a()))}function m(e){let t=c(),n=l()[0]/t;return n>1.5?2:n>1?Math.max(2,Math.floor(e/2)):e}const h=Math.max(2,Math.min(4,Math.floor(c()*.5)));var g=class{crawler;indexing=!1;graphStore;hashCache;get isIndexing(){return this.indexing}constructor(e,t){this.embedder=e,this.store=t,this.crawler=new n}setGraphStore(e){this.graphStore=e}setHashCache(e){this.hashCache=e}async index(e,t){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{return await this.doIndex(e,t,{})}finally{this.indexing=!1}}async
|
|
1
|
+
import{generateRecordId as e,hashContent as t}from"./file-hasher.js";import{FilesystemCrawler as n}from"./filesystem-crawler.js";import{extractGraph as r}from"./graph-extractor.js";import{AIKIT_PATHS as i,createLogger as a,detectContentType as o,serializeError as s}from"../../core/dist/index.js";import{availableParallelism as c,loadavg as l}from"node:os";import{createChunkerSync as u}from"../../chunker/dist/index.js";const d=a(`indexer`),f=()=>new Promise(e=>setImmediate(e));async function p(e,t,n,r){let i=0;async function a(){for(;i<e.length;){let n=i++;try{await t(e[n])}catch(t){r?.(e[n],t)}n%10==0&&await f()}}await Promise.all(Array.from({length:Math.min(n,e.length)},()=>a()))}function m(e){let t=c(),n=l()[0]/t;return n>1.5?2:n>1?Math.max(2,Math.floor(e/2)):e}const h=Math.max(2,Math.min(4,Math.floor(c()*.5)));var g=class{crawler;indexing=!1;graphStore;hashCache;get isIndexing(){return this.indexing}constructor(e,t){this.embedder=e,this.store=t,this.crawler=new n}setGraphStore(e){this.graphStore=e}setHashCache(e){this.hashCache=e}async index(e,t){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{return await this.doIndex(e,t,{})}finally{this.indexing=!1}}async getChangedFiles(e){let t=e.indexing.concurrency??h,n=await this.crawlSources(e),{filesToProcess:r}=await this.planIndexWork(n,t,{});return r.map(e=>e.relativePath)}async indexFiles(e,t,n){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{return await this.doIndexFiles(e,t,n)}finally{this.indexing=!1}}async doIndex(e,t,n={}){let r=Date.now(),i=e.indexing.concurrency??h;t?.({phase:`crawling`,filesTotal:0,filesProcessed:0,chunksTotal:0,chunksProcessed:0});let a=await this.crawlSources(e),{filesToProcess:o,filesSkipped:s,pathsToRemove:c}=await this.planIndexWork(a,i,{skipHashCheck:n.skipHashCheck}),{filesProcessed:l,chunksCreated:u}=await this.processFiles(o,i,t,{graphCleared:n.graphCleared}),d=await this.cleanupRemovedFiles(c,i,o.length,l,u,t);return this.hashCache?.flush(),t?.({phase:`done`,filesTotal:o.length,filesProcessed:l,chunksTotal:u,chunksProcessed:u}),{filesProcessed:l,filesSkipped:s,chunksCreated:u,filesRemoved:d,durationMs:Date.now()-r}}async doIndexFiles(e,t,n){let r=Date.now(),i=e.indexing.concurrency??h,a=new Set(t);if(a.size===0)return{filesProcessed:0,filesSkipped:0,chunksCreated:0,filesRemoved:0,durationMs:Date.now()-r};n?.({phase:`crawling`,filesTotal:0,filesProcessed:0,chunksTotal:0,chunksProcessed:0});let o=await this.crawlSources(e),{filesToProcess:s,filesSkipped:c}=await this.planIndexWork(o,i,{requestedPaths:a}),{filesProcessed:l,chunksCreated:u}=await this.processFiles(s,i,n,{});return this.hashCache?.flush(),n?.({phase:`done`,filesTotal:s.length,filesProcessed:l,chunksTotal:u,chunksProcessed:u}),{filesProcessed:l,filesSkipped:c,chunksCreated:u,filesRemoved:0,durationMs:Date.now()-r}}async crawlSources(e){return(await Promise.all(e.sources.map(e=>this.crawler.crawl({rootDir:e.path,excludePatterns:e.excludePatterns})))).flat()}async planIndexWork(e,n,r){let i=r.requestedPaths,a=i?e.filter(e=>i.has(e.relativePath)):e;if(r.skipHashCheck)return{filesToProcess:a,filesSkipped:0,pathsToRemove:[]};let o=i?[]:await this.getPathsToRemove(e),c=0,l=[];return await p(a,async e=>{let n=t(e.content);if(this.hashCache){if(this.hashCache.get(e.relativePath)===n){c++;return}}else{let t=await this.store.getBySourcePath(e.relativePath);if(t.length>0&&t[0].fileHash===n){c++;return}}l.push(e)},m(n),(e,t)=>d.error(`Hash check failed`,{sourcePath:e.relativePath,...s(t)})),{filesToProcess:l,filesSkipped:c,pathsToRemove:o}}async getPathsToRemove(e){let t=await this.store.listSourcePaths(),n=new Set(e.map(e=>e.relativePath));return t.filter(e=>!n.has(e)&&!e.startsWith(`${i.aiCurated}/`))}async processFiles(n,i,a,c={}){let l=0,f=0,h=n.length,g=[],_=[],v=0,y=[],b=[],x=new Map,S=0,C=async()=>{if(y.length===0)return;let e=y,t=b,n=x;y=[],b=[],x=new Map,S=0,await this.store.upsert(e,t);for(let[e,t]of n)this.hashCache?.set(e,t)},w=async()=>{if(this.graphStore){try{g.length>0&&await this.graphStore.upsertNodes(g),_.length>0&&await this.graphStore.upsertEdges(_)}catch(e){d.warn(`Graph batch flush failed`,s(e))}g=[],_=[],v=0}};return await p(n,async n=>{a?.({phase:`chunking`,filesTotal:h,filesProcessed:l,chunksTotal:f,chunksProcessed:f,currentFile:n.relativePath});let i=o(n.relativePath),p=u(n.extension).chunk(n.content,{sourcePath:n.relativePath,contentType:i});if(p.length===0)return;a?.({phase:`embedding`,filesTotal:h,filesProcessed:l,chunksTotal:f+p.length,chunksProcessed:f,currentFile:n.relativePath});let m=await this.embedder.embedBatch(p.map(e=>e.text)),T=t(n.content),E=p.map((t,r)=>({id:e(n.relativePath,r),content:t.text,sourcePath:t.sourcePath,contentType:t.contentType,headingPath:t.headingPath,chunkIndex:t.chunkIndex,totalChunks:t.totalChunks,startLine:t.startLine,endLine:t.endLine,fileHash:T,indexedAt:new Date().toISOString(),origin:`indexed`,tags:[],version:1}));if(a?.({phase:`storing`,filesTotal:h,filesProcessed:l,chunksTotal:f+p.length,chunksProcessed:f,currentFile:n.relativePath}),y.push(...E),b.push(...m),x.set(n.relativePath,T),S++,S>=20&&await C(),this.graphStore)try{c.graphCleared||await this.graphStore.deleteBySourcePath(n.relativePath);let e=r(n.content,n.relativePath);e.nodes.length>0&&g.push(...e.nodes),e.edges.length>0&&_.push(...e.edges),v++,v>=50&&await w()}catch(e){d.warn(`Graph extraction failed`,{sourcePath:n.relativePath,...s(e)})}l++,f+=p.length},m(i),(e,t)=>d.error(`Processing failed`,{sourcePath:e.relativePath,...s(t)})),await C(),await w(),{filesProcessed:l,chunksCreated:f}}async cleanupRemovedFiles(e,t,n,r,i,a){if(e.length===0)return 0;let o=0;return a?.({phase:`cleanup`,filesTotal:n,filesProcessed:r,chunksTotal:i,chunksProcessed:i}),await p(e,async e=>{await this.store.deleteBySourcePath(e),this.hashCache?.delete(e),this.graphStore&&await this.graphStore.deleteBySourcePath(e).catch(t=>d.warn(`Graph cleanup failed`,{sourcePath:e,...s(t)})),o++},m(t),(e,t)=>d.error(`Cleanup failed`,{sourcePath:e,...s(t)})),o}async reindexAll(e,t){if(this.indexing)throw Error(`Indexing is already in progress`);this.indexing=!0;try{if(await this.store.dropTable(),this.graphStore)try{let e=await this.graphStore.getStats();e.nodeCount>0&&(await this.graphStore.clear(),d.info(`Graph store cleared`,{nodeCount:e.nodeCount,edgeCount:e.edgeCount}))}catch(e){d.warn(`Graph store clear failed`,s(e))}return await this.doReindex(e,t)}catch(e){throw this.indexing=!1,e}}async doReindex(e,t){try{return await this.doIndex(e,t,{skipHashCheck:!0,graphCleared:!0})}finally{this.indexing=!1}}async getStats(){return this.store.getStats()}};export{g as IncrementalIndexer};
|
|
@@ -3,4 +3,5 @@ import { CrawlOptions, CrawlResult, FilesystemCrawler } from "./filesystem-crawl
|
|
|
3
3
|
import { ExtractedGraph, extractGraph } from "./graph-extractor.js";
|
|
4
4
|
import { FileHashCache } from "./hash-cache.js";
|
|
5
5
|
import { IncrementalIndexer, IndexProgress, IndexResult, ProgressCallback } from "./incremental-indexer.js";
|
|
6
|
-
|
|
6
|
+
import { SmartIndexScheduler } from "./smart-index-scheduler.js";
|
|
7
|
+
export { type CrawlOptions, type CrawlResult, type ExtractedGraph, FileHashCache, FilesystemCrawler, IncrementalIndexer, type IndexProgress, type IndexResult, type ProgressCallback, SmartIndexScheduler, extractGraph, generateRecordId, hashContent };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{generateRecordId as e,hashContent as t}from"./file-hasher.js";import{FilesystemCrawler as n}from"./filesystem-crawler.js";import{extractGraph as r}from"./graph-extractor.js";import{FileHashCache as i}from"./hash-cache.js";import{IncrementalIndexer as a}from"./incremental-indexer.js";export{i as FileHashCache,n as FilesystemCrawler,a as IncrementalIndexer,r as extractGraph,e as generateRecordId,t as hashContent};
|
|
1
|
+
import{generateRecordId as e,hashContent as t}from"./file-hasher.js";import{FilesystemCrawler as n}from"./filesystem-crawler.js";import{extractGraph as r}from"./graph-extractor.js";import{FileHashCache as i}from"./hash-cache.js";import{IncrementalIndexer as a}from"./incremental-indexer.js";import{SmartIndexScheduler as o}from"./smart-index-scheduler.js";export{i as FileHashCache,n as FilesystemCrawler,a as IncrementalIndexer,o as SmartIndexScheduler,r as extractGraph,e as generateRecordId,t as hashContent};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { IncrementalIndexer } from "./incremental-indexer.js";
|
|
2
|
+
import { KBConfig } from "../../core/dist/index.js";
|
|
3
|
+
|
|
4
|
+
//#region packages/indexer/src/smart-index-scheduler.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* SmartIndexScheduler trickles indexing work over time instead of running
|
|
7
|
+
* large idle-triggered indexing passes.
|
|
8
|
+
*/
|
|
9
|
+
declare class SmartIndexScheduler {
|
|
10
|
+
private readonly indexer;
|
|
11
|
+
private readonly config;
|
|
12
|
+
private trickleTimer;
|
|
13
|
+
private readonly trickleIntervalMs;
|
|
14
|
+
private readonly batchSize;
|
|
15
|
+
private readonly priorityQueue;
|
|
16
|
+
private changedFiles;
|
|
17
|
+
private lastRefreshTime;
|
|
18
|
+
private refreshing;
|
|
19
|
+
constructor(indexer: IncrementalIndexer, config: KBConfig);
|
|
20
|
+
/** Start the trickle indexing loop. */
|
|
21
|
+
start(): void;
|
|
22
|
+
/** Stop the scheduler and clear all timers. */
|
|
23
|
+
stop(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Add file paths to the front of the priority queue for near-term indexing.
|
|
26
|
+
*/
|
|
27
|
+
prioritize(...paths: string[]): void;
|
|
28
|
+
private readPositiveIntEnv;
|
|
29
|
+
private scheduleTick;
|
|
30
|
+
private tick;
|
|
31
|
+
private getCpuCount;
|
|
32
|
+
private pickFiles;
|
|
33
|
+
private maybeRefreshChangedFiles;
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { SmartIndexScheduler };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createLogger as e}from"../../core/dist/index.js";import{availableParallelism as t,loadavg as n}from"node:os";const r=e(`smart-index`),i=1.5;var a=class{trickleTimer=null;trickleIntervalMs;batchSize;priorityQueue=[];changedFiles=[];lastRefreshTime=0;refreshing=!1;constructor(e,t){this.indexer=e,this.config=t,this.trickleIntervalMs=this.readPositiveIntEnv(`AIKIT_SMART_TRICKLE_MS`,12e4),this.batchSize=this.readPositiveIntEnv(`AIKIT_SMART_BATCH_SIZE`,1)}start(){this.stop(),r.info(`Smart index scheduler started (trickle mode)`,{intervalMs:this.trickleIntervalMs,batchSize:this.batchSize}),this.scheduleTick()}stop(){this.trickleTimer&&=(clearTimeout(this.trickleTimer),null)}prioritize(...e){let t=[...new Set(e.filter(Boolean))];for(let e of t){let t=this.priorityQueue.indexOf(e);t>=0&&this.priorityQueue.splice(t,1)}for(let e of t.reverse())this.priorityQueue.unshift(e);t.length>0&&r.info(`Files prioritized for trickle indexing`,{added:t.length,queued:this.priorityQueue.length})}readPositiveIntEnv(e,t){let n=Number(process.env[e]);return Number.isFinite(n)&&n>0?n:t}scheduleTick(){this.trickleTimer=setTimeout(()=>void this.tick(),this.trickleIntervalMs),this.trickleTimer.unref&&this.trickleTimer.unref()}async tick(){try{if(this.indexer.isIndexing){r.info(`Skipping trickle tick — indexing already in progress`);return}let e=this.getCpuCount(),t=n()[0];if(e>0&&t/e>i){r.info(`Skipping trickle tick — system load too high`,{load:t.toFixed(2),cpuCount:e,threshold:i});return}let a=await this.pickFiles();if(a.length===0){await this.maybeRefreshChangedFiles();return}r.info(`Trickle indexing tick started`,{count:a.length,files:a});let o=await this.indexer.indexFiles(this.config,a);this.changedFiles=this.changedFiles.filter(e=>!a.includes(e)),r.info(`Trickle indexing tick complete`,{filesProcessed:o.filesProcessed,filesSkipped:o.filesSkipped,chunksCreated:o.chunksCreated})}catch(e){r.error(`Trickle indexing tick failed`,{error:String(e)})}finally{this.scheduleTick()}}getCpuCount(){try{return typeof t==`function`?t():4}catch{return 4}}async pickFiles(){let e=[];for(;e.length<this.batchSize&&this.priorityQueue.length>0;){let t=this.priorityQueue.shift();t&&!e.includes(t)&&e.push(t)}if(e.length<this.batchSize)for(await this.maybeRefreshChangedFiles();e.length<this.batchSize&&this.changedFiles.length>0;){let t=this.changedFiles.shift();t&&!e.includes(t)&&e.push(t)}return e}async maybeRefreshChangedFiles(){let e=Date.now();if(!(this.refreshing||this.changedFiles.length>0&&e-this.lastRefreshTime<6e5)){this.refreshing=!0;try{this.changedFiles=await this.indexer.getChangedFiles(this.config),this.lastRefreshTime=e,this.changedFiles.length>0&&r.info(`Refreshed changed files for trickle indexing`,{count:this.changedFiles.length})}catch(e){r.error(`Failed to refresh changed files for trickle indexing`,{error:String(e)})}finally{this.refreshing=!1}}}};export{a as SmartIndexScheduler};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { KBConfig } from "../../core/dist/index.js";
|
|
2
2
|
|
|
3
3
|
//#region packages/server/src/config.d.ts
|
|
4
|
+
type IndexMode = NonNullable<KBConfig['indexMode']>;
|
|
5
|
+
declare function resolveIndexMode(config: KBConfig): IndexMode;
|
|
4
6
|
declare function loadConfig(): KBConfig;
|
|
5
7
|
/**
|
|
6
8
|
* Re-target an existing config to a new workspace root.
|
|
@@ -11,4 +13,4 @@ declare function loadConfig(): KBConfig;
|
|
|
11
13
|
*/
|
|
12
14
|
declare function reconfigureForWorkspace(config: KBConfig, workspaceRoot: string): void;
|
|
13
15
|
//#endregion
|
|
14
|
-
export { loadConfig, reconfigureForWorkspace };
|
|
16
|
+
export { loadConfig, reconfigureForWorkspace, resolveIndexMode };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as e,readFileSync as t}from"node:fs";import{dirname as n,resolve as r}from"node:path";import{fileURLToPath as i}from"node:url";import{AIKIT_PATHS as a,createLogger as o,getPartitionDir as s,isUserInstalled as c,registerWorkspace as l,serializeError as u}from"../../core/dist/index.js";const d=n(i(import.meta.url)),f=o(`server`);function p(e,t,n){let i=r(e),a=r(t);if(!i.startsWith(a))throw Error(`Config ${n} path escapes workspace root: ${e} is not under ${t}`);return i}function m(){let i=process.env.AIKIT_CONFIG_PATH??(e(r(process.cwd(),`aikit.config.json`))?r(process.cwd(),`aikit.config.json`):r(d,`..`,`..`,`..`,`aikit.config.json`));try{if(!e(i))return f.info(`No config file found, using defaults`,{configPath:i}),
|
|
1
|
+
import{existsSync as e,readFileSync as t}from"node:fs";import{dirname as n,resolve as r}from"node:path";import{fileURLToPath as i}from"node:url";import{AIKIT_PATHS as a,createLogger as o,getPartitionDir as s,isUserInstalled as c,registerWorkspace as l,serializeError as u}from"../../core/dist/index.js";const d=n(i(import.meta.url)),f=o(`server`),p=[`auto`,`manual`,`smart`];function m(e){return typeof e==`string`&&p.includes(e)}function h(e,t,n){let i=r(e),a=r(t);if(!i.startsWith(a))throw Error(`Config ${n} path escapes workspace root: ${e} is not under ${t}`);return i}function g(e){let t=process.env.AIKIT_INDEX_MODE;if(m(t))return t;if(e.indexMode)return e.indexMode;let n=process.env.AIKIT_AUTO_INDEX;return n===void 0?e.autoIndex===void 0?`smart`:e.autoIndex?`auto`:`manual`:n===`true`?`auto`:`manual`}function _(){let i=process.env.AIKIT_CONFIG_PATH??(e(r(process.cwd(),`aikit.config.json`))?r(process.cwd(),`aikit.config.json`):r(d,`..`,`..`,`..`,`aikit.config.json`));try{if(!e(i))return f.info(`No config file found, using defaults`,{configPath:i}),v();let o=t(i,`utf-8`),s=JSON.parse(o);if(!s.sources||!Array.isArray(s.sources)||s.sources.length===0)throw Error(`Config must have at least one source`);if(!s.store?.path)throw Error(`Config must specify store.path`);if(s.autoIndex!==void 0&&typeof s.autoIndex!=`boolean`)throw Error(`Config autoIndex must be a boolean`);if(s.indexMode!==void 0&&!m(s.indexMode))throw Error(`Config indexMode must be one of: ${p.join(`, `)}`);let c=n(i);return s.sources=s.sources.map(e=>({...e,path:h(r(c,e.path),c,`source`)})),s.store.path=h(r(c,s.store.path),c,`store`),s.curated=s.curated??{path:a.aiCurated},s.curated.path=h(r(c,s.curated.path),c,`curated`),y(s,c),s.indexMode=g(s),s}catch(e){return f.error(`Failed to load config`,{configPath:i,...u(e)}),f.warn(`Falling back to default configuration`,{configPath:i}),v()}}function v(){let e=process.env.AIKIT_WORKSPACE_ROOT??process.cwd(),t={sources:[{path:e,excludePatterns:[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],serverName:`aikit`,indexing:{chunkSize:1500,chunkOverlap:200,minChunkSize:100},embedding:{model:`mixedbread-ai/mxbai-embed-large-v1`,dimensions:1024},store:{backend:`lancedb`,path:r(e,a.data)},curated:{path:r(e,a.aiCurated)},onboardDir:r(e,a.aiKb),stateDir:r(e,a.state)};return y(t,e),t.indexMode=g(t),t}function y(e,t){if(!c())return;let n=t,i=l(n);e.store.path=r(s(i.partition)),e.onboardDir=r(s(i.partition),`onboard`),e.stateDir=r(s(i.partition),`state`),e.curated||={path:r(n,a.aiCurated)}}function b(t,n){if(!e(n))throw Error(`Workspace root does not exist: ${n}`);f.info(`Reconfiguring for workspace root`,{workspaceRoot:n});try{process.chdir(n),f.info(`Changed process cwd to workspace root`,{cwd:process.cwd()})}catch(e){f.warn(`Failed to chdir to workspace root`,{workspaceRoot:n,...u(e)})}t.sources=[{path:n,excludePatterns:t.sources[0]?.excludePatterns??[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],t.store.path=r(n,a.data),t.curated={path:r(n,a.aiCurated)},t.onboardDir=r(n,a.aiKb),t.stateDir=r(n,a.state),y(t,n)}export{_ as loadConfig,b as reconfigureForWorkspace,g as resolveIndexMode};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readFileSync as e}from"node:fs";import{dirname as t,resolve as n}from"node:path";import{fileURLToPath as r}from"node:url";import{createLogger as i,serializeError as a}from"../../core/dist/index.js";import{parseArgs as o}from"node:util";const s=t(r(import.meta.url)),c=(()=>{try{let t=n(s,`..`,`..`,`..`,`package.json`);return JSON.parse(e(t,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}})(),l=i(`server`),{values:u}=o({options:{transport:{type:`string`,default:process.env.AIKIT_TRANSPORT??`stdio`},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}});async function d(){if(process.on(`unhandledRejection`,e=>{l.error(`Unhandled rejection`,a(e))}),l.info(`Starting MCP AI Kit server`,{version:c}),u.transport===`http`){let[{default:e},{loadConfig:t},{registerDashboardRoutes:
|
|
1
|
+
import{readFileSync as e}from"node:fs";import{dirname as t,resolve as n}from"node:path";import{fileURLToPath as r}from"node:url";import{createLogger as i,serializeError as a}from"../../core/dist/index.js";import{parseArgs as o}from"node:util";const s=t(r(import.meta.url)),c=(()=>{try{let t=n(s,`..`,`..`,`..`,`package.json`);return JSON.parse(e(t,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}})(),l=i(`server`),{values:u}=o({options:{transport:{type:`string`,default:process.env.AIKIT_TRANSPORT??`stdio`},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}});async function d(){if(process.on(`unhandledRejection`,e=>{l.error(`Unhandled rejection`,a(e))}),l.info(`Starting MCP AI Kit server`,{version:c}),u.transport===`http`){let[{default:e},{loadConfig:t,resolveIndexMode:n},{registerDashboardRoutes:r,resolveDashboardDir:i}]=await Promise.all([import(`express`),import(`./config.js`),import(`./dashboard-static.js`)]),o=t();l.info(`Config loaded`,{sourceCount:o.sources.length,storePath:o.store.path});let s=e();s.use(e.json());let c=Number(u.port);s.use((e,t,n)=>{if(t.setHeader(`Access-Control-Allow-Origin`,process.env.AIKIT_CORS_ORIGIN??`http://localhost:${c}`),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization`),e.method===`OPTIONS`){t.status(204).end();return}n()}),r(s,i(),l),s.get(`/health`,(e,t)=>{t.json({status:`ok`})});let d=!1,f=null,p=null,m=null,h=Promise.resolve();s.post(`/mcp`,async(e,t)=>{if(!d||!p||!m){t.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let n=h,r;h=new Promise(e=>{r=e}),await n;try{let n=new m({sessionIdGenerator:void 0});await p.connect(n),await n.handleRequest(e,t,e.body),n.close()}catch(e){if(l.error(`MCP handler error`,a(e)),!t.headersSent){let n=e instanceof Error?e.message:String(e),r=n.includes(`Not Acceptable`);t.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?n:`Internal server error`},id:null})}}finally{r()}}),s.get(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))}),s.delete(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))});let g=s.listen(c,`127.0.0.1`,()=>{l.info(`MCP server listening`,{url:`http://127.0.0.1:${c}/mcp`,port:c}),setTimeout(async()=>{try{let[{createLazyServer:e,ALL_TOOL_NAMES:t},{StreamableHTTPServerTransport:r},{checkForUpdates:i,autoUpgradeScaffold:s}]=await Promise.all([import(`./server.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check.js`)]);i(),s();let c=e(o);p=c.server,m=r,d=!0,l.info(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:t.length,resourceCount:2}),c.startInit();let u=n(o);u===`auto`?c.ready.then(async()=>{try{let e=o.sources.map(e=>e.path).join(`, `);l.info(`Running initial index`,{sourcePaths:e}),await c.runInitialIndex(),l.info(`Initial index complete`)}catch(e){l.error(`Initial index failed; will retry on aikit_reindex`,a(e))}}).catch(e=>l.error(`AI Kit init or indexing failed`,a(e))):u===`smart`?c.ready.then(async()=>{try{if(!c.kb)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`);f=new e(c.kb.indexer,o),f.start(),c.setSmartScheduler(f),l.info(`Smart index scheduler started (HTTP mode)`)}catch(e){l.error(`Failed to start smart index scheduler`,a(e))}}).catch(e=>l.error(`AI Kit initialization failed`,a(e))):(c.ready.catch(e=>l.error(`AI Kit initialization failed`,a(e))),l.info(`Initial full indexing skipped in HTTP mode`,{indexMode:u}))}catch(e){l.error(`Failed to load server modules`,a(e))}},100)}),_=async e=>{l.info(`Shutdown signal received`,{signal:e}),f?.stop(),g.close(),p&&await p.close(),process.exit(0)};process.on(`SIGINT`,()=>_(`SIGINT`)),process.on(`SIGTERM`,()=>_(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:n},{createLazyServer:i},{checkForUpdates:o,autoUpgradeScaffold:s},{RootsListChangedNotificationSchema:c}]=await Promise.all([import(`./config.js`),import(`./server.js`),import(`./version-check.js`),import(`@modelcontextprotocol/sdk/types.js`)]),u=e();l.info(`Config loaded`,{sourceCount:u.sources.length,storePath:u.store.path}),o(),s();let d=i(u),{server:f,startInit:p,ready:m,runInitialIndex:h}=d,{StdioServerTransport:g}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),_=new g;await f.connect(_),l.info(`MCP server started`,{transport:`stdio`});let v=e=>{if(e.length===0)return!1;let n=e[0].uri,i=n.startsWith(`file://`)?r(n):n;return l.info(`MCP roots resolved`,{rootUri:n,rootPath:i,rootCount:e.length}),t(u,i),!0},y=!1;try{y=v((await f.server.listRoots()).roots),y||l.info(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(e){l.warn(`MCP roots/list not supported by client; using cwd fallback`,{cwd:process.cwd(),...a(e)}),y=!0}y||=await new Promise(e=>{let t=setTimeout(()=>{l.warn(`Timed out waiting for MCP roots/list_changed; using cwd fallback`,{cwd:process.cwd()}),e(!1)},5e3);f.server.setNotificationHandler(c,async()=>{clearTimeout(t);try{e(v((await f.server.listRoots()).roots))}catch(t){l.warn(`roots/list retry failed after notification`,a(t)),e(!1)}})}),p();let b=null,x=()=>{b&&clearTimeout(b),b=setTimeout(()=>{l.info(`Auto-shutdown: no activity for 30 minutes — exiting`),process.exit(0)},18e5),b.unref&&b.unref()};x(),process.stdin.on(`data`,()=>x()),m.catch(e=>{l.error(`Initialization failed — server will continue with limited tools`,a(e))});let S=n(u);S===`auto`?h().catch(e=>l.error(`Initial index failed`,a(e))):S===`smart`?m.then(async()=>{try{if(!d.kb)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(d.kb.indexer,u);t.start(),d.setSmartScheduler(t),l.info(`Smart index scheduler started (stdio mode)`)}catch(e){l.error(`Failed to start smart index scheduler`,a(e))}}).catch(e=>l.error(`AI Kit init failed for smart scheduler`,a(e))):l.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:S})}}d().catch(e=>{l.error(`Fatal error`,a(e)),process.exit(1)});export{};
|
|
@@ -42,8 +42,12 @@ declare function createLazyServer(config: KBConfig): {
|
|
|
42
42
|
server: McpServer; /** Call after MCP roots are resolved (or fallback decided) to start heavy init. */
|
|
43
43
|
startInit: () => void;
|
|
44
44
|
ready: Promise<void>;
|
|
45
|
-
runInitialIndex: () => Promise<void>; /**
|
|
46
|
-
|
|
45
|
+
runInitialIndex: () => Promise<void>; /** Initialized AI Kit components after lazy startup completes. */
|
|
46
|
+
readonly kb: KnowledgeBaseComponents | null; /** Background task scheduler — use to queue heavy operations and check status. */
|
|
47
|
+
scheduler: BackgroundTaskScheduler; /** Set the smart index scheduler for tool invocation prioritization. */
|
|
48
|
+
setSmartScheduler: (s: {
|
|
49
|
+
prioritize: (...paths: string[]) => void;
|
|
50
|
+
} | null) => void;
|
|
47
51
|
};
|
|
48
52
|
//#endregion
|
|
49
53
|
export { ALL_TOOL_NAMES, KnowledgeBaseComponents, createLazyServer, createMcpServer, createServer, initializeKnowledgeBase, registerMcpTools };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{BackgroundTaskScheduler as e}from"./background-task.js";import{clearCompletionCache as t}from"./completions.js";import{CuratedKnowledgeManager as n}from"./curated-manager.js";import{createElicitor as r,noopElicitor as i}from"./elicitor.js";import{IdleTimer as a}from"./idle-timer.js";import{bridgeMcpLogging as o}from"./mcp-logging.js";import{MemoryMonitor as s}from"./memory-monitor.js";import{registerPrompts as c}from"./prompts.js";import{installReplayInterceptor as l}from"./replay-interceptor.js";import{ResourceNotifier as u}from"./resources/resource-notifier.js";import{registerResources as d}from"./resources/resources.js";import{createSamplingClient as f}from"./sampling.js";import{installStructuredContentGuard as p}from"./structured-content-guard.js";import{getToolMeta as m}from"./tool-metadata.js";import{installToolPrefix as h}from"./tool-prefix.js";import{ToolTimeoutError as g,getToolTimeout as _,withTimeout as v}from"./tool-timeout.js";import{registerAnalyzeDependenciesTool as y,registerAnalyzeDiagramTool as b,registerAnalyzeEntryPointsTool as x,registerAnalyzePatternsTool as S,registerAnalyzeStructureTool as ee,registerAnalyzeSymbolsTool as te,registerBlastRadiusTool as C}from"./tools/analyze.tools.js";import{registerAuditTool as w}from"./tools/audit.tool.js";import{registerBrainstormTool as T}from"./tools/brainstorm.tool.js";import{initBridgeComponents as ne,registerErPullTool as E,registerErPushTool as D,registerErSyncStatusTool as O}from"./tools/bridge.tools.js";import{registerConfigTool as k}from"./tools/config.tool.js";import{registerCompactTool as re,registerDeadSymbolsTool as A,registerFileSummaryTool as j,registerFindTool as ie,registerScopeMapTool as ae,registerSymbolTool as oe,registerTraceTool as se}from"./tools/context.tools.js";import{registerErEvolveReviewTool as ce}from"./tools/evolution.tools.js";import{registerBatchTool as le,registerCheckTool as ue,registerDelegateTool as de,registerEvalTool as fe,registerParseOutputTool as pe,registerTestRunTool as M}from"./tools/execution.tools.js";import{registerFlowTools as me}from"./tools/flow.tools.js";import{registerDigestTool as he,registerEvidenceMapTool as N,registerForgeClassifyTool as P,registerForgeGroundTool as ge,registerStratumCardTool as _e}from"./tools/forge.tools.js";import{registerForgetTool as ve}from"./tools/forget.tool.js";import{registerGraphTool as ye}from"./tools/graph.tool.js";import{registerGuideTool as F,registerHealthTool as I,registerProcessTool as L,registerWatchTool as R,registerWebFetchTool as z}from"./tools/infra.tools.js";import{registerListTool as be}from"./tools/list.tool.js";import{registerLookupTool as xe}from"./tools/lookup.tool.js";import{registerCodemodTool as B,registerDataTransformTool as V,registerDiffParseTool as H,registerGitContextTool as U,registerRenameTool as W}from"./tools/manipulation.tools.js";import{registerOnboardTool as Se}from"./tools/onboard.tool.js";import{registerCheckpointTool as G,registerLaneTool as K,registerQueueTool as q,registerStashTool as J,registerWorksetTool as Ce}from"./tools/persistence.tools.js";import{registerErUpdatePolicyTool as we}from"./tools/policy.tools.js";import{registerPresentTool as Te}from"./tools/present/tool.js";import"./tools/present/index.js";import{registerProduceKnowledgeTool as Ee}from"./tools/produce.tool.js";import{registerReadTool as De}from"./tools/read.tool.js";import{registerReindexTool as Oe}from"./tools/reindex.tool.js";import{registerRememberTool as ke}from"./tools/remember.tool.js";import{registerReplayTool as Ae}from"./tools/replay.tool.js";import{registerRestoreTool as je}from"./tools/restore.tool.js";import{registerSearchTool as Me}from"./tools/search.tool.js";import{getCurrentVersion as Ne}from"./version-check.js";import{registerEarlyStatusTool as Pe,registerStatusTool as Fe}from"./tools/status.tool.js";import{registerUpdateTool as Ie}from"./tools/update.tool.js";import{registerChangelogTool as Le,registerEncodeTool as Re,registerEnvTool as ze,registerHttpTool as Be,registerMeasureTool as Ve,registerRegexTestTool as He,registerSchemaValidateTool as Ue,registerSnippetTool as We,registerTimeTool as Ge,registerWebSearchTool as Ke}from"./tools/utility.tools.js";import{existsSync as qe,statSync as Je}from"node:fs";import{resolve as Ye}from"node:path";import{AIKIT_PATHS as Xe,createLogger as Ze,serializeError as Y}from"../../core/dist/index.js";import{initializeWasm as Qe}from"../../chunker/dist/index.js";import{OnnxEmbedder as $e}from"../../embeddings/dist/index.js";import{EvolutionCollector as et,PolicyStore as tt}from"../../enterprise-bridge/dist/index.js";import{FileHashCache as nt,IncrementalIndexer as rt}from"../../indexer/dist/index.js";import{SqliteGraphStore as it,createStore as at}from"../../store/dist/index.js";import{FileCache as ot}from"../../tools/dist/index.js";import{McpServer as st}from"@modelcontextprotocol/sdk/server/mcp.js";const X=Ze(`server`);async function Z(e){X.info(`Initializing AI Kit components`);let[t,r,i,a]=await Promise.all([(async()=>{let t=new $e({model:e.embedding.model,dimensions:e.embedding.dimensions});return await t.initialize(),X.info(`Embedder loaded`,{modelId:t.modelId,dimensions:t.dimensions}),t})(),(async()=>{let t=await at({backend:e.store.backend,path:e.store.path});return await t.initialize(),X.info(`Store initialized`),t})(),(async()=>{let t=new it({path:e.store.path});return await t.initialize(),X.info(`Graph store initialized`),t})(),(async()=>{let e=await Qe();return e?X.info(`WASM tree-sitter enabled for AST analysis`):X.warn(`WASM tree-sitter not available; analyzers will use regex fallback`),e})()]),o=new rt(t,r),s=new nt(e.store.path);s.load(),o.setHashCache(s);let c=e.curated.path,l=new n(c,r,t);o.setGraphStore(i);let u=ne(e.er),d=u?new tt(e.curated.path):void 0;d&&X.info(`Policy store initialized`,{ruleCount:d.getRules().length});let f=u?new et:void 0,p=Ye(e.sources[0]?.path??process.cwd(),Xe.aiKb),m=qe(p),h=e.onboardDir?qe(e.onboardDir):!1,g=m||h,_,v=m?p:e.onboardDir;if(g&&v)try{_=Je(v).mtime.toISOString()}catch{}return X.info(`Onboard state detected`,{onboardComplete:g,onboardTimestamp:_,aiKbExists:m,onboardDirExists:h}),{embedder:t,store:r,indexer:o,curated:l,graphStore:i,fileCache:new ot,bridge:u,policyStore:d,evolutionCollector:f,onboardComplete:g,onboardTimestamp:_}}function ct(e,t){let n=new st({name:t.serverName??`aikit`,version:Ne()},{capabilities:{logging:{}}});return o(n),h(n,t.toolPrefix??``),Q(n,e,t,r(n),new u(n),f(n)),c(n,{curated:e.curated,store:e.store,graphStore:e.graphStore}),n}function Q(e,t,n,r,i,a){l(e),p(e),Me(e,t.embedder,t.store,t.graphStore,t.bridge,t.evolutionCollector,a),xe(e,t.store),Fe(e,t.store,t.graphStore,t.curated,{onboardComplete:t.onboardComplete,onboardTimestamp:t.onboardTimestamp},n),k(e,n),Oe(e,t.indexer,n,t.curated,t.store,i),ke(e,t.curated,t.policyStore,t.evolutionCollector,i),Ie(e,t.curated,i),ve(e,t.curated,i),De(e,t.curated),be(e,t.curated),ee(e,t.store,t.embedder),y(e,t.store,t.embedder),te(e,t.store,t.embedder),S(e,t.store,t.embedder),x(e,t.store,t.embedder),b(e,t.store,t.embedder),C(e,t.store,t.embedder,t.graphStore),Ee(e,n),Se(e,t.store,t.embedder,n),ye(e,t.graphStore),w(e,t.store,t.embedder);let o=n.sources[0]?.path??process.cwd();re(e,t.embedder,t.fileCache,o),ae(e,t.embedder,t.store),ie(e,t.embedder,t.store),pe(e),Ce(e),ue(e),le(e,t.embedder,t.store),oe(e,t.embedder,t.store,t.graphStore),fe(e),M(e),J(e),U(e),H(e),W(e),B(e),je(e),j(e,t.fileCache,o),G(e),V(e),se(e,t.embedder,t.store),L(e),R(e),A(e,t.embedder,t.store),de(e,a),I(e),K(e),q(e),z(e),F(e),N(e),he(e,t.embedder),P(e),_e(e,t.embedder,t.fileCache),ge(e,t.embedder,t.store),Te(e,r),r&&T(e,r),Ke(e),Be(e),He(e),Re(e),Ve(e),Le(e),Ue(e),We(e),ze(e),Ge(e),me(e,n),t.bridge&&(D(e,t.bridge,t.evolutionCollector),E(e,t.bridge),O(e,t.bridge)),t.policyStore&&we(e,t.policyStore),t.evolutionCollector&&ce(e,t.evolutionCollector),d(e,t.store,t.curated),Ae(e)}async function lt(e){let t=await Z(e),n=ct(t,e);X.info(`MCP server configured`,{toolCount:$.length,resourceCount:2});let r=async()=>{try{let n=e.sources.map(e=>e.path).join(`, `);X.info(`Running initial index`,{sourcePaths:n});let r=await t.indexer.index(e,e=>{e.phase===`crawling`||e.phase===`done`||(e.phase===`chunking`&&e.currentFile&&X.debug(`Indexing file`,{current:e.filesProcessed+1,total:e.filesTotal,file:e.currentFile}),e.phase===`cleanup`&&X.debug(`Index cleanup`,{staleEntries:e.filesTotal-e.filesProcessed}))});X.info(`Initial index complete`,{filesProcessed:r.filesProcessed,filesSkipped:r.filesSkipped,chunksCreated:r.chunksCreated,durationMs:r.durationMs});try{await t.store.createFtsIndex()}catch(e){X.warn(`FTS index creation failed`,Y(e))}try{let e=await t.curated.reindexAll();X.info(`Curated re-index complete`,{indexed:e.indexed})}catch(e){X.error(`Curated re-index failed`,Y(e))}}catch(e){X.error(`Initial index failed; will retry on aikit_reindex`,Y(e))}},i=async()=>{X.info(`Shutting down`),await Promise.all([t.embedder.shutdown().catch(()=>{}),t.graphStore.close().catch(()=>{}),t.store.close().catch(()=>{})]),process.exit(0)};process.on(`SIGINT`,i),process.on(`SIGTERM`,i);let a=process.ppid,o=setInterval(()=>{try{process.kill(a,0)}catch{X.info(`Parent process died; shutting down`,{parentPid:a}),clearInterval(o),i()}},5e3);return o.unref(),{server:n,runInitialIndex:r,shutdown:i}}const ut=new Set(`batch.brainstorm.changelog.check.checkpoint.codemod.compact.config.data_transform.delegate.diff_parse.digest.encode.env.eval.evidence_map.file_summary.forge_classify.git_context.graph.guide.health.http.lane.measure.onboard.parse_output.present.process.produce_knowledge.queue.read.regex_test.reindex.remember.rename.replay.restore.schema_validate.scope_map.snippet.stash.status.stratum_card.test_run.time.update.forget.list.watch.web_fetch.web_search.workset`.split(`.`)),dt=5e3,ft=new Set(`brainstorm.changelog.check.checkpoint.codemod.data_transform.delegate.diff_parse.encode.env.eval.evidence_map.forge_classify.git_context.guide.present.health.http.lane.measure.parse_output.process.produce_knowledge.queue.regex_test.rename.replay.restore.schema_validate.snippet.stash.status.test_run.time.watch.web_fetch.web_search.workset`.split(`.`));function pt(e){ue(e),fe(e),M(e),pe(e),de(e),U(e),H(e),W(e),B(e),V(e),Ce(e),J(e),G(e),je(e),K(e),q(e),I(e),L(e),R(e),z(e),F(e),N(e),P(e),Te(e),T(e,i),Ee(e),Ae(e),Pe(e),Ke(e),Be(e),He(e),Re(e),Ve(e),Le(e),Ue(e),We(e),ze(e),Ge(e)}const $=`analyze_dependencies.analyze_diagram.analyze_entry_points.analyze_patterns.analyze_structure.analyze_symbols.audit.batch.blast_radius.brainstorm.changelog.check.checkpoint.codemod.compact.config.data_transform.dead_symbols.delegate.diff_parse.digest.encode.env.eval.evidence_map.file_summary.find.flow_info.flow_list.flow_reset.flow_start.flow_status.flow_step.forge_classify.forge_ground.forget.git_context.graph.guide.health.http.lane.list.lookup.measure.onboard.parse_output.present.process.produce_knowledge.queue.read.regex_test.reindex.remember.rename.replay.restore.schema_validate.scope_map.search.snippet.stash.status.stratum_card.symbol.test_run.time.trace.update.watch.web_fetch.web_search.workset`.split(`.`);function mt(n){let i=new st({name:n.serverName??`aikit`,version:Ne()},{capabilities:{logging:{}}}),l=`initializing`,d=``,p=!1,y=null,b=()=>l===`failed`?[`❌ AI Kit initialization failed — this tool is unavailable.`,``,d?`Error: ${d}`:``,``,`**35 tools are still available** and fully functional:`,`check, eval, test_run, git_context, health, measure, web_fetch, web_search,`,`regex_test, encode, stash, checkpoint, lane, process, time, env, and more.`,``,`Try restarting the MCP server to retry initialization.`].filter(Boolean).join(`
|
|
1
|
+
import{BackgroundTaskScheduler as e}from"./background-task.js";import{clearCompletionCache as t}from"./completions.js";import{CuratedKnowledgeManager as n}from"./curated-manager.js";import{createElicitor as r,noopElicitor as i}from"./elicitor.js";import{IdleTimer as a}from"./idle-timer.js";import{bridgeMcpLogging as o}from"./mcp-logging.js";import{MemoryMonitor as s}from"./memory-monitor.js";import{registerPrompts as c}from"./prompts.js";import{installReplayInterceptor as l}from"./replay-interceptor.js";import{ResourceNotifier as u}from"./resources/resource-notifier.js";import{registerResources as d}from"./resources/resources.js";import{createSamplingClient as f}from"./sampling.js";import{installStructuredContentGuard as p}from"./structured-content-guard.js";import{getToolMeta as m}from"./tool-metadata.js";import{installToolPrefix as h}from"./tool-prefix.js";import{ToolTimeoutError as g,getToolTimeout as _,withTimeout as v}from"./tool-timeout.js";import{registerAnalyzeDependenciesTool as y,registerAnalyzeDiagramTool as b,registerAnalyzeEntryPointsTool as x,registerAnalyzePatternsTool as ee,registerAnalyzeStructureTool as S,registerAnalyzeSymbolsTool as C,registerBlastRadiusTool as w}from"./tools/analyze.tools.js";import{registerAuditTool as te}from"./tools/audit.tool.js";import{registerBrainstormTool as T}from"./tools/brainstorm.tool.js";import{initBridgeComponents as E,registerErPullTool as D,registerErPushTool as O,registerErSyncStatusTool as ne}from"./tools/bridge.tools.js";import{registerConfigTool as k}from"./tools/config.tool.js";import{registerCompactTool as A,registerDeadSymbolsTool as j,registerFileSummaryTool as M,registerFindTool as re,registerScopeMapTool as N,registerSymbolTool as P,registerTraceTool as ie}from"./tools/context.tools.js";import{registerErEvolveReviewTool as ae}from"./tools/evolution.tools.js";import{registerBatchTool as oe,registerCheckTool as se,registerDelegateTool as ce,registerEvalTool as le,registerParseOutputTool as ue,registerTestRunTool as F}from"./tools/execution.tools.js";import{registerFlowTools as de}from"./tools/flow.tools.js";import{registerDigestTool as fe,registerEvidenceMapTool as I,registerForgeClassifyTool as L,registerForgeGroundTool as pe,registerStratumCardTool as me}from"./tools/forge.tools.js";import{registerForgetTool as he}from"./tools/forget.tool.js";import{registerGraphTool as ge}from"./tools/graph.tool.js";import{registerGuideTool as R,registerHealthTool as z,registerProcessTool as B,registerWatchTool as V,registerWebFetchTool as H}from"./tools/infra.tools.js";import{registerListTool as _e}from"./tools/list.tool.js";import{registerLookupTool as ve}from"./tools/lookup.tool.js";import{registerCodemodTool as U,registerDataTransformTool as W,registerDiffParseTool as G,registerGitContextTool as K,registerRenameTool as q}from"./tools/manipulation.tools.js";import{registerOnboardTool as ye}from"./tools/onboard.tool.js";import{registerCheckpointTool as be,registerLaneTool as xe,registerQueueTool as Se,registerStashTool as Ce,registerWorksetTool as we}from"./tools/persistence.tools.js";import{registerErUpdatePolicyTool as Te}from"./tools/policy.tools.js";import{registerPresentTool as Ee}from"./tools/present/tool.js";import"./tools/present/index.js";import{registerProduceKnowledgeTool as De}from"./tools/produce.tool.js";import{registerReadTool as Oe}from"./tools/read.tool.js";import{registerReindexTool as ke}from"./tools/reindex.tool.js";import{registerRememberTool as Ae}from"./tools/remember.tool.js";import{registerReplayTool as je}from"./tools/replay.tool.js";import{registerRestoreTool as Me}from"./tools/restore.tool.js";import{registerSearchTool as Ne}from"./tools/search.tool.js";import{getCurrentVersion as Pe}from"./version-check.js";import{registerEarlyStatusTool as Fe,registerStatusTool as Ie}from"./tools/status.tool.js";import{registerUpdateTool as Le}from"./tools/update.tool.js";import{registerChangelogTool as Re,registerEncodeTool as ze,registerEnvTool as Be,registerHttpTool as Ve,registerMeasureTool as He,registerRegexTestTool as Ue,registerSchemaValidateTool as We,registerSnippetTool as Ge,registerTimeTool as Ke,registerWebSearchTool as J}from"./tools/utility.tools.js";import{existsSync as qe,statSync as Je}from"node:fs";import{resolve as Ye}from"node:path";import{AIKIT_PATHS as Xe,createLogger as Ze,serializeError as Y}from"../../core/dist/index.js";import{initializeWasm as Qe}from"../../chunker/dist/index.js";import{OnnxEmbedder as $e}from"../../embeddings/dist/index.js";import{EvolutionCollector as et,PolicyStore as tt}from"../../enterprise-bridge/dist/index.js";import{FileHashCache as nt,IncrementalIndexer as rt}from"../../indexer/dist/index.js";import{SqliteGraphStore as it,createStore as at}from"../../store/dist/index.js";import{FileCache as ot}from"../../tools/dist/index.js";import{McpServer as st}from"@modelcontextprotocol/sdk/server/mcp.js";const X=Ze(`server`);async function Z(e){X.info(`Initializing AI Kit components`);let[t,r,i,a]=await Promise.all([(async()=>{let t=new $e({model:e.embedding.model,dimensions:e.embedding.dimensions});return await t.initialize(),X.info(`Embedder loaded`,{modelId:t.modelId,dimensions:t.dimensions}),t})(),(async()=>{let t=await at({backend:e.store.backend,path:e.store.path});return await t.initialize(),X.info(`Store initialized`),t})(),(async()=>{let t=new it({path:e.store.path});return await t.initialize(),X.info(`Graph store initialized`),t})(),(async()=>{let e=await Qe();return e?X.info(`WASM tree-sitter enabled for AST analysis`):X.warn(`WASM tree-sitter not available; analyzers will use regex fallback`),e})()]),o=new rt(t,r),s=new nt(e.store.path);s.load(),o.setHashCache(s);let c=e.curated.path,l=new n(c,r,t);o.setGraphStore(i);let u=E(e.er),d=u?new tt(e.curated.path):void 0;d&&X.info(`Policy store initialized`,{ruleCount:d.getRules().length});let f=u?new et:void 0,p=Ye(e.sources[0]?.path??process.cwd(),Xe.aiKb),m=qe(p),h=e.onboardDir?qe(e.onboardDir):!1,g=m||h,_,v=m?p:e.onboardDir;if(g&&v)try{_=Je(v).mtime.toISOString()}catch{}return X.info(`Onboard state detected`,{onboardComplete:g,onboardTimestamp:_,aiKbExists:m,onboardDirExists:h}),{embedder:t,store:r,indexer:o,curated:l,graphStore:i,fileCache:new ot,bridge:u,policyStore:d,evolutionCollector:f,onboardComplete:g,onboardTimestamp:_}}function ct(e,t){let n=new st({name:t.serverName??`aikit`,version:Pe()},{capabilities:{logging:{}}});return o(n),h(n,t.toolPrefix??``),Q(n,e,t,r(n),new u(n),f(n)),c(n,{curated:e.curated,store:e.store,graphStore:e.graphStore}),n}function Q(e,t,n,r,i,a){l(e),p(e),Ne(e,t.embedder,t.store,t.graphStore,t.bridge,t.evolutionCollector,a),ve(e,t.store),Ie(e,t.store,t.graphStore,t.curated,{onboardComplete:t.onboardComplete,onboardTimestamp:t.onboardTimestamp},n),k(e,n),ke(e,t.indexer,n,t.curated,t.store,i),Ae(e,t.curated,t.policyStore,t.evolutionCollector,i),Le(e,t.curated,i),he(e,t.curated,i),Oe(e,t.curated),_e(e,t.curated),S(e,t.store,t.embedder),y(e,t.store,t.embedder),C(e,t.store,t.embedder),ee(e,t.store,t.embedder),x(e,t.store,t.embedder),b(e,t.store,t.embedder),w(e,t.store,t.embedder,t.graphStore),De(e,n),ye(e,t.store,t.embedder,n),ge(e,t.graphStore),te(e,t.store,t.embedder);let o=n.sources[0]?.path??process.cwd();A(e,t.embedder,t.fileCache,o),N(e,t.embedder,t.store),re(e,t.embedder,t.store),ue(e),we(e),se(e),oe(e,t.embedder,t.store),P(e,t.embedder,t.store,t.graphStore),le(e),F(e),Ce(e),K(e),G(e),q(e),U(e),Me(e),M(e,t.fileCache,o),be(e),W(e),ie(e,t.embedder,t.store,t.graphStore),B(e),V(e),j(e,t.embedder,t.store),ce(e,a),z(e),xe(e),Se(e),H(e),R(e),I(e),fe(e,t.embedder),L(e),me(e,t.embedder,t.fileCache),pe(e,t.embedder,t.store),Ee(e,r),r&&T(e,r),J(e),Ve(e),Ue(e),ze(e),He(e),Re(e),We(e),Ge(e),Be(e),Ke(e),de(e,n),t.bridge&&(O(e,t.bridge,t.evolutionCollector),D(e,t.bridge),ne(e,t.bridge)),t.policyStore&&Te(e,t.policyStore),t.evolutionCollector&&ae(e,t.evolutionCollector),d(e,t.store,t.curated),je(e)}async function lt(e){let t=await Z(e),n=ct(t,e);X.info(`MCP server configured`,{toolCount:$.length,resourceCount:2});let r=async()=>{try{let n=e.sources.map(e=>e.path).join(`, `);X.info(`Running initial index`,{sourcePaths:n});let r=await t.indexer.index(e,e=>{e.phase===`crawling`||e.phase===`done`||(e.phase===`chunking`&&e.currentFile&&X.debug(`Indexing file`,{current:e.filesProcessed+1,total:e.filesTotal,file:e.currentFile}),e.phase===`cleanup`&&X.debug(`Index cleanup`,{staleEntries:e.filesTotal-e.filesProcessed}))});X.info(`Initial index complete`,{filesProcessed:r.filesProcessed,filesSkipped:r.filesSkipped,chunksCreated:r.chunksCreated,durationMs:r.durationMs});try{await t.store.createFtsIndex()}catch(e){X.warn(`FTS index creation failed`,Y(e))}try{let e=await t.curated.reindexAll();X.info(`Curated re-index complete`,{indexed:e.indexed})}catch(e){X.error(`Curated re-index failed`,Y(e))}}catch(e){X.error(`Initial index failed; will retry on aikit_reindex`,Y(e))}},i=async()=>{X.info(`Shutting down`),await Promise.all([t.embedder.shutdown().catch(()=>{}),t.graphStore.close().catch(()=>{}),t.store.close().catch(()=>{})]),process.exit(0)};process.on(`SIGINT`,i),process.on(`SIGTERM`,i);let a=process.ppid,o=setInterval(()=>{try{process.kill(a,0)}catch{X.info(`Parent process died; shutting down`,{parentPid:a}),clearInterval(o),i()}},5e3);return o.unref(),{server:n,runInitialIndex:r,shutdown:i}}const ut=new Set(`batch.brainstorm.changelog.check.checkpoint.codemod.compact.config.data_transform.delegate.diff_parse.digest.encode.env.eval.evidence_map.file_summary.forge_classify.git_context.graph.guide.health.http.lane.measure.onboard.parse_output.present.process.produce_knowledge.queue.read.regex_test.reindex.remember.rename.replay.restore.schema_validate.scope_map.snippet.stash.status.stratum_card.test_run.time.update.forget.list.watch.web_fetch.web_search.workset`.split(`.`)),dt=5e3,ft=new Set(`brainstorm.changelog.check.checkpoint.codemod.data_transform.delegate.diff_parse.encode.env.eval.evidence_map.forge_classify.git_context.guide.present.health.http.lane.measure.parse_output.process.produce_knowledge.queue.regex_test.rename.replay.restore.schema_validate.snippet.stash.status.test_run.time.watch.web_fetch.web_search.workset`.split(`.`));function pt(e){se(e),le(e),F(e),ue(e),ce(e),K(e),G(e),q(e),U(e),W(e),we(e),Ce(e),be(e),Me(e),xe(e),Se(e),z(e),B(e),V(e),H(e),R(e),I(e),L(e),Ee(e),T(e,i),De(e),je(e),Fe(e),J(e),Ve(e),Ue(e),ze(e),He(e),Re(e),We(e),Ge(e),Be(e),Ke(e)}const $=`analyze_dependencies.analyze_diagram.analyze_entry_points.analyze_patterns.analyze_structure.analyze_symbols.audit.batch.blast_radius.brainstorm.changelog.check.checkpoint.codemod.compact.config.data_transform.dead_symbols.delegate.diff_parse.digest.encode.env.eval.evidence_map.file_summary.find.flow_info.flow_list.flow_reset.flow_start.flow_status.flow_step.forge_classify.forge_ground.forget.git_context.graph.guide.health.http.lane.list.lookup.measure.onboard.parse_output.present.process.produce_knowledge.queue.read.regex_test.reindex.remember.rename.replay.restore.schema_validate.scope_map.search.snippet.stash.status.stratum_card.symbol.test_run.time.trace.update.watch.web_fetch.web_search.workset`.split(`.`);function mt(n){let i=new st({name:n.serverName??`aikit`,version:Pe()},{capabilities:{logging:{}}}),l=`initializing`,d=``,p=!1,y=null,b=null,x=null;function ee(e){if(!e||typeof e!=`object`)return[];let t=e,n=[];for(let e of[`path`,`file`,`source_path`,`sourcePath`,`filePath`]){let r=t[e];typeof r==`string`&&r&&n.push(r)}for(let e of[`changed_files`,`paths`,`files`]){let r=t[e];if(Array.isArray(r))for(let e of r){if(typeof e==`string`){n.push(e);continue}e&&typeof e==`object`&&typeof e.path==`string`&&n.push(e.path)}}if(Array.isArray(t.sources))for(let e of t.sources)e&&typeof e==`object`&&typeof e.path==`string`&&n.push(e.path);return n}let S=()=>l===`failed`?[`❌ AI Kit initialization failed — this tool is unavailable.`,``,d?`Error: ${d}`:``,``,`**35 tools are still available** and fully functional:`,`check, eval, test_run, git_context, health, measure, web_fetch, web_search,`,`regex_test, encode, stash, checkpoint, lane, process, time, env, and more.`,``,`Try restarting the MCP server to retry initialization.`].filter(Boolean).join(`
|
|
2
2
|
`):[`AI Kit is still initializing (loading embeddings model & store).`,``,`**35 tools are already available** while initialization completes — including:`,`check, eval, test_run, git_context, health, measure, web_fetch, web_search,`,`regex_test, encode, stash, checkpoint, lane, process, time, env, and more.`,``,`This tool requires the AI Kit index. Please retry in a few seconds,`,`or use one of the available tools above in the meantime.`].join(`
|
|
3
|
-
`);o(i),h(i,n.toolPrefix??``);let
|
|
3
|
+
`);o(i),h(i,n.toolPrefix??``);let C=i.sendToolListChanged.bind(i);i.sendToolListChanged=()=>{};let w=[];for(let e of $){let t=m(e),n=i.registerTool(e,{title:t.title,description:`${t.title} — initializing, available shortly`,inputSchema:{},annotations:t.annotations},async()=>({content:[{type:`text`,text:S()}]}));ft.has(e)?n.remove():w.push(n)}pt(i),i.sendToolListChanged=C;let te=i.registerResource(`aikit-status`,`aikit://status`,{description:`AI Kit status (initializing...)`,mimeType:`text/plain`},async()=>({contents:[{uri:`aikit://status`,text:`AI Kit is initializing...`,mimeType:`text/plain`}]})),T=i.registerPrompt(`_init`,{description:`AI Kit is initializing prompts...`},async()=>({messages:[{role:`user`,content:{type:`text`,text:S()}}]})),E,D=new Promise(e=>{E=e}),O,ne=new Promise(e=>{O=e}),k=()=>O?.(),A=(async()=>{await ne;let e;try{e=await Z(n)}catch(e){l=`failed`,d=e instanceof Error?e.message:String(e),X.error(`AI Kit initialization failed — server continuing with zero-dep tools only`,{error:d});return}let o=i.sendToolListChanged.bind(i);i.sendToolListChanged=()=>{};let m=i.sendPromptListChanged.bind(i);i.sendPromptListChanged=()=>{};let h=i.sendResourceListChanged.bind(i);i.sendResourceListChanged=()=>{};for(let e of w)e.remove();te.remove(),T.remove();let S=i._registeredTools??{};for(let e of ft)S[e]?.remove();let C=new u(i),D=f(i);Q(i,e,n,r(i),C,D),c(i),i.sendToolListChanged=o,i.sendPromptListChanged=m,i.sendResourceListChanged=h,Promise.resolve(i.sendToolListChanged()).catch(()=>{}),Promise.resolve(i.sendPromptListChanged()).catch(()=>{}),Promise.resolve(i.sendResourceListChanged()).catch(()=>{});let O=i._registeredTools??{};for(let[t,n]of Object.entries(O)){if(ut.has(t))continue;let r=n.handler;n.handler=async(...n)=>{if(!e.indexer.isIndexing)return r(...n);let i=p?`re-indexing`:`running initial index`,a=new Promise(e=>setTimeout(()=>e({content:[{type:`text`,text:`⏳ AI Kit is ${i}. The tool "${t}" timed out waiting for index data (${dt/1e3}s).\n\nThe existing index may be temporarily locked. Please retry shortly — indexing will complete automatically.`}]}),dt));return Promise.race([r(...n),a])}}for(let[e,t]of Object.entries(O)){let n=t.handler,r=_(e);t.handler=async(...t)=>{try{return await v(()=>n(...t),r,e)}catch(t){if(t instanceof g)return{content:[{type:`text`,text:`⏳ Tool "${e}" timed out after ${r/1e3}s. This may indicate a long-running operation. Please retry or break the task into smaller steps.`}]};throw t}}}let k=Object.keys(O).length;k<$.length&&X.warn(`ALL_TOOL_NAMES count mismatch`,{expectedToolCount:$.length,registeredToolCount:k}),X.info(`MCP server configured`,{toolCount:$.length,resourceCount:4});let A=new s;A.onPressure((e,n)=>{e===`warning`&&t(),e===`critical`&&(X.warn(`Memory pressure critical — consider restarting`,{rssMB:Math.round(n/1024/1024)}),t())}),A.start();let j=new a;b=j,j.onIdle(async()=>{if(M.isRunning||e.indexer.isIndexing){X.info(`Idle cleanup deferred — background tasks still running`),j.touch();return}X.info(`Idle cleanup: closing store and graph connections`);try{await Promise.all([e.store.close().catch(()=>{}),e.graphStore.close().catch(()=>{})])}catch{}}),j.touch();for(let e of Object.values(O)){let t=e.handler;e.handler=async(...e)=>{if(j.touch(),x){let t=ee(e[0]);t.length>0&&x.prioritize(...t)}return t(...e)}}y=e,E?.(e)})(),j=async()=>{let e=await D;b?.setBusy(!0);try{let t=n.sources.map(e=>e.path).join(`, `);X.info(`Running initial index`,{sourcePaths:t});let r=await e.indexer.index(n,e=>{e.phase===`crawling`||e.phase===`done`||(e.phase===`chunking`&&e.currentFile&&X.debug(`Indexing file`,{current:e.filesProcessed+1,total:e.filesTotal,file:e.currentFile}),e.phase===`cleanup`&&X.debug(`Index cleanup`,{staleEntries:e.filesTotal-e.filesProcessed}))});p=!0,X.info(`Initial index complete`,{filesProcessed:r.filesProcessed,filesSkipped:r.filesSkipped,chunksCreated:r.chunksCreated,durationMs:r.durationMs});try{await e.store.createFtsIndex()}catch(e){X.warn(`FTS index creation failed`,Y(e))}try{let t=await e.curated.reindexAll();X.info(`Curated re-index complete`,{indexed:t.indexed})}catch(e){X.error(`Curated re-index failed`,Y(e))}}catch(e){X.error(`Initial index failed; will retry on aikit_reindex`,Y(e))}finally{b?.setBusy(!1)}},M=new e,re=()=>M.schedule({name:`initial-index`,fn:j}),N=process.ppid,P=setInterval(()=>{try{process.kill(N,0)}catch{X.info(`Parent process died; shutting down`,{parentPid:N}),clearInterval(P),D.then(async e=>{await Promise.all([e.embedder.shutdown().catch(()=>{}),e.graphStore.close().catch(()=>{}),e.store.close().catch(()=>{})])}).catch(()=>{}).finally(()=>process.exit(0))}},5e3);return P.unref(),{server:i,startInit:k,ready:A,runInitialIndex:re,get kb(){return y},scheduler:M,setSmartScheduler(e){x=e}}}export{$ as ALL_TOOL_NAMES,mt as createLazyServer,ct as createMcpServer,lt as createServer,Z as initializeKnowledgeBase,Q as registerMcpTools};
|
|
@@ -9,7 +9,7 @@ declare function registerScopeMapTool(server: McpServer, embedder: IEmbedder, st
|
|
|
9
9
|
declare function registerFindTool(server: McpServer, embedder: IEmbedder, store: IKnowledgeStore): void;
|
|
10
10
|
declare function registerSymbolTool(server: McpServer, embedder: IEmbedder, store: IKnowledgeStore, graphStore?: IGraphStore): void;
|
|
11
11
|
declare function registerFileSummaryTool(server: McpServer, cache: FileCache, rootPath: string): void;
|
|
12
|
-
declare function registerTraceTool(server: McpServer, embedder: IEmbedder, store: IKnowledgeStore): void;
|
|
12
|
+
declare function registerTraceTool(server: McpServer, embedder: IEmbedder, store: IKnowledgeStore, graphStore?: IGraphStore): void;
|
|
13
13
|
declare function registerDeadSymbolsTool(server: McpServer, embedder: IEmbedder, store: IKnowledgeStore): void;
|
|
14
14
|
//#endregion
|
|
15
15
|
export { registerCompactTool, registerDeadSymbolsTool, registerFileSummaryTool, registerFindTool, registerScopeMapTool, registerSymbolTool, registerTraceTool };
|
|
@@ -3,8 +3,8 @@ import{getToolMeta as e}from"../tool-metadata.js";import{CompactOutputSchema as
|
|
|
3
3
|
`)+"\n\n---\n_Next: Use `search` to dive into specific files, or `compact` to compress file contents for context._";return{content:[{type:`text`,text:a?T(s,a):s}],structuredContent:{files:o.files.map(e=>({path:e.path,relevance:e.relevance,estimatedTokens:e.estimatedTokens,...e.focusRanges.length>0?{focusLines:e.focusRanges.map(e=>`L${e.start}-${e.end}`)}:{}})),totalFiles:o.files.length,totalEstimatedTokens:o.totalEstimatedTokens,task:e}}}catch(e){return E.error(`Scope map failed`,g(e)),{content:[{type:`text`,text:`Scope map failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function k(t,n,r){let a=e(`find`);t.registerTool(`find`,{title:a.title,description:`Multi-strategy search combining vector, FTS, glob, and regex. Use for precise queries needing multiple strategies. mode=examples finds real usage of a symbol. For general discovery use search instead.`,outputSchema:i,inputSchema:{query:f.string().optional().describe(`Semantic/keyword search query (required for mode "examples")`),glob:f.string().optional().describe(`File glob pattern (search mode only)`),pattern:f.string().optional().describe(`Regex pattern to match in content (search mode only)`),limit:f.number().min(1).max(50).default(10).describe(`Max results`),content_type:f.enum(p).optional().describe(`Filter by content type`),mode:f.enum([`search`,`examples`]).default(`search`).describe(`Mode: "search" (default) for federated search, "examples" to find usage examples of a symbol/pattern`),max_tokens:f.number().min(100).max(5e4).optional().describe(`Maximum token budget for the response. When set, output is truncated to fit.`),workspaces:f.array(f.string()).optional().describe(`Cross-workspace search: partition names or folder basenames to include. Use ["*"] for all. User-level mode only.`)},annotations:a.annotations},async({query:e,glob:t,pattern:i,limit:a,content_type:o,mode:u,max_tokens:d,workspaces:f})=>{try{if(u===`examples`){if(!e)return{content:[{type:`text`,text:`Error: "query" is required for mode "examples".`}],isError:!0};let t=await x(n,r,{query:e,limit:a,contentType:o}),i=JSON.stringify(t);return{content:[{type:`text`,text:d?T(i,d):i}]}}let p=await y(n,r,{query:e,glob:t,pattern:i,limit:a,contentType:o}),h=``;if(f&&f.length>0&&e){let t=l(f,m(process.cwd()));if(t.length>0){let{stores:r,closeAll:i}=await c(t);try{let i=await s(r,await n.embedQuery(e),{limit:a,contentType:o});for(let e of i)p.results.push({path:`[${e.workspace}] ${e.record.sourcePath}`,score:e.score,source:`cross-workspace`,lineRange:e.record.startLine?{start:e.record.startLine,end:e.record.endLine}:void 0,preview:e.record.content.slice(0,200)});p.results.sort((e,t)=>t.score-e.score),p.results=p.results.slice(0,a),p.totalFound=p.results.length,h=` + ${t.length} workspace(s)`}finally{await i()}}}if(p.results.length===0)return{content:[{type:`text`,text:`No results found.${p.failedStrategies?.length?`\nStrategies attempted: ${p.strategies.join(`, `)}\nFailed: ${p.failedStrategies.map(e=>`${e.strategy} (${e.reason})`).join(`, `)}`:p.strategies.length===0?`
|
|
4
4
|
No search strategies were activated. Provide at least one of: query, glob, or pattern.`:``}`}],structuredContent:{matches:[],totalMatches:0,pattern:e??t??i??``,truncated:!1}};let g=[`Found ${p.totalFound} results via ${p.strategies.join(` + `)}${h}`,``,...p.results.map(e=>{let t=e.lineRange?`:${e.lineRange.start}-${e.lineRange.end}`:``,n=e.preview?`\n ${e.preview.slice(0,100)}...`:``;return`- [${e.source}] ${e.path}${t} (${(e.score*100).toFixed(0)}%)${n}`})];return{content:[{type:`text`,text:d?T(g.join(`
|
|
5
5
|
`),d):g.join(`
|
|
6
|
-
`)}],structuredContent:{matches:p.results.map(e=>({path:e.path,...e.lineRange?{line:e.lineRange.start}:{},matchType:e.source,preview:e.preview?.slice(0,200)??``})),totalMatches:p.totalFound,pattern:e??t??i??``,truncated:p.results.length<p.totalFound}}}catch(e){return E.error(`Find failed`,g(e)),{content:[{type:`text`,text:`Find failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function A(t,n,r,i){let a=e(`symbol`);t.registerTool(`symbol`,{title:a.title,description:`Find definition, imports, and references of a named symbol (function, class, type). For tracing data flow across call sites use trace instead.`,inputSchema:{name:f.string().describe(`Symbol name to look up (function, class, type, etc.)`),limit:f.number().min(1).max(50).default(20).describe(`Max results per category`),workspaces:f.array(f.string()).optional().describe(`Cross-workspace search: partition names or folder basenames to include. Use ["*"] for all. User-level mode only.`)},outputSchema:o,annotations:a.annotations},async({name:e,limit:t,workspaces:a})=>{try{let o=await C(n,r,{name:e,limit:t,graphStore:i});if(a&&a.length>0){let r=l(a,m(process.cwd()));if(r.length>0){let{stores:i,closeAll:a}=await c(r);try{for(let[r,a]of i){let i=await C(n,a,{name:e,limit:t});i.definedIn&&!o.definedIn&&(o.definedIn={...i.definedIn,path:`[${r}] ${i.definedIn.path}`});for(let e of i.referencedIn)o.referencedIn.push({...e,path:`[${r}] ${e.path}`});if(i.importedBy){o.importedBy=o.importedBy??[];for(let e of i.importedBy)o.importedBy.push({...e,path:`[${r}] ${e.path}`})}}}finally{await a()}}}let s={name:o.name,definedIn:o.definedIn??null,importedBy:o.importedBy??[],referencedIn:o.referencedIn??[],graphContext:o.graphContext??null};return{content:[{type:`text`,text:P(o)}],structuredContent:s}}catch(e){return E.error(`Symbol lookup failed`,g(e)),{content:[{type:`text`,text:`Symbol lookup failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function j(t,n,i){let a=e(`file_summary`);t.registerTool(`file_summary`,{title:a.title,description:`Create a concise structural summary of a source file: imports, exports, functions, classes, interfaces, and types.`,outputSchema:r,inputSchema:{path:f.string().describe(`Absolute path to the file to summarize`)},annotations:a.annotations},async({path:e})=>{try{let t=u(e)?e:d(i,e),r=await v({path:t,content:(await n.get(t)).content});return{content:[{type:`text`,text:F(r)}],structuredContent:{path:r.path,language:r.language,lines:r.lines,imports:r.imports?.length??0,exports:r.exports?.length??0,functions:r.functions?.length??0,classes:r.classes?.length??0}}}catch(e){return E.error(`File summary failed`,g(e)),{content:[{type:`text`,text:`File summary failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function M(t,n,r){let
|
|
7
|
-
`)}]}}catch(e){return E.error(`Trace failed`,g(e)),{content:[{type:`text`,text:`Trace failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function N(t,r,i){let a=e(`dead_symbols`);t.registerTool(`dead_symbols`,{title:a.title,description:`Find exported symbols that appear to be unused because they are never imported or re-exported.`,outputSchema:n,inputSchema:{path:f.string().optional().describe(`Root path to scope the search (default: cwd)`),limit:f.number().min(1).max(500).default(100).optional().describe(`Maximum exported symbols to scan`)},annotations:a.annotations},async({path:e,limit:t})=>{try{let n=await b(r,i,{rootPath:e,limit:t}),a=[`## Dead Symbol Analysis`,``,`**Exports scanned:** ${n.totalExports}`,`**Dead in source:** ${n.totalDeadSource} (actionable)`,`**Dead in docs:** ${n.totalDeadDocs} (informational — code samples in .md files)`,``];if(n.deadInSource.length>0){a.push(`### Dead in Source (actionable)`);for(let e of n.deadInSource)a.push(`- \`${e.name}\` (${e.kind}) — ${e.path}:${e.line}`);a.push(``)}if(n.deadInDocs.length>0){a.push(`### Dead in Docs (informational)`),a.push(`_${n.totalDeadDocs} symbol(s) found only in documentation code samples — not actionable dead code._`);for(let e of n.deadInDocs.slice(0,5))a.push(`- \`${e.name}\` — ${e.path}:${e.line}`);n.deadInDocs.length>5&&a.push(`- _... ${n.deadInDocs.length-5} more omitted_`)}return n.totalDeadSource>0?a.push(``,`---`,`_Next: \`codemod\` to remove ${n.totalDeadSource} unused exports | \`symbol\` to verify usage before removing_`):a.push(``,`---`,"_Next: `check` — no dead symbols found, validate types and lint_"),{content:[{type:`text`,text:a.join(`
|
|
6
|
+
`)}],structuredContent:{matches:p.results.map(e=>({path:e.path,...e.lineRange?{line:e.lineRange.start}:{},matchType:e.source,preview:e.preview?.slice(0,200)??``})),totalMatches:p.totalFound,pattern:e??t??i??``,truncated:p.results.length<p.totalFound}}}catch(e){return E.error(`Find failed`,g(e)),{content:[{type:`text`,text:`Find failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function A(t,n,r,i){let a=e(`symbol`);t.registerTool(`symbol`,{title:a.title,description:`Find definition, imports, and references of a named symbol (function, class, type). For tracing data flow across call sites use trace instead.`,inputSchema:{name:f.string().describe(`Symbol name to look up (function, class, type, etc.)`),limit:f.number().min(1).max(50).default(20).describe(`Max results per category`),workspaces:f.array(f.string()).optional().describe(`Cross-workspace search: partition names or folder basenames to include. Use ["*"] for all. User-level mode only.`)},outputSchema:o,annotations:a.annotations},async({name:e,limit:t,workspaces:a})=>{try{let o=await C(n,r,{name:e,limit:t,graphStore:i});if(a&&a.length>0){let r=l(a,m(process.cwd()));if(r.length>0){let{stores:i,closeAll:a}=await c(r);try{for(let[r,a]of i){let i=await C(n,a,{name:e,limit:t});i.definedIn&&!o.definedIn&&(o.definedIn={...i.definedIn,path:`[${r}] ${i.definedIn.path}`});for(let e of i.referencedIn)o.referencedIn.push({...e,path:`[${r}] ${e.path}`});if(i.importedBy){o.importedBy=o.importedBy??[];for(let e of i.importedBy)o.importedBy.push({...e,path:`[${r}] ${e.path}`})}}}finally{await a()}}}let s={name:o.name,definedIn:o.definedIn??null,importedBy:o.importedBy??[],referencedIn:o.referencedIn??[],graphContext:o.graphContext??null};return{content:[{type:`text`,text:P(o)}],structuredContent:s}}catch(e){return E.error(`Symbol lookup failed`,g(e)),{content:[{type:`text`,text:`Symbol lookup failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function j(t,n,i){let a=e(`file_summary`);t.registerTool(`file_summary`,{title:a.title,description:`Create a concise structural summary of a source file: imports, exports, functions, classes, interfaces, and types.`,outputSchema:r,inputSchema:{path:f.string().describe(`Absolute path to the file to summarize`)},annotations:a.annotations},async({path:e})=>{try{let t=u(e)?e:d(i,e),r=await v({path:t,content:(await n.get(t)).content});return{content:[{type:`text`,text:F(r)}],structuredContent:{path:r.path,language:r.language,lines:r.lines,imports:r.imports?.length??0,exports:r.exports?.length??0,functions:r.functions?.length??0,classes:r.classes?.length??0}}}catch(e){return E.error(`File summary failed`,g(e)),{content:[{type:`text`,text:`File summary failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function M(t,n,r,i){let a=e(`trace`);t.registerTool(`trace`,{title:a.title,description:`Follow data flow forward/backward across imports and call sites from a starting symbol or file:line. For finding a single symbol definition use symbol instead.`,inputSchema:{start:f.string().describe(`Starting point — symbol name or file:line reference`),direction:f.enum([`forward`,`backward`,`both`]).describe(`Which direction to trace relationships`),max_depth:f.number().min(1).max(10).default(3).optional().describe(`Maximum trace depth`)},annotations:a.annotations},async({start:e,direction:t,max_depth:a})=>{try{let o=await w(n,r,{start:e,direction:t,maxDepth:a,graphStore:i}),s=[`## Trace: ${o.start}`,`Direction: ${o.direction} | Depth: ${o.depth}`,``];if(o.graphContext&&(s.push(`### Graph Context`),o.graphContext.definingModule&&s.push(`- Module: ${o.graphContext.definingModule}`),o.graphContext.community&&s.push(`- Community: ${o.graphContext.community}`),o.graphContext.importedByModules.length>0&&s.push(`- Imported by modules: ${o.graphContext.importedByModules.join(`, `)}`),o.graphContext.siblingSymbols.length>0&&s.push(`- Sibling symbols: ${o.graphContext.siblingSymbols.join(`, `)}`),s.push(``)),o.nodes.length===0)s.push(`No connections found.`);else{let e=o.nodes.filter(e=>e.relationship===`calls`),t=o.nodes.filter(e=>e.relationship===`called-by`),n=o.nodes.filter(e=>e.relationship===`imports`),r=o.nodes.filter(e=>e.relationship===`imported-by`),i=o.nodes.filter(e=>e.relationship===`references`);if(e.length>0){s.push(`### Calls (${e.length})`);for(let t of e){let e=t.scope?` (from ${t.scope}())`:``;s.push(`- ${t.symbol}() — ${t.path}:${t.line}${e}`)}s.push(``)}if(t.length>0){s.push(`### Called by (${t.length})`);for(let e of t){let t=e.scope?` in ${e.scope}()`:``;s.push(`- ${e.symbol}()${t} — ${e.path}:${e.line}`)}s.push(``)}if(n.length>0){s.push(`### Imports (${n.length})`);for(let e of n)s.push(`- ${e.symbol} — ${e.path}:${e.line}`);s.push(``)}if(r.length>0){s.push(`### Imported by (${r.length})`);for(let e of r)s.push(`- ${e.path}:${e.line}`);s.push(``)}if(i.length>0){s.push(`### References (${i.length})`);for(let e of i)s.push(`- ${e.path}:${e.line}`);s.push(``)}}return s.push(`---`,"_Next: `symbol` for definition details | `compact` to read a referenced file | `blast_radius` for impact analysis_"),{content:[{type:`text`,text:s.join(`
|
|
7
|
+
`)}],structuredContent:{start:o.start,direction:o.direction,depth:o.depth,nodes:o.nodes,graphContext:o.graphContext??null}}}catch(e){return E.error(`Trace failed`,g(e)),{content:[{type:`text`,text:`Trace failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function N(t,r,i){let a=e(`dead_symbols`);t.registerTool(`dead_symbols`,{title:a.title,description:`Find exported symbols that appear to be unused because they are never imported or re-exported.`,outputSchema:n,inputSchema:{path:f.string().optional().describe(`Root path to scope the search (default: cwd)`),limit:f.number().min(1).max(500).default(100).optional().describe(`Maximum exported symbols to scan`)},annotations:a.annotations},async({path:e,limit:t})=>{try{let n=await b(r,i,{rootPath:e,limit:t}),a=[`## Dead Symbol Analysis`,``,`**Exports scanned:** ${n.totalExports}`,`**Dead in source:** ${n.totalDeadSource} (actionable)`,`**Dead in docs:** ${n.totalDeadDocs} (informational — code samples in .md files)`,``];if(n.deadInSource.length>0){a.push(`### Dead in Source (actionable)`);for(let e of n.deadInSource)a.push(`- \`${e.name}\` (${e.kind}) — ${e.path}:${e.line}`);a.push(``)}if(n.deadInDocs.length>0){a.push(`### Dead in Docs (informational)`),a.push(`_${n.totalDeadDocs} symbol(s) found only in documentation code samples — not actionable dead code._`);for(let e of n.deadInDocs.slice(0,5))a.push(`- \`${e.name}\` — ${e.path}:${e.line}`);n.deadInDocs.length>5&&a.push(`- _... ${n.deadInDocs.length-5} more omitted_`)}return n.totalDeadSource>0?a.push(``,`---`,`_Next: \`codemod\` to remove ${n.totalDeadSource} unused exports | \`symbol\` to verify usage before removing_`):a.push(``,`---`,"_Next: `check` — no dead symbols found, validate types and lint_"),{content:[{type:`text`,text:a.join(`
|
|
8
8
|
`)}],structuredContent:{symbols:[...n.deadInSource,...n.deadInDocs].map(e=>({name:e.name,path:e.path,...e.line===void 0?{}:{line:e.line},kind:e.kind})),totalDead:n.totalDeadSource+n.totalDeadDocs}}}catch(e){return E.error(`Dead symbol scan failed`,g(e)),{content:[{type:`text`,text:`Dead symbol scan failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function P(e){let t=[`Symbol: ${e.name}`];if(e.definedIn){let n=`Defined in: ${e.definedIn.path}:${e.definedIn.line} (${e.definedIn.kind})`;e.definedIn.signature&&(n+=`\nSignature: ${e.definedIn.signature}`),t.push(n)}else t.push(`Defined in: not found`);if(t.push(``,`Imported by:`),e.importedBy.length===0)t.push(` none`);else for(let n of e.importedBy)t.push(` - ${n.path}:${n.line} ${n.importStatement}`);if(t.push(``,`Referenced in:`),e.referencedIn.length===0)t.push(` none`);else for(let n of e.referencedIn){let e=`scope`in n&&n.scope?` in ${n.scope}()`:``;t.push(` - ${n.path}:${n.line}${e} ${n.context}`)}if(e.graphContext){let n=e.graphContext;t.push(``,`Graph context:`),n.definingModule&&t.push(` Module: ${n.definingModule}`),n.importedByModules.length>0&&t.push(` Imported by modules: ${n.importedByModules.join(`, `)}`),n.siblingSymbols.length>0&&t.push(` Sibling symbols: ${n.siblingSymbols.join(`, `)}`)}return t.join(`
|
|
9
9
|
`)}function F(e){let t=[e.path,`Language: ${e.language}`,`Lines: ${e.lines}`,`Estimated tokens: ~${e.estimatedTokens}`,``,`Imports (${e.imports.length}):`,...I(e.imports),``,`Exports (${e.exports.length}):`,...I(e.exports),``,`Functions (${e.functions.length}):`,...I(e.functions.map(e=>`${e.name} @ line ${e.line}${e.exported?` [exported]`:``}${`signature`in e&&e.signature?` — ${e.signature}`:``}`)),``,`Classes (${e.classes.length}):`,...I(e.classes.map(e=>`${e.name} @ line ${e.line}${e.exported?` [exported]`:``}${e.signature?` — ${e.signature}`:``}`)),``,`Interfaces (${e.interfaces.length}):`,...I(e.interfaces.map(e=>`${e.name} @ line ${e.line}${`exported`in e&&e.exported?` [exported]`:``}`)),``,`Types (${e.types.length}):`,...I(e.types.map(e=>`${e.name} @ line ${e.line}${`exported`in e&&e.exported?` [exported]`:``}`))];if(`importDetails`in e&&e.importDetails&&e.importDetails.length>0){let n=e.importDetails.filter(e=>e.isExternal).length,r=e.importDetails.length-n;t.push(``,`Import breakdown: ${n} external, ${r} internal`)}if(`callEdges`in e&&e.callEdges&&e.callEdges.length>0){t.push(``,`Call edges (${e.callEdges.length} intra-file):`);for(let n of e.callEdges.slice(0,30))t.push(` - ${n.caller}() → ${n.callee}() @ line ${n.line}`);e.callEdges.length>30&&t.push(` - ... ${e.callEdges.length-30} more`)}return t.join(`
|
|
10
10
|
`)}function I(e){return e.length===0?[` none`]:e.map(e=>` - ${e}`)}export{D as registerCompactTool,N as registerDeadSymbolsTool,j as registerFileSummaryTool,k as registerFindTool,O as registerScopeMapTool,A as registerSymbolTool,M as registerTraceTool};
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import{getToolMeta as e}from"../tool-metadata.js";import{GraphOutputSchema as t}from"../output-schemas.js";import{z as n}from"zod";import{createLogger as r,serializeError as i}from"../../../core/dist/index.js";import{graphQuery as a}from"../../../tools/dist/index.js";const o=r(`tools`),s=n.object({id:n.string().optional().describe(`Node ID (auto-generated if omitted)`),type:n.string().describe(`Node type (entity, service, api, concept, decision)`),name:n.string().describe(`Display name`),properties:n.record(n.string(),n.unknown()).optional().describe(`Arbitrary properties`),sourceRecordId:n.string().optional().describe(`Back-link to knowledge record ID`),sourcePath:n.string().optional().describe(`Source file path`)}),c=n.object({id:n.string().optional().describe(`Edge ID (auto-generated if omitted)`),fromId:n.string().describe(`Source node ID`),toId:n.string().describe(`Target node ID`),type:n.string().describe(`Relationship type (depends-on, implements, calls, affects)`),weight:n.number().min(0).max(1).optional().describe(`Relationship weight`),properties:n.record(n.string(),n.unknown()).optional().describe(`Arbitrary properties`)});function l(r,l){let u=e(`graph`);r.registerTool(`graph`,{title:u.title,description:`Query and manage the knowledge graph. Find nodes/edges, traverse connections, add entities and relationships. The graph captures structural relationships between concepts discovered in the codebase.`,outputSchema:t,inputSchema:{action:n.enum([`find_nodes`,`find_edges`,`neighbors`,`traverse`,`stats`,`validate`,`add`,`delete`,`clear`]).describe(`Action: find_nodes (search nodes), find_edges (search edges), neighbors (direct connections), traverse (multi-hop), stats (graph overview), validate (check graph integrity), add (insert nodes/edges), delete (remove nodes), clear (remove all)`),node_type:n.string().optional().describe(`Node type filter (for find_nodes)`),name_pattern:n.string().optional().describe(`Name substring match (for find_nodes)`),source_path:n.string().optional().describe(`Source path filter`),node_id:n.string().optional().describe(`Node ID (for neighbors, traverse, delete)`),edge_type:n.string().optional().describe(`Edge type filter`),from_id:n.string().optional().describe(`Source node ID (for find_edges)`),to_id:n.string().optional().describe(`Target node ID (for find_edges)`),direction:n.enum([`outgoing`,`incoming`,`both`]).default(`both`).describe(`Traversal direction`),max_depth:n.number().min(1).max(5).default(2).describe(`Max traversal depth`),limit:n.number().min(1).max(100).default(50).describe(`Max results`),nodes:n.array(s).max(500).optional().describe(`Nodes to add (for action=add)`),edges:n.array(c).max(500).optional().describe(`Edges to add (for action=add)`)},annotations:u.annotations},async e=>{try{let t=await a(l,{action:e.action,nodeType:e.node_type,namePattern:e.name_pattern,sourcePath:e.source_path,nodeId:e.node_id,edgeType:e.edge_type,fromId:e.from_id,toId:e.to_id,direction:e.direction,maxDepth:e.max_depth,limit:e.limit,nodes:e.nodes,edges:e.edges}),n=[t.summary];if(t.nodes&&t.nodes.length>0){n.push(`
|
|
1
|
+
import{getToolMeta as e}from"../tool-metadata.js";import{GraphOutputSchema as t}from"../output-schemas.js";import{z as n}from"zod";import{createLogger as r,serializeError as i}from"../../../core/dist/index.js";import{graphQuery as a}from"../../../tools/dist/index.js";const o=r(`tools`),s=n.object({id:n.string().optional().describe(`Node ID (auto-generated if omitted)`),type:n.string().describe(`Node type (entity, service, api, concept, decision)`),name:n.string().describe(`Display name`),properties:n.record(n.string(),n.unknown()).optional().describe(`Arbitrary properties`),sourceRecordId:n.string().optional().describe(`Back-link to knowledge record ID`),sourcePath:n.string().optional().describe(`Source file path`)}),c=n.object({id:n.string().optional().describe(`Edge ID (auto-generated if omitted)`),fromId:n.string().describe(`Source node ID`),toId:n.string().describe(`Target node ID`),type:n.string().describe(`Relationship type (depends-on, implements, calls, affects)`),weight:n.number().min(0).max(1).optional().describe(`Relationship weight`),properties:n.record(n.string(),n.unknown()).optional().describe(`Arbitrary properties`)});function l(r,l){let u=e(`graph`);r.registerTool(`graph`,{title:u.title,description:`Query and manage the knowledge graph. Find nodes/edges, traverse connections, add entities and relationships, detect communities, trace processes, and inspect full symbol context. The graph captures structural relationships between concepts discovered in the codebase.`,outputSchema:t,inputSchema:{action:n.enum([`find_nodes`,`find_edges`,`neighbors`,`traverse`,`stats`,`validate`,`add`,`delete`,`clear`,`detect_communities`,`set_community`,`trace_process`,`list_processes`,`delete_process`,`depth_traverse`,`cohesion`,`symbol360`]).describe(`Action: find_nodes (search nodes), find_edges (search edges), neighbors (direct connections), traverse (multi-hop), stats (graph overview), validate (check graph integrity), add (insert nodes/edges), delete (remove nodes), clear (remove all), detect_communities (find clusters), set_community (label a node), trace_process (persist execution flow), list_processes (list traced flows), delete_process (remove a flow), depth_traverse (bucket traversal by depth), cohesion (score a community), symbol360 (full node context)`),node_type:n.string().optional().describe(`Node type filter (for find_nodes)`),name_pattern:n.string().optional().describe(`Name substring match (for find_nodes)`),source_path:n.string().optional().describe(`Source path filter`),node_id:n.string().optional().describe(`Node ID (for neighbors, traverse, delete)`),edge_type:n.string().optional().describe(`Edge type filter`),from_id:n.string().optional().describe(`Source node ID (for find_edges)`),to_id:n.string().optional().describe(`Target node ID (for find_edges)`),direction:n.enum([`outgoing`,`incoming`,`both`]).default(`both`).describe(`Traversal direction`),max_depth:n.number().min(1).max(5).default(2).describe(`Max traversal depth`),limit:n.number().min(1).max(100).default(50).describe(`Max results`),nodes:n.array(s).max(500).optional().describe(`Nodes to add (for action=add)`),edges:n.array(c).max(500).optional().describe(`Edges to add (for action=add)`),community:n.string().optional().describe(`Community label (for set_community, cohesion)`),process_id:n.string().optional().describe(`Process ID (for delete_process)`),label:n.string().optional().describe(`Label for process tracing (for trace_process)`)},annotations:u.annotations},async e=>{try{let t=await a(l,{action:e.action,nodeType:e.node_type,namePattern:e.name_pattern,sourcePath:e.source_path,nodeId:e.node_id,edgeType:e.edge_type,fromId:e.from_id,toId:e.to_id,direction:e.direction,maxDepth:e.max_depth,limit:e.limit,nodes:e.nodes,edges:e.edges,community:e.community,processId:e.process_id,label:e.label}),n=[t.summary];if(t.nodes&&t.nodes.length>0){n.push(`
|
|
2
2
|
### Nodes`);for(let e of t.nodes){let t=Object.keys(e.properties).length>0?` — ${JSON.stringify(e.properties)}`:``;n.push(`- **${e.name}** (${e.type}, id: \`${e.id}\`)${t}`)}}if(t.edges&&t.edges.length>0){n.push(`
|
|
3
3
|
### Edges`);for(let e of t.edges)n.push(`- \`${e.fromId}\` —[${e.type}]→ \`${e.toId}\`${e.weight===1?``:` (weight: ${e.weight})`}`)}if(t.stats&&(n.push(`\nNode types: ${JSON.stringify(t.stats.nodeTypes)}`),n.push(`Edge types: ${JSON.stringify(t.stats.edgeTypes)}`)),t.validation){if(n.push(`
|
|
4
|
-
### Validation`),n.push(`- **Valid**: ${t.validation.valid?`yes`:`no`}`),t.validation.danglingEdges.length>0){n.push(`- **Dangling edges**:`);for(let e of t.validation.danglingEdges)n.push(` - \`${e.edgeId}\` references missing node \`${e.missingNodeId}\``)}t.validation.orphanNodes.length>0&&n.push(`- **Orphan nodes**: ${t.validation.orphanNodes.map(e=>`\`${e}\``).join(`, `)}`)}
|
|
4
|
+
### Validation`),n.push(`- **Valid**: ${t.validation.valid?`yes`:`no`}`),t.validation.danglingEdges.length>0){n.push(`- **Dangling edges**:`);for(let e of t.validation.danglingEdges)n.push(` - \`${e.edgeId}\` references missing node \`${e.missingNodeId}\``)}t.validation.orphanNodes.length>0&&n.push(`- **Orphan nodes**: ${t.validation.orphanNodes.map(e=>`\`${e}\``).join(`, `)}`)}if(t.communities){n.push(`
|
|
5
|
+
### Communities`);for(let[e,r]of Object.entries(t.communities))n.push(`- **${e}**: ${r.length} node(s) — ${r.slice(0,5).map(e=>`\`${e}\``).join(`, `)}${r.length>5?`…`:``}`)}if(t.process&&(n.push(`
|
|
6
|
+
### Process`),n.push(`- **${t.process.label}** (id: \`${t.process.id}\`)`),n.push(`- Entry: \`${t.process.entryNodeId}\``),n.push(`- Steps: ${t.process.steps.map(e=>`\`${e}\``).join(` → `)}`)),t.processes&&t.processes.length>0){n.push(`
|
|
7
|
+
### Processes`);for(let e of t.processes)n.push(`- **${e.label}** (id: \`${e.id}\`) — ${e.steps.length} step(s)`)}if(t.depthGroups){n.push(`
|
|
8
|
+
### Depth Groups`);for(let[e,r]of Object.entries(t.depthGroups))n.push(`- **Depth ${e}**: ${r.map(e=>`${e.name} (${e.type})`).join(`, `)}`)}if(t.cohesionScore!==void 0&&n.push(`\n**Cohesion Score**: ${(t.cohesionScore*100).toFixed(1)}%`),t.symbol360){let e=t.symbol360;n.push(`
|
|
9
|
+
### 360° Symbol View`),n.push(`- **Node**: ${e.node.name} (${e.node.type})`),n.push(`- **Community**: ${e.community??`none`}`),n.push(`- **Incoming**: ${e.incoming.length} edge(s)`),n.push(`- **Outgoing**: ${e.outgoing.length} edge(s)`),n.push(`- **Processes**: ${e.processes.length}`)}return n.push("\n---\n_Next: Use `graph(traverse)` to explore connections, `graph(add)` to insert entities, `graph(symbol360)` for full node context, or `graph(detect_communities)` to find clusters._"),{content:[{type:`text`,text:n.join(`
|
|
5
10
|
`)}],structuredContent:{nodes:(t.nodes??[]).map(e=>({id:e.id,name:e.name,type:e.type,...e.sourcePath?{sourcePath:e.sourcePath}:{}})),edges:(t.edges??[]).map(e=>({fromId:e.fromId,toId:e.toId,type:e.type})),totalNodes:t.stats?.nodeCount??t.nodes?.length??0,totalEdges:t.stats?.edgeCount??t.edges?.length??0,query:e.action}}}catch(e){return o.error(`Graph query failed`,i(e)),{content:[{type:`text`,text:`Graph query failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}export{l as registerGraphTool};
|