@vpxa/aikit 0.1.1 → 0.1.3

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.
Files changed (150) hide show
  1. package/README.md +8 -8
  2. package/package.json +1 -1
  3. package/packages/aikit-client/dist/types.d.ts +3 -3
  4. package/packages/cli/dist/aikit-init.d.ts +1 -1
  5. package/packages/cli/dist/aikit-init.js +1 -1
  6. package/packages/cli/dist/commands/context-cmds.js +1 -1
  7. package/packages/cli/dist/commands/environment.js +1 -1
  8. package/packages/cli/dist/commands/init/config.d.ts +1 -1
  9. package/packages/cli/dist/commands/init/config.js +2 -2
  10. package/packages/cli/dist/commands/init/constants.d.ts +3 -3
  11. package/packages/cli/dist/commands/init/index.d.ts +4 -4
  12. package/packages/cli/dist/commands/init/index.js +4 -4
  13. package/packages/cli/dist/commands/init/templates.js +12 -12
  14. package/packages/cli/dist/commands/init/user.d.ts +3 -3
  15. package/packages/cli/dist/commands/init/user.js +2 -2
  16. package/packages/cli/dist/commands/search.js +1 -1
  17. package/packages/cli/dist/commands/system.js +4 -4
  18. package/packages/cli/dist/commands/upgrade.js +1 -1
  19. package/packages/cli/dist/commands/workspace.js +1 -1
  20. package/packages/cli/dist/helpers.js +1 -1
  21. package/packages/cli/dist/index.d.ts +1 -1
  22. package/packages/core/dist/constants.d.ts +3 -3
  23. package/packages/core/dist/global-registry.d.ts +7 -1
  24. package/packages/core/dist/global-registry.js +1 -1
  25. package/packages/core/dist/index.d.ts +2 -2
  26. package/packages/core/dist/index.js +1 -1
  27. package/packages/core/dist/types.d.ts +6 -2
  28. package/packages/dashboard/dist/assets/{index-BjA4YODs.js → index-CO2S9BKY.js} +2 -2
  29. package/packages/dashboard/dist/assets/index-CO2S9BKY.js.map +1 -0
  30. package/packages/dashboard/dist/index.html +2 -2
  31. package/packages/enterprise-bridge/dist/er-client.d.ts +1 -1
  32. package/packages/flows/dist/git.js +1 -1
  33. package/packages/flows/dist/registry.d.ts +3 -3
  34. package/packages/flows/dist/registry.js +1 -1
  35. package/packages/flows/dist/symlinks.js +1 -1
  36. package/packages/indexer/dist/filesystem-crawler.js +1 -1
  37. package/packages/indexer/dist/hash-cache.js +1 -1
  38. package/packages/indexer/dist/incremental-indexer.js +1 -1
  39. package/packages/kb-client/dist/direct-client.d.ts +37 -0
  40. package/packages/kb-client/dist/direct-client.js +1 -0
  41. package/packages/kb-client/dist/index.d.ts +5 -0
  42. package/packages/kb-client/dist/index.js +1 -0
  43. package/packages/kb-client/dist/mcp-client.d.ts +19 -0
  44. package/packages/kb-client/dist/mcp-client.js +4 -0
  45. package/packages/kb-client/dist/parsers.d.ts +35 -0
  46. package/packages/kb-client/dist/parsers.js +2 -0
  47. package/packages/kb-client/dist/types.d.ts +62 -0
  48. package/packages/kb-client/dist/types.js +1 -0
  49. package/packages/present/dist/index.html +28 -28
  50. package/packages/server/dist/background-task.d.ts +47 -0
  51. package/packages/server/dist/background-task.js +1 -0
  52. package/packages/server/dist/config.js +1 -1
  53. package/packages/server/dist/idle-timer.d.ts +33 -0
  54. package/packages/server/dist/idle-timer.js +1 -0
  55. package/packages/server/dist/index.js +1 -1
  56. package/packages/server/dist/memory-monitor.d.ts +37 -0
  57. package/packages/server/dist/memory-monitor.js +1 -0
  58. package/packages/server/dist/prompts.js +5 -5
  59. package/packages/server/dist/resource-links.d.ts +1 -1
  60. package/packages/server/dist/resource-links.js +1 -1
  61. package/packages/server/dist/resources/curated-resources.d.ts +2 -2
  62. package/packages/server/dist/resources/curated-resources.js +2 -2
  63. package/packages/server/dist/resources/resource-notifier.d.ts +1 -1
  64. package/packages/server/dist/resources/resource-notifier.js +1 -1
  65. package/packages/server/dist/resources/resources.js +1 -1
  66. package/packages/server/dist/server.d.ts +4 -2
  67. package/packages/server/dist/server.js +3 -3
  68. package/packages/server/dist/tool-metadata.d.ts +1 -1
  69. package/packages/server/dist/tool-metadata.js +1 -1
  70. package/packages/server/dist/tool-timeout.d.ts +27 -0
  71. package/packages/server/dist/tool-timeout.js +1 -0
  72. package/packages/server/dist/tools/bridge.tools.d.ts +1 -1
  73. package/packages/server/dist/tools/bridge.tools.js +3 -3
  74. package/packages/server/dist/tools/config.tool.d.ts +8 -0
  75. package/packages/server/dist/tools/config.tool.js +12 -0
  76. package/packages/server/dist/tools/evolution.tools.js +1 -1
  77. package/packages/server/dist/tools/flow.tools.js +1 -1
  78. package/packages/server/dist/tools/infra.tools.js +1 -1
  79. package/packages/server/dist/tools/onboard.tool.js +1 -1
  80. package/packages/server/dist/tools/present/browser.js +9 -9
  81. package/packages/server/dist/tools/present/tool.js +4 -4
  82. package/packages/server/dist/tools/reindex.tool.js +1 -1
  83. package/packages/server/dist/tools/search.tool.js +4 -4
  84. package/packages/server/dist/tools/status.tool.d.ts +1 -1
  85. package/packages/server/dist/tools/status.tool.js +3 -3
  86. package/packages/store/dist/sqlite-graph-store.d.ts +3 -0
  87. package/packages/store/dist/sqlite-graph-store.js +3 -3
  88. package/packages/tools/dist/checkpoint.js +1 -1
  89. package/packages/tools/dist/config-extractor.js +1 -1
  90. package/packages/tools/dist/evidence-map.js +1 -1
  91. package/packages/tools/dist/find.d.ts +1 -1
  92. package/packages/tools/dist/forge-ground.d.ts +1 -1
  93. package/packages/tools/dist/guide.js +1 -1
  94. package/packages/tools/dist/lane.js +1 -1
  95. package/packages/tools/dist/onboard.d.ts +2 -2
  96. package/packages/tools/dist/onboard.js +2 -2
  97. package/packages/tools/dist/queue.js +1 -1
  98. package/packages/tools/dist/replay.js +1 -1
  99. package/packages/tools/dist/response-envelope.d.ts +1 -1
  100. package/packages/tools/dist/restore-points.js +1 -1
  101. package/packages/tools/dist/schema-validate.js +1 -1
  102. package/packages/tools/dist/snippet.js +1 -1
  103. package/packages/tools/dist/stash.js +1 -1
  104. package/packages/tools/dist/synthesis-engine.js +2 -2
  105. package/packages/tools/dist/workset.js +1 -1
  106. package/packages/tui/dist/{App-DU2KEylW.js → App-DpjN3iS-.js} +1 -1
  107. package/packages/tui/dist/App.d.ts +1 -1
  108. package/packages/tui/dist/App.js +1 -1
  109. package/packages/tui/dist/LogPanel-Db-SeZhR.js +3 -0
  110. package/packages/tui/dist/hooks/useKBClient.d.ts +1 -1
  111. package/packages/tui/dist/{index-BXafekwr.d.ts → index-MXJeXmCf.d.ts} +3 -3
  112. package/packages/tui/dist/index.d.ts +1 -1
  113. package/packages/tui/dist/index.js +1 -1
  114. package/packages/tui/dist/panels/LogPanel.js +1 -1
  115. package/scaffold/README.md +192 -192
  116. package/scaffold/definitions/bodies.mjs +16 -16
  117. package/scaffold/definitions/plugins.mjs +1 -1
  118. package/scaffold/definitions/prompts.mjs +6 -6
  119. package/scaffold/definitions/protocols.mjs +12 -12
  120. package/scaffold/definitions/tools.mjs +1 -1
  121. package/scaffold/flows/aikit-advanced/skills/execute/SKILL.md +124 -124
  122. package/scaffold/flows/aikit-advanced/skills/plan/SKILL.md +100 -100
  123. package/scaffold/flows/aikit-advanced/skills/spec/SKILL.md +100 -100
  124. package/scaffold/flows/aikit-advanced/skills/task/SKILL.md +99 -99
  125. package/scaffold/flows/aikit-advanced/skills/verify/SKILL.md +122 -122
  126. package/scaffold/flows/aikit-basic/skills/assess/SKILL.md +82 -82
  127. package/scaffold/flows/aikit-basic/skills/implement/SKILL.md +105 -105
  128. package/scaffold/flows/aikit-basic/skills/verify/SKILL.md +96 -96
  129. package/scaffold/general/agents/Debugger.agent.md +2 -2
  130. package/scaffold/general/agents/Documenter.agent.md +2 -2
  131. package/scaffold/general/agents/Explorer.agent.md +2 -2
  132. package/scaffold/general/agents/Frontend.agent.md +1 -1
  133. package/scaffold/general/agents/Implementer.agent.md +2 -2
  134. package/scaffold/general/agents/Orchestrator.agent.md +1 -1
  135. package/scaffold/general/agents/Planner.agent.md +2 -2
  136. package/scaffold/general/agents/Refactor.agent.md +2 -2
  137. package/scaffold/general/agents/Security.agent.md +2 -2
  138. package/scaffold/general/agents/_shared/architect-reviewer-base.md +1 -1
  139. package/scaffold/general/agents/_shared/code-agent-base.md +6 -6
  140. package/scaffold/general/agents/_shared/code-reviewer-base.md +1 -1
  141. package/scaffold/general/agents/_shared/forge-protocol.md +1 -1
  142. package/scaffold/general/agents/_shared/researcher-base.md +3 -3
  143. package/scaffold/general/prompts/ask.prompt.md +4 -4
  144. package/scaffold/general/prompts/debug.prompt.md +1 -1
  145. package/scaffold/general/prompts/plan.prompt.md +1 -1
  146. package/scaffold/general/skills/aikit/SKILL.md +5 -5
  147. package/scaffold/general/skills/multi-agents-development/SKILL.md +435 -435
  148. package/scaffold/general/skills/present/SKILL.md +424 -424
  149. package/packages/dashboard/dist/assets/index-BjA4YODs.js.map +0 -1
  150. package/packages/tui/dist/LogPanel-Bo8a8QXB.js +0 -3
@@ -0,0 +1,47 @@
1
+ //#region packages/server/src/background-task.d.ts
2
+ /**
3
+ * Background task scheduler — runs heavy operations without blocking MCP request handling.
4
+ *
5
+ * Instead of worker_threads (which would duplicate ~200 MB+ ONNX models per thread),
6
+ * this scheduler:
7
+ * 1. Queues tasks and runs them sequentially (prevents OOM from parallel heavy ops)
8
+ * 2. Provides `yieldToEventLoop()` that heavy loops can call between iterations to
9
+ * keep the MCP JSON-RPC transport responsive
10
+ * 3. Tracks running/pending state for status reporting
11
+ *
12
+ * Why not worker_threads?
13
+ * - ONNX WASM model (~200 MB) must be loaded per thread — doubles memory
14
+ * - tree-sitter WASM and sql.js WASM cannot be shared across threads
15
+ * - The existing adaptive-concurrency indexer already parallelises I/O within the main thread
16
+ */
17
+ interface BackgroundTask {
18
+ name: string;
19
+ fn: () => Promise<void>;
20
+ }
21
+ /**
22
+ * Yield control to the event loop so pending I/O (MCP transport, timers)
23
+ * can be processed. Call this inside tight loops that would otherwise
24
+ * starve the event loop (e.g., embedding 500 chunks in a row).
25
+ *
26
+ * Cost: ~1 ms per call on most systems — negligible for batch work when
27
+ * called every 10-50 iterations.
28
+ */
29
+ declare function yieldToEventLoop(): Promise<void>;
30
+ declare class BackgroundTaskScheduler {
31
+ private readonly queue;
32
+ private running;
33
+ /** Whether a task is currently executing. */
34
+ get isRunning(): boolean;
35
+ /** Name of the currently running task, or null. */
36
+ get currentTask(): string | null;
37
+ /** Number of tasks waiting in the queue. */
38
+ get pendingCount(): number;
39
+ /**
40
+ * Enqueue a task. Returns a Promise that resolves when the task completes
41
+ * (or rejects if it throws). Tasks run sequentially in FIFO order.
42
+ */
43
+ schedule(task: BackgroundTask): Promise<void>;
44
+ private processQueue;
45
+ }
46
+ //#endregion
47
+ export { BackgroundTask, BackgroundTaskScheduler, yieldToEventLoop };
@@ -0,0 +1 @@
1
+ import{createLogger as e}from"../../core/dist/index.js";const t=e(`background-task`);function n(){return new Promise(e=>setImmediate(e))}var r=class{queue=[];running=null;get isRunning(){return this.running!==null}get currentTask(){return this.running}get pendingCount(){return this.queue.length}schedule(e){return new Promise((t,n)=>{this.queue.push({...e,resolve:t,reject:n}),this.running||this.processQueue()})}async processQueue(){for(;this.queue.length>0;){let e=this.queue.shift();if(!e)break;this.running=e.name,t.info(`Background task started`,{task:e.name,pending:this.queue.length});let n=Date.now();try{await e.fn();let r=Date.now()-n;t.info(`Background task completed`,{task:e.name,durationMs:r}),e.resolve()}catch(r){let i=Date.now()-n;t.error(`Background task failed`,{task:e.name,durationMs:i,err:r}),e.reject(r instanceof Error?r:Error(String(r)))}}this.running=null}};export{r as BackgroundTaskScheduler,n as yieldToEventLoop};
@@ -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(),`kb.config.json`))?r(process.cwd(),`kb.config.json`):r(d,`..`,`..`,`..`,`kb.config.json`));try{if(!e(i))return f.info(`No config file found, using defaults`,{configPath:i}),h();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`);let c=n(i);return s.sources=s.sources.map(e=>({...e,path:p(r(c,e.path),c,`source`)})),s.store.path=p(r(c,s.store.path),c,`store`),s.curated=s.curated??{path:a.aiCurated},s.curated.path=p(r(c,s.curated.path),c,`curated`),g(s,c),s}catch(e){return f.error(`Failed to load config`,{configPath:i,...u(e)}),f.warn(`Falling back to default configuration`,{configPath:i}),h()}}function h(){let e=process.env.AIKIT_WORKSPACE_ROOT??process.cwd(),t={sources:[{path:e,excludePatterns:[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],serverName:`knowledge-base`,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)};return g(t,e),t}function g(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.curated||={path:r(n,a.aiCurated)}}function _(e,t){f.info(`Reconfiguring for workspace root`,{workspaceRoot:t});try{process.chdir(t),f.info(`Changed process cwd to workspace root`,{cwd:process.cwd()})}catch(e){f.warn(`Failed to chdir to workspace root`,{workspaceRoot:t,...u(e)})}e.sources=[{path:t,excludePatterns:e.sources[0]?.excludePatterns??[`node_modules/**`,`dist/**`,`.git/**`,`coverage/**`,`*.lock`,`pnpm-lock.yaml`]}],e.store.path=r(t,a.data),e.curated={path:r(t,a.aiCurated)},e.onboardDir=r(t,a.aiKb),g(e,t)}export{m as loadConfig,_ as reconfigureForWorkspace};
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}),h();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`);let c=n(i);return s.sources=s.sources.map(e=>({...e,path:p(r(c,e.path),c,`source`)})),s.store.path=p(r(c,s.store.path),c,`store`),s.curated=s.curated??{path:a.aiCurated},s.curated.path=p(r(c,s.curated.path),c,`curated`),g(s,c),s}catch(e){return f.error(`Failed to load config`,{configPath:i,...u(e)}),f.warn(`Falling back to default configuration`,{configPath:i}),h()}}function h(){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`,autoIndex:!1,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 g(t,e),t}function g(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 _(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),g(t,n)}export{m as loadConfig,_ as reconfigureForWorkspace};
@@ -0,0 +1,33 @@
1
+ //#region packages/server/src/idle-timer.d.ts
2
+ /**
3
+ * Resource lifecycle manager — tracks tool activity and closes idle resources.
4
+ *
5
+ * When no tool has been invoked for `idleMs`, the manager calls the registered
6
+ * cleanup callbacks. Resources are re-initialised lazily on next tool call.
7
+ */
8
+ interface IdleTimerOptions {
9
+ /** Milliseconds of inactivity before cleanup fires. @default 300_000 */
10
+ idleMs?: number;
11
+ }
12
+ declare class IdleTimer {
13
+ private timer;
14
+ private readonly cleanupFns;
15
+ private readonly idleMs;
16
+ private disposed;
17
+ /** When true, cleanup is suppressed (e.g. during long-running indexing). */
18
+ private _busy;
19
+ constructor(opts?: IdleTimerOptions);
20
+ /** Mark the server as busy (suppresses idle cleanup while true). */
21
+ setBusy(busy: boolean): void;
22
+ /** Register a cleanup callback that runs when idle threshold is reached. */
23
+ onIdle(fn: () => void | Promise<void>): void;
24
+ /** Call this on every tool invocation to reset the idle countdown. */
25
+ touch(): void;
26
+ /** Cancel the pending idle timer without running cleanup. */
27
+ cancel(): void;
28
+ /** Stop the timer permanently and release all callbacks. */
29
+ dispose(): void;
30
+ private runCleanup;
31
+ }
32
+ //#endregion
33
+ export { IdleTimer, IdleTimerOptions };
@@ -0,0 +1 @@
1
+ import{createLogger as e}from"../../core/dist/index.js";const t=e(`idle-timer`);var n=class{timer=null;cleanupFns=[];idleMs;disposed=!1;_busy=!1;constructor(e){this.idleMs=e?.idleMs??3e5}setBusy(e){this._busy=e,e?this.cancel():this.touch()}onIdle(e){this.cleanupFns.push(e)}touch(){this.disposed||this._busy||(this.cancel(),this.timer=setTimeout(()=>{this.runCleanup()},this.idleMs),this.timer.unref&&this.timer.unref())}cancel(){this.timer&&=(clearTimeout(this.timer),null)}dispose(){this.cancel(),this.cleanupFns.length=0,this.disposed=!0}async runCleanup(){if(this._busy){t.info(`Skipping idle cleanup — background work in progress`);return}t.info(`Idle for ${this.idleMs/1e3}s — running cleanup`);let e=await Promise.allSettled(this.cleanupFns.map(e=>e()));for(let n of e)n.status===`rejected`&&t.warn(`Idle cleanup callback failed`,{error:String(n.reason)})}};export{n as IdleTimer};
@@ -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 Knowledge Base server`,{version:c}),u.transport===`http`){let[{default:e},{loadConfig:t},{registerDashboardRoutes:n,resolveDashboardDir:r}]=await Promise.all([import(`express`),import(`./config.js`),import(`./dashboard-static.js`)]),i=t();l.info(`Config loaded`,{sourceCount:i.sources.length,storePath:i.store.path});let o=e();o.use(e.json());let s=Number(u.port);o.use((e,t,n)=>{if(t.setHeader(`Access-Control-Allow-Origin`,process.env.AIKIT_CORS_ORIGIN??`http://localhost:${s}`),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()}),n(o,r(),l),o.get(`/health`,(e,t)=>{t.json({status:`ok`})});let c=!1,d=null,f=null,p=Promise.resolve();o.post(`/mcp`,async(e,t)=>{if(!c||!d||!f){t.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let n=p,r;p=new Promise(e=>{r=e}),await n;try{let n=new f({sessionIdGenerator:void 0});await d.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()}}),o.get(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))}),o.delete(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))});let m=o.listen(s,`127.0.0.1`,()=>{l.info(`MCP server listening`,{url:`http://127.0.0.1:${s}/mcp`,port:s}),setTimeout(async()=>{try{let[{createLazyServer:e,ALL_TOOL_NAMES:t},{StreamableHTTPServerTransport:n},{checkForUpdates:r,autoUpgradeScaffold:o}]=await Promise.all([import(`./server.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check.js`)]);r(),o();let s=e(i);d=s.server,f=n,c=!0,l.info(`MCP server configured (lazy — KB initializing in background)`,{toolCount:t.length,resourceCount:2}),s.startInit(),process.env.AIKIT_AUTO_INDEX===`true`?s.ready.then(async()=>{try{let e=i.sources.map(e=>e.path).join(`, `);l.info(`Running initial index`,{sourcePaths:e}),await s.runInitialIndex(),l.info(`Initial index complete`)}catch(e){l.error(`Initial index failed; will retry on aikit_reindex`,a(e))}}).catch(e=>l.error(`KB init or indexing failed`,a(e))):(s.ready.catch(e=>l.error(`KB initialization failed`,a(e))),l.info(`Auto-index disabled in HTTP mode (set AIKIT_AUTO_INDEX=true to enable)`))}catch(e){l.error(`Failed to load server modules`,a(e))}},100)}),h=async e=>{l.info(`Shutdown signal received`,{signal:e}),m.close(),d&&await d.close(),process.exit(0)};process.on(`SIGINT`,()=>h(`SIGINT`)),process.on(`SIGTERM`,()=>h(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t},{createLazyServer:n},{checkForUpdates:i,autoUpgradeScaffold:o},{RootsListChangedNotificationSchema:s}]=await Promise.all([import(`./config.js`),import(`./server.js`),import(`./version-check.js`),import(`@modelcontextprotocol/sdk/types.js`)]),c=e();l.info(`Config loaded`,{sourceCount:c.sources.length,storePath:c.store.path}),i(),o();let{server:u,startInit:d,ready:f,runInitialIndex:p}=n(c),{StdioServerTransport:m}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),h=new m;await u.connect(h),l.info(`MCP server started`,{transport:`stdio`});let g=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(c,i),!0},_=!1;try{_=g((await u.server.listRoots()).roots),_||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)}),_=!0}_||=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);u.server.setNotificationHandler(s,async()=>{clearTimeout(t);try{e(g((await u.server.listRoots()).roots))}catch(t){l.warn(`roots/list retry failed after notification`,a(t)),e(!1)}})}),d(),f.catch(e=>{l.error(`Initialization failed — server will continue with limited tools`,a(e))}),process.env.AIKIT_AUTO_INDEX===`false`?l.warn(`Auto-index disabled; use aikit_reindex to index manually`):p().catch(e=>l.error(`Initial index failed`,a(e)))}}d().catch(e=>{l.error(`Fatal error`,a(e)),process.exit(1)});export{};
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:n,resolveDashboardDir:r}]=await Promise.all([import(`express`),import(`./config.js`),import(`./dashboard-static.js`)]),i=t();l.info(`Config loaded`,{sourceCount:i.sources.length,storePath:i.store.path});let o=e();o.use(e.json());let s=Number(u.port);o.use((e,t,n)=>{if(t.setHeader(`Access-Control-Allow-Origin`,process.env.AIKIT_CORS_ORIGIN??`http://localhost:${s}`),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()}),n(o,r(),l),o.get(`/health`,(e,t)=>{t.json({status:`ok`})});let c=!1,d=null,f=null,p=Promise.resolve();o.post(`/mcp`,async(e,t)=>{if(!c||!d||!f){t.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let n=p,r;p=new Promise(e=>{r=e}),await n;try{let n=new f({sessionIdGenerator:void 0});await d.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()}}),o.get(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))}),o.delete(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))});let m=o.listen(s,`127.0.0.1`,()=>{l.info(`MCP server listening`,{url:`http://127.0.0.1:${s}/mcp`,port:s}),setTimeout(async()=>{try{let[{createLazyServer:e,ALL_TOOL_NAMES:t},{StreamableHTTPServerTransport:n},{checkForUpdates:r,autoUpgradeScaffold:o}]=await Promise.all([import(`./server.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check.js`)]);r(),o();let s=e(i);d=s.server,f=n,c=!0,l.info(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:t.length,resourceCount:2}),s.startInit(),process.env.AIKIT_AUTO_INDEX===`true`?s.ready.then(async()=>{try{let e=i.sources.map(e=>e.path).join(`, `);l.info(`Running initial index`,{sourcePaths:e}),await s.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))):(s.ready.catch(e=>l.error(`AI Kit initialization failed`,a(e))),l.info(`Auto-index disabled in HTTP mode (set AIKIT_AUTO_INDEX=true to enable)`))}catch(e){l.error(`Failed to load server modules`,a(e))}},100)}),h=async e=>{l.info(`Shutdown signal received`,{signal:e}),m.close(),d&&await d.close(),process.exit(0)};process.on(`SIGINT`,()=>h(`SIGINT`)),process.on(`SIGTERM`,()=>h(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t},{createLazyServer:n},{checkForUpdates:i,autoUpgradeScaffold:o},{RootsListChangedNotificationSchema:s}]=await Promise.all([import(`./config.js`),import(`./server.js`),import(`./version-check.js`),import(`@modelcontextprotocol/sdk/types.js`)]),c=e();l.info(`Config loaded`,{sourceCount:c.sources.length,storePath:c.store.path}),i(),o();let{server:u,startInit:d,ready:f,runInitialIndex:p}=n(c),{StdioServerTransport:m}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),h=new m;await u.connect(h),l.info(`MCP server started`,{transport:`stdio`});let g=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(c,i),!0},_=!1;try{_=g((await u.server.listRoots()).roots),_||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)}),_=!0}_||=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);u.server.setNotificationHandler(s,async()=>{clearTimeout(t);try{e(g((await u.server.listRoots()).roots))}catch(t){l.warn(`roots/list retry failed after notification`,a(t)),e(!1)}})}),d();let v=null,y=()=>{v&&clearTimeout(v),v=setTimeout(()=>{l.info(`Auto-shutdown: no activity for 30 minutes — exiting`),process.exit(0)},18e5),v.unref&&v.unref()};y(),process.stdin.on(`data`,()=>y()),f.catch(e=>{l.error(`Initialization failed — server will continue with limited tools`,a(e))}),process.env.AIKIT_AUTO_INDEX===`true`||process.env.AIKIT_AUTO_INDEX===void 0&&c.autoIndex===!0?p().catch(e=>l.error(`Initial index failed`,a(e))):l.warn(`Auto-index disabled; use aikit_reindex to index manually`)}}d().catch(e=>{l.error(`Fatal error`,a(e)),process.exit(1)});export{};
@@ -0,0 +1,37 @@
1
+ //#region packages/server/src/memory-monitor.d.ts
2
+ /**
3
+ * Memory monitor — periodically checks RSS and logs warnings when thresholds are exceeded.
4
+ *
5
+ * Also exposes `getRssBytes()` for on-demand checks and a `onPressure` callback
6
+ * for triggering cache eviction or GC hints when memory is high.
7
+ */
8
+ interface MemoryMonitorOptions {
9
+ /** RSS bytes above which a warning is logged. @default 4 GB */
10
+ warningBytes?: number;
11
+ /** RSS bytes above which pressure callbacks fire. @default 8 GB */
12
+ criticalBytes?: number;
13
+ /** Polling interval in milliseconds. @default 60 000 */
14
+ intervalMs?: number;
15
+ }
16
+ type PressureLevel = 'normal' | 'warning' | 'critical';
17
+ declare class MemoryMonitor {
18
+ private timer;
19
+ private readonly warningBytes;
20
+ private readonly criticalBytes;
21
+ private readonly intervalMs;
22
+ private readonly pressureFns;
23
+ private lastLevel;
24
+ constructor(opts?: MemoryMonitorOptions);
25
+ /** Register a callback for memory pressure events. */
26
+ onPressure(fn: (level: PressureLevel, rssBytes: number) => void): void;
27
+ /** Start periodic monitoring. */
28
+ start(): void;
29
+ /** Stop monitoring. */
30
+ stop(): void;
31
+ /** Return current RSS in bytes. */
32
+ getRssBytes(): number;
33
+ /** Run a single check. */
34
+ check(): PressureLevel;
35
+ }
36
+ //#endregion
37
+ export { MemoryMonitor, MemoryMonitorOptions, PressureLevel };
@@ -0,0 +1 @@
1
+ import{createLogger as e}from"../../core/dist/index.js";const t=e(`memory-monitor`);var n=class{timer=null;warningBytes;criticalBytes;intervalMs;pressureFns=[];lastLevel=`normal`;constructor(e){this.warningBytes=e?.warningBytes??4294967296,this.criticalBytes=e?.criticalBytes??8589934592,this.intervalMs=e?.intervalMs??6e4}onPressure(e){this.pressureFns.push(e)}start(){this.timer||(this.timer=setInterval(()=>this.check(),this.intervalMs),this.timer.unref&&this.timer.unref(),t.info(`Memory monitor started`,{warningMB:Math.round(this.warningBytes/1024/1024),criticalMB:Math.round(this.criticalBytes/1024/1024),intervalSec:Math.round(this.intervalMs/1e3)}))}stop(){this.timer&&=(clearInterval(this.timer),null)}getRssBytes(){return process.memoryUsage.rss()}check(){let e=this.getRssBytes(),n=`normal`;if(e>=this.criticalBytes?n=`critical`:e>=this.warningBytes&&(n=`warning`),n!==this.lastLevel||n===`critical`){let r=Math.round(e/1024/1024);n===`critical`?t.warn(`Memory CRITICAL: ${r}MB RSS — consider restarting the server`):n===`warning`?t.warn(`Memory WARNING: ${r}MB RSS`):this.lastLevel!==`normal`&&t.info(`Memory returned to normal: ${r}MB RSS`),this.lastLevel=n}if(n!==`normal`)for(let t of this.pressureFns)try{t(n,e)}catch{}return n===`critical`&&typeof globalThis.gc==`function`&&globalThis.gc(),n}};export{n as MemoryMonitor};
@@ -1,11 +1,11 @@
1
- import{completeCheckpointNames as e,completeCuratedPaths as t,completeFilePaths as n,completeStashKeys as r,completeSymbolNames as i,completeWorksetNames as a}from"./completions.js";import{completable as o}from"@modelcontextprotocol/sdk/server/completable.js";import{z as s}from"zod";function c(c,l){if(c.registerPrompt(`ready`,{title:`KB Ready`,description:`Knowledge base is ready — quick-start guide for search, onboard, and workflows`},async()=>({messages:[{role:`user`,content:{type:`text`,text:[`Knowledge base is ready. Quick start:`,``,'• **New project?** → `onboard({ path: "." })` for full codebase analysis','• **Returning?** → `status({})` then `search({ query: "SESSION CHECKPOINT", origin: "curated" })`','• **Exploring?** → `guide({ goal: "your task" })` for workflow recommendations','• **Quick lookup?** → `search({ query: "your question" })`'].join(`
1
+ import{completeCheckpointNames as e,completeCuratedPaths as t,completeFilePaths as n,completeStashKeys as r,completeSymbolNames as i,completeWorksetNames as a}from"./completions.js";import{completable as o}from"@modelcontextprotocol/sdk/server/completable.js";import{z as s}from"zod";function c(c,l){if(c.registerPrompt(`ready`,{title:`AI Kit Ready`,description:`AI Kit is ready — quick-start guide for search, onboard, and workflows`},async()=>({messages:[{role:`user`,content:{type:`text`,text:[`AI Kit is ready. Quick start:`,``,'• **New project?** → `onboard({ path: "." })` for full codebase analysis','• **Returning?** → `status({})` then `search({ query: "SESSION CHECKPOINT", origin: "curated" })`','• **Exploring?** → `guide({ goal: "your task" })` for workflow recommendations','• **Quick lookup?** → `search({ query: "your question" })`'].join(`
2
2
  `)}}]})),c.registerPrompt(`onboard`,{title:`Onboard Codebase`,description:`Analyze the codebase for first-time onboarding — runs all analyzers and produces a knowledge summary`,argsSchema:{path:s.string().optional().describe(`Path to analyze (default: workspace root)`)}},async({path:e})=>({messages:[{role:`user`,content:{type:`text`,text:[`Run the full onboarding workflow for "${e??`.`}"`,``,`1. \`onboard({ path: "${e??`.`}" })\` — full codebase analysis`,`2. \`produce_knowledge({ path: "${e??`.`}" })\` — generate synthesis`,"3. `remember` key findings as curated entries","4. `status` to verify index health"].join(`
3
- `)}}]})),c.registerPrompt(`sessionStart`,{title:`Start KB Session`,description:`Initialize a KB session — check status, list knowledge, and resume from last checkpoint`},async()=>({messages:[{role:`user`,content:{type:`text`,text:[`Run the session start protocol:`,``,"1. `status({})` — check KB health and onboard state","2. `list()` — see stored knowledge entries",'3. `search({ query: "SESSION CHECKPOINT", origin: "curated" })` — resume prior work'].join(`
4
- `)}}]})),c.registerPrompt(`sessionEnd`,{title:`End KB Session`,description:`Persist decisions and create a session checkpoint before ending`,argsSchema:{summary:s.string().describe(`Brief summary of decisions made, blockers encountered, and next steps`)}},async({summary:e})=>({messages:[{role:`user`,content:{type:`text`,text:[`Run the session end protocol:`,``,'1. `remember({ title: "Session checkpoint: '+e.slice(0,60)+`...", content: "`+e.replace(/"/g,`\\"`)+'", category: "conventions" })` — persist findings',"2. `reindex({})` — refresh search index if files changed",`3. Confirm session data saved`].join(`
5
- `)}}]})),c.registerPrompt(`search`,{title:`Search Knowledge Base`,description:`Search the knowledge base with hybrid semantic + keyword search`,argsSchema:{query:s.string().describe(`Search query`)}},async({query:e})=>({messages:[{role:`user`,content:{type:`text`,text:`Search the knowledge base for: "${e}"\n\nUse \`search({ query: "${e.replace(/"/g,`\\"`)}" })\` to find relevant code, documentation, and curated knowledge.`}}]})),c.registerPrompt(`remember`,{title:`Remember Knowledge`,description:`Store a decision, convention, or finding as curated knowledge`,argsSchema:{title:s.string().describe(`Title of the knowledge entry`),content:s.string().describe(`Content to remember`),category:s.enum([`conventions`,`decisions`,`patterns`,`blockers`,`tasks`]).optional().describe(`Category (default: conventions)`)}},async({title:e,content:t,category:n})=>({messages:[{role:`user`,content:{type:`text`,text:`Store this knowledge:\n\n\`remember({ title: "${e.replace(/"/g,`\\"`)}", content: "${t.replace(/"/g,`\\"`).slice(0,200)}...", category: "${n??`conventions`}" })\``}}]})),c.registerPrompt(`planTask`,{title:`Plan a Task`,description:`Generate a reading plan and scope map for a development task`,argsSchema:{task:s.string().describe(`Description of the task to plan`)}},async({task:e})=>({messages:[{role:`user`,content:{type:`text`,text:[`Plan implementation for: "${e}"`,``,'1. `search({ query: "'+e.replace(/"/g,`\\"`)+'" })` — find related code and prior decisions','2. `scope_map({ task: "'+e.replace(/"/g,`\\"`)+'" })` — generate a reading plan',"3. For each recommended file, use `file_summary` then `compact` for detail","4. `blast_radius` on planned changes to assess impact"].join(`
3
+ `)}}]})),c.registerPrompt(`sessionStart`,{title:`Start AI Kit Session`,description:`Initialize an AI Kit session — check status, list knowledge, and resume from last checkpoint`},async()=>({messages:[{role:`user`,content:{type:`text`,text:[`Run the session start protocol:`,``,"1. `status({})` — check AI Kit health and onboard state","2. `list()` — see stored knowledge entries",'3. `search({ query: "SESSION CHECKPOINT", origin: "curated" })` — resume prior work'].join(`
4
+ `)}}]})),c.registerPrompt(`sessionEnd`,{title:`End AI Kit Session`,description:`Persist decisions and create a session checkpoint before ending`,argsSchema:{summary:s.string().describe(`Brief summary of decisions made, blockers encountered, and next steps`)}},async({summary:e})=>({messages:[{role:`user`,content:{type:`text`,text:[`Run the session end protocol:`,``,'1. `remember({ title: "Session checkpoint: '+e.slice(0,60)+`...", content: "`+e.replace(/"/g,`\\"`)+'", category: "conventions" })` — persist findings',"2. `reindex({})` — refresh search index if files changed",`3. Confirm session data saved`].join(`
5
+ `)}}]})),c.registerPrompt(`search`,{title:`Search AI Kit`,description:`Search AI Kit with hybrid semantic + keyword search`,argsSchema:{query:s.string().describe(`Search query`)}},async({query:e})=>({messages:[{role:`user`,content:{type:`text`,text:`Search AI Kit for: "${e}"\n\nUse \`search({ query: "${e.replace(/"/g,`\\"`)}" })\` to find relevant code, documentation, and curated knowledge.`}}]})),c.registerPrompt(`remember`,{title:`Remember Knowledge`,description:`Store a decision, convention, or finding as curated knowledge`,argsSchema:{title:s.string().describe(`Title of the knowledge entry`),content:s.string().describe(`Content to remember`),category:s.enum([`conventions`,`decisions`,`patterns`,`blockers`,`tasks`]).optional().describe(`Category (default: conventions)`)}},async({title:e,content:t,category:n})=>({messages:[{role:`user`,content:{type:`text`,text:`Store this knowledge:\n\n\`remember({ title: "${e.replace(/"/g,`\\"`)}", content: "${t.replace(/"/g,`\\"`).slice(0,200)}...", category: "${n??`conventions`}" })\``}}]})),c.registerPrompt(`planTask`,{title:`Plan a Task`,description:`Generate a reading plan and scope map for a development task`,argsSchema:{task:s.string().describe(`Description of the task to plan`)}},async({task:e})=>({messages:[{role:`user`,content:{type:`text`,text:[`Plan implementation for: "${e}"`,``,'1. `search({ query: "'+e.replace(/"/g,`\\"`)+'" })` — find related code and prior decisions','2. `scope_map({ task: "'+e.replace(/"/g,`\\"`)+'" })` — generate a reading plan',"3. For each recommended file, use `file_summary` then `compact` for detail","4. `blast_radius` on planned changes to assess impact"].join(`
6
6
  `)}}]})),c.registerPrompt(`investigate`,{title:`Investigate Bug`,description:`Bug investigation workflow — parse error, find symbols, trace data flow, assess impact`,argsSchema:{error:s.string().describe(`Error message, stack trace, or bug description`)}},async({error:e})=>({messages:[{role:`user`,content:{type:`text`,text:[`Investigate this error:`,"```",e,"```",``,`Follow the bug investigation workflow:`,"1. `parse_output({ text: <error> })` — extract structured data from the error","2. `symbol({ name: <relevant symbol> })` — find definition and references",'3. `trace({ symbol: <symbol>, direction: "backward" })` — trace data flow to find root cause',"4. `blast_radius({ changed_files: [<affected files>] })` — assess fix impact"].join(`
7
7
  `)}}]})),!l)return;let{curated:u,store:d,graphStore:f}=l;c.registerPrompt(`read_knowledge`,{title:`Read Knowledge`,description:`Read a curated knowledge entry by path — with autocomplete`,argsSchema:{path:o(s.string().describe(`Path of the curated entry (e.g. conventions/naming.md)`),async e=>t(u,e))}},async({path:e})=>({messages:[{role:`user`,content:{type:`text`,text:`Read the curated knowledge entry: \`read({ path: "${e}" })\``}}]})),c.registerPrompt(`update_knowledge`,{title:`Update Knowledge`,description:`Update an existing curated knowledge entry — with autocomplete`,argsSchema:{path:o(s.string().describe(`Path of the curated entry to update`),async e=>t(u,e)),content:s.string().describe(`New content for the entry`)}},async({path:e,content:t})=>({messages:[{role:`user`,content:{type:`text`,text:`Update the curated entry at "${e}":\n\n\`update({ path: "${e}", content: "${t.replace(/"/g,`\\"`).slice(0,200)}..." })\``}}]})),c.registerPrompt(`forget_knowledge`,{title:`Forget Knowledge`,description:`Delete a curated knowledge entry — with autocomplete`,argsSchema:{path:o(s.string().describe(`Path of the curated entry to delete`),async e=>t(u,e))}},async({path:e})=>({messages:[{role:`user`,content:{type:`text`,text:`Delete the curated entry: \`forget({ path: "${e}" })\``}}]})),c.registerPrompt(`lookup_file`,{title:`Lookup File`,description:`Look up an indexed file — with autocomplete`,argsSchema:{path:o(s.string().describe(`Source file path`),async e=>n(d,e))}},async({path:e})=>({messages:[{role:`user`,content:{type:`text`,text:`Look up the indexed file: \`file_summary({ path: "${e}" })\``}}]})),c.registerPrompt(`find_symbol`,{title:`Find Symbol`,description:`Find a symbol definition and references — with autocomplete`,argsSchema:{name:o(s.string().describe(`Symbol name`),async e=>i(f,e))}},async({name:e})=>({messages:[{role:`user`,content:{type:`text`,text:`Find symbol: \`symbol({ name: "${e}" })\``}}]})),c.registerPrompt(`get_stash`,{title:`Get Stash`,description:`Retrieve a stashed value by key — with autocomplete`,argsSchema:{key:o(s.string().describe(`Stash key`),e=>r(e))}},async({key:e})=>({messages:[{role:`user`,content:{type:`text`,text:`Get stashed value: \`stash({ action: "get", key: "${e}" })\``}}]})),c.registerPrompt(`get_workset`,{title:`Get Workset`,description:`Load a saved workset by name — with autocomplete`,argsSchema:{name:o(s.string().describe(`Workset name`),e=>a(e))}},async({name:e})=>({messages:[{role:`user`,content:{type:`text`,text:`Load workset: \`workset({ action: "load", name: "${e}" })\``}}]})),c.registerPrompt(`load_checkpoint`,{title:`Load Checkpoint`,description:`Restore a saved checkpoint by name — with autocomplete`,argsSchema:{name:o(s.string().describe(`Checkpoint name`),t=>e(t))}},async({name:e})=>({messages:[{role:`user`,content:{type:`text`,text:`Load checkpoint: \`checkpoint({ action: "load", name: "${e}" })\``}}]})),c.registerPrompt(`audit_workflow`,{title:`Audit Workflow`,description:`Run a full project quality audit: check → test_run → audit → produce recommendations`},async()=>({messages:[{role:`user`,content:{type:`text`,text:[`## Audit Workflow`,``,`Execute the following tools in sequence:`,``,"1. `check({})` — Run typecheck + lint","2. `test_run({})` — Run all tests","3. `audit({})` — Full project audit","4. Review findings and `remember` important patterns",``,`Report: pass/fail status, error counts, audit recommendations, and suggested next steps.`].join(`
8
- `)}}]})),c.registerPrompt(`refactor_workflow`,{title:`Refactor Workflow`,description:`Safe refactoring workflow: analyze → blast_radius → implement → verify`},async()=>({messages:[{role:`user`,content:{type:`text`,text:[`## Refactor Workflow`,``,`For the target files/symbols:`,``,"1. `analyze_structure({ path })` — Understand current structure","2. `analyze_dependencies({ path })` — Map dependency graph","3. `blast_radius({ changed_files })` — Assess impact scope",`4. Implement changes carefully`,"5. `check({})` + `test_run({})` — Verify nothing broke","6. `reindex({})` — Update KB with changes",``,`What would you like to refactor?`].join(`
8
+ `)}}]})),c.registerPrompt(`refactor_workflow`,{title:`Refactor Workflow`,description:`Safe refactoring workflow: analyze → blast_radius → implement → verify`},async()=>({messages:[{role:`user`,content:{type:`text`,text:[`## Refactor Workflow`,``,`For the target files/symbols:`,``,"1. `analyze_structure({ path })` — Understand current structure","2. `analyze_dependencies({ path })` — Map dependency graph","3. `blast_radius({ changed_files })` — Assess impact scope",`4. Implement changes carefully`,"5. `check({})` + `test_run({})` — Verify nothing broke","6. `reindex({})` — Update AI Kit with changes",``,`What would you like to refactor?`].join(`
9
9
  `)}}]})),c.registerPrompt(`forge_workflow`,{title:`FORGE Workflow`,description:`Full FORGE protocol: classify → ground → implement with quality gates`},async()=>({messages:[{role:`user`,content:{type:`text`,text:[`## FORGE Quality Gate Workflow`,``,"1. `forge_classify({ task })` — Determine complexity tier (floor/standard/critical)","2. `forge_ground({ task, files, root_path })` — Full grounding analysis",`3. Review typed unknowns and constraints`,`4. Implement with evidence tracking`,'5. `evidence_map({ action: "validate" })` — Verify all claims',"6. `check({})` + `test_run({})` — Final verification",``,`Describe the task to classify:`].join(`
10
10
  `)}}]})),c.registerPrompt(`investigate_workflow`,{title:`Investigate Issue`,description:`Bug investigation workflow: trace → analyze → find root cause → fix`},async()=>({messages:[{role:`user`,content:{type:`text`,text:[`## Bug Investigation Workflow`,``,"1. `parse_output({ output })` — Parse error messages if available","2. `symbol({ name })` — Find the failing symbol",'3. `trace({ symbol, direction: "backward" })` — Trace data flow to root cause',"4. `blast_radius({ changed_files })` — Assess impact of fix",`5. Implement fix`,"6. `check({})` + `test_run({})` — Verify fix works",``,`Describe the issue:`].join(`
11
11
  `)}}]})),c.registerPrompt(`context_workflow`,{title:`Build Context`,description:`Progressive context building: file_summary → compact → digest for deep understanding`},async()=>({messages:[{role:`user`,content:{type:`text`,text:[`## Context Building Workflow`,``,`Build understanding progressively:`,``,"1. `file_summary({ path })` — Structure overview (~50 tokens)","2. `compact({ path, query })` — Extract relevant sections (5-20x reduction)","3. `digest({ sources })` — Multi-file compressed summary","4. `stratum_card({ files })` — Reusable reference card",``,`For project-wide context:`,"- `scope_map({ task })` — Reading plan for a specific task",'- `workset({ action: "save" })` — Save working set for later',``,`What do you need to understand?`].join(`
@@ -1,7 +1,7 @@
1
1
  //#region packages/server/src/resource-links.d.ts
2
2
  /**
3
3
  * Helpers for emitting resource_link content blocks in tool results.
4
- * Centralises the `kb://curated/{path}` URI scheme so all tools stay consistent.
4
+ * Centralises the `aikit://curated/{path}` URI scheme so all tools stay consistent.
5
5
  */
6
6
  /** Shape of a resource_link content block (matches MCP SDK ResourceLink). */
7
7
  interface ResourceLinkBlock {
@@ -1 +1 @@
1
- function e(e,t,n){if(!(!e||typeof e!=`string`)&&!(e.includes(`..`)||e.startsWith(`/`)||e.startsWith(`[`)))return{type:`resource_link`,uri:`kb://curated/${e}`,name:t??e,mimeType:`text/markdown`,...n?{description:n}:{}}}function t(t){let n=new Set,r=[];for(let i of t){let t=e(i.path,i.title,i.category?`[${i.category}]`:void 0);t&&!n.has(t.uri)&&(n.add(t.uri),r.push(t))}return r}function n(e){if(e.startsWith(`.ai/curated/`))return e.slice(12)}export{e as curatedResourceLink,t as curatedResourceLinks,n as extractCuratedPath};
1
+ function e(e,t,n){if(!(!e||typeof e!=`string`)&&!(e.includes(`..`)||e.startsWith(`/`)||e.startsWith(`[`)))return{type:`resource_link`,uri:`aikit://curated/${e}`,name:t??e,mimeType:`text/markdown`,...n?{description:n}:{}}}function t(t){let n=new Set,r=[];for(let i of t){let t=e(i.path,i.title,i.category?`[${i.category}]`:void 0);t&&!n.has(t.uri)&&(n.add(t.uri),r.push(t))}return r}function n(e){if(e.startsWith(`.ai/curated/`))return e.slice(12)}export{e as curatedResourceLink,t as curatedResourceLinks,n as extractCuratedPath};
@@ -5,8 +5,8 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
5
  /**
6
6
  * Register curated knowledge as browsable MCP resources.
7
7
  *
8
- * - `kb://curated` — index listing all curated entries
9
- * - `kb://curated/{path}` — individual entry by path (e.g. `decisions/use-lancedb.md`)
8
+ * - `aikit://curated` — index listing all curated entries
9
+ * - `aikit://curated/{path}` — individual entry by path (e.g. `decisions/use-lancedb.md`)
10
10
  */
11
11
  declare function registerCuratedResources(server: McpServer, curated: CuratedKnowledgeManager): void;
12
12
  //#endregion
@@ -1,2 +1,2 @@
1
- import{ResourceTemplate as e}from"@modelcontextprotocol/sdk/server/mcp.js";function t(t,n){t.resource(`aikit-curated-index`,`kb://curated`,{description:`Index of all curated knowledge entries`,mimeType:`text/markdown`},async()=>{let e=(await n.list()).map(e=>`- [${e.title}](kb://curated/${e.path}) — ${e.category}`);return{contents:[{uri:`kb://curated`,text:`# Curated Knowledge Index\n\n${e.length>0?e.join(`
2
- `):`_No curated entries yet._`}`,mimeType:`text/markdown`}]}});let r=new e(`kb://curated/{+path}`,{list:async()=>({resources:(await n.list()).map(e=>({uri:`kb://curated/${e.path}`,name:e.title,description:`[${e.category}] ${e.contentPreview?.slice(0,80)??``}`,mimeType:`text/markdown`}))})});t.resource(`aikit-curated-entry`,r,{description:`A curated knowledge entry`,mimeType:`text/markdown`},async(e,t)=>{let r=t.path;if(!r)throw Error(`Missing path variable in curated resource URI`);let i=await n.read(r);return{contents:[{uri:e.toString(),text:`---\ntitle: ${i.title}\ncategory: ${i.category}\ntags: ${i.tags?.join(`, `)??``}\nversion: ${i.version??1}\n---\n\n${i.content??i.contentPreview??``}`,mimeType:`text/markdown`}]}})}export{t as registerCuratedResources};
1
+ import{ResourceTemplate as e}from"@modelcontextprotocol/sdk/server/mcp.js";function t(t,n){t.resource(`aikit-curated-index`,`aikit://curated`,{description:`Index of all curated knowledge entries`,mimeType:`text/markdown`},async()=>{let e=(await n.list()).map(e=>`- [${e.title}](aikit://curated/${e.path}) — ${e.category}`);return{contents:[{uri:`aikit://curated`,text:`# Curated Knowledge Index\n\n${e.length>0?e.join(`
2
+ `):`_No curated entries yet._`}`,mimeType:`text/markdown`}]}});let r=new e(`aikit://curated/{+path}`,{list:async()=>({resources:(await n.list()).map(e=>({uri:`aikit://curated/${e.path}`,name:e.title,description:`[${e.category}] ${e.contentPreview?.slice(0,80)??``}`,mimeType:`text/markdown`}))})});t.resource(`aikit-curated-entry`,r,{description:`A curated knowledge entry`,mimeType:`text/markdown`},async(e,t)=>{let r=t.path;if(!r)throw Error(`Missing path variable in curated resource URI`);let i=await n.read(r);return{contents:[{uri:e.toString(),text:`---\ntitle: ${i.title}\ncategory: ${i.category}\ntags: ${i.tags?.join(`, `)??``}\nversion: ${i.version??1}\n---\n\n${i.content??i.contentPreview??``}`,mimeType:`text/markdown`}]}})}export{t as registerCuratedResources};
@@ -5,7 +5,7 @@ declare class ResourceNotifier {
5
5
  private readonly mcpServer;
6
6
  constructor(mcpServer: McpServer);
7
7
  /**
8
- * Notify that the KB status resource has changed.
8
+ * Notify that the AI Kit status resource has changed.
9
9
  * Call after: reindex, onboard, remember, forget operations.
10
10
  */
11
11
  notifyStatusChanged(): Promise<void>;
@@ -1 +1 @@
1
- import{createLogger as e}from"../../../core/dist/index.js";const t=e(`resource-notifier`);var n=class{constructor(e){this.mcpServer=e}async notifyStatusChanged(){await this.sendUpdate(`kb://status`)}async notifyFileTreeChanged(){await this.sendUpdate(`kb://file-tree`)}async notifyCuratedIndexChanged(){await this.sendUpdate(`kb://curated`)}async notifyCuratedEntryChanged(e){await this.sendUpdate(`kb://curated/${e}`)}async notifyResourceListChanged(){try{await this.mcpServer.server.sendResourceListChanged()}catch(e){t.debug(`sendResourceListChanged failed`,{error:String(e)})}}async notifyAfterReindex(){await Promise.allSettled([this.notifyStatusChanged(),this.notifyFileTreeChanged()])}async notifyAfterCuratedWrite(e){let t=[this.notifyStatusChanged(),this.notifyCuratedIndexChanged()];e&&t.push(this.notifyCuratedEntryChanged(e)),await Promise.allSettled(t)}async sendUpdate(e){try{await this.mcpServer.server.sendResourceUpdated({uri:e})}catch(n){t.debug(`sendResourceUpdated failed`,{uri:e,error:String(n)})}}};const r={notifyStatusChanged:async()=>{},notifyFileTreeChanged:async()=>{},notifyCuratedIndexChanged:async()=>{},notifyCuratedEntryChanged:async()=>{},notifyResourceListChanged:async()=>{},notifyAfterReindex:async()=>{},notifyAfterCuratedWrite:async()=>{}};export{n as ResourceNotifier,r as noopResourceNotifier};
1
+ import{createLogger as e}from"../../../core/dist/index.js";const t=e(`resource-notifier`);var n=class{constructor(e){this.mcpServer=e}async notifyStatusChanged(){await this.sendUpdate(`aikit://status`)}async notifyFileTreeChanged(){await this.sendUpdate(`aikit://file-tree`)}async notifyCuratedIndexChanged(){await this.sendUpdate(`aikit://curated`)}async notifyCuratedEntryChanged(e){await this.sendUpdate(`aikit://curated/${e}`)}async notifyResourceListChanged(){try{await this.mcpServer.server.sendResourceListChanged()}catch(e){t.debug(`sendResourceListChanged failed`,{error:String(e)})}}async notifyAfterReindex(){await Promise.allSettled([this.notifyStatusChanged(),this.notifyFileTreeChanged()])}async notifyAfterCuratedWrite(e){let t=[this.notifyStatusChanged(),this.notifyCuratedIndexChanged()];e&&t.push(this.notifyCuratedEntryChanged(e)),await Promise.allSettled(t)}async sendUpdate(e){try{await this.mcpServer.server.sendResourceUpdated({uri:e})}catch(n){t.debug(`sendResourceUpdated failed`,{uri:e,error:String(n)})}}};const r={notifyStatusChanged:async()=>{},notifyFileTreeChanged:async()=>{},notifyCuratedIndexChanged:async()=>{},notifyCuratedEntryChanged:async()=>{},notifyResourceListChanged:async()=>{},notifyAfterReindex:async()=>{},notifyAfterCuratedWrite:async()=>{}};export{n as ResourceNotifier,r as noopResourceNotifier};
@@ -1,2 +1,2 @@
1
- import{registerCuratedResources as e}from"./curated-resources.js";function t(t,n,r){t.resource(`aikit-status`,`kb://status`,{description:`Current knowledge base status and statistics`,mimeType:`text/plain`},async()=>{let e=await n.getStats();return{contents:[{uri:`kb://status`,text:`Knowledge Base: ${e.totalRecords} records from ${e.totalFiles} files. Last indexed: ${e.lastIndexedAt??`Never`}`,mimeType:`text/plain`}]}}),t.resource(`aikit-file-tree`,`kb://file-tree`,{description:`List of all indexed source files`,mimeType:`text/plain`},async()=>({contents:[{uri:`kb://file-tree`,text:(await n.listSourcePaths()).sort().join(`
1
+ import{registerCuratedResources as e}from"./curated-resources.js";function t(t,n,r){t.resource(`aikit-status`,`aikit://status`,{description:`Current AI Kit status and statistics`,mimeType:`text/plain`},async()=>{let e=await n.getStats();return{contents:[{uri:`aikit://status`,text:`AI Kit: ${e.totalRecords} records from ${e.totalFiles} files. Last indexed: ${e.lastIndexedAt??`Never`}`,mimeType:`text/plain`}]}}),t.resource(`aikit-file-tree`,`aikit://file-tree`,{description:`List of all indexed source files`,mimeType:`text/plain`},async()=>({contents:[{uri:`aikit://file-tree`,text:(await n.listSourcePaths()).sort().join(`
2
2
  `),mimeType:`text/plain`}]})),e(t,r)}export{t as registerResources};
@@ -1,3 +1,4 @@
1
+ import { BackgroundTaskScheduler } from "./background-task.js";
1
2
  import { CuratedKnowledgeManager } from "./curated-manager.js";
2
3
  import { ResourceNotifier } from "./resources/resource-notifier.js";
3
4
  import { ISamplingClient } from "./sampling.js";
@@ -36,12 +37,13 @@ declare function createServer(config: KBConfig): Promise<{
36
37
  runInitialIndex: () => Promise<void>;
37
38
  shutdown: () => Promise<void>;
38
39
  }>;
39
- declare const ALL_TOOL_NAMES: readonly ["analyze_dependencies", "analyze_diagram", "analyze_entry_points", "analyze_patterns", "analyze_structure", "analyze_symbols", "audit", "batch", "blast_radius", "brainstorm", "changelog", "check", "checkpoint", "codemod", "compact", "data_transform", "dead_symbols", "delegate", "diff_parse", "digest", "encode", "env", "eval", "evidence_map", "file_summary", "find", "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"];
40
+ declare const ALL_TOOL_NAMES: readonly ["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"];
40
41
  declare function createLazyServer(config: KBConfig): {
41
42
  server: McpServer; /** Call after MCP roots are resolved (or fallback decided) to start heavy init. */
42
43
  startInit: () => void;
43
44
  ready: Promise<void>;
44
- runInitialIndex: () => Promise<void>;
45
+ runInitialIndex: () => Promise<void>; /** Background task scheduler — use to queue heavy operations and check status. */
46
+ scheduler: BackgroundTaskScheduler;
45
47
  };
46
48
  //#endregion
47
49
  export { ALL_TOOL_NAMES, KnowledgeBaseComponents, createLazyServer, createMcpServer, createServer, initializeKnowledgeBase, registerMcpTools };
@@ -1,3 +1,3 @@
1
- import{CuratedKnowledgeManager as e}from"./curated-manager.js";import{createElicitor as t,noopElicitor as n}from"./elicitor.js";import{bridgeMcpLogging as r}from"./mcp-logging.js";import{registerPrompts as i}from"./prompts.js";import{installReplayInterceptor as a}from"./replay-interceptor.js";import{ResourceNotifier as o}from"./resources/resource-notifier.js";import{registerResources as s}from"./resources/resources.js";import{createSamplingClient as c}from"./sampling.js";import{installStructuredContentGuard as l}from"./structured-content-guard.js";import{getToolMeta as u}from"./tool-metadata.js";import{installToolPrefix as d}from"./tool-prefix.js";import{registerAnalyzeDependenciesTool as f,registerAnalyzeDiagramTool as p,registerAnalyzeEntryPointsTool as m,registerAnalyzePatternsTool as h,registerAnalyzeStructureTool as g,registerAnalyzeSymbolsTool as _,registerBlastRadiusTool as v}from"./tools/analyze.tools.js";import{registerAuditTool as y}from"./tools/audit.tool.js";import{registerBrainstormTool as b}from"./tools/brainstorm.tool.js";import{initBridgeComponents as x,registerErPullTool as S,registerErPushTool as C,registerErSyncStatusTool as w}from"./tools/bridge.tools.js";import{registerCompactTool as T,registerDeadSymbolsTool as ee,registerFileSummaryTool as te,registerFindTool as ne,registerScopeMapTool as re,registerSymbolTool as ie,registerTraceTool as ae}from"./tools/context.tools.js";import{registerErEvolveReviewTool as oe}from"./tools/evolution.tools.js";import{registerBatchTool as se,registerCheckTool as E,registerDelegateTool as ce,registerEvalTool as D,registerParseOutputTool as O,registerTestRunTool as k}from"./tools/execution.tools.js";import{registerFlowTools as le}from"./tools/flow.tools.js";import{registerDigestTool as ue,registerEvidenceMapTool as A,registerForgeClassifyTool as j,registerForgeGroundTool as de,registerStratumCardTool as fe}from"./tools/forge.tools.js";import{registerForgetTool as pe}from"./tools/forget.tool.js";import{registerGraphTool as me}from"./tools/graph.tool.js";import{registerGuideTool as M,registerHealthTool as N,registerProcessTool as P,registerWatchTool as F,registerWebFetchTool as I}from"./tools/infra.tools.js";import{registerListTool as he}from"./tools/list.tool.js";import{registerLookupTool as ge}from"./tools/lookup.tool.js";import{registerCodemodTool as L,registerDataTransformTool as R,registerDiffParseTool as z,registerGitContextTool as B,registerRenameTool as V}from"./tools/manipulation.tools.js";import{registerOnboardTool as _e}from"./tools/onboard.tool.js";import{registerCheckpointTool as H,registerLaneTool as U,registerQueueTool as W,registerStashTool as G,registerWorksetTool as K}from"./tools/persistence.tools.js";import{registerErUpdatePolicyTool as ve}from"./tools/policy.tools.js";import{registerPresentTool as q}from"./tools/present/tool.js";import"./tools/present/index.js";import{registerProduceKnowledgeTool as ye}from"./tools/produce.tool.js";import{registerReadTool as be}from"./tools/read.tool.js";import{registerReindexTool as xe}from"./tools/reindex.tool.js";import{registerRememberTool as Se}from"./tools/remember.tool.js";import{registerReplayTool as Ce}from"./tools/replay.tool.js";import{registerRestoreTool as we}from"./tools/restore.tool.js";import{registerSearchTool as Te}from"./tools/search.tool.js";import{getCurrentVersion as Ee}from"./version-check.js";import{registerEarlyStatusTool as De,registerStatusTool as Oe}from"./tools/status.tool.js";import{registerUpdateTool as ke}from"./tools/update.tool.js";import{registerChangelogTool as Ae,registerEncodeTool as je,registerEnvTool as Me,registerHttpTool as Ne,registerMeasureTool as Pe,registerRegexTestTool as Fe,registerSchemaValidateTool as Ie,registerSnippetTool as Le,registerTimeTool as Re,registerWebSearchTool as ze}from"./tools/utility.tools.js";import{existsSync as Be,statSync as Ve}from"node:fs";import{resolve as He}from"node:path";import{AIKIT_PATHS as Ue,createLogger as We,serializeError as J}from"../../core/dist/index.js";import{initializeWasm as Ge}from"../../chunker/dist/index.js";import{OnnxEmbedder as Ke}from"../../embeddings/dist/index.js";import{EvolutionCollector as qe,PolicyStore as Je}from"../../enterprise-bridge/dist/index.js";import{FileHashCache as Ye,IncrementalIndexer as Xe}from"../../indexer/dist/index.js";import{SqliteGraphStore as Ze,createStore as Qe}from"../../store/dist/index.js";import{FileCache as $e}from"../../tools/dist/index.js";import{McpServer as et}from"@modelcontextprotocol/sdk/server/mcp.js";const Y=We(`server`);async function X(t){Y.info(`Initializing knowledge base components`);let[n,r,i,a]=await Promise.all([(async()=>{let e=new Ke({model:t.embedding.model,dimensions:t.embedding.dimensions});return await e.initialize(),Y.info(`Embedder loaded`,{modelId:e.modelId,dimensions:e.dimensions}),e})(),(async()=>{let e=await Qe({backend:t.store.backend,path:t.store.path});return await e.initialize(),Y.info(`Store initialized`),e})(),(async()=>{let e=new Ze({path:t.store.path});return await e.initialize(),Y.info(`Graph store initialized`),e})(),(async()=>{let e=await Ge();return e?Y.info(`WASM tree-sitter enabled for AST analysis`):Y.warn(`WASM tree-sitter not available; analyzers will use regex fallback`),e})()]),o=new Xe(n,r),s=new Ye(t.store.path);s.load(),o.setHashCache(s);let c=t.curated.path,l=new e(c,r,n);o.setGraphStore(i);let u=x(t.er),d=u?new Je(t.curated.path):void 0;d&&Y.info(`Policy store initialized`,{ruleCount:d.getRules().length});let f=u?new qe:void 0,p=He(t.sources[0]?.path??process.cwd(),Ue.aiKb),m=Be(p),h=t.onboardDir?Be(t.onboardDir):!1,g=m||h,_,v=m?p:t.onboardDir;if(g&&v)try{_=Ve(v).mtime.toISOString()}catch{}return Y.info(`Onboard state detected`,{onboardComplete:g,onboardTimestamp:_,aiKbExists:m,onboardDirExists:h}),{embedder:n,store:r,indexer:o,curated:l,graphStore:i,fileCache:new $e,bridge:u,policyStore:d,evolutionCollector:f,onboardComplete:g,onboardTimestamp:_}}function tt(e,n){let a=new et({name:n.serverName??`knowledge-base`,version:Ee()},{capabilities:{logging:{}}});return r(a),d(a,n.toolPrefix??``),Z(a,e,n,t(a),new o(a),c(a)),i(a,{curated:e.curated,store:e.store,graphStore:e.graphStore}),a}function Z(e,t,n,r,i,o){a(e),l(e),Te(e,t.embedder,t.store,t.graphStore,t.bridge,t.evolutionCollector,o),ge(e,t.store),Oe(e,t.store,t.graphStore,t.curated,{onboardComplete:t.onboardComplete,onboardTimestamp:t.onboardTimestamp},n),xe(e,t.indexer,n,t.curated,t.store,i),Se(e,t.curated,t.policyStore,t.evolutionCollector,i),ke(e,t.curated,i),pe(e,t.curated,i),be(e,t.curated),he(e,t.curated),g(e,t.store,t.embedder),f(e,t.store,t.embedder),_(e,t.store,t.embedder),h(e,t.store,t.embedder),m(e,t.store,t.embedder),p(e,t.store,t.embedder),v(e,t.store,t.embedder,t.graphStore),ye(e,n),_e(e,t.store,t.embedder,n),me(e,t.graphStore),y(e,t.store,t.embedder);let c=n.sources[0]?.path??process.cwd();T(e,t.embedder,t.fileCache,c),re(e,t.embedder,t.store),ne(e,t.embedder,t.store),O(e),K(e),E(e),se(e,t.embedder,t.store),ie(e,t.embedder,t.store,t.graphStore),D(e),k(e),G(e),B(e),z(e),V(e),L(e),we(e),te(e,t.fileCache,c),H(e),R(e),ae(e,t.embedder,t.store),P(e),F(e),ee(e,t.embedder,t.store),ce(e,o),N(e),U(e),W(e),I(e),M(e),A(e),ue(e,t.embedder),j(e),fe(e,t.embedder,t.fileCache),de(e,t.embedder,t.store),q(e,r),r&&b(e,r),ze(e),Ne(e),Fe(e),je(e),Pe(e),Ae(e),Ie(e),Le(e),Me(e),Re(e),le(e,n),t.bridge&&(C(e,t.bridge,t.evolutionCollector),S(e,t.bridge),w(e,t.bridge)),t.policyStore&&ve(e,t.policyStore),t.evolutionCollector&&oe(e,t.evolutionCollector),s(e,t.store,t.curated),Ce(e)}async function nt(e){let t=await X(e),n=tt(t,e);Y.info(`MCP server configured`,{toolCount:$.length,resourceCount:2});let r=async()=>{try{let n=e.sources.map(e=>e.path).join(`, `);Y.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&&Y.debug(`Indexing file`,{current:e.filesProcessed+1,total:e.filesTotal,file:e.currentFile}),e.phase===`cleanup`&&Y.debug(`Index cleanup`,{staleEntries:e.filesTotal-e.filesProcessed}))});Y.info(`Initial index complete`,{filesProcessed:r.filesProcessed,filesSkipped:r.filesSkipped,chunksCreated:r.chunksCreated,durationMs:r.durationMs});try{await t.store.createFtsIndex()}catch(e){Y.warn(`FTS index creation failed`,J(e))}try{let e=await t.curated.reindexAll();Y.info(`Curated re-index complete`,{indexed:e.indexed})}catch(e){Y.error(`Curated re-index failed`,J(e))}}catch(e){Y.error(`Initial index failed; will retry on aikit_reindex`,J(e))}},i=async()=>{Y.info(`Shutting down`),await t.embedder.shutdown().catch(()=>{}),await t.graphStore.close().catch(()=>{}),await t.store.close(),process.exit(0)};process.on(`SIGINT`,i),process.on(`SIGTERM`,i);let a=process.ppid,o=setInterval(()=>{try{process.kill(a,0)}catch{Y.info(`Parent process died; shutting down`,{parentPid:a}),clearInterval(o),i()}},5e3);return o.unref(),{server:n,runInitialIndex:r,shutdown:i}}const rt=new Set(`batch.brainstorm.changelog.check.checkpoint.codemod.compact.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(`.`)),it=5e3,Q=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 at(e){E(e),D(e),k(e),O(e),ce(e),B(e),z(e),V(e),L(e),R(e),K(e),G(e),H(e),we(e),U(e),W(e),N(e),P(e),F(e),I(e),M(e),A(e),j(e),q(e),b(e,n),ye(e),Ce(e),De(e),ze(e),Ne(e),Fe(e),je(e),Pe(e),Ae(e),Ie(e),Le(e),Me(e),Re(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.data_transform.dead_symbols.delegate.diff_parse.digest.encode.env.eval.evidence_map.file_summary.find.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 ot(e){let n=new et({name:e.serverName??`knowledge-base`,version:Ee()},{capabilities:{logging:{}}}),a=`initializing`,s=``,l=!1,f=()=>a===`failed`?[`❌ KB initialization failed — this tool is unavailable.`,``,s?`Error: ${s}`:``,``,`**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
- `):[`KB 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 knowledge base index. Please retry in a few seconds,`,`or use one of the available tools above in the meantime.`].join(`
3
- `);r(n),d(n,e.toolPrefix??``);let p=n.sendToolListChanged.bind(n);n.sendToolListChanged=()=>{};let m=[];for(let e of $){let t=u(e),r=n.registerTool(e,{title:t.title,description:`${t.title} — initializing, available shortly`,inputSchema:{},annotations:t.annotations},async()=>({content:[{type:`text`,text:f()}]}));Q.has(e)?r.remove():m.push(r)}at(n),n.sendToolListChanged=p;let h=n.resource(`aikit-status`,`kb://status`,{description:`Knowledge base status (initializing...)`,mimeType:`text/plain`},async()=>({contents:[{uri:`kb://status`,text:`KB is initializing...`,mimeType:`text/plain`}]})),g=n.prompt(`_init`,`KB is initializing prompts...`,async()=>({messages:[{role:`user`,content:{type:`text`,text:f()}}]})),_,v=new Promise(e=>{_=e}),y,b=new Promise(e=>{y=e}),x=()=>y?.(),S=(async()=>{await b;let r;try{r=await X(e)}catch(e){a=`failed`,s=e instanceof Error?e.message:String(e),Y.error(`KB initialization failed — server continuing with zero-dep tools only`,{error:s});return}let u=n.sendToolListChanged.bind(n);n.sendToolListChanged=()=>{};let d=n.sendPromptListChanged.bind(n);n.sendPromptListChanged=()=>{};let f=n.sendResourceListChanged.bind(n);n.sendResourceListChanged=()=>{};for(let e of m)e.remove();h.remove(),g.remove();let p=n._registeredTools??{};for(let e of Q)p[e]?.remove();let v=new o(n),y=c(n);Z(n,r,e,t(n),v,y),i(n),n.sendToolListChanged=u,n.sendPromptListChanged=d,n.sendResourceListChanged=f,Promise.resolve(n.sendToolListChanged()).catch(()=>{}),Promise.resolve(n.sendPromptListChanged()).catch(()=>{}),Promise.resolve(n.sendResourceListChanged()).catch(()=>{});let x=n._registeredTools??{};for(let[e,t]of Object.entries(x)){if(rt.has(e))continue;let n=t.handler;t.handler=async(...t)=>{if(!r.indexer.isIndexing)return n(...t);let i=l?`re-indexing`:`running initial index`,a=new Promise(t=>setTimeout(()=>t({content:[{type:`text`,text:`⏳ KB is ${i}. The tool "${e}" timed out waiting for index data (${it/1e3}s).\n\nThe existing index may be temporarily locked. Please retry shortly — indexing will complete automatically.`}]}),it));return Promise.race([n(...t),a])}}let S=Object.keys(x).length;S!==$.length&&Y.warn(`ALL_TOOL_NAMES count mismatch`,{expectedToolCount:$.length,registeredToolCount:S}),Y.info(`MCP server configured`,{toolCount:$.length,resourceCount:4}),_?.(r)})(),C=async()=>{let t=await v;try{let n=e.sources.map(e=>e.path).join(`, `);Y.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&&Y.debug(`Indexing file`,{current:e.filesProcessed+1,total:e.filesTotal,file:e.currentFile}),e.phase===`cleanup`&&Y.debug(`Index cleanup`,{staleEntries:e.filesTotal-e.filesProcessed}))});l=!0,Y.info(`Initial index complete`,{filesProcessed:r.filesProcessed,filesSkipped:r.filesSkipped,chunksCreated:r.chunksCreated,durationMs:r.durationMs});try{await t.store.createFtsIndex()}catch(e){Y.warn(`FTS index creation failed`,J(e))}try{let e=await t.curated.reindexAll();Y.info(`Curated re-index complete`,{indexed:e.indexed})}catch(e){Y.error(`Curated re-index failed`,J(e))}}catch(e){Y.error(`Initial index failed; will retry on aikit_reindex`,J(e))}},w=process.ppid,T=setInterval(()=>{try{process.kill(w,0)}catch{Y.info(`Parent process died; shutting down`,{parentPid:w}),clearInterval(T),v.then(async e=>{await e.embedder.shutdown().catch(()=>{}),await e.graphStore.close().catch(()=>{}),await e.store.close().catch(()=>{})}).catch(()=>{}).finally(()=>process.exit(0))}},5e3);return T.unref(),{server:n,startInit:x,ready:S,runInitialIndex:C}}export{$ as ALL_TOOL_NAMES,ot as createLazyServer,tt as createMcpServer,nt as createServer,X as initializeKnowledgeBase,Z as registerMcpTools};
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(`
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 x=i.sendToolListChanged.bind(i);i.sendToolListChanged=()=>{};let S=[];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:b()}]}));ft.has(e)?n.remove():S.push(n)}pt(i),i.sendToolListChanged=x;let ee=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`}]})),te=i.registerPrompt(`_init`,{description:`AI Kit is initializing prompts...`},async()=>({messages:[{role:`user`,content:{type:`text`,text:b()}}]})),C,w=new Promise(e=>{C=e}),T,ne=new Promise(e=>{T=e}),E=()=>T?.(),D=(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 S)e.remove();ee.remove(),te.remove();let b=i._registeredTools??{};for(let e of ft)b[e]?.remove();let x=new u(i),w=f(i);Q(i,e,n,r(i),x,w),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 T=i._registeredTools??{};for(let[t,n]of Object.entries(T)){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(T)){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 E=Object.keys(T).length;E<$.length&&X.warn(`ALL_TOOL_NAMES count mismatch`,{expectedToolCount:$.length,registeredToolCount:E}),X.info(`MCP server configured`,{toolCount:$.length,resourceCount:4});let D=new s;D.onPressure((e,n)=>{e===`warning`&&t(),e===`critical`&&(X.warn(`Memory pressure critical — consider restarting`,{rssMB:Math.round(n/1024/1024)}),t())}),D.start();let O=new a;y=O,O.onIdle(async()=>{if(k.isRunning||e.indexer.isIndexing){X.info(`Idle cleanup deferred — background tasks still running`),O.touch();return}X.info(`Idle cleanup: closing store and graph connections`);try{await Promise.all([e.store.close().catch(()=>{}),e.graphStore.close().catch(()=>{})])}catch{}}),O.touch();for(let e of Object.values(T)){let t=e.handler;e.handler=async(...e)=>(O.touch(),t(...e))}C?.(e)})(),O=async()=>{let e=await w;y?.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{y?.setBusy(!1)}},k=new e,re=()=>k.schedule({name:`initial-index`,fn:O}),A=process.ppid,j=setInterval(()=>{try{process.kill(A,0)}catch{X.info(`Parent process died; shutting down`,{parentPid:A}),clearInterval(j),w.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 j.unref(),{server:i,startInit:E,ready:D,runInitialIndex:re,scheduler:k}}export{$ as ALL_TOOL_NAMES,mt as createLazyServer,ct as createMcpServer,lt as createServer,Z as initializeKnowledgeBase,Q as registerMcpTools};
@@ -1,6 +1,6 @@
1
1
  //#region packages/server/src/tool-metadata.d.ts
2
2
  /**
3
- * Centralized tool metadata registry for all KB MCP tools.
3
+ * Centralized tool metadata registry for all AI Kit MCP tools.
4
4
  *
5
5
  * Provides `title` and `annotations` (readOnlyHint, destructiveHint) for each tool.
6
6
  * Used by both placeholder registration (lazy startup) and real tool registration
@@ -1 +1 @@
1
- const e={search:{title:`Hybrid Search`,annotations:{readOnlyHint:!0,idempotentHint:!0}},find:{title:`Federated Find`,annotations:{readOnlyHint:!0,idempotentHint:!0}},symbol:{title:`Symbol Resolver`,annotations:{readOnlyHint:!0,idempotentHint:!0}},trace:{title:`Data Flow Tracer`,annotations:{readOnlyHint:!0,idempotentHint:!0}},scope_map:{title:`Task Scope Map`,annotations:{readOnlyHint:!0,idempotentHint:!0}},lookup:{title:`Chunk Lookup`,annotations:{readOnlyHint:!0,idempotentHint:!0}},dead_symbols:{title:`Dead Symbol Finder`,annotations:{readOnlyHint:!0,idempotentHint:!0}},file_summary:{title:`File Summary`,annotations:{readOnlyHint:!0,idempotentHint:!0}},analyze_structure:{title:`Analyze Structure`,annotations:{readOnlyHint:!0,idempotentHint:!0}},analyze_dependencies:{title:`Analyze Dependencies`,annotations:{readOnlyHint:!0,idempotentHint:!0}},analyze_symbols:{title:`Analyze Symbols`,annotations:{readOnlyHint:!0,idempotentHint:!0}},analyze_patterns:{title:`Analyze Patterns`,annotations:{readOnlyHint:!0,idempotentHint:!0}},analyze_entry_points:{title:`Analyze Entry Points`,annotations:{readOnlyHint:!0,idempotentHint:!0}},analyze_diagram:{title:`Analyze Diagram`,annotations:{readOnlyHint:!0,idempotentHint:!0}},blast_radius:{title:`Blast Radius`,annotations:{readOnlyHint:!0,idempotentHint:!0}},brainstorm:{title:`Brainstorm Session`,annotations:{readOnlyHint:!0,idempotentHint:!0}},remember:{title:`Remember Knowledge`,annotations:{readOnlyHint:!1}},read:{title:`Read Knowledge`,annotations:{readOnlyHint:!0,idempotentHint:!0}},update:{title:`Update Knowledge`,annotations:{readOnlyHint:!1}},forget:{title:`Forget Knowledge`,annotations:{readOnlyHint:!1,destructiveHint:!0}},list:{title:`List Knowledge`,annotations:{readOnlyHint:!0,idempotentHint:!0}},produce_knowledge:{title:`Produce Knowledge`,annotations:{readOnlyHint:!0,idempotentHint:!0}},compact:{title:`Semantic Compactor`,annotations:{readOnlyHint:!0,idempotentHint:!0}},digest:{title:`Multi-Source Digest`,annotations:{readOnlyHint:!0,idempotentHint:!0}},stratum_card:{title:`Stratum Card`,annotations:{readOnlyHint:!0,idempotentHint:!0}},forge_ground:{title:`FORGE Ground`,annotations:{readOnlyHint:!0,idempotentHint:!0}},forge_classify:{title:`FORGE Classify`,annotations:{readOnlyHint:!0,idempotentHint:!0}},evidence_map:{title:`Evidence Map`,annotations:{readOnlyHint:!1}},present:{title:`Rich Content Presenter`,annotations:{readOnlyHint:!0,idempotentHint:!0}},check:{title:`Typecheck & Lint`,annotations:{readOnlyHint:!0,openWorldHint:!0}},test_run:{title:`Run Tests`,annotations:{readOnlyHint:!0,openWorldHint:!0}},eval:{title:`Evaluate Code`,annotations:{readOnlyHint:!1,openWorldHint:!0}},batch:{title:`Batch Operations`,annotations:{readOnlyHint:!0,idempotentHint:!0}},audit:{title:`Project Audit`,annotations:{readOnlyHint:!0,idempotentHint:!0}},rename:{title:`Rename Symbol`,annotations:{readOnlyHint:!1,destructiveHint:!0}},restore:{title:`Restore`,annotations:{readOnlyHint:!1}},codemod:{title:`Codemod`,annotations:{readOnlyHint:!1,destructiveHint:!0}},data_transform:{title:`Data Transform`,annotations:{readOnlyHint:!0,idempotentHint:!0}},stash:{title:`Stash Values`,annotations:{readOnlyHint:!1}},checkpoint:{title:`Session Checkpoint`,annotations:{readOnlyHint:!1}},workset:{title:`Workset Manager`,annotations:{readOnlyHint:!1}},lane:{title:`Exploration Lane`,annotations:{readOnlyHint:!1}},git_context:{title:`Git Context`,annotations:{readOnlyHint:!0,idempotentHint:!0}},diff_parse:{title:`Diff Parser`,annotations:{readOnlyHint:!0,idempotentHint:!0}},parse_output:{title:`Parse Build Output`,annotations:{readOnlyHint:!0,idempotentHint:!0}},process:{title:`Process Manager`,annotations:{readOnlyHint:!1,openWorldHint:!0}},watch:{title:`File Watcher`,annotations:{readOnlyHint:!1,openWorldHint:!0}},delegate:{title:`Delegate Task`,annotations:{readOnlyHint:!1,openWorldHint:!0}},status:{title:`KB Status`,annotations:{readOnlyHint:!0,idempotentHint:!0}},health:{title:`Health Check`,annotations:{readOnlyHint:!0,idempotentHint:!0}},reindex:{title:`Reindex`,annotations:{readOnlyHint:!1}},onboard:{title:`Onboard Codebase`,annotations:{readOnlyHint:!1}},graph:{title:`Knowledge Graph`,annotations:{readOnlyHint:!1}},guide:{title:`Tool Guide`,annotations:{readOnlyHint:!0,idempotentHint:!0}},replay:{title:`Replay History`,annotations:{readOnlyHint:!0,idempotentHint:!0}},changelog:{title:`Generate Changelog`,annotations:{readOnlyHint:!0,idempotentHint:!0}},regex_test:{title:`Regex Tester`,annotations:{readOnlyHint:!0,idempotentHint:!0}},encode:{title:`Encode / Decode`,annotations:{readOnlyHint:!0,idempotentHint:!0}},measure:{title:`Code Metrics`,annotations:{readOnlyHint:!0,idempotentHint:!0}},schema_validate:{title:`Schema Validator`,annotations:{readOnlyHint:!0,idempotentHint:!0}},snippet:{title:`Code Snippets`,annotations:{readOnlyHint:!1}},env:{title:`Environment Info`,annotations:{readOnlyHint:!0,idempotentHint:!0}},time:{title:`Date & Time`,annotations:{readOnlyHint:!0,idempotentHint:!0}},web_fetch:{title:`Web Fetch`,annotations:{readOnlyHint:!0,openWorldHint:!0}},web_search:{title:`Web Search`,annotations:{readOnlyHint:!0,openWorldHint:!0}},http:{title:`HTTP Request`,annotations:{readOnlyHint:!1,openWorldHint:!0}},queue:{title:`Operation Queue`,annotations:{readOnlyHint:!1}},bridge_push:{title:`Bridge Push`,annotations:{readOnlyHint:!1}},bridge_pull:{title:`Bridge Pull`,annotations:{readOnlyHint:!0,idempotentHint:!0}},bridge_sync:{title:`Bridge Sync Status`,annotations:{readOnlyHint:!0,idempotentHint:!0}},evolution_state:{title:`Evolution State`,annotations:{readOnlyHint:!1}},policy_check:{title:`Policy Check`,annotations:{readOnlyHint:!0,idempotentHint:!0}},flow_list:{title:`Flow List`,annotations:{readOnlyHint:!0,idempotentHint:!0}},flow_info:{title:`Flow Info`,annotations:{readOnlyHint:!0,idempotentHint:!0}},flow_start:{title:`Flow Start`,annotations:{readOnlyHint:!1}},flow_step:{title:`Flow Step`,annotations:{readOnlyHint:!1}},flow_status:{title:`Flow Status`,annotations:{readOnlyHint:!0,idempotentHint:!0}},flow_reset:{title:`Flow Reset`,annotations:{readOnlyHint:!1}}};function t(t){return e[t]??{title:t,annotations:{readOnlyHint:!1}}}export{e as TOOL_METADATA,t as getToolMeta};
1
+ const e={search:{title:`Hybrid Search`,annotations:{readOnlyHint:!0,idempotentHint:!0}},find:{title:`Federated Find`,annotations:{readOnlyHint:!0,idempotentHint:!0}},symbol:{title:`Symbol Resolver`,annotations:{readOnlyHint:!0,idempotentHint:!0}},trace:{title:`Data Flow Tracer`,annotations:{readOnlyHint:!0,idempotentHint:!0}},scope_map:{title:`Task Scope Map`,annotations:{readOnlyHint:!0,idempotentHint:!0}},lookup:{title:`Chunk Lookup`,annotations:{readOnlyHint:!0,idempotentHint:!0}},dead_symbols:{title:`Dead Symbol Finder`,annotations:{readOnlyHint:!0,idempotentHint:!0}},file_summary:{title:`File Summary`,annotations:{readOnlyHint:!0,idempotentHint:!0}},analyze_structure:{title:`Analyze Structure`,annotations:{readOnlyHint:!0,idempotentHint:!0}},analyze_dependencies:{title:`Analyze Dependencies`,annotations:{readOnlyHint:!0,idempotentHint:!0}},analyze_symbols:{title:`Analyze Symbols`,annotations:{readOnlyHint:!0,idempotentHint:!0}},analyze_patterns:{title:`Analyze Patterns`,annotations:{readOnlyHint:!0,idempotentHint:!0}},analyze_entry_points:{title:`Analyze Entry Points`,annotations:{readOnlyHint:!0,idempotentHint:!0}},analyze_diagram:{title:`Analyze Diagram`,annotations:{readOnlyHint:!0,idempotentHint:!0}},blast_radius:{title:`Blast Radius`,annotations:{readOnlyHint:!0,idempotentHint:!0}},brainstorm:{title:`Brainstorm Session`,annotations:{readOnlyHint:!0,idempotentHint:!0}},remember:{title:`Remember Knowledge`,annotations:{readOnlyHint:!1}},read:{title:`Read Knowledge`,annotations:{readOnlyHint:!0,idempotentHint:!0}},update:{title:`Update Knowledge`,annotations:{readOnlyHint:!1}},forget:{title:`Forget Knowledge`,annotations:{readOnlyHint:!1,destructiveHint:!0}},list:{title:`List Knowledge`,annotations:{readOnlyHint:!0,idempotentHint:!0}},produce_knowledge:{title:`Produce Knowledge`,annotations:{readOnlyHint:!0,idempotentHint:!0}},compact:{title:`Semantic Compactor`,annotations:{readOnlyHint:!0,idempotentHint:!0}},digest:{title:`Multi-Source Digest`,annotations:{readOnlyHint:!0,idempotentHint:!0}},stratum_card:{title:`Stratum Card`,annotations:{readOnlyHint:!0,idempotentHint:!0}},forge_ground:{title:`FORGE Ground`,annotations:{readOnlyHint:!0,idempotentHint:!0}},forge_classify:{title:`FORGE Classify`,annotations:{readOnlyHint:!0,idempotentHint:!0}},evidence_map:{title:`Evidence Map`,annotations:{readOnlyHint:!1}},present:{title:`Rich Content Presenter`,annotations:{readOnlyHint:!0,idempotentHint:!0}},check:{title:`Typecheck & Lint`,annotations:{readOnlyHint:!0,openWorldHint:!0}},test_run:{title:`Run Tests`,annotations:{readOnlyHint:!0,openWorldHint:!0}},eval:{title:`Evaluate Code`,annotations:{readOnlyHint:!1,openWorldHint:!0}},batch:{title:`Batch Operations`,annotations:{readOnlyHint:!0,idempotentHint:!0}},audit:{title:`Project Audit`,annotations:{readOnlyHint:!0,idempotentHint:!0}},rename:{title:`Rename Symbol`,annotations:{readOnlyHint:!1,destructiveHint:!0}},restore:{title:`Restore`,annotations:{readOnlyHint:!1}},codemod:{title:`Codemod`,annotations:{readOnlyHint:!1,destructiveHint:!0}},data_transform:{title:`Data Transform`,annotations:{readOnlyHint:!0,idempotentHint:!0}},stash:{title:`Stash Values`,annotations:{readOnlyHint:!1}},checkpoint:{title:`Session Checkpoint`,annotations:{readOnlyHint:!1}},workset:{title:`Workset Manager`,annotations:{readOnlyHint:!1}},lane:{title:`Exploration Lane`,annotations:{readOnlyHint:!1}},git_context:{title:`Git Context`,annotations:{readOnlyHint:!0,idempotentHint:!0}},diff_parse:{title:`Diff Parser`,annotations:{readOnlyHint:!0,idempotentHint:!0}},parse_output:{title:`Parse Build Output`,annotations:{readOnlyHint:!0,idempotentHint:!0}},process:{title:`Process Manager`,annotations:{readOnlyHint:!1,openWorldHint:!0}},watch:{title:`File Watcher`,annotations:{readOnlyHint:!1,openWorldHint:!0}},delegate:{title:`Delegate Task`,annotations:{readOnlyHint:!1,openWorldHint:!0}},config:{title:`Configuration Manager`,annotations:{readOnlyHint:!1}},status:{title:`AI Kit Status`,annotations:{readOnlyHint:!0,idempotentHint:!0}},health:{title:`Health Check`,annotations:{readOnlyHint:!0,idempotentHint:!0}},reindex:{title:`Reindex`,annotations:{readOnlyHint:!1}},onboard:{title:`Onboard Codebase`,annotations:{readOnlyHint:!1}},graph:{title:`Knowledge Graph`,annotations:{readOnlyHint:!1}},guide:{title:`Tool Guide`,annotations:{readOnlyHint:!0,idempotentHint:!0}},replay:{title:`Replay History`,annotations:{readOnlyHint:!0,idempotentHint:!0}},changelog:{title:`Generate Changelog`,annotations:{readOnlyHint:!0,idempotentHint:!0}},regex_test:{title:`Regex Tester`,annotations:{readOnlyHint:!0,idempotentHint:!0}},encode:{title:`Encode / Decode`,annotations:{readOnlyHint:!0,idempotentHint:!0}},measure:{title:`Code Metrics`,annotations:{readOnlyHint:!0,idempotentHint:!0}},schema_validate:{title:`Schema Validator`,annotations:{readOnlyHint:!0,idempotentHint:!0}},snippet:{title:`Code Snippets`,annotations:{readOnlyHint:!1}},env:{title:`Environment Info`,annotations:{readOnlyHint:!0,idempotentHint:!0}},time:{title:`Date & Time`,annotations:{readOnlyHint:!0,idempotentHint:!0}},web_fetch:{title:`Web Fetch`,annotations:{readOnlyHint:!0,openWorldHint:!0}},web_search:{title:`Web Search`,annotations:{readOnlyHint:!0,openWorldHint:!0}},http:{title:`HTTP Request`,annotations:{readOnlyHint:!1,openWorldHint:!0}},queue:{title:`Operation Queue`,annotations:{readOnlyHint:!1}},bridge_push:{title:`Bridge Push`,annotations:{readOnlyHint:!1}},bridge_pull:{title:`Bridge Pull`,annotations:{readOnlyHint:!0,idempotentHint:!0}},bridge_sync:{title:`Bridge Sync Status`,annotations:{readOnlyHint:!0,idempotentHint:!0}},evolution_state:{title:`Evolution State`,annotations:{readOnlyHint:!1}},policy_check:{title:`Policy Check`,annotations:{readOnlyHint:!0,idempotentHint:!0}},flow_list:{title:`Flow List`,annotations:{readOnlyHint:!0,idempotentHint:!0}},flow_info:{title:`Flow Info`,annotations:{readOnlyHint:!0,idempotentHint:!0}},flow_start:{title:`Flow Start`,annotations:{readOnlyHint:!1}},flow_step:{title:`Flow Step`,annotations:{readOnlyHint:!1}},flow_status:{title:`Flow Status`,annotations:{readOnlyHint:!0,idempotentHint:!0}},flow_reset:{title:`Flow Reset`,annotations:{readOnlyHint:!1}}};function t(t){return e[t]??{title:t,annotations:{readOnlyHint:!1}}}export{e as TOOL_METADATA,t as getToolMeta};
@@ -0,0 +1,27 @@
1
+ //#region packages/server/src/tool-timeout.d.ts
2
+ /**
3
+ * Tool timeout wrapper — ensures no tool handler can run indefinitely.
4
+ *
5
+ * Every MCP tool handler is wrapped with a configurable timeout.
6
+ * Heavy tools (onboard, reindex, produce_knowledge, analyzers) get a longer deadline.
7
+ */
8
+ /** Default timeout for normal tool handlers (120 seconds). */
9
+ declare const DEFAULT_TOOL_TIMEOUT_MS = 120000;
10
+ /** Extended timeout for heavy tool handlers (10 minutes). */
11
+ declare const HEAVY_TOOL_TIMEOUT_MS = 600000;
12
+ declare class ToolTimeoutError extends Error {
13
+ readonly toolName: string;
14
+ readonly timeoutMs: number;
15
+ constructor(toolName: string, timeoutMs: number);
16
+ }
17
+ /**
18
+ * Return the timeout for a given tool name.
19
+ */
20
+ declare function getToolTimeout(toolName: string): number;
21
+ /**
22
+ * Wrap an async function with a timeout. If the function doesn't resolve
23
+ * within `timeoutMs`, the returned promise rejects with a `ToolTimeoutError`.
24
+ */
25
+ declare function withTimeout<T>(fn: () => Promise<T>, timeoutMs: number, toolName: string): Promise<T>;
26
+ //#endregion
27
+ export { DEFAULT_TOOL_TIMEOUT_MS, HEAVY_TOOL_TIMEOUT_MS, ToolTimeoutError, getToolTimeout, withTimeout };
@@ -0,0 +1 @@
1
+ import{createLogger as e}from"../../core/dist/index.js";const t=e(`tool-timeout`),n=12e4,r=6e5,i=new Set([`onboard`,`reindex`,`produce_knowledge`,`analyze_structure`,`analyze_dependencies`,`analyze_symbols`,`analyze_patterns`,`analyze_entry_points`,`analyze_diagram`,`codemod`,`batch`,`audit`]);var a=class extends Error{constructor(e,t){super(`Tool "${e}" timed out after ${t}ms`),this.toolName=e,this.timeoutMs=t,this.name=`ToolTimeoutError`}};function o(e){return i.has(e)?r:n}function s(e,n,r){return new Promise((i,o)=>{let s=!1,c=setTimeout(()=>{if(!s){s=!0;let e=new a(r,n);t.warn(e.message),o(e)}},n);c.unref&&c.unref(),e().then(e=>{s||(s=!0,clearTimeout(c),i(e))},e=>{s||(s=!0,clearTimeout(c),o(e))})})}export{n as DEFAULT_TOOL_TIMEOUT_MS,r as HEAVY_TOOL_TIMEOUT_MS,a as ToolTimeoutError,o as getToolTimeout,s as withTimeout};
@@ -2,7 +2,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { ERBridgeConfig, ERCache, ERClient, EvolutionCollector, PushAdapter } from "../../../enterprise-bridge/dist/index.js";
3
3
 
4
4
  //#region packages/server/src/tools/bridge.tools.d.ts
5
- /** Resolve ER bridge config from KBConfig.er + env */
5
+ /** Resolve ER bridge config from server config + env */
6
6
  declare function resolveErBridgeConfig(erConfig?: {
7
7
  enabled: boolean;
8
8
  baseUrl: string;
@@ -1,6 +1,6 @@
1
- import{getToolMeta as e}from"../tool-metadata.js";import{z as t}from"zod";import{createLogger as n,serializeError as r}from"../../../core/dist/index.js";import{ERCache as i,ERClient as a,PushAdapter as o}from"../../../enterprise-bridge/dist/index.js";const s=n(`tools`);function c(e){if(!e?.enabled)return;let t=process.env.AIKIT_ER_API_KEY;if(!t){s.warn(`ER bridge enabled but AIKIT_ER_API_KEY not set; disabling`);return}return{enabled:!0,baseUrl:e.baseUrl,apiKey:t,timeoutMs:e.timeoutMs??5e3,cacheTtlMs:e.cacheTtlMs??360*60*1e3,cacheMaxEntries:e.cacheMaxEntries??100,fallbackThreshold:e.fallbackThreshold??.45}}function l(e){let t=c(e);if(t)try{let e=new a(t),n=new i({maxEntries:t.cacheMaxEntries,defaultTtl:t.cacheTtlMs}),r=new o(e);try{let e=new URL(t.baseUrl).hostname;s.info(`ER bridge initialized`,{host:e})}catch{s.info(`ER bridge initialized`)}return{client:e,cache:n,pushAdapter:r,config:t}}catch(e){s.warn(`ER bridge initialization failed`,r(e));return}}function u(n,i,a){let o=e(`er_push`);n.registerTool(`er_push`,{title:o.title,description:`Push a curated knowledge entry to Enterprise RAG. The entry is stored via ER's curated_remember tool and becomes immediately searchable in the enterprise knowledge base.`,inputSchema:{title:t.string().min(3).max(120).describe(`Title for the knowledge entry`),content:t.string().min(10).max(1e5).describe(`Markdown content to push (max 100KB)`),category:t.string().regex(/^[a-z][a-z0-9-]*$/).default(`conventions`).describe(`Category slug (e.g., "decisions", "patterns", "conventions")`),tags:t.array(t.string()).default([]).describe(`Optional tags`),rule_id:t.string().optional().describe(`ID of the classification rule that motivated this push (from remember classification signals). Improves rule effectiveness tracking.`)},annotations:o.annotations},async({title:e,content:t,category:n,tags:o,rule_id:c})=>{try{let r=`${n}/${e.toLowerCase().replace(/[^a-z0-9]+/g,`-`)}`,s=await i.pushAdapter.push(r,{title:e,content:t,category:n,tags:o});return s.pushed?(a&&a.recordPush(r,s.pushed,c),{content:[{type:`text`,text:`Pushed to ER: **${e}**\n\nRemote path: \`${s.remotePath??`unknown`}\`\nTimestamp: ${s.timestamp}\n\n---\n_Next: Use \`er_pull\` to verify the entry is searchable in ER, or \`er_sync_status\` to see push history._`}]}):(a&&a.recordPush(r,!1,c),{content:[{type:`text`,text:`ER push failed: ${s.error??`Unknown error`}\n\n_The local KB is unaffected. You can retry or check ER health with \`er_sync_status\`._`}],isError:!0})}catch(t){if(s.error(`ER push failed`,r(t)),a){let t=`${n}/${e.toLowerCase().replace(/[^a-z0-9]+/g,`-`)}`;a.recordPush(t,!1,c)}return{content:[{type:`text`,text:`ER push failed: operation unsuccessful
1
+ import{getToolMeta as e}from"../tool-metadata.js";import{z as t}from"zod";import{createLogger as n,serializeError as r}from"../../../core/dist/index.js";import{ERCache as i,ERClient as a,PushAdapter as o}from"../../../enterprise-bridge/dist/index.js";const s=n(`tools`);function c(e){if(!e?.enabled)return;let t=process.env.AIKIT_ER_API_KEY;if(!t){s.warn(`ER bridge enabled but AIKIT_ER_API_KEY not set; disabling`);return}return{enabled:!0,baseUrl:e.baseUrl,apiKey:t,timeoutMs:e.timeoutMs??5e3,cacheTtlMs:e.cacheTtlMs??360*60*1e3,cacheMaxEntries:e.cacheMaxEntries??100,fallbackThreshold:e.fallbackThreshold??.45}}function l(e){let t=c(e);if(t)try{let e=new a(t),n=new i({maxEntries:t.cacheMaxEntries,defaultTtl:t.cacheTtlMs}),r=new o(e);try{let e=new URL(t.baseUrl).hostname;s.info(`ER bridge initialized`,{host:e})}catch{s.info(`ER bridge initialized`)}return{client:e,cache:n,pushAdapter:r,config:t}}catch(e){s.warn(`ER bridge initialization failed`,r(e));return}}function u(n,i,a){let o=e(`er_push`);n.registerTool(`er_push`,{title:o.title,description:`Push a curated knowledge entry to Enterprise RAG. The entry is stored via ER's curated_remember tool and becomes immediately searchable in the enterprise AI Kit.`,inputSchema:{title:t.string().min(3).max(120).describe(`Title for the knowledge entry`),content:t.string().min(10).max(1e5).describe(`Markdown content to push (max 100KB)`),category:t.string().regex(/^[a-z][a-z0-9-]*$/).default(`conventions`).describe(`Category slug (e.g., "decisions", "patterns", "conventions")`),tags:t.array(t.string()).default([]).describe(`Optional tags`),rule_id:t.string().optional().describe(`ID of the classification rule that motivated this push (from remember classification signals). Improves rule effectiveness tracking.`)},annotations:o.annotations},async({title:e,content:t,category:n,tags:o,rule_id:c})=>{try{let r=`${n}/${e.toLowerCase().replace(/[^a-z0-9]+/g,`-`)}`,s=await i.pushAdapter.push(r,{title:e,content:t,category:n,tags:o});return s.pushed?(a&&a.recordPush(r,s.pushed,c),{content:[{type:`text`,text:`Pushed to ER: **${e}**\n\nRemote path: \`${s.remotePath??`unknown`}\`\nTimestamp: ${s.timestamp}\n\n---\n_Next: Use \`er_pull\` to verify the entry is searchable in ER, or \`er_sync_status\` to see push history._`}]}):(a&&a.recordPush(r,!1,c),{content:[{type:`text`,text:`ER push failed: ${s.error??`Unknown error`}\n\n_The local AI Kit is unaffected. You can retry or check ER health with \`er_sync_status\`._`}],isError:!0})}catch(t){if(s.error(`ER push failed`,r(t)),a){let t=`${n}/${e.toLowerCase().replace(/[^a-z0-9]+/g,`-`)}`;a.recordPush(t,!1,c)}return{content:[{type:`text`,text:`ER push failed: operation unsuccessful
2
2
 
3
- _The local KB is unaffected. You can retry or check ER health with \`er_sync_status\`._`}],isError:!0}}})}function d(n,i){let a=e(`er_pull`);n.registerTool(`er_pull`,{title:a.title,description:`Explicitly search the Enterprise RAG knowledge base. Returns results from the enterprise system only (not local KB). Uses a cache with 6-hour TTL to reduce API calls.`,inputSchema:{query:t.string().min(1).max(2e3).describe(`Search query for ER knowledge base (max 2000 chars)`),max_results:t.number().min(1).max(20).default(5).describe(`Maximum results to return`),bypass_cache:t.boolean().default(!0).describe(`Skip cache and fetch fresh results from ER (default: true per DR-001)`)},annotations:a.annotations},async({query:e,max_results:t,bypass_cache:n})=>{try{if(!n){let n=i.cache.get(e);if(n)return{content:[{type:`text`,text:`${n.slice(0,t).map((e,t)=>`### Result ${t+1} (score: ${e.score.toFixed(3)}, source: ER cached)\n- **Source**: ${e.sourcePath}\n\n${e.content}`).join(`
3
+ _The local AI Kit is unaffected. You can retry or check ER health with \`er_sync_status\`._`}],isError:!0}}})}function d(n,i){let a=e(`er_pull`);n.registerTool(`er_pull`,{title:a.title,description:`Explicitly search the Enterprise RAG AI Kit. Returns results from the enterprise system only (not local AI Kit). Uses a cache with 6-hour TTL to reduce API calls.`,inputSchema:{query:t.string().min(1).max(2e3).describe(`Search query for Enterprise RAG AI Kit (max 2000 chars)`),max_results:t.number().min(1).max(20).default(5).describe(`Maximum results to return`),bypass_cache:t.boolean().default(!0).describe(`Skip cache and fetch fresh results from ER (default: true per DR-001)`)},annotations:a.annotations},async({query:e,max_results:t,bypass_cache:n})=>{try{if(!n){let n=i.cache.get(e);if(n)return{content:[{type:`text`,text:`${n.slice(0,t).map((e,t)=>`### Result ${t+1} (score: ${e.score.toFixed(3)}, source: ER cached)\n- **Source**: ${e.sourcePath}\n\n${e.content}`).join(`
4
4
 
5
5
  ---
6
6
 
@@ -10,6 +10,6 @@ _The local KB is unaffected. You can retry or check ER health with \`er_sync_sta
10
10
 
11
11
  `)}\n\n---\n_Source: Enterprise RAG (${r.length} results) | Results cached for ${Math.floor(i.config.cacheTtlMs/36e5)}h_`}]}}catch(e){return s.error(`ER pull failed`,r(e)),{content:[{type:`text`,text:`ER pull failed: search request unsuccessful
12
12
 
13
- _Enterprise RAG may be unavailable. Local KB search is unaffected._`}],isError:!0}}})}function f(n,i){let a=e(`er_sync_status`);n.registerTool(`er_sync_status`,{title:a.title,description:`Show the status of the Enterprise RAG bridge: health, cache stats, and push history.`,inputSchema:{check_health:t.boolean().default(!0).describe(`Whether to ping ER health endpoint (adds latency)`)},annotations:a.annotations},async({check_health:e})=>{try{let t=i.cache.stats(),n=i.pushAdapter.getStatus(),r=new URL(i.config.baseUrl),a=`${r.protocol}//${r.hostname}${r.port?`:${r.port}`:``}`,o=`_Health check skipped_`;if(e){let e=await i.client.health();o=e.healthy?`✅ Healthy (HTTP ${e.status})`:`❌ Unhealthy${e.status?` (HTTP ${e.status})`:``}`}let s=[`## ER Bridge Status
13
+ _Enterprise RAG may be unavailable. Local AI Kit search is unaffected._`}],isError:!0}}})}function f(n,i){let a=e(`er_sync_status`);n.registerTool(`er_sync_status`,{title:a.title,description:`Show the status of the Enterprise RAG bridge: health, cache stats, and push history.`,inputSchema:{check_health:t.boolean().default(!0).describe(`Whether to ping ER health endpoint (adds latency)`)},annotations:a.annotations},async({check_health:e})=>{try{let t=i.cache.stats(),n=i.pushAdapter.getStatus(),r=new URL(i.config.baseUrl),a=`${r.protocol}//${r.hostname}${r.port?`:${r.port}`:``}`,o=`_Health check skipped_`;if(e){let e=await i.client.health();o=e.healthy?`✅ Healthy (HTTP ${e.status})`:`❌ Unhealthy${e.status?` (HTTP ${e.status})`:``}`}let s=[`## ER Bridge Status
14
14
  `,`**Endpoint**: \`${a}\``,`**Health**: ${o}`,`**Threshold**: ${i.config.fallbackThreshold} (vector similarity for auto-fallback)`,``,`### Cache`,`- Entries: ${t.size} / ${t.maxEntries}`,`- TTL: ${Math.floor(t.defaultTtlMs/36e5)}h`,``,`### Push History`,`- Total pushed: ${n.totalPushed}`,`- Successful: ${n.successCount}`,`- Failed: ${n.failCount}`];return n.lastPush&&s.push(`- Last push: "${n.lastPush.title}" at ${n.lastPush.pushedAt} (${n.lastPush.status})`),s.push("\n---\n_Next: Use `er_push` to send knowledge to ER, or `er_pull` to search ER._"),{content:[{type:`text`,text:s.join(`
15
15
  `)}]}}catch(e){return s.error(`ER sync status failed`,r(e)),{content:[{type:`text`,text:`ER sync status failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}export{l as initBridgeComponents,d as registerErPullTool,u as registerErPushTool,f as registerErSyncStatusTool,c as resolveErBridgeConfig};
@@ -0,0 +1,8 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { KBConfig } from "../../../core/dist/index.js";
3
+
4
+ //#region packages/server/src/tools/config.tool.d.ts
5
+ type KBServer = McpServer;
6
+ declare function registerConfigTool(server: KBServer, config: KBConfig): void;
7
+ //#endregion
8
+ export { registerConfigTool };
@@ -0,0 +1,12 @@
1
+ import{getToolMeta as e}from"../tool-metadata.js";import{buildDashboardHtml as t,buildFormHtml as n}from"./present/templates.js";import{existsSync as r,readFileSync as i,writeFileSync as a}from"node:fs";import{resolve as o}from"node:path";import{z as s}from"zod";import{createLogger as c}from"../../../core/dist/index.js";import{RESOURCE_MIME_TYPE as l,registerAppResource as u,registerAppTool as d}from"@modelcontextprotocol/ext-apps/server";const f=s.object({action:s.enum([`view`,`update`]).default(`view`).describe(`Action to perform: view current configuration or update it`),updates:s.record(s.string(),s.unknown()).optional().describe(`Partial configuration to merge when action is "update". Supports nested paths like { "indexing": { "chunkSize": 2000 } }`)}),p=c(`config-tool`),m=`ui://aikit/config.html`,h=[`serverName`,`toolPrefix`,`autoIndex`,`sources`,`indexing`];function g(){let e=process.env.AIKIT_CONFIG_PATH;if(e&&r(e))return e;let t=o(process.cwd(),`aikit.config.json`);return r(t)?t:``}function _(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function v(e,t){let n={...e};for(let[e,r]of Object.entries(t)){let t=n[e];if(_(t)&&_(r)){n[e]=v(t,r);continue}n[e]=r}return n}function y(e){return e===void 0?`undefined`:JSON.stringify(e)}function b(e,t,n,r=``){let i=[];for(let[a,o]of Object.entries(n)){let n=r?`${r}.${a}`:a,s=e[a],c=t[a];if(_(o)&&_(s)&&_(c)){i.push(...b(s,c,o,n));continue}y(s)!==y(c)&&i.push(`- ${n}: ${y(s)} -> ${y(c)}`)}return i}function x(e){let t=[];for(let[n,r]of Object.entries(e)){if(n===`store`||n===`embedding`||n===`er`){t.push(`Field "${n}" cannot be updated through this tool because it requires a restart.`);continue}if(n===`onboardDir`||n===`stateDir`||n===`curated`){t.push(`Field "${n}" cannot be updated through this tool because it requires a restart.`);continue}if(n===`autoIndex`){typeof r!=`boolean`&&t.push(`autoIndex must be a boolean.`);continue}if(n===`serverName`||n===`toolPrefix`){typeof r!=`string`&&t.push(`${n} must be a string.`);continue}if(n===`sources`){(!Array.isArray(r)||r.length===0)&&t.push(`sources must be a non-empty array.`);continue}if(n===`indexing`){if(!_(r)){t.push(`indexing must be an object.`);continue}for(let[e,n]of Object.entries(r)){if(e!==`chunkSize`&&e!==`chunkOverlap`&&e!==`minChunkSize`&&e!==`concurrency`){t.push(`indexing.${e} is not updatable through this tool.`);continue}(typeof n!=`number`||!Number.isFinite(n)||n<=0)&&t.push(`indexing.${e} must be a positive number.`)}continue}t.push(`Field "${n}" is not updatable through this tool.`)}return t}function S(e){let t=[];if(`autoIndex`in e&&typeof e.autoIndex!=`boolean`&&t.push(`autoIndex must be a boolean.`),`serverName`in e&&e.serverName!==void 0&&typeof e.serverName!=`string`&&t.push(`serverName must be a string.`),`toolPrefix`in e&&e.toolPrefix!==void 0&&typeof e.toolPrefix!=`string`&&t.push(`toolPrefix must be a string.`),(!Array.isArray(e.sources)||e.sources.length===0)&&t.push(`sources must be a non-empty array.`),!_(e.indexing))return t.push(`indexing must be an object.`),t;for(let n of[`chunkSize`,`chunkOverlap`,`minChunkSize`,`concurrency`]){let r=e.indexing[n];r!==void 0&&(typeof r!=`number`||!Number.isFinite(r)||r<=0)&&t.push(`indexing.${n} must be a positive number.`)}return t}function C(e){let t=JSON.parse(i(e,`utf-8`));if(!_(t))throw Error(`Config file must contain a JSON object.`);return t}function w(e,t){return[`AI Kit Configuration`,`Config file: ${t}`,``,JSON.stringify(e,null,2)].join(`
2
+ `)}function T(e){return e===void 0?``:_(e)||Array.isArray(e)?JSON.stringify(e,null,2):String(e)}function E(e){return t({metrics:Object.entries(e).map(([e,t])=>({label:e,value:_(t)||Array.isArray(t)?JSON.stringify(t,null,2):String(t),status:`info`}))})}function D(e){return n({fields:h.map(t=>{let n=e[t];return typeof n==`boolean`?{name:t,label:t,type:`select`,options:[`true`,`false`],value:String(n)}:{name:t,label:t,type:_(n)||Array.isArray(n)?`textarea`:`text`,value:T(n)}})})}function O(e,t){return`<!DOCTYPE html><html><head><meta charset="utf-8"><title>${e}</title><style>:root{--aikit-bg:#1e1e1e;--aikit-surface:#252526;--aikit-surface2:#2d2d30;--aikit-border:#3c3c3c;--aikit-text:#e5e7eb;--aikit-muted:#9ca3af;--aikit-accent:#60a5fa;--aikit-success:#22c55e;font-family:system-ui,sans-serif}body{margin:0;padding:20px;background:var(--aikit-bg);color:var(--aikit-text);font-family:system-ui,sans-serif}h2{margin:0 0 16px}</style></head><body><h2>${e}</h2>${t}</body></html>`}function k(e,t,n){u(e,`AI Kit Config App`,m,{description:`View and update AI Kit configuration`},async()=>({contents:[{uri:m,mimeType:l,text:O(t,n)}]}))}function A(t,n){let r=e(`config`);d(t,`config`,{title:r.title,description:`View and update AI Kit server configuration. Use action "view" to see current settings, or "update" to modify configuration values. Changes are written to aikit.config.json and take effect on next server restart. Some settings (store, embedding) require a full restart.`,inputSchema:f,annotations:r.annotations,_meta:{ui:{resourceUri:m}}},async e=>{let{action:r,updates:i}=e;if(r===`view`){let e=g(),r=e||`(runtime config only; no aikit.config.json found)`;try{let i=e?C(e):n,a=w(i,r);return k(t,`Configuration`,E(i)),{content:[{type:`text`,text:a}],ui:{type:`resource`,uri:m}}}catch(t){return p.error(`Failed to read config for view`,{configPath:e,error:t instanceof Error?t.message:String(t)}),{content:[{type:`text`,text:`Failed to read configuration from ${r}: ${t instanceof Error?t.message:String(t)}`}]}}}if(!i)return k(t,`Configuration Form`,D(n)),{content:[{type:`text`,text:`No updates provided. Pass an updates object when action is "update".`}],ui:{type:`resource`,uri:m}};let o=g();if(!o)return k(t,`Configuration Form`,D(n)),{content:[{type:`text`,text:`No config file found to update.`}],ui:{type:`resource`,uri:m}};let s=x(i);if(s.length>0)return k(t,`Configuration Form`,D(C(o))),{content:[{type:`text`,text:`Configuration update rejected:\n${s.map(e=>`- ${e}`).join(`
3
+ `)}`}],ui:{type:`resource`,uri:m}};try{let e=C(o),n=v(e,i),r=S(n);if(r.length>0)return k(t,`Configuration Form`,D(e)),{content:[{type:`text`,text:`Configuration update rejected:\n${r.map(e=>`- ${e}`).join(`
4
+ `)}`}],ui:{type:`resource`,uri:m}};a(o,JSON.stringify(n,null,2),`utf-8`);let s=b(e,n,i),c=`Configuration updated successfully.
5
+
6
+ Config file: ${o}
7
+
8
+ Changed values:
9
+ ${s.length>0?s.join(`
10
+ `):`- No effective changes; requested values already matched the file.`}
11
+
12
+ These changes take effect on the next server restart.`;return k(t,`Configuration`,E(n)),{content:[{type:`text`,text:c}],ui:{type:`resource`,uri:m}}}catch(e){return p.error(`Failed to update config`,{configPath:o,error:e instanceof Error?e.message:String(e)}),{content:[{type:`text`,text:`Failed to update configuration in ${o}: ${e instanceof Error?e.message:String(e)}`}]}}})}export{A as registerConfigTool};