@vpxa/kb 0.1.30 → 0.1.31

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 (41) hide show
  1. package/package.json +1 -1
  2. package/packages/analyzers/dist/dependency-analyzer.js +3 -3
  3. package/packages/analyzers/dist/entry-point-analyzer.js +3 -3
  4. package/packages/analyzers/dist/pattern-analyzer.js +2 -2
  5. package/packages/analyzers/dist/structure-analyzer.js +2 -2
  6. package/packages/chunker/dist/wasm/languages.js +1 -1
  7. package/packages/chunker/wasm/tree-sitter-c.wasm +0 -0
  8. package/packages/chunker/wasm/tree-sitter-c_sharp.wasm +0 -0
  9. package/packages/chunker/wasm/tree-sitter-cpp.wasm +0 -0
  10. package/packages/chunker/wasm/tree-sitter-kotlin.wasm +0 -0
  11. package/packages/chunker/wasm/tree-sitter-php.wasm +0 -0
  12. package/packages/chunker/wasm/tree-sitter-ruby.wasm +0 -0
  13. package/packages/chunker/wasm/tree-sitter-scala.wasm +0 -0
  14. package/packages/chunker/wasm/tree-sitter-swift.wasm +0 -0
  15. package/packages/server/dist/auto-gc.d.ts +30 -0
  16. package/packages/server/dist/auto-gc.js +1 -0
  17. package/packages/server/dist/index.js +1 -1
  18. package/packages/server/dist/replay-interceptor.d.ts +14 -1
  19. package/packages/server/dist/replay-interceptor.js +1 -1
  20. package/packages/server/dist/server.js +2 -2
  21. package/packages/server/dist/tools/context.tools.js +2 -2
  22. package/packages/server/dist/tools/forge.tools.js +1 -1
  23. package/packages/server/dist/tools/present-utils.js +1 -1
  24. package/packages/server/dist/tools/present.tool.js +3 -2
  25. package/packages/server/dist/tools/search.tool.js +5 -5
  26. package/packages/server/dist/tools/status.tool.d.ts +7 -1
  27. package/packages/server/dist/tools/status.tool.js +3 -2
  28. package/packages/server/dist/version-check.d.ts +9 -1
  29. package/packages/server/dist/version-check.js +1 -1
  30. package/packages/tools/dist/compact.d.ts +2 -0
  31. package/packages/tools/dist/compact.js +2 -2
  32. package/packages/tools/dist/index.d.ts +2 -2
  33. package/packages/tools/dist/index.js +1 -1
  34. package/packages/tools/dist/text-utils.d.ts +7 -1
  35. package/packages/tools/dist/text-utils.js +1 -1
  36. package/packages/tui/dist/{App-DXY0-tlW.js → App-DGdjV2_f.js} +1 -1
  37. package/packages/tui/dist/App.js +1 -1
  38. package/packages/tui/dist/LogPanel-akibVigF.js +3 -0
  39. package/packages/tui/dist/index.js +1 -1
  40. package/packages/tui/dist/panels/LogPanel.js +1 -1
  41. package/packages/tui/dist/LogPanel-D6u6o84n.js +0 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vpxa/kb",
3
- "version": "0.1.30",
3
+ "version": "0.1.31",
4
4
  "type": "module",
5
5
  "description": "Local-first AI developer toolkit — knowledge base, code analysis, context management, and developer tools for LLM agents",
6
6
  "license": "MIT",
@@ -1,8 +1,8 @@
1
- import{readFile as e,readdir as t}from"node:fs/promises";import{dirname as n,extname as r,join as i,relative as a,resolve as o}from"node:path";import{SUPPORTED_EXTENSIONS as s,WasmRuntime as c,extractImports as l}from"../../chunker/dist/index.js";const u=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.mjs`,`.cjs`,`.py`,`.java`,`.go`,`.cs`,`.kt`,`.scala`,`.rb`,`.rs`,`.php`,`.swift`]),d=[{regex:/import\s+(?:(?:type\s+)?(?:(?:\{[^}]*\}|[\w*]+)\s+from\s+)?)['"]([^'"]+)['"]/g,confidence:`high`},{regex:/import\(\s*['"]([^'"]+)['"]\s*\)/g,confidence:`medium`},{regex:/require\(\s*['"]([^'"]+)['"]\s*\)/g,confidence:`medium`},{regex:/^from\s+([\w.]+)\s+import\b/gm,confidence:`high`,lang:`python`},{regex:/^import\s+([\w.]+)\s*$/gm,confidence:`high`,lang:`python`},{regex:/^import\s+(?:static\s+)?([\w.]+(?:\.\*)?)\s*;/gm,confidence:`high`,lang:`java`},{regex:/(?:^import\s+|^\s+)[""]([^""]+)[""]/gm,confidence:`high`,lang:`go`},{regex:/^using\s+(?:static\s+)?([\w.]+)\s*;/gm,confidence:`high`,lang:`csharp`},{regex:/^use\s+([\w:]+(?:::\w+)*)/gm,confidence:`high`,lang:`rust`},{regex:/^use\s+([\w\\]+)\s*;/gm,confidence:`high`,lang:`php`},{regex:/require(?:_relative)?\s+['"]([^'"]+)['"]/g,confidence:`medium`,lang:`ruby`},{regex:/^import\s+(\w+)\s*$/gm,confidence:`high`,lang:`swift`}],f=new Set([`node_modules`,`.git`,`dist`,`build`,`coverage`,`.turbo`,`.cache`,`cdk.out`]),p=[/\.(test|spec)\.[jt]sx?$/,/\/__tests__\//,/\/test\//,/\/tests\//],m={".ts":`js`,".tsx":`js`,".js":`js`,".jsx":`js`,".mjs":`js`,".cjs":`js`,".py":`python`,".java":`java`,".kt":`java`,".scala":`java`,".go":`go`,".cs":`csharp`,".rs":`rust`,".php":`php`,".rb":`ruby`,".swift":`swift`};function h(e,t){return!t||t===`js`?!e.startsWith(`.`)&&!e.startsWith(`/`):t===`python`?!e.startsWith(`.`):t===`java`?!e.startsWith(`com.`)||e.startsWith(`com.amazonaws`)||e.startsWith(`com.google`)||e.startsWith(`com.fasterxml`):t===`go`?e.includes(`.`)&&!e.startsWith(`.`):t===`csharp`?e.startsWith(`System`)||e.startsWith(`Microsoft`)||e.startsWith(`Newtonsoft`)||e.startsWith(`Amazon`):t===`rust`?!e.startsWith(`crate::`)&&!e.startsWith(`self::`)&&!e.startsWith(`super::`):!0}function g(e){return p.some(t=>t.test(e))}var _=class{name=`dependencies`;workspacePackages=new Map;async analyze(t,n={}){let{format:i=`markdown`}=n,o=Date.now();this.workspacePackages=await this.buildWorkspaceMap(t);let u=!1;try{await c.ensure(),u=!0}catch{}let d=await this.collectFiles(t),f=[];for(let n of d){let i=await e(n,`utf-8`),o=r(n).toLowerCase(),c=a(t,n).replace(/\\/g,`/`);if(u&&s.has(o)){let e=await l(i,o,c);if(e.length>0)f.push(...e);else{let e=this.extractImportsRegex(i,n,t);f.push(...e)}}else{let e=this.extractImportsRegex(i,n,t);f.push(...e)}}let p=this.groupExternalDeps(f),m=this.groupInternalDeps(f,t),h=this.buildReverseGraph(f,t),g=this.buildTestCoverage(f,t);return{output:i===`json`?JSON.stringify({external:p,internal:m,reverseGraph:h,testCoverage:g},null,2):i===`mermaid`?this.formatMermaid(m):this.formatMarkdown(p,m,t,g),data:{external:p,internal:m,reverseGraph:h,testCoverage:g,totalImports:f.length},meta:{analyzedAt:new Date().toISOString(),scope:t,fileCount:d.length,durationMs:Date.now()-o}}}async collectFiles(e){let n=[],a=async e=>{let o=await t(e,{withFileTypes:!0});for(let t of o){if(f.has(t.name)||t.name.startsWith(`.`))continue;let o=i(e,t.name);t.isDirectory()?await a(o):u.has(r(t.name))&&n.push(o)}};return await a(e),n}extractImportsRegex(e,t,n){let i=[],o=m[r(t).toLowerCase()];for(let r of d){if(r.lang&&r.lang!==o||!r.lang&&o&&o!==`js`)continue;let s=new RegExp(r.regex.source,r.regex.flags),c;for(;(c=s.exec(e))!==null;){let e=c[1],s=h(e,o);i.push({source:e,specifiers:[],filePath:a(n,t).replace(/\\/g,`/`),isExternal:s,confidence:r.confidence})}}return i}groupExternalDeps(e){let t={};for(let n of e){if(!n.isExternal)continue;let e=m[r(n.filePath).toLowerCase()],i;if(e===`java`){let e=n.source.split(`.`);for(;e.length>1;){let t=e[e.length-1];if(t===`*`||/^[A-Z]/.test(t))e.pop();else break}i=e.length>=2?e.slice(0,2).join(`.`):e.join(`.`)}else if(e===`python`)i=n.source.split(`.`)[0];else if(e===`go`)i=n.source;else if(e===`csharp`){let e=n.source.split(`.`);i=e.length>=2?e.slice(0,2).join(`.`):n.source}else i=n.source.startsWith(`@`)?n.source.split(`/`).slice(0,2).join(`/`):n.source.split(`/`)[0];t[i]||(t[i]={count:0,confidence:n.confidence,usedBy:new Set}),t[i].count++,t[i].usedBy.add(n.filePath),n.confidence===`high`?t[i].confidence=`high`:n.confidence===`medium`&&t[i].confidence===`low`&&(t[i].confidence=`medium`)}let n={};for(let[e,r]of Object.entries(t))n[e]={count:r.count,confidence:r.confidence,usedBy:[...r.usedBy]};return n}groupInternalDeps(e,t){let n={};for(let t of e)t.isExternal||(n[t.filePath]||(n[t.filePath]=new Set),n[t.filePath].add(t.source));let r={};for(let[e,t]of Object.entries(n))r[e]=[...t];return r}buildReverseGraph(e,t){let r={};for(let t of e){let e=n(t.filePath),i=this.resolveImportPath(t.source,e);i&&(r[i]||(r[i]=new Set),r[i].add(t.filePath))}let i={};for(let[e,t]of Object.entries(r))i[e]=[...t];return i}buildTestCoverage(e,t){let r={};for(let t of e){if(!g(t.filePath))continue;let e=n(t.filePath),i=this.resolveImportPath(t.source,e);!i||g(i)||(r[i]||(r[i]=new Set),r[i].add(t.filePath))}let i={};for(let[e,t]of Object.entries(r))i[e]=[...t];return i}resolveImportPath(e,t){if(e.startsWith(`.`))return i(t,e).replace(/\\/g,`/`).replace(/\.[jt]sx?$/,``);let n=e.startsWith(`@`)?e.split(`/`).slice(0,2).join(`/`):e.split(`/`)[0],r=this.workspacePackages.get(n);return r?r.replace(/\.[jt]sx?$/,``):null}async buildWorkspaceMap(n){let r=new Map;for(let s of[`packages`,`functions`,`libs`,`apps`,`cdk`]){let c=i(n,s);try{let s=await t(c,{withFileTypes:!0});for(let t of s)if(!(!t.isDirectory()||f.has(t.name)))try{let s=i(c,t.name,`package.json`),l=JSON.parse(await e(s,`utf-8`));if(l.name){let e=l.main??l.exports?.[`.`]??`src/index.ts`,i=a(n,o(c,t.name,e)).replace(/\\/g,`/`);r.set(l.name,i)}}catch{}}catch{}}return r}formatMarkdown(e,t,n,r){let i=[];i.push(`## Dependencies: ${n}\n`);let a=Object.entries(e).sort((e,t)=>t[1].count-e[1].count),o=a.length,s=a.reduce((e,[,t])=>e+t.count,0),c=a.slice(0,5).map(([e])=>e);i.push(`**${o} external packages**, **${s} total imports**, **${Object.keys(t).length} files** with internal imports.\n`),c.length>0&&i.push(`**Top dependencies**: ${c.join(`, `)}\n`),i.push(`### External Dependencies
2
- `),i.push(`| Package | Imports | Used By |`),i.push(`|---------|---------|---------|`);for(let[e,t]of a)i.push(`| ${e} | ${t.count} | ${t.usedBy.length} ${t.usedBy.length===1?`file`:`files`} |`);if(r&&Object.keys(r).length>0){let e=Object.keys(r).length,n=Object.keys(t).filter(e=>!g(e)&&!r[e.replace(/\\.[jt]sx?$/,``)]);i.push(`
1
+ import{readFile as e,readdir as t,stat as n}from"node:fs/promises";import{dirname as r,extname as i,join as a,relative as o,resolve as s}from"node:path";import{SUPPORTED_EXTENSIONS as c,WasmRuntime as l,extractImports as u}from"../../chunker/dist/index.js";const d=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.mjs`,`.cjs`,`.py`,`.java`,`.go`,`.cs`,`.kt`,`.scala`,`.rb`,`.rs`,`.php`,`.swift`]),f=[{regex:/import\s+(?:(?:type\s+)?(?:(?:\{[^}]*\}|[\w*]+)\s+from\s+)?)['"]([^'"]+)['"]/g,confidence:`high`},{regex:/import\(\s*['"]([^'"]+)['"]\s*\)/g,confidence:`medium`},{regex:/require\(\s*['"]([^'"]+)['"]\s*\)/g,confidence:`medium`},{regex:/^from\s+([\w.]+)\s+import\b/gm,confidence:`high`,lang:`python`},{regex:/^import\s+([\w.]+)\s*$/gm,confidence:`high`,lang:`python`},{regex:/^import\s+(?:static\s+)?([\w.]+(?:\.\*)?)\s*;/gm,confidence:`high`,lang:`java`},{regex:/(?:^import\s+|^\s+)[""]([^""]+)[""]/gm,confidence:`high`,lang:`go`},{regex:/^using\s+(?:static\s+)?([\w.]+)\s*;/gm,confidence:`high`,lang:`csharp`},{regex:/^use\s+([\w:]+(?:::\w+)*)/gm,confidence:`high`,lang:`rust`},{regex:/^use\s+([\w\\]+)\s*;/gm,confidence:`high`,lang:`php`},{regex:/require(?:_relative)?\s+['"]([^'"]+)['"]/g,confidence:`medium`,lang:`ruby`},{regex:/^import\s+(\w+)\s*$/gm,confidence:`high`,lang:`swift`}],p=new Set([`node_modules`,`.git`,`dist`,`build`,`coverage`,`.turbo`,`.cache`,`cdk.out`]),m=[/\.(test|spec)\.[jt]sx?$/,/\/__tests__\//,/\/test\//,/\/tests\//],h={".ts":`js`,".tsx":`js`,".js":`js`,".jsx":`js`,".mjs":`js`,".cjs":`js`,".py":`python`,".java":`java`,".kt":`java`,".scala":`java`,".go":`go`,".cs":`csharp`,".rs":`rust`,".php":`php`,".rb":`ruby`,".swift":`swift`};function g(e,t){return!t||t===`js`?!e.startsWith(`.`)&&!e.startsWith(`/`):t===`python`?!e.startsWith(`.`):t===`java`?!e.startsWith(`com.`)||e.startsWith(`com.amazonaws`)||e.startsWith(`com.google`)||e.startsWith(`com.fasterxml`):t===`go`?e.includes(`.`)&&!e.startsWith(`.`):t===`csharp`?e.startsWith(`System`)||e.startsWith(`Microsoft`)||e.startsWith(`Newtonsoft`)||e.startsWith(`Amazon`):t===`rust`?!e.startsWith(`crate::`)&&!e.startsWith(`self::`)&&!e.startsWith(`super::`):!0}function _(e){return m.some(t=>t.test(e))}var v=class{name=`dependencies`;workspacePackages=new Map;async analyze(t,n={}){let{format:r=`markdown`}=n,a=Date.now();this.workspacePackages=await this.buildWorkspaceMap(t);let s=!1;try{await l.ensure(),s=!0}catch{}let d=await this.collectFiles(t),f=[];for(let n of d){let r=await e(n,`utf-8`),a=i(n).toLowerCase(),l=o(t,n).replace(/\\/g,`/`);if(s&&c.has(a)){let e=await u(r,a,l);if(e.length>0)f.push(...e);else{let e=this.extractImportsRegex(r,n,t);f.push(...e)}}else{let e=this.extractImportsRegex(r,n,t);f.push(...e)}}let p=this.groupExternalDeps(f),m=this.groupInternalDeps(f,t),h=this.buildReverseGraph(f,t),g=this.buildTestCoverage(f,t);return{output:r===`json`?JSON.stringify({external:p,internal:m,reverseGraph:h,testCoverage:g},null,2):r===`mermaid`?this.formatMermaid(m):this.formatMarkdown(p,m,t,g),data:{external:p,internal:m,reverseGraph:h,testCoverage:g,totalImports:f.length},meta:{analyzedAt:new Date().toISOString(),scope:t,fileCount:d.length,durationMs:Date.now()-a}}}async collectFiles(e){let r=[],o=async e=>{if(!(await n(e).catch(()=>null))?.isDirectory())return;let s=await t(e,{withFileTypes:!0});for(let t of s){if(p.has(t.name)||t.name.startsWith(`.`))continue;let n=a(e,t.name);t.isDirectory()?await o(n):d.has(i(t.name))&&r.push(n)}};return await o(e),r}extractImportsRegex(e,t,n){let r=[],a=h[i(t).toLowerCase()];for(let i of f){if(i.lang&&i.lang!==a||!i.lang&&a&&a!==`js`)continue;let s=new RegExp(i.regex.source,i.regex.flags),c;for(;(c=s.exec(e))!==null;){let e=c[1],s=g(e,a);r.push({source:e,specifiers:[],filePath:o(n,t).replace(/\\/g,`/`),isExternal:s,confidence:i.confidence})}}return r}groupExternalDeps(e){let t={};for(let n of e){if(!n.isExternal)continue;let e=h[i(n.filePath).toLowerCase()],r;if(e===`java`){let e=n.source.split(`.`);for(;e.length>1;){let t=e[e.length-1];if(t===`*`||/^[A-Z]/.test(t))e.pop();else break}r=e.length>=2?e.slice(0,2).join(`.`):e.join(`.`)}else if(e===`python`)r=n.source.split(`.`)[0];else if(e===`go`)r=n.source;else if(e===`csharp`){let e=n.source.split(`.`);r=e.length>=2?e.slice(0,2).join(`.`):n.source}else r=n.source.startsWith(`@`)?n.source.split(`/`).slice(0,2).join(`/`):n.source.split(`/`)[0];t[r]||(t[r]={count:0,confidence:n.confidence,usedBy:new Set}),t[r].count++,t[r].usedBy.add(n.filePath),n.confidence===`high`?t[r].confidence=`high`:n.confidence===`medium`&&t[r].confidence===`low`&&(t[r].confidence=`medium`)}let n={};for(let[e,r]of Object.entries(t))n[e]={count:r.count,confidence:r.confidence,usedBy:[...r.usedBy]};return n}groupInternalDeps(e,t){let n={};for(let t of e)t.isExternal||(n[t.filePath]||(n[t.filePath]=new Set),n[t.filePath].add(t.source));let r={};for(let[e,t]of Object.entries(n))r[e]=[...t];return r}buildReverseGraph(e,t){let n={};for(let t of e){let e=r(t.filePath),i=this.resolveImportPath(t.source,e);i&&(n[i]||(n[i]=new Set),n[i].add(t.filePath))}let i={};for(let[e,t]of Object.entries(n))i[e]=[...t];return i}buildTestCoverage(e,t){let n={};for(let t of e){if(!_(t.filePath))continue;let e=r(t.filePath),i=this.resolveImportPath(t.source,e);!i||_(i)||(n[i]||(n[i]=new Set),n[i].add(t.filePath))}let i={};for(let[e,t]of Object.entries(n))i[e]=[...t];return i}resolveImportPath(e,t){if(e.startsWith(`.`))return a(t,e).replace(/\\/g,`/`).replace(/\.[jt]sx?$/,``);let n=e.startsWith(`@`)?e.split(`/`).slice(0,2).join(`/`):e.split(`/`)[0],r=this.workspacePackages.get(n);return r?r.replace(/\.[jt]sx?$/,``):null}async buildWorkspaceMap(n){let r=new Map;for(let i of[`packages`,`functions`,`libs`,`apps`,`cdk`]){let c=a(n,i);try{let i=await t(c,{withFileTypes:!0});for(let t of i)if(!(!t.isDirectory()||p.has(t.name)))try{let i=a(c,t.name,`package.json`),l=JSON.parse(await e(i,`utf-8`));if(l.name){let e=l.main??l.exports?.[`.`]??`src/index.ts`,i=o(n,s(c,t.name,e)).replace(/\\/g,`/`);r.set(l.name,i)}}catch{}}catch{}}return r}formatMarkdown(e,t,n,r){let i=[];i.push(`## Dependencies: ${n}\n`);let a=Object.entries(e).sort((e,t)=>t[1].count-e[1].count),o=a.length,s=a.reduce((e,[,t])=>e+t.count,0),c=a.slice(0,5).map(([e])=>e);i.push(`**${o} external packages**, **${s} total imports**, **${Object.keys(t).length} files** with internal imports.\n`),c.length>0&&i.push(`**Top dependencies**: ${c.join(`, `)}\n`),i.push(`### External Dependencies
2
+ `),i.push(`| Package | Imports | Used By |`),i.push(`|---------|---------|---------|`);for(let[e,t]of a)i.push(`| ${e} | ${t.count} | ${t.usedBy.length} ${t.usedBy.length===1?`file`:`files`} |`);if(r&&Object.keys(r).length>0){let e=Object.keys(r).length,n=Object.keys(t).filter(e=>!_(e)&&!r[e.replace(/\\.[jt]sx?$/,``)]);i.push(`
3
3
  ### Test Coverage Summary
4
4
  `),i.push(`**${e} source modules** with test coverage.`),n.length>0&&i.push(`**${n.length} source files** with no detected test coverage.`);let a=Object.entries(r).sort((e,t)=>t[1].length-e[1].length);i.push(`
5
5
  **Most-tested modules:**
6
6
  `);for(let[e,t]of a.slice(0,10)){let n=e.replace(/\/dist\/[^/]*$/,`/src/index`).replace(/\.mjs$/,`.ts`);i.push(`- ${n} (${t.length} ${t.length===1?`test`:`tests`})`)}}return i.join(`
7
7
  `)}formatMermaid(e){let t=[`graph LR`],n=e=>e.replace(/[^a-zA-Z0-9]/g,`_`);for(let[r,i]of Object.entries(e).slice(0,40)){let e=n(r);for(let a of i){let i=n(a);t.push(` ${e}["${r}"] --> ${i}["${a}"]`)}}return t.join(`
8
- `)}};export{_ as DependencyAnalyzer};
8
+ `)}};export{v as DependencyAnalyzer};
@@ -1,4 +1,4 @@
1
- import{access as e,readFile as t,readdir as n}from"node:fs/promises";import{extname as r,join as i,relative as a,resolve as o}from"node:path";import{SUPPORTED_EXTENSIONS as s,WasmRuntime as c,detectEntryPoints as l}from"../../chunker/dist/index.js";const u=new Set([`node_modules`,`.git`,`dist`,`build`,`coverage`,`.turbo`,`.cache`,`cdk.out`,`__pycache__`,`.venv`,`target`,`bin`,`obj`,`.gradle`,`venv`,`env`]),d=new Set([`test`,`tests`,`__tests__`,`spec`,`specs`,`test-utils`]),f=[/export\s+const\s+(handler|main)\s*(?::[^=]*)?\s*=/,/export\s+(?:async\s+)?function\s+(handler|main)\s*\(/,/export\s+const\s+(\w+Handler)\s*(?::[^=]*)?\s*=/,/export\s+default\s+app/,/^app\s*=\s*(?:Flask|FastAPI)\s*\(/m,/^urlpatterns\s*=\s*\[/m,/^if\s+__name__\s*==\s*['"]__main__['"]:/m,/public\s+static\s+void\s+main\s*\(\s*String/,/@SpringBootApplication/,/^func\s+main\s*\(\s*\)/m],p=/export\s+(?:default\s+)?class\s+(\w+)\s+extends\s+(?:Construct|Stack|NestedStack|Stage)/,m=[/from\s+['"]vitest['"]/,/from\s+['"]jest['"]/,/from\s+['"]mocha['"]/,/import\s+.*['"]@jest\/globals['"]/,/require\s*\(\s*['"](?:vitest|jest|mocha)['"]\s*\)/],h=[{regex:/SqsEventSource|SQSEvent|sqs/i,trigger:`SQS`},{regex:/SnsEventSource|SNSEvent|sns/i,trigger:`SNS`},{regex:/ApiGateway|APIGatewayEvent|httpApi|restApi/i,trigger:`API Gateway`},{regex:/ScheduleExpression|EventBridgeRule|schedule/i,trigger:`EventBridge Schedule`},{regex:/S3EventSource|S3Event|s3/i,trigger:`S3`},{regex:/DynamoEventSource|DynamoDBStream/i,trigger:`DynamoDB Stream`},{regex:/@RequestMapping|@GetMapping|@PostMapping/i,trigger:`HTTP Endpoint`},{regex:/http\.ListenAndServe|gin\.Default|echo\.New/i,trigger:`HTTP Server`},{regex:/app\.route\(|@app\.get|@app\.post|@router\./i,trigger:`HTTP Route`}];var g=class{name=`entry-points`;async analyze(e,t={}){let n=Date.now(),r=[],i=await this.findWorkspacePackages(e);if(i.length>0)for(let t of i){let n=await this.fromPackageJson(t,e);r.push(...n)}else{let t=await this.fromPackageJson(e,e);r.push(...t)}let a=await this.fromHandlerExports(e);return r.push(...a),{output:this.formatMarkdown(r,e),data:{entryPoints:r,total:r.length},meta:{analyzedAt:new Date().toISOString(),scope:e,fileCount:r.length,durationMs:Date.now()-n}}}async fromPackageJson(n,r){let o=[],s=a(r,n).replace(/\\/g,`/`)||`.`;try{let r=i(n,`package.json`);await e(r);let a=JSON.parse(await t(r,`utf-8`)),c=s===`.`?``:`${s}/`;if(a.main&&o.push({name:a.name?`${a.name}:main`:`main`,type:`main`,filePath:`${c}${a.main}`}),a.bin){let e=typeof a.bin==`string`?{[a.name??`cli`]:a.bin}:a.bin;for(let[t,n]of Object.entries(e))o.push({name:t,type:`cli`,filePath:`${c}${n}`})}if(a.exports){let e=this.parseExportsField(a.exports,a.name??s,c);o.push(...e)}a.scripts?.start&&o.push({name:a.name?`${a.name}:start`:`start`,type:`server`,filePath:a.scripts.start,trigger:`npm start`})}catch{}return o}parseExportsField(e,t,n){let r=[];if(typeof e==`string`)return r.push({name:t,type:`main`,filePath:`${n}${e}`}),r;if(typeof e!=`object`||!e)return r;for(let[i,a]of Object.entries(e)){if(!i.startsWith(`.`))continue;let e=i===`.`?t:`${t}/${i.slice(2)}`,o=this.resolveExportValue(a);o&&r.push({name:e,type:`main`,filePath:`${n}${o}`})}return r}resolveExportValue(e){if(typeof e==`string`)return e;if(typeof e!=`object`||!e)return;let t=e;for(let e of[`import`,`default`,`require`])if(typeof t[e]==`string`)return t[e];for(let e of Object.values(t))if(typeof e==`string`)return e}async findWorkspacePackages(n){let r=[];try{let a=i(n,`pnpm-workspace.yaml`);await e(a);let o=await t(a,`utf-8`),s=this.parsePnpmWorkspaceYaml(o);for(let e of s){let t=await this.expandWorkspaceGlob(n,e);r.push(...t)}if(r.length>0)return r}catch{}try{let e=i(n,`package.json`),a=JSON.parse(await t(e,`utf-8`)),o=Array.isArray(a.workspaces)?a.workspaces:a.workspaces?.packages??[];for(let e of o){let t=await this.expandWorkspaceGlob(n,e);r.push(...t)}}catch{}return r}parsePnpmWorkspaceYaml(e){let t=[],n=!1;for(let r of e.split(`
2
- `)){let e=r.trim();if(e===`packages:`){n=!0;continue}if(n){if(e.startsWith(`- `))t.push(e.slice(2).replace(/^['"]|['"]$/g,``));else if(e&&!e.startsWith(`#`))break}}return t}async expandWorkspaceGlob(t,r){let a=[],s=r.indexOf(`*`);if(s===-1){let n=o(t,r);try{await e(i(n,`package.json`)),a.push(n)}catch{}return a}let c=o(t,r.slice(0,s));try{let t=await n(c,{withFileTypes:!0});for(let n of t){if(!n.isDirectory()||u.has(n.name))continue;let t=i(c,n.name);try{await e(i(t,`package.json`)),a.push(t)}catch{}}}catch{}return a}async fromHandlerExports(e){let n=[],i=await this.collectFiles(e),o=!1;try{await c.ensure(),o=!0}catch{}for(let c of i)try{let i=await t(c,`utf-8`),u=a(e,c).replace(/\\/g,`/`),m=r(c);if(!u.split(`/`).some(e=>d.has(e))){let e=!1;if(o&&s.has(m)){let t=await l(i,m,u);for(let r of t)r.trigger||(r.type===`cdk-construct`?r.trigger=`CDK Construct`:r.trigger=this.detectTrigger(i)),n.push(r),e=!0}if(!e)for(let t of f){let r=i.match(t);if(r){let t=r[1]??this.inferNameFromFile(u);(t===`handler`||t===`main`)&&(t=this.deriveContextualName(u)??t);let a=/@SpringBootApplication/.test(i)?`HTTP Server`:this.detectTrigger(i);n.push({name:t,type:this.inferEntryType(r[1]??t,u),filePath:u,trigger:a}),e=!0;break}}if(!e){let e=i.match(p);e&&n.push({name:e[1],type:`cdk-construct`,filePath:u,trigger:`CDK Construct`})}}this.isTestFile(u,i)&&n.push({name:this.inferNameFromFile(u),type:`test`,filePath:u,trigger:`Test Suite`})}catch{}return n}isTestFile(e,t){return/\.(test|spec)\.[jt]sx?$/.test(e)?m.some(e=>e.test(t)):!1}inferNameFromFile(e){return(e.split(/[/\\]/).pop()??`default`).replace(/\.\w+$/,``)}deriveContextualName(e){let t=e.split(`/`).filter(e=>e!==`src`&&e!==`lib`);if(t.pop(),t.length===0)return;let n=t.filter(e=>![`services`,`functions`,`lambdas`,`handlers`,`packages`,`apps`].includes(e));if(n.length===0)return;let r=n.slice(-2);return r.length===2&&r[1].startsWith(r[0])?r[1]:r.join(`-`)}inferEntryType(e,t){return e===`handler`||e===`main`||t.includes(`handler`)||/functions[/]/.test(t)||e.endsWith(`Handler`)?`lambda-handler`:(t.endsWith(`.py`)||t.endsWith(`.go`)||t.endsWith(`.java`),`main`)}detectTrigger(e){for(let t of h)if(t.regex.test(e))return t.trigger}async collectFiles(e){let t=[],a=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.java`,`.py`,`.go`,`.cs`,`.kt`,`.rb`,`.rs`,`.php`,`.swift`]),o=async(e,s)=>{if(s>10)return;let c=await n(e,{withFileTypes:!0});for(let n of c){if(u.has(n.name)||n.name.startsWith(`.`))continue;let c=i(e,n.name);n.isDirectory()?await o(c,s+1):a.has(r(n.name))&&t.push(c)}};return await o(e,0),t}formatMarkdown(e,t){let n=[];if(n.push(`## Entry Points: ${t}\n`),n.push(`**${e.length} entry ${e.length===1?`point`:`points`}** found\n`),e.length===0)return n.push(`No entry points detected.`),n.join(`
1
+ import{access as e,readFile as t,readdir as n,stat as r}from"node:fs/promises";import{extname as i,join as a,relative as o,resolve as s}from"node:path";import{SUPPORTED_EXTENSIONS as c,WasmRuntime as l,detectEntryPoints as u}from"../../chunker/dist/index.js";const d=new Set([`node_modules`,`.git`,`dist`,`build`,`coverage`,`.turbo`,`.cache`,`cdk.out`,`__pycache__`,`.venv`,`target`,`bin`,`obj`,`.gradle`,`venv`,`env`]),f=new Set([`test`,`tests`,`__tests__`,`spec`,`specs`,`test-utils`]),p=[/export\s+const\s+(handler|main)\s*(?::[^=]*)?\s*=/,/export\s+(?:async\s+)?function\s+(handler|main)\s*\(/,/export\s+const\s+(\w+Handler)\s*(?::[^=]*)?\s*=/,/export\s+default\s+app/,/^app\s*=\s*(?:Flask|FastAPI)\s*\(/m,/^urlpatterns\s*=\s*\[/m,/^if\s+__name__\s*==\s*['"]__main__['"]:/m,/public\s+static\s+void\s+main\s*\(\s*String/,/@SpringBootApplication/,/^func\s+main\s*\(\s*\)/m],m=/export\s+(?:default\s+)?class\s+(\w+)\s+extends\s+(?:Construct|Stack|NestedStack|Stage)/,h=[/from\s+['"]vitest['"]/,/from\s+['"]jest['"]/,/from\s+['"]mocha['"]/,/import\s+.*['"]@jest\/globals['"]/,/require\s*\(\s*['"](?:vitest|jest|mocha)['"]\s*\)/],g=[{regex:/SqsEventSource|SQSEvent|sqs/i,trigger:`SQS`},{regex:/SnsEventSource|SNSEvent|sns/i,trigger:`SNS`},{regex:/ApiGateway|APIGatewayEvent|httpApi|restApi/i,trigger:`API Gateway`},{regex:/ScheduleExpression|EventBridgeRule|schedule/i,trigger:`EventBridge Schedule`},{regex:/S3EventSource|S3Event|s3/i,trigger:`S3`},{regex:/DynamoEventSource|DynamoDBStream/i,trigger:`DynamoDB Stream`},{regex:/@RequestMapping|@GetMapping|@PostMapping/i,trigger:`HTTP Endpoint`},{regex:/http\.ListenAndServe|gin\.Default|echo\.New/i,trigger:`HTTP Server`},{regex:/app\.route\(|@app\.get|@app\.post|@router\./i,trigger:`HTTP Route`}];var _=class{name=`entry-points`;async analyze(e,t={}){let n=Date.now(),r=[],i=await this.findWorkspacePackages(e);if(i.length>0)for(let t of i){let n=await this.fromPackageJson(t,e);r.push(...n)}else{let t=await this.fromPackageJson(e,e);r.push(...t)}let a=await this.fromHandlerExports(e);return r.push(...a),{output:this.formatMarkdown(r,e),data:{entryPoints:r,total:r.length},meta:{analyzedAt:new Date().toISOString(),scope:e,fileCount:r.length,durationMs:Date.now()-n}}}async fromPackageJson(n,r){let i=[],s=o(r,n).replace(/\\/g,`/`)||`.`;try{let r=a(n,`package.json`);await e(r);let o=JSON.parse(await t(r,`utf-8`)),c=s===`.`?``:`${s}/`;if(o.main&&i.push({name:o.name?`${o.name}:main`:`main`,type:`main`,filePath:`${c}${o.main}`}),o.bin){let e=typeof o.bin==`string`?{[o.name??`cli`]:o.bin}:o.bin;for(let[t,n]of Object.entries(e))i.push({name:t,type:`cli`,filePath:`${c}${n}`})}if(o.exports){let e=this.parseExportsField(o.exports,o.name??s,c);i.push(...e)}o.scripts?.start&&i.push({name:o.name?`${o.name}:start`:`start`,type:`server`,filePath:o.scripts.start,trigger:`npm start`})}catch{}return i}parseExportsField(e,t,n){let r=[];if(typeof e==`string`)return r.push({name:t,type:`main`,filePath:`${n}${e}`}),r;if(typeof e!=`object`||!e)return r;for(let[i,a]of Object.entries(e)){if(!i.startsWith(`.`))continue;let e=i===`.`?t:`${t}/${i.slice(2)}`,o=this.resolveExportValue(a);o&&r.push({name:e,type:`main`,filePath:`${n}${o}`})}return r}resolveExportValue(e){if(typeof e==`string`)return e;if(typeof e!=`object`||!e)return;let t=e;for(let e of[`import`,`default`,`require`])if(typeof t[e]==`string`)return t[e];for(let e of Object.values(t))if(typeof e==`string`)return e}async findWorkspacePackages(n){let r=[];try{let i=a(n,`pnpm-workspace.yaml`);await e(i);let o=await t(i,`utf-8`),s=this.parsePnpmWorkspaceYaml(o);for(let e of s){let t=await this.expandWorkspaceGlob(n,e);r.push(...t)}if(r.length>0)return r}catch{}try{let e=a(n,`package.json`),i=JSON.parse(await t(e,`utf-8`)),o=Array.isArray(i.workspaces)?i.workspaces:i.workspaces?.packages??[];for(let e of o){let t=await this.expandWorkspaceGlob(n,e);r.push(...t)}}catch{}return r}parsePnpmWorkspaceYaml(e){let t=[],n=!1;for(let r of e.split(`
2
+ `)){let e=r.trim();if(e===`packages:`){n=!0;continue}if(n){if(e.startsWith(`- `))t.push(e.slice(2).replace(/^['"]|['"]$/g,``));else if(e&&!e.startsWith(`#`))break}}return t}async expandWorkspaceGlob(t,r){let i=[],o=r.indexOf(`*`);if(o===-1){let n=s(t,r);try{await e(a(n,`package.json`)),i.push(n)}catch{}return i}let c=s(t,r.slice(0,o));try{let t=await n(c,{withFileTypes:!0});for(let n of t){if(!n.isDirectory()||d.has(n.name))continue;let t=a(c,n.name);try{await e(a(t,`package.json`)),i.push(t)}catch{}}}catch{}return i}async fromHandlerExports(e){let n=[],r=await this.collectFiles(e),a=!1;try{await l.ensure(),a=!0}catch{}for(let s of r)try{let r=await t(s,`utf-8`),l=o(e,s).replace(/\\/g,`/`),d=i(s);if(!l.split(`/`).some(e=>f.has(e))){let e=!1;if(a&&c.has(d)){let t=await u(r,d,l);for(let i of t)i.trigger||(i.type===`cdk-construct`?i.trigger=`CDK Construct`:i.trigger=this.detectTrigger(r)),n.push(i),e=!0}if(!e)for(let t of p){let i=r.match(t);if(i){let t=i[1]??this.inferNameFromFile(l);(t===`handler`||t===`main`)&&(t=this.deriveContextualName(l)??t);let a=/@SpringBootApplication/.test(r)?`HTTP Server`:this.detectTrigger(r);n.push({name:t,type:this.inferEntryType(i[1]??t,l),filePath:l,trigger:a}),e=!0;break}}if(!e){let e=r.match(m);e&&n.push({name:e[1],type:`cdk-construct`,filePath:l,trigger:`CDK Construct`})}}this.isTestFile(l,r)&&n.push({name:this.inferNameFromFile(l),type:`test`,filePath:l,trigger:`Test Suite`})}catch{}return n}isTestFile(e,t){return/\.(test|spec)\.[jt]sx?$/.test(e)?h.some(e=>e.test(t)):!1}inferNameFromFile(e){return(e.split(/[/\\]/).pop()??`default`).replace(/\.\w+$/,``)}deriveContextualName(e){let t=e.split(`/`).filter(e=>e!==`src`&&e!==`lib`);if(t.pop(),t.length===0)return;let n=t.filter(e=>![`services`,`functions`,`lambdas`,`handlers`,`packages`,`apps`].includes(e));if(n.length===0)return;let r=n.slice(-2);return r.length===2&&r[1].startsWith(r[0])?r[1]:r.join(`-`)}inferEntryType(e,t){return e===`handler`||e===`main`||t.includes(`handler`)||/functions[/]/.test(t)||e.endsWith(`Handler`)?`lambda-handler`:(t.endsWith(`.py`)||t.endsWith(`.go`)||t.endsWith(`.java`),`main`)}detectTrigger(e){for(let t of g)if(t.regex.test(e))return t.trigger}async collectFiles(e){let t=[],o=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.java`,`.py`,`.go`,`.cs`,`.kt`,`.rb`,`.rs`,`.php`,`.swift`]),s=async(e,c)=>{if(c>10||!(await r(e).catch(()=>null))?.isDirectory())return;let l=await n(e,{withFileTypes:!0});for(let n of l){if(d.has(n.name)||n.name.startsWith(`.`))continue;let r=a(e,n.name);n.isDirectory()?await s(r,c+1):o.has(i(n.name))&&t.push(r)}};return await s(e,0),t}formatMarkdown(e,t){let n=[];if(n.push(`## Entry Points: ${t}\n`),n.push(`**${e.length} entry ${e.length===1?`point`:`points`}** found\n`),e.length===0)return n.push(`No entry points detected.`),n.join(`
3
3
  `);let r=new Map;for(let t of e){let e=r.get(t.type)??[];e.push(t),r.set(t.type,e)}let i=[`lambda-handler`,`main`,`server`,`cli`,`bin`,`cdk-construct`,`test`],a=[...r.entries()].sort((e,t)=>i.indexOf(e[0])-i.indexOf(t[0]));n.push(`| Name | Type | File | Trigger |`),n.push(`|------|------|------|---------|`);for(let[,e]of a)for(let t of e)n.push(`| ${t.name} | ${t.type} | ${t.filePath} | ${t.trigger??`—`} |`);return n.join(`
4
- `)}};export{g as EntryPointAnalyzer};
4
+ `)}};export{_ as EntryPointAnalyzer};
@@ -1,2 +1,2 @@
1
- import{access as e,readFile as t,readdir as n}from"node:fs/promises";import{extname as r,join as i,relative as a}from"node:path";import{SUPPORTED_EXTENSIONS as o,WasmRuntime as s,detectPatterns as c}from"../../chunker/dist/index.js";const l=new Set([`node_modules`,`.git`,`dist`,`build`,`coverage`,`.turbo`,`.cache`,`cdk.out`,`__pycache__`,`.venv`,`target`,`bin`,`obj`,`.gradle`,`venv`,`env`]),u=[{dirs:[`adapters`,`ports`],pattern:`Hexagonal Architecture`,description:`Ports & adapters (hexagonal) separation`},{dirs:[`domain`,`infrastructure`,`application`],pattern:`Clean Architecture`,description:`Layered with domain/infrastructure separation`},{dirs:[`controllers`,`models`],pattern:`MVC Pattern`,description:`Model-View-Controller structure`},{dirs:[`repositories`],pattern:`Repository Pattern`,description:`Data access abstraction via repositories`},{dirs:[`factories`],pattern:`Factory Pattern`,description:`Object creation via factories`},{dirs:[`handlers`],pattern:`Handler Pattern`,description:`Event/request handler separation`},{dirs:[`middleware`],pattern:`Middleware Pattern`,description:`Request pipeline middleware`},{dirs:[`hooks`],pattern:`React Hooks`,description:`Custom React hooks for logic reuse`},{dirs:[`components`],pattern:`Component Architecture`,description:`UI component-based structure`},{dirs:[`stacks`,`constructs`],pattern:`CDK IaC`,description:`AWS CDK infrastructure as code`},{dirs:[`lambdas`,`functions`],pattern:`Serverless`,description:`Serverless function architecture`}];function d(e){if(e.length<=3)return e;let t=new Map;for(let n of e){let e=n.split(`/`),r=e.length>1?e.slice(0,-1).join(`/`):`.`,i=t.get(r);i?i.push(n):t.set(r,[n])}let n=[];for(let[e,r]of t)r.length>=3?n.push(`${e}/ (${r.length} files)`):n.push(...r);return n.slice(0,5)}const f=[{regex:/container\.register|@injectable|@inject/i,pattern:`Dependency Injection`,description:`IoC container or DI decorators`},{regex:/\.pipe\(|Observable|BehaviorSubject/i,pattern:`Reactive (RxJS)`,description:`Reactive programming with observables`,lang:`js`},{regex:/createContext|useContext/i,pattern:`React Context`,description:`React Context API for state sharing`,lang:`js`},{regex:/createSlice|configureStore/i,pattern:`Redux Toolkit`,description:`Redux state management`,lang:`js`},{regex:/defineStore|usePinia/i,pattern:`Pinia Store`,description:`Vue Pinia state management`,lang:`js`},{regex:/\.(test|spec)\.[jt]sx?|describe\s*\(|\bit\s*\([\s'"]/i,pattern:`Test Suite`,description:`Unit/integration test files`},{regex:/@SpringBootApplication|@EnableAutoConfiguration/,pattern:`Spring Boot`,description:`Spring Boot application framework`,lang:`java`,definitive:!0},{regex:/@Autowired|@Component|@Service|@Repository|@Controller/,pattern:`Spring DI`,description:`Spring dependency injection`,lang:`java`},{regex:/@RestController|@RequestMapping|@GetMapping|@PostMapping/,pattern:`Spring REST`,description:`Spring REST API controllers`,lang:`java`},{regex:/app\s*=\s*Flask\s*\(|@app\.route/,pattern:`Flask`,description:`Flask web framework`,lang:`python`},{regex:/app\s*=\s*FastAPI\s*\(|@app\.get|@app\.post/,pattern:`FastAPI`,description:`FastAPI web framework`,lang:`python`},{regex:/func\s+main\s*\(\s*\)|http\.ListenAndServe/,pattern:`Go Application`,description:`Go main application`,lang:`go`},{regex:/export\s+(?:async\s+)?function\s+create[A-Z]\w+/,pattern:`Factory`,description:`Object creation via create*() functions`,lang:`js`},{regex:/(?:export\s+)?function\s+wrap[A-Z]\w+/,pattern:`Wrapper/Decorator`,description:`Higher-order function wrapping`,lang:`js`},{regex:/(?:const|let)\s+\w+\s*=\s*new\s+(?:Map|WeakMap)\s*[<(]/,pattern:`Singleton Cache`,description:`Module-level cache with lazy initialization`,lang:`js`},{regex:/Record<string,\s*(?:\w+)?Handler>|\.(?:get|post|put|delete)\s*\(/,pattern:`Router/Dispatcher`,description:`Request routing/dispatch table`,lang:`js`},{regex:/export\s+(?:default\s+)?class\s+\w+\s+extends\s+(?:Construct|Stack|NestedStack|Stage)/,pattern:`CDK Construct`,description:`AWS CDK infrastructure construct`,lang:`js`,definitive:!0}];var p=class{name=`patterns`;async analyze(e,t={}){let n=Date.now(),r=await this.collectDirectories(e),i=this.detectDirectoryPatterns(r,e),a=await this.collectCodeFiles(e),o=await this.detectCodePatterns(a,e),s=[...i,...o],c=await this.detectConfigPatterns(e),l=c.find(e=>e.pattern===`Maven`||e.pattern===`Gradle`||e.pattern===`Gradle (Kotlin DSL)`||e.pattern===`Node.js Project`||e.pattern===`Go Module`||e.pattern===`Rust (Cargo)`),u=new Set([`Ruby (Bundler)`,`PHP (Composer)`,`Swift Package`,`SBT`]);for(let e of c)l&&u.has(e.pattern)||s.push(e);return{output:this.formatMarkdown(s,e),data:{patterns:s,total:s.length},meta:{analyzedAt:new Date().toISOString(),scope:e,fileCount:a.length,durationMs:Date.now()-n}}}async collectDirectories(e){let t=[],r=async(e,a)=>{if(a>5)return;let o=await n(e,{withFileTypes:!0});for(let n of o){if(!n.isDirectory()||l.has(n.name)||n.name.startsWith(`.`))continue;let o=i(e,n.name);t.push(n.name),await r(o,a+1)}};return await r(e,0),t}async collectCodeFiles(e){let t=[],a=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.java`,`.py`,`.go`,`.cs`,`.kt`,`.scala`,`.rb`,`.rs`,`.php`,`.swift`]),o=async e=>{let s=await n(e,{withFileTypes:!0});for(let n of s){if(l.has(n.name)||n.name.startsWith(`.`))continue;let s=i(e,n.name);n.isDirectory()?await o(s):a.has(r(n.name))&&t.push(s)}};return await o(e),t}detectDirectoryPatterns(e,t){let n=new Set(e.map(e=>e.toLowerCase())),r=[];for(let e of u){let t=e.dirs.filter(e=>n.has(e));t.length!==0&&(e.dirs.length>1&&t.length<2||r.push({pattern:e.pattern,description:e.description,locations:t.map(e=>`${e}/`),confidence:t.length===e.dirs.length?`high`:`medium`}))}return r}async detectCodePatterns(e,n){let i=[],l={},u=!1;try{await s.ensure(),u=!0}catch{}let p=e.filter(e=>/Application\.\w+$|Main\.\w+$|app\.\w+$|main\.\w+$/i.test(e)||/Controller|Service|Handler|Router/i.test(e)),m=e.filter(e=>!p.includes(e)),h=[...p.slice(0,50),...m.slice(0,150)];for(let e of h)try{let i=await t(e,`utf-8`),s=r(e).toLowerCase(),d=a(n,e).replace(/\\/g,`/`);if(u&&o.has(s)){let e=await c(i,s,d);for(let t of e){l[t.pattern]||(l[t.pattern]=new Set);for(let e of t.locations)l[t.pattern].add(e)}}let p=s===`.java`||s===`.kt`||s===`.scala`?`java`:s===`.py`?`python`:s===`.go`?`go`:`js`;for(let e of f)e.lang&&e.lang!==p||e.regex.test(i)&&(l[e.pattern]||(l[e.pattern]=new Set),l[e.pattern].add(d))}catch{}for(let e of f){let t=l[e.pattern];if(t&&t.size>0){let n=d([...t]);i.push({pattern:e.pattern,description:e.description,locations:n,confidence:e.definitive||t.size>=3?`high`:t.size>=2?`medium`:`low`})}}let g=new Set(f.map(e=>e.pattern));for(let[e,t]of Object.entries(l)){if(g.has(e)||t.size===0)continue;let n=d([...t]);i.push({pattern:e,description:`Detected via AST analysis`,locations:n,confidence:t.size>=3?`high`:t.size>=2?`medium`:`low`})}return i}async detectConfigPatterns(t){let n=[];for(let r of[{file:`Dockerfile`,pattern:`Docker`,description:`Containerized application`},{file:`docker-compose.yml`,pattern:`Docker Compose`,description:`Container orchestration`},{file:`cdk.json`,pattern:`AWS CDK`,description:`AWS CDK infrastructure as code`},{file:`terraform.tf`,pattern:`Terraform`,description:`Terraform IaC`},{file:`main.tf`,pattern:`Terraform`,description:`Terraform IaC`}])try{await e(i(t,r.file)),n.push({pattern:r.pattern,description:r.description,locations:[r.file],confidence:`high`})}catch{}return n}formatMarkdown(e,t){let n=[];n.push(`## Patterns Detected: ${t}\n`),n.push(`**${e.length} patterns** found\n`);let r={high:[],medium:[],low:[]};for(let t of e)r[t.confidence].push(t);for(let[e,t]of Object.entries(r))if(t.length!==0){n.push(`### ${e.charAt(0).toUpperCase()+e.slice(1)} Confidence\n`);for(let e of t)n.push(`- **${e.pattern}**: ${e.description}`),n.push(` Locations: ${e.locations.slice(0,5).join(`, `)}`);n.push(``)}return n.join(`
2
- `)}};export{p as PatternAnalyzer};
1
+ import{access as e,readFile as t,readdir as n,stat as r}from"node:fs/promises";import{extname as i,join as a,relative as o}from"node:path";import{SUPPORTED_EXTENSIONS as s,WasmRuntime as c,detectPatterns as l}from"../../chunker/dist/index.js";const u=new Set([`node_modules`,`.git`,`dist`,`build`,`coverage`,`.turbo`,`.cache`,`cdk.out`,`__pycache__`,`.venv`,`target`,`bin`,`obj`,`.gradle`,`venv`,`env`]),d=[{dirs:[`adapters`,`ports`],pattern:`Hexagonal Architecture`,description:`Ports & adapters (hexagonal) separation`},{dirs:[`domain`,`infrastructure`,`application`],pattern:`Clean Architecture`,description:`Layered with domain/infrastructure separation`},{dirs:[`controllers`,`models`],pattern:`MVC Pattern`,description:`Model-View-Controller structure`},{dirs:[`repositories`],pattern:`Repository Pattern`,description:`Data access abstraction via repositories`},{dirs:[`factories`],pattern:`Factory Pattern`,description:`Object creation via factories`},{dirs:[`handlers`],pattern:`Handler Pattern`,description:`Event/request handler separation`},{dirs:[`middleware`],pattern:`Middleware Pattern`,description:`Request pipeline middleware`},{dirs:[`hooks`],pattern:`React Hooks`,description:`Custom React hooks for logic reuse`},{dirs:[`components`],pattern:`Component Architecture`,description:`UI component-based structure`},{dirs:[`stacks`,`constructs`],pattern:`CDK IaC`,description:`AWS CDK infrastructure as code`},{dirs:[`lambdas`,`functions`],pattern:`Serverless`,description:`Serverless function architecture`}];function f(e){if(e.length<=3)return e;let t=new Map;for(let n of e){let e=n.split(`/`),r=e.length>1?e.slice(0,-1).join(`/`):`.`,i=t.get(r);i?i.push(n):t.set(r,[n])}let n=[];for(let[e,r]of t)r.length>=3?n.push(`${e}/ (${r.length} files)`):n.push(...r);return n.slice(0,5)}const p=[{regex:/container\.register|@injectable|@inject/i,pattern:`Dependency Injection`,description:`IoC container or DI decorators`},{regex:/\.pipe\(|Observable|BehaviorSubject/i,pattern:`Reactive (RxJS)`,description:`Reactive programming with observables`,lang:`js`},{regex:/createContext|useContext/i,pattern:`React Context`,description:`React Context API for state sharing`,lang:`js`},{regex:/createSlice|configureStore/i,pattern:`Redux Toolkit`,description:`Redux state management`,lang:`js`},{regex:/defineStore|usePinia/i,pattern:`Pinia Store`,description:`Vue Pinia state management`,lang:`js`},{regex:/\.(test|spec)\.[jt]sx?|describe\s*\(|\bit\s*\([\s'"]/i,pattern:`Test Suite`,description:`Unit/integration test files`},{regex:/@SpringBootApplication|@EnableAutoConfiguration/,pattern:`Spring Boot`,description:`Spring Boot application framework`,lang:`java`,definitive:!0},{regex:/@Autowired|@Component|@Service|@Repository|@Controller/,pattern:`Spring DI`,description:`Spring dependency injection`,lang:`java`},{regex:/@RestController|@RequestMapping|@GetMapping|@PostMapping/,pattern:`Spring REST`,description:`Spring REST API controllers`,lang:`java`},{regex:/app\s*=\s*Flask\s*\(|@app\.route/,pattern:`Flask`,description:`Flask web framework`,lang:`python`},{regex:/app\s*=\s*FastAPI\s*\(|@app\.get|@app\.post/,pattern:`FastAPI`,description:`FastAPI web framework`,lang:`python`},{regex:/func\s+main\s*\(\s*\)|http\.ListenAndServe/,pattern:`Go Application`,description:`Go main application`,lang:`go`},{regex:/export\s+(?:async\s+)?function\s+create[A-Z]\w+/,pattern:`Factory`,description:`Object creation via create*() functions`,lang:`js`},{regex:/(?:export\s+)?function\s+wrap[A-Z]\w+/,pattern:`Wrapper/Decorator`,description:`Higher-order function wrapping`,lang:`js`},{regex:/(?:const|let)\s+\w+\s*=\s*new\s+(?:Map|WeakMap)\s*[<(]/,pattern:`Singleton Cache`,description:`Module-level cache with lazy initialization`,lang:`js`},{regex:/Record<string,\s*(?:\w+)?Handler>|\.(?:get|post|put|delete)\s*\(/,pattern:`Router/Dispatcher`,description:`Request routing/dispatch table`,lang:`js`},{regex:/export\s+(?:default\s+)?class\s+\w+\s+extends\s+(?:Construct|Stack|NestedStack|Stage)/,pattern:`CDK Construct`,description:`AWS CDK infrastructure construct`,lang:`js`,definitive:!0}];var m=class{name=`patterns`;async analyze(e,t={}){let n=Date.now(),r=await this.collectDirectories(e),i=this.detectDirectoryPatterns(r,e),a=await this.collectCodeFiles(e),o=await this.detectCodePatterns(a,e),s=[...i,...o],c=await this.detectConfigPatterns(e),l=c.find(e=>e.pattern===`Maven`||e.pattern===`Gradle`||e.pattern===`Gradle (Kotlin DSL)`||e.pattern===`Node.js Project`||e.pattern===`Go Module`||e.pattern===`Rust (Cargo)`),u=new Set([`Ruby (Bundler)`,`PHP (Composer)`,`Swift Package`,`SBT`]);for(let e of c)l&&u.has(e.pattern)||s.push(e);return{output:this.formatMarkdown(s,e),data:{patterns:s,total:s.length},meta:{analyzedAt:new Date().toISOString(),scope:e,fileCount:a.length,durationMs:Date.now()-n}}}async collectDirectories(e){let t=[],i=async(e,o)=>{if(o>5||!(await r(e).catch(()=>null))?.isDirectory())return;let s=await n(e,{withFileTypes:!0});for(let n of s){if(!n.isDirectory()||u.has(n.name)||n.name.startsWith(`.`))continue;let r=a(e,n.name);t.push(n.name),await i(r,o+1)}};return await i(e,0),t}async collectCodeFiles(e){let t=[],r=new Set([`.ts`,`.tsx`,`.js`,`.jsx`,`.java`,`.py`,`.go`,`.cs`,`.kt`,`.scala`,`.rb`,`.rs`,`.php`,`.swift`]),o=async e=>{let s=await n(e,{withFileTypes:!0});for(let n of s){if(u.has(n.name)||n.name.startsWith(`.`))continue;let s=a(e,n.name);n.isDirectory()?await o(s):r.has(i(n.name))&&t.push(s)}};return await o(e),t}detectDirectoryPatterns(e,t){let n=new Set(e.map(e=>e.toLowerCase())),r=[];for(let e of d){let t=e.dirs.filter(e=>n.has(e));t.length!==0&&(e.dirs.length>1&&t.length<2||r.push({pattern:e.pattern,description:e.description,locations:t.map(e=>`${e}/`),confidence:t.length===e.dirs.length?`high`:`medium`}))}return r}async detectCodePatterns(e,n){let r=[],a={},u=!1;try{await c.ensure(),u=!0}catch{}let d=e.filter(e=>/Application\.\w+$|Main\.\w+$|app\.\w+$|main\.\w+$/i.test(e)||/Controller|Service|Handler|Router/i.test(e)),m=e.filter(e=>!d.includes(e)),h=[...d.slice(0,50),...m.slice(0,150)];for(let e of h)try{let r=await t(e,`utf-8`),c=i(e).toLowerCase(),d=o(n,e).replace(/\\/g,`/`);if(u&&s.has(c)){let e=await l(r,c,d);for(let t of e){a[t.pattern]||(a[t.pattern]=new Set);for(let e of t.locations)a[t.pattern].add(e)}}let f=c===`.java`||c===`.kt`||c===`.scala`?`java`:c===`.py`?`python`:c===`.go`?`go`:`js`;for(let e of p)e.lang&&e.lang!==f||e.regex.test(r)&&(a[e.pattern]||(a[e.pattern]=new Set),a[e.pattern].add(d))}catch{}for(let e of p){let t=a[e.pattern];if(t&&t.size>0){let n=f([...t]);r.push({pattern:e.pattern,description:e.description,locations:n,confidence:e.definitive||t.size>=3?`high`:t.size>=2?`medium`:`low`})}}let g=new Set(p.map(e=>e.pattern));for(let[e,t]of Object.entries(a)){if(g.has(e)||t.size===0)continue;let n=f([...t]);r.push({pattern:e,description:`Detected via AST analysis`,locations:n,confidence:t.size>=3?`high`:t.size>=2?`medium`:`low`})}return r}async detectConfigPatterns(t){let n=[];for(let r of[{file:`Dockerfile`,pattern:`Docker`,description:`Containerized application`},{file:`docker-compose.yml`,pattern:`Docker Compose`,description:`Container orchestration`},{file:`cdk.json`,pattern:`AWS CDK`,description:`AWS CDK infrastructure as code`},{file:`terraform.tf`,pattern:`Terraform`,description:`Terraform IaC`},{file:`main.tf`,pattern:`Terraform`,description:`Terraform IaC`}])try{await e(a(t,r.file)),n.push({pattern:r.pattern,description:r.description,locations:[r.file],confidence:`high`})}catch{}return n}formatMarkdown(e,t){let n=[];n.push(`## Patterns Detected: ${t}\n`),n.push(`**${e.length} patterns** found\n`);let r={high:[],medium:[],low:[]};for(let t of e)r[t.confidence].push(t);for(let[e,t]of Object.entries(r))if(t.length!==0){n.push(`### ${e.charAt(0).toUpperCase()+e.slice(1)} Confidence\n`);for(let e of t)n.push(`- **${e.pattern}**: ${e.description}`),n.push(` Locations: ${e.locations.slice(0,5).join(`, `)}`);n.push(``)}return n.join(`
2
+ `)}};export{m as PatternAnalyzer};
@@ -1,4 +1,4 @@
1
- import{readdir as e,stat as t}from"node:fs/promises";import{extname as n,join as r}from"node:path";const i={src:`Application source`,lib:`Library code`,dist:`Build output`,build:`Build output`,test:`Tests`,tests:`Tests`,spec:`Tests`,__tests__:`Tests`,docs:`Documentation`,scripts:`Build/utility scripts`,config:`Configuration`,handlers:`Entry point handlers`,controllers:`HTTP controllers`,routes:`API routes`,middleware:`Middleware`,services:`Business logic services`,domain:`Domain/business logic`,infrastructure:`External integrations`,adapters:`Adapter implementations`,ports:`Port interfaces`,models:`Data models`,entities:`Domain entities`,repositories:`Data access`,utils:`Utilities`,helpers:`Helper functions`,types:`Type definitions`,interfaces:`Interface definitions`,constants:`Constants`,cdk:`CDK infrastructure`,stacks:`CDK stacks`,constructs:`CDK constructs`,lambdas:`Lambda functions`,components:`UI components`,hooks:`React hooks`,pages:`Page components`,layouts:`Layout components`,store:`State management`,assets:`Static assets`,styles:`Stylesheets`,fixtures:`Test fixtures`,mocks:`Test mocks`,migrations:`Database migrations`},a={".ts":`TypeScript`,".tsx":`React TSX`,".js":`JavaScript`,".jsx":`React JSX`,".mjs":`ES Module`,".cjs":`CommonJS`,".json":`JSON`,".yaml":`YAML`,".yml":`YAML`,".md":`Markdown`,".mdx":`MDX`,".py":`Python`,".go":`Go`,".rs":`Rust`,".java":`Java`,".sh":`Shell`,".ps1":`PowerShell`,".css":`CSS`,".scss":`SCSS`,".html":`HTML`,".sql":`SQL`,".graphql":`GraphQL`,".proto":`Protocol Buffers`,".toml":`TOML`,".env":`Environment`},o=new Set([`node_modules`,`.git`,`dist`,`build`,`.next`,`.nuxt`,`coverage`,`.turbo`,`.cache`,`__pycache__`,`.venv`,`.terraform`,`cdk.out`]),s=new Set(`.ts,.tsx,.js,.jsx,.mjs,.cjs,.java,.kt,.kts,.scala,.py,.go,.rs,.rb,.php,.swift,.cs,.c,.cpp,.h,.hpp,.sh,.bash,.ps1,.sql,.graphql,.gql,.proto,.json,.yaml,.yml,.toml,.env,.ini,.cfg,.xml,.pom,.gradle,.tf,.hcl,.lock,.mjs`.split(`,`)),c=new Set([`__tests__`,`test`,`tests`,`spec`,`__mocks__`,`__fixtures__`,`fixtures`,`mocks`]);var l=class{name=`structure`;async analyze(e,t={}){let{format:n=`markdown`,maxDepth:r=6,sourceOnly:i=!1,maxTokens:a}=t,o=Date.now(),s=await this.buildTree(e,0,r,i),c=this.computeStats(s);return{output:n===`json`?JSON.stringify({tree:s,stats:c},null,2):this.formatMarkdownWithBudget(s,c,e,a),data:{tree:s,stats:c},meta:{analyzedAt:new Date().toISOString(),scope:e,fileCount:c.totalFiles,durationMs:Date.now()-o}}}async buildTree(c,l,u,d){let f=await e(c,{withFileTypes:!0}),p=[];for(let e of f.sort((e,t)=>e.name.localeCompare(t.name))){if(o.has(e.name)||e.name.startsWith(`.`)&&e.name!==`.env.example`)continue;let i=r(c,e.name);if(e.isDirectory()&&l<u){let e=await this.buildTree(i,l+1,u,d);if(d&&(!e.children||e.children.length===0))continue;p.push(e)}else if(e.isFile()){let r=n(e.name).toLowerCase();if(d&&r&&!s.has(r)||d&&!r)continue;let o=await t(i);p.push({name:e.name,type:`file`,language:a[r]??(r||`unknown`),size:o.size})}}let m=c.split(/[/\\]/).pop()??c;return{name:m,type:`directory`,purpose:i[m.toLowerCase()],children:p}}computeStats(e){let t={},n=0,r=0,i=e=>{if(e.type===`file`){n++,r+=e.size??0;let i=e.language??`unknown`;t[i]=(t[i]??0)+1}e.children?.forEach(i)};return i(e),{totalFiles:n,totalSize:r,languages:t}}formatMarkdownWithBudget(e,t,n,r){let i=this.formatMarkdown(e,t,n,1);if(!r||this.estimateTokens(i)<=r)return i;let a=this.formatMarkdown(e,t,n,2);return this.estimateTokens(a)<=r?`${a}\n\n> _Tree pruned to Level 2: leaf directories collapsed to fit token budget._`:this.formatMarkdown(e,t,n,3)+`
1
+ import{readdir as e,stat as t}from"node:fs/promises";import{basename as n,extname as r,join as i}from"node:path";const a={src:`Application source`,lib:`Library code`,dist:`Build output`,build:`Build output`,test:`Tests`,tests:`Tests`,spec:`Tests`,__tests__:`Tests`,docs:`Documentation`,scripts:`Build/utility scripts`,config:`Configuration`,handlers:`Entry point handlers`,controllers:`HTTP controllers`,routes:`API routes`,middleware:`Middleware`,services:`Business logic services`,domain:`Domain/business logic`,infrastructure:`External integrations`,adapters:`Adapter implementations`,ports:`Port interfaces`,models:`Data models`,entities:`Domain entities`,repositories:`Data access`,utils:`Utilities`,helpers:`Helper functions`,types:`Type definitions`,interfaces:`Interface definitions`,constants:`Constants`,cdk:`CDK infrastructure`,stacks:`CDK stacks`,constructs:`CDK constructs`,lambdas:`Lambda functions`,components:`UI components`,hooks:`React hooks`,pages:`Page components`,layouts:`Layout components`,store:`State management`,assets:`Static assets`,styles:`Stylesheets`,fixtures:`Test fixtures`,mocks:`Test mocks`,migrations:`Database migrations`},o={".ts":`TypeScript`,".tsx":`React TSX`,".js":`JavaScript`,".jsx":`React JSX`,".mjs":`ES Module`,".cjs":`CommonJS`,".json":`JSON`,".yaml":`YAML`,".yml":`YAML`,".md":`Markdown`,".mdx":`MDX`,".py":`Python`,".go":`Go`,".rs":`Rust`,".java":`Java`,".sh":`Shell`,".ps1":`PowerShell`,".css":`CSS`,".scss":`SCSS`,".html":`HTML`,".sql":`SQL`,".graphql":`GraphQL`,".proto":`Protocol Buffers`,".toml":`TOML`,".env":`Environment`},s=new Set([`node_modules`,`.git`,`dist`,`build`,`.next`,`.nuxt`,`coverage`,`.turbo`,`.cache`,`__pycache__`,`.venv`,`.terraform`,`cdk.out`]),c=new Set(`.ts,.tsx,.js,.jsx,.mjs,.cjs,.java,.kt,.kts,.scala,.py,.go,.rs,.rb,.php,.swift,.cs,.c,.cpp,.h,.hpp,.sh,.bash,.ps1,.sql,.graphql,.gql,.proto,.json,.yaml,.yml,.toml,.env,.ini,.cfg,.xml,.pom,.gradle,.tf,.hcl,.lock,.mjs`.split(`,`)),l=new Set([`__tests__`,`test`,`tests`,`spec`,`__mocks__`,`__fixtures__`,`fixtures`,`mocks`]);var u=class{name=`structure`;async analyze(e,t={}){let{format:n=`markdown`,maxDepth:r=6,sourceOnly:i=!1,maxTokens:a}=t,o=Date.now(),s=await this.buildTree(e,0,r,i),c=this.computeStats(s);return{output:n===`json`?JSON.stringify({tree:s,stats:c},null,2):this.formatMarkdownWithBudget(s,c,e,a),data:{tree:s,stats:c},meta:{analyzedAt:new Date().toISOString(),scope:e,fileCount:c.totalFiles,durationMs:Date.now()-o}}}async buildTree(l,u,d,f){if(!(await t(l)).isDirectory())return{name:n(l),type:`file`,children:[]};let p=await e(l,{withFileTypes:!0}),m=[];for(let e of p.sort((e,t)=>e.name.localeCompare(t.name))){if(s.has(e.name)||e.name.startsWith(`.`)&&e.name!==`.env.example`)continue;let n=i(l,e.name);if(e.isDirectory()&&u<d){let e=await this.buildTree(n,u+1,d,f);if(f&&(!e.children||e.children.length===0))continue;m.push(e)}else if(e.isFile()){let i=r(e.name).toLowerCase();if(f&&i&&!c.has(i)||f&&!i)continue;let a=await t(n);m.push({name:e.name,type:`file`,language:o[i]??(i||`unknown`),size:a.size})}}let h=l.split(/[/\\]/).pop()??l;return{name:h,type:`directory`,purpose:a[h.toLowerCase()],children:m}}computeStats(e){let t={},n=0,r=0,i=e=>{if(e.type===`file`){n++,r+=e.size??0;let i=e.language??`unknown`;t[i]=(t[i]??0)+1}e.children?.forEach(i)};return i(e),{totalFiles:n,totalSize:r,languages:t}}formatMarkdownWithBudget(e,t,n,r){let i=this.formatMarkdown(e,t,n,1);if(!r||this.estimateTokens(i)<=r)return i;let a=this.formatMarkdown(e,t,n,2);return this.estimateTokens(a)<=r?`${a}\n\n> _Tree pruned to Level 2: leaf directories collapsed to fit token budget._`:this.formatMarkdown(e,t,n,3)+`
2
2
 
3
3
  > _Tree pruned to Level 3: top-level directories only to fit token budget._`}formatMarkdown(e,t,n,r=1){let i=[];return i.push(`## Project Structure: ${n}\n`),i.push(`**${t.totalFiles} files** | Languages: ${Object.entries(t.languages).map(([e,t])=>`${e} (${t})`).join(`, `)}\n`),i.push("```"),r===3?this.renderTreeLevel3(e,i):this.renderTree(e,``,i,r),i.push("```"),i.join(`
4
- `)}renderTree(e,t,n,r=1){let i=e.purpose?` ── ${e.purpose}`:``;if(e.type===`directory`){let a=e.name.toLowerCase();if(c.has(a)&&e.children){let r=this.countFiles(e);n.push(`${t}${e.name}/${i} (${r} files)`);return}if(r>=2&&this.isLeafDir(e)){n.push(`${t}${e.name}/${i} (${this.leafDirSummary(e)})`);return}n.push(`${t}${e.name}/${i}`),e.children?.forEach((i,a)=>{let o=a===(e.children?.length??0)-1,s=o?`└── `:`├── `,c=t+(o?` `:`│ `);i.type===`directory`?this.renderTree(i,c,n,r):n.push(`${t}${s}${i.name}`)})}else n.push(`${t}${e.name}`)}renderTreeLevel3(e,t){for(let n of e.children??[]){let e=n.purpose?` ── ${n.purpose}`:``;if(n.type===`directory`){let r=this.countFiles(n);t.push(`${n.name}/${e} (${r} files)`)}else t.push(n.name)}}estimateTokens(e){return Math.ceil(e.length/4)}isLeafDir(e){return e.type===`directory`&&(e.children??[]).every(e=>e.type===`file`)}leafDirSummary(e){let t={};for(let n of e.children??[]){let e=n.language??`unknown`;t[e]=(t[e]??0)+1}return`${Object.values(t).reduce((e,t)=>e+t,0)} files — ${Object.entries(t).map(([e,t])=>`${e} (${t})`).join(`, `)}`}countFiles(e){return e.type===`file`?1:(e.children??[]).reduce((e,t)=>e+this.countFiles(t),0)}};export{l as StructureAnalyzer};
4
+ `)}renderTree(e,t,n,r=1){let i=e.purpose?` ── ${e.purpose}`:``;if(e.type===`directory`){let a=e.name.toLowerCase();if(l.has(a)&&e.children){let r=this.countFiles(e);n.push(`${t}${e.name}/${i} (${r} files)`);return}if(r>=2&&this.isLeafDir(e)){n.push(`${t}${e.name}/${i} (${this.leafDirSummary(e)})`);return}n.push(`${t}${e.name}/${i}`),e.children?.forEach((i,a)=>{let o=a===(e.children?.length??0)-1,s=o?`└── `:`├── `,c=t+(o?` `:`│ `);i.type===`directory`?this.renderTree(i,c,n,r):n.push(`${t}${s}${i.name}`)})}else n.push(`${t}${e.name}`)}renderTreeLevel3(e,t){for(let n of e.children??[]){let e=n.purpose?` ── ${n.purpose}`:``;if(n.type===`directory`){let r=this.countFiles(n);t.push(`${n.name}/${e} (${r} files)`)}else t.push(n.name)}}estimateTokens(e){return Math.ceil(e.length/4)}isLeafDir(e){return e.type===`directory`&&(e.children??[]).every(e=>e.type===`file`)}leafDirSummary(e){let t={};for(let n of e.children??[]){let e=n.language??`unknown`;t[e]=(t[e]??0)+1}return`${Object.values(t).reduce((e,t)=>e+t,0)} files — ${Object.entries(t).map(([e,t])=>`${e} (${t})`).join(`, `)}`}countFiles(e){return e.type===`file`?1:(e.children??[]).reduce((e,t)=>e+this.countFiles(t),0)}};export{u as StructureAnalyzer};
@@ -1 +1 @@
1
- import{dirname as e,join as t}from"node:path";import{existsSync as n}from"node:fs";import{fileURLToPath as r}from"node:url";const i=t(e(r(import.meta.url)),`..`,`..`,`wasm`),a={".ts":`tree-sitter-typescript.wasm`,".tsx":`tree-sitter-typescript.wasm`,".mts":`tree-sitter-typescript.wasm`,".cts":`tree-sitter-typescript.wasm`,".js":`tree-sitter-javascript.wasm`,".jsx":`tree-sitter-javascript.wasm`,".mjs":`tree-sitter-javascript.wasm`,".cjs":`tree-sitter-javascript.wasm`,".py":`tree-sitter-python.wasm`,".go":`tree-sitter-go.wasm`,".rs":`tree-sitter-rust.wasm`,".java":`tree-sitter-java.wasm`},o=new Set(Object.keys(a));function s(e){let r=a[e];if(!r)return null;let o=t(i,r);return n(o)?o:null}function c(){let e=t(i,`tree-sitter.wasm`);return n(e)?e:null}export{o as SUPPORTED_EXTENSIONS,s as resolveGrammarPath,c as resolveParserWasmPath};
1
+ import{dirname as e,join as t}from"node:path";import{existsSync as n}from"node:fs";import{fileURLToPath as r}from"node:url";const i=t(e(r(import.meta.url)),`..`,`..`,`wasm`),a={".ts":`tree-sitter-typescript.wasm`,".tsx":`tree-sitter-typescript.wasm`,".mts":`tree-sitter-typescript.wasm`,".cts":`tree-sitter-typescript.wasm`,".js":`tree-sitter-javascript.wasm`,".jsx":`tree-sitter-javascript.wasm`,".mjs":`tree-sitter-javascript.wasm`,".cjs":`tree-sitter-javascript.wasm`,".py":`tree-sitter-python.wasm`,".go":`tree-sitter-go.wasm`,".rs":`tree-sitter-rust.wasm`,".java":`tree-sitter-java.wasm`,".kt":`tree-sitter-kotlin.wasm`,".kts":`tree-sitter-kotlin.wasm`,".scala":`tree-sitter-scala.wasm`,".sc":`tree-sitter-scala.wasm`,".c":`tree-sitter-c.wasm`,".h":`tree-sitter-c.wasm`,".cpp":`tree-sitter-cpp.wasm`,".cc":`tree-sitter-cpp.wasm`,".cxx":`tree-sitter-cpp.wasm`,".hpp":`tree-sitter-cpp.wasm`,".hxx":`tree-sitter-cpp.wasm`,".cs":`tree-sitter-c_sharp.wasm`,".swift":`tree-sitter-swift.wasm`,".rb":`tree-sitter-ruby.wasm`,".php":`tree-sitter-php.wasm`},o=new Set(Object.keys(a));function s(e){let r=a[e];if(!r)return null;let o=t(i,r);return n(o)?o:null}function c(){let e=t(i,`tree-sitter.wasm`);return n(e)?e:null}export{o as SUPPORTED_EXTENSIONS,s as resolveGrammarPath,c as resolveParserWasmPath};
@@ -0,0 +1,30 @@
1
+ //#region packages/server/src/auto-gc.d.ts
2
+ /**
3
+ * P1-13: Self-tuning garbage collection based on p95 latency.
4
+ *
5
+ * Monitors tool call latency via the replay-interceptor's rolling buffer.
6
+ * When p95 exceeds a threshold the system enters "degraded" state and
7
+ * triggers progressive GC actions. A cooldown period prevents over-collection.
8
+ */
9
+ type GcState = 'healthy' | 'warming' | 'degraded';
10
+ interface GcStatus {
11
+ state: GcState;
12
+ p95: number;
13
+ lastGcAt: number | null;
14
+ gcCount: number;
15
+ bufferSize: number;
16
+ }
17
+ type GcCallback = () => Promise<void>;
18
+ /**
19
+ * Evaluate the current latency profile and optionally trigger GC.
20
+ *
21
+ * Call this periodically (e.g. every N tool calls) from the replay interceptor.
22
+ * The optional `gcCallback` receives control when a GC cycle is triggered —
23
+ * the caller decides *what* to clean up (pruning stale curated entries,
24
+ * vacuuming SQLite, removing orphaned graph nodes, etc.).
25
+ */
26
+ declare function checkAndMaybeGc(gcCallback?: GcCallback): void;
27
+ /** Return a snapshot of the GC health state for the status tool. */
28
+ declare function getGcStatus(): GcStatus;
29
+ //#endregion
30
+ export { GcCallback, checkAndMaybeGc, getGcStatus };
@@ -0,0 +1 @@
1
+ import{getLatencyBuffer as e}from"./replay-interceptor.js";import{createLogger as t}from"../../core/dist/index.js";const n=t(`auto-gc`);let r=`warming`,i=null,a=0;function o(){let t=[...e()];if(t.length<10)return 0;t.sort((e,t)=>e-t);let n=Math.floor(t.length*.95);return t[Math.min(n,t.length-1)]}function s(e){let t=o();if(t===0){r=`warming`;return}if(t>500){r=`degraded`;let o=Date.now();if(i&&o-i<36e5){n.debug(`GC cooldown active — skipping`,{lastGcAgoMs:o-i});return}i=o,a++,n.warn(`p95 latency exceeds threshold, triggering GC`,{p95:t,cycle:a}),e&&e().catch(e=>n.error(`GC callback failed`,{err:String(e)}))}else t<200&&(r=`healthy`)}function c(){return{state:r,p95:o(),lastGcAt:i,gcCount:a,bufferSize:e().length}}export{s as checkAndMaybeGc,c as getGcStatus};
@@ -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.KB_TRANSPORT??`stdio`},port:{type:`string`,default:process.env.KB_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.KB_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}]=await Promise.all([import(`./server.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check.js`)]);r();let o=e(i);d=o.server,f=n,c=!0,l.info(`MCP server configured (lazy — KB initializing in background)`,{toolCount:t.length,resourceCount:2}),o.startInit(),process.env.KB_AUTO_INDEX===`true`?o.ready.then(async()=>{try{let e=i.sources.map(e=>e.path).join(`, `);l.info(`Running initial index`,{sourcePaths:e}),await o.runInitialIndex(),l.info(`Initial index complete`)}catch(e){l.error(`Initial index failed; will retry on kb_reindex`,a(e))}}).catch(e=>l.error(`KB init or indexing failed`,a(e))):(o.ready.catch(e=>l.error(`KB initialization failed`,a(e))),l.info(`Auto-index disabled in HTTP mode (set KB_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},{RootsListChangedNotificationSchema:o}]=await Promise.all([import(`./config.js`),import(`./server.js`),import(`./version-check.js`),import(`@modelcontextprotocol/sdk/types.js`)]),s=e();l.info(`Config loaded`,{sourceCount:s.sources.length,storePath:s.store.path}),i();let{server:c,startInit:u,ready:d,runInitialIndex:f}=n(s),{StdioServerTransport:p}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),m=new p;await c.connect(m),l.info(`MCP server started`,{transport:`stdio`});let h=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(s,i),!0},g=!1;try{g=h((await c.server.listRoots()).roots),g||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)}),g=!0}g||=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);c.server.setNotificationHandler(o,async()=>{clearTimeout(t);try{e(h((await c.server.listRoots()).roots))}catch(t){l.warn(`roots/list retry failed after notification`,a(t)),e(!1)}})}),u(),d.catch(e=>{l.error(`Initialization failed — server will continue with limited tools`,a(e))}),process.env.KB_AUTO_INDEX===`false`?l.warn(`Auto-index disabled; use kb_reindex to index manually`):f().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.KB_TRANSPORT??`stdio`},port:{type:`string`,default:process.env.KB_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.KB_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.KB_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 kb_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 KB_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.KB_AUTO_INDEX===`false`?l.warn(`Auto-index disabled; use kb_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,10 +1,23 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
 
3
3
  //#region packages/server/src/replay-interceptor.d.ts
4
+ interface ToolStats {
5
+ callCount: number;
6
+ totalDurationMs: number;
7
+ totalInputChars: number;
8
+ totalOutputChars: number;
9
+ errorCount: number;
10
+ }
11
+ /** Get per-tool invocation statistics for the current session. */
12
+ declare function getToolTelemetry(): Array<{
13
+ tool: string;
14
+ } & ToolStats>;
15
+ /** Get the rolling latency buffer (last N tool call durations in ms). */
16
+ declare function getLatencyBuffer(): readonly number[];
4
17
  /**
5
18
  * Wrap the McpServer's registerTool method so that every tool invocation
6
19
  * is logged to the replay JSONL audit trail.
7
20
  */
8
21
  declare function installReplayInterceptor(server: McpServer): void;
9
22
  //#endregion
10
- export { installReplayInterceptor };
23
+ export { getLatencyBuffer, getToolTelemetry, installReplayInterceptor };
@@ -1 +1 @@
1
- import{replayAppend as e}from"../../tools/dist/index.js";const t=/key|token|secret|auth|password|bearer/i,n=new Set([`eval`,`env`]);function r(e,r){if(n.has(e))return JSON.stringify({_redacted:!0,tool:e});if(e===`http`&&r.headers&&typeof r.headers==`object`){let e={...r},n={};for(let[e,i]of Object.entries(r.headers))n[e]=t.test(e)?`[REDACTED]`:i;return e.headers=n,JSON.stringify(e).slice(0,200)}return JSON.stringify(r).slice(0,200)}function i(t){let n=t.registerTool.bind(t);t.registerTool=(t,i,a)=>n(t,i,async(n,i)=>{let o=Date.now();try{let s=await a(n,i);return e({ts:new Date().toISOString(),source:`mcp`,tool:t,input:r(t,n),durationMs:Date.now()-o,status:`ok`,output:JSON.stringify(s).slice(0,200)}),s}catch(i){throw e({ts:new Date().toISOString(),source:`mcp`,tool:t,input:r(t,n),durationMs:Date.now()-o,status:`error`,output:i instanceof Error?i.message:String(i)}),i}})}export{i as installReplayInterceptor};
1
+ import{checkAndMaybeGc as e}from"./auto-gc.js";import{replayAppend as t}from"../../tools/dist/index.js";const n=/key|token|secret|auth|password|bearer/i,r=new Set([`eval`,`env`]);function i(e,t){if(r.has(e))return JSON.stringify({_redacted:!0,tool:e});if(e===`http`&&t.headers&&typeof t.headers==`object`){let e={...t},r={};for(let[e,i]of Object.entries(t.headers))r[e]=n.test(e)?`[REDACTED]`:i;return e.headers=r,JSON.stringify(e).slice(0,200)}return JSON.stringify(t).slice(0,200)}const a=new Map,o=[];function s(t,n,r,i,s){let c=a.get(t);c||(c={callCount:0,totalDurationMs:0,totalInputChars:0,totalOutputChars:0,errorCount:0},a.set(t,c)),c.callCount++,c.totalDurationMs+=n,c.totalInputChars+=r,c.totalOutputChars+=i,s&&c.errorCount++,o.push(n),o.length>100&&o.shift(),o.length>=10&&o.length%20==0&&e()}function c(){return Array.from(a.entries()).map(([e,t])=>({tool:e,...t}))}function l(){return o}function u(e){let n=e.registerTool.bind(e);e.registerTool=(e,r,a)=>n(e,r,async(n,r)=>{let o=Date.now(),c=JSON.stringify(n??{}).length;try{let l=await a(n,r),u=Date.now()-o,d=JSON.stringify(l);return t({ts:new Date().toISOString(),source:`mcp`,tool:e,input:i(e,n),durationMs:u,status:`ok`,output:d.slice(0,200)}),s(e,u,c,d.length,!1),l}catch(r){let a=Date.now()-o;throw t({ts:new Date().toISOString(),source:`mcp`,tool:e,input:i(e,n),durationMs:a,status:`error`,output:r instanceof Error?r.message:String(r)}),s(e,a,c,0,!0),r}})}export{l as getLatencyBuffer,c as getToolTelemetry,u as installReplayInterceptor};
@@ -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 ee,registerAnalyzeSymbolsTool as g,registerBlastRadiusTool as _}from"./tools/analyze.tools.js";import{registerAuditTool as v}from"./tools/audit.tool.js";import{registerBrainstormTool as y}from"./tools/brainstorm.tool.js";import{initBridgeComponents as b,registerErPullTool as x,registerErPushTool as S,registerErSyncStatusTool as C}from"./tools/bridge.tools.js";import{registerCompactTool as w,registerDeadSymbolsTool as te,registerFileSummaryTool as ne,registerFindTool as re,registerScopeMapTool as ie,registerSymbolTool as ae,registerTraceTool as oe}from"./tools/context.tools.js";import{registerErEvolveReviewTool as se}from"./tools/evolution.tools.js";import{registerBatchTool as ce,registerCheckTool as le,registerDelegateTool as ue,registerEvalTool as de,registerParseOutputTool as fe,registerTestRunTool as T}from"./tools/execution.tools.js";import{registerDigestTool as pe,registerEvidenceMapTool as E,registerForgeClassifyTool as D,registerForgeGroundTool as me,registerStratumCardTool as he}from"./tools/forge.tools.js";import{registerForgetTool as ge}from"./tools/forget.tool.js";import{registerGraphTool as _e}from"./tools/graph.tool.js";import{registerGuideTool as O,registerHealthTool as k,registerProcessTool as A,registerWatchTool as j,registerWebFetchTool as M}from"./tools/infra.tools.js";import{registerListTool as ve}from"./tools/list.tool.js";import{registerLookupTool as ye}from"./tools/lookup.tool.js";import{registerCodemodTool as N,registerDataTransformTool as P,registerDiffParseTool as F,registerGitContextTool as I,registerRenameTool as L}from"./tools/manipulation.tools.js";import{registerOnboardTool as be}from"./tools/onboard.tool.js";import{registerCheckpointTool as R,registerLaneTool as z,registerQueueTool as B,registerStashTool as V,registerWorksetTool as H}from"./tools/persistence.tools.js";import{registerErUpdatePolicyTool as xe}from"./tools/policy.tools.js";import{registerPresentTool as U}from"./tools/present.tool.js";import{registerProduceKnowledgeTool as W}from"./tools/produce.tool.js";import{registerReadTool as Se}from"./tools/read.tool.js";import{registerReindexTool as Ce}from"./tools/reindex.tool.js";import{registerRememberTool as we}from"./tools/remember.tool.js";import{registerReplayTool as G}from"./tools/replay.tool.js";import{registerRestoreTool as Te}from"./tools/restore.tool.js";import{registerSearchTool as Ee}from"./tools/search.tool.js";import{getCurrentVersion as K}from"./version-check.js";import{registerStatusTool as De}from"./tools/status.tool.js";import{registerUpdateTool as Oe}from"./tools/update.tool.js";import{registerChangelogTool as q,registerEncodeTool as J,registerEnvTool as ke,registerHttpTool as Ae,registerMeasureTool as je,registerRegexTestTool as Me,registerSchemaValidateTool as Ne,registerSnippetTool as Pe,registerTimeTool as Fe,registerWebSearchTool as Ie}from"./tools/utility.tools.js";import{existsSync as Le,statSync as Re}from"node:fs";import{resolve as ze}from"node:path";import{KB_PATHS as Be,createLogger as Ve,serializeError as Y}from"../../core/dist/index.js";import{initializeWasm as He}from"../../chunker/dist/index.js";import{OnnxEmbedder as Ue}from"../../embeddings/dist/index.js";import{EvolutionCollector as We,PolicyStore as Ge}from"../../enterprise-bridge/dist/index.js";import{FileHashCache as Ke,IncrementalIndexer as qe}from"../../indexer/dist/index.js";import{SqliteGraphStore as Je,createStore as Ye}from"../../store/dist/index.js";import{FileCache as Xe}from"../../tools/dist/index.js";import{McpServer as Ze}from"@modelcontextprotocol/sdk/server/mcp.js";const X=Ve(`server`);async function Z(t){X.info(`Initializing knowledge base components`);let[n,r,i,a]=await Promise.all([(async()=>{let e=new Ue({model:t.embedding.model,dimensions:t.embedding.dimensions});return await e.initialize(),X.info(`Embedder loaded`,{modelId:e.modelId,dimensions:e.dimensions}),e})(),(async()=>{let e=await Ye({backend:t.store.backend,path:t.store.path});return await e.initialize(),X.info(`Store initialized`),e})(),(async()=>{let e=new Je({path:t.store.path});return await e.initialize(),X.info(`Graph store initialized`),e})(),(async()=>{let e=await He();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 qe(n,r),s=new Ke(t.store.path);s.load(),o.setHashCache(s);let c=t.curated.path,l=new e(c,r,n);o.setGraphStore(i);let u=b(t.er),d=u?new Ge(t.curated.path):void 0;d&&X.info(`Policy store initialized`,{ruleCount:d.getRules().length});let f=u?new We:void 0,p=ze(t.sources[0]?.path??process.cwd(),Be.aiKb),m=Le(p),h;if(m)try{h=Re(p).mtime.toISOString()}catch{}return X.info(`Onboard state detected`,{onboardComplete:m,onboardTimestamp:h}),{embedder:n,store:r,indexer:o,curated:l,graphStore:i,fileCache:new Xe,bridge:u,policyStore:d,evolutionCollector:f,onboardComplete:m,onboardTimestamp:h}}function Qe(e,n){let a=new Ze({name:n.serverName??`knowledge-base`,version:K()},{capabilities:{logging:{}}});return r(a),d(a,n.toolPrefix??``),Q(a,e,n,t(a),new o(a),c(a)),i(a,{curated:e.curated,store:e.store,graphStore:e.graphStore}),a}function Q(e,t,n,r,i,o){a(e),l(e),Ee(e,t.embedder,t.store,t.graphStore,t.bridge,t.evolutionCollector,o),ye(e,t.store),De(e,t.store,t.graphStore,t.curated,{onboardComplete:t.onboardComplete,onboardTimestamp:t.onboardTimestamp},n),Ce(e,t.indexer,n,t.curated,t.store,i),we(e,t.curated,t.policyStore,t.evolutionCollector,i),Oe(e,t.curated,i),ge(e,t.curated,i),Se(e,t.curated),ve(e,t.curated),ee(e,t.store,t.embedder),f(e,t.store,t.embedder),g(e,t.store,t.embedder),h(e,t.store,t.embedder),m(e,t.store,t.embedder),p(e,t.store,t.embedder),_(e,t.store,t.embedder,t.graphStore),W(e,n),be(e,t.store,t.embedder,n),_e(e,t.graphStore),v(e,t.store,t.embedder),w(e,t.embedder,t.fileCache),ie(e,t.embedder,t.store),re(e,t.embedder,t.store),fe(e),H(e),le(e),ce(e,t.embedder,t.store),ae(e,t.embedder,t.store,t.graphStore),de(e),T(e),V(e),I(e),F(e),L(e),N(e),Te(e),ne(e,t.fileCache),R(e),P(e),oe(e,t.embedder,t.store),A(e),j(e),te(e,t.embedder,t.store),ue(e,o),k(e),z(e),B(e),M(e),O(e),E(e),pe(e,t.embedder),D(e),he(e,t.embedder,t.fileCache),me(e,t.embedder,t.store),U(e,r),r&&y(e,r),Ie(e),Ae(e),Me(e),J(e),je(e),q(e),Ne(e),Pe(e),ke(e),Fe(e),t.bridge&&(S(e,t.bridge,t.evolutionCollector),x(e,t.bridge),C(e,t.bridge)),t.policyStore&&xe(e,t.policyStore),t.evolutionCollector&&se(e,t.evolutionCollector),s(e,t.store,t.curated),G(e)}async function $e(e){let t=await Z(e),n=Qe(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 kb_reindex`,Y(e))}},i=async()=>{X.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{X.info(`Parent process died; shutting down`,{parentPid:a}),clearInterval(o),i()}},5e3);return o.unref(),{server:n,runInitialIndex:r,shutdown:i}}const et=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(`.`)),tt=5e3,nt=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.test_run.time.watch.web_fetch.web_search.workset`.split(`.`));function rt(e){le(e),de(e),T(e),fe(e),ue(e),I(e),F(e),L(e),N(e),P(e),H(e),V(e),R(e),Te(e),z(e),B(e),k(e),A(e),j(e),M(e),O(e),E(e),D(e),U(e),y(e,n),W(e),G(e),Ie(e),Ae(e),Me(e),J(e),je(e),q(e),Ne(e),Pe(e),ke(e),Fe(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 it(e){let n=new Ze({name:e.serverName??`knowledge-base`,version:K()},{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(`
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 ee,registerAnalyzeSymbolsTool as g,registerBlastRadiusTool as _}from"./tools/analyze.tools.js";import{registerAuditTool as v}from"./tools/audit.tool.js";import{registerBrainstormTool as y}from"./tools/brainstorm.tool.js";import{initBridgeComponents as b,registerErPullTool as x,registerErPushTool as te,registerErSyncStatusTool as S}from"./tools/bridge.tools.js";import{registerCompactTool as C,registerDeadSymbolsTool as ne,registerFileSummaryTool as re,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 w,registerEvalTool as T,registerParseOutputTool as E,registerTestRunTool as D}from"./tools/execution.tools.js";import{registerDigestTool as de,registerEvidenceMapTool as O,registerForgeClassifyTool as k,registerForgeGroundTool as fe,registerStratumCardTool as pe}from"./tools/forge.tools.js";import{registerForgetTool as me}from"./tools/forget.tool.js";import{registerGraphTool as he}from"./tools/graph.tool.js";import{registerGuideTool as A,registerHealthTool as j,registerProcessTool as M,registerWatchTool as N,registerWebFetchTool as P}from"./tools/infra.tools.js";import{registerListTool as ge}from"./tools/list.tool.js";import{registerLookupTool as _e}from"./tools/lookup.tool.js";import{registerCodemodTool as F,registerDataTransformTool as I,registerDiffParseTool as L,registerGitContextTool as R,registerRenameTool as z}from"./tools/manipulation.tools.js";import{registerOnboardTool as ve}from"./tools/onboard.tool.js";import{registerCheckpointTool as B,registerLaneTool as V,registerQueueTool as H,registerStashTool as U,registerWorksetTool as W}from"./tools/persistence.tools.js";import{registerErUpdatePolicyTool as ye}from"./tools/policy.tools.js";import{registerPresentTool as G}from"./tools/present.tool.js";import{registerProduceKnowledgeTool as K}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{KB_PATHS as Ue,createLogger as We,serializeError as q}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 J}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=b(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;if(m)try{h=Ve(p).mtime.toISOString()}catch{}return Y.info(`Onboard state detected`,{onboardComplete:m,onboardTimestamp:h}),{embedder:n,store:r,indexer:o,curated:l,graphStore:i,fileCache:new $e,bridge:u,policyStore:d,evolutionCollector:f,onboardComplete:m,onboardTimestamp:h}}function et(e,n){let a=new J({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),_e(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),me(e,t.curated,i),be(e,t.curated),ge(e,t.curated),ee(e,t.store,t.embedder),f(e,t.store,t.embedder),g(e,t.store,t.embedder),h(e,t.store,t.embedder),m(e,t.store,t.embedder),p(e,t.store,t.embedder),_(e,t.store,t.embedder,t.graphStore),K(e,n),ve(e,t.store,t.embedder,n),he(e,t.graphStore),v(e,t.store,t.embedder),C(e,t.embedder,t.fileCache),ae(e,t.embedder,t.store),ie(e,t.embedder,t.store),E(e),W(e),ue(e),le(e,t.embedder,t.store),oe(e,t.embedder,t.store,t.graphStore),T(e),D(e),U(e),R(e),L(e),z(e),F(e),we(e),re(e,t.fileCache),B(e),I(e),se(e,t.embedder,t.store),M(e),N(e),ne(e,t.embedder,t.store),w(e,o),j(e),V(e),H(e),P(e),A(e),O(e),de(e,t.embedder),k(e),pe(e,t.embedder,t.fileCache),fe(e,t.embedder,t.store),G(e,r),r&&y(e,r),ze(e),Ne(e),Fe(e),je(e),Pe(e),Ae(e),Ie(e),Le(e),Me(e),Re(e),t.bridge&&(te(e,t.bridge,t.evolutionCollector),x(e,t.bridge),S(e,t.bridge)),t.policyStore&&ye(e,t.policyStore),t.evolutionCollector&&ce(e,t.evolutionCollector),s(e,t.store,t.curated),Ce(e)}async function tt(e){let t=await X(e),n=et(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`,q(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`,q(e))}}catch(e){Y.error(`Initial index failed; will retry on kb_reindex`,q(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 nt=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(`.`)),rt=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 it(e){ue(e),T(e),D(e),E(e),w(e),R(e),L(e),z(e),F(e),I(e),W(e),U(e),B(e),we(e),V(e),H(e),j(e),M(e),N(e),P(e),A(e),O(e),k(e),G(e),y(e,n),K(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 at(e){let n=new J({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
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()}]}));nt.has(e)?r.remove():m.push(r)}rt(n),n.sendToolListChanged=p;let h=n.resource(`kb-status`,`kb://status`,{description:`Knowledge base status (initializing...)`,mimeType:`text/plain`},async()=>({contents:[{uri:`kb://status`,text:`KB is initializing...`,mimeType:`text/plain`}]})),ee=n.prompt(`_init`,`KB is initializing prompts...`,async()=>({messages:[{role:`user`,content:{type:`text`,text:f()}}]})),g,_=new Promise(e=>{g=e}),v,y=new Promise(e=>{v=e}),b=()=>v?.(),x=(async()=>{await y;let r;try{r=await Z(e)}catch(e){a=`failed`,s=e instanceof Error?e.message:String(e),X.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(),ee.remove();let p=n._registeredTools??{};for(let e of nt)p[e]?.remove();let _=new o(n),v=c(n);Q(n,r,e,t(n),_,v),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 b=n._registeredTools??{};for(let[e,t]of Object.entries(b)){if(et.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 (${tt/1e3}s).\n\nThe existing index may be temporarily locked. Please retry shortly — indexing will complete automatically.`}]}),tt));return Promise.race([n(...t),a])}}let x=Object.keys(b).length;x!==$.length&&X.warn(`ALL_TOOL_NAMES count mismatch`,{expectedToolCount:$.length,registeredToolCount:x}),X.info(`MCP server configured`,{toolCount:$.length,resourceCount:4}),g?.(r)})(),S=async()=>{let t=await _;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}))});l=!0,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 kb_reindex`,Y(e))}},C=process.ppid,w=setInterval(()=>{try{process.kill(C,0)}catch{X.info(`Parent process died; shutting down`,{parentPid:C}),clearInterval(w),_.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 w.unref(),{server:n,startInit:b,ready:x,runInitialIndex:S}}export{$ as ALL_TOOL_NAMES,it as createLazyServer,Qe as createMcpServer,$e as createServer,Z as initializeKnowledgeBase,Q as registerMcpTools};
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)}it(n),n.sendToolListChanged=p;let h=n.resource(`kb-status`,`kb://status`,{description:`Knowledge base status (initializing...)`,mimeType:`text/plain`},async()=>({contents:[{uri:`kb://status`,text:`KB is initializing...`,mimeType:`text/plain`}]})),ee=n.prompt(`_init`,`KB is initializing prompts...`,async()=>({messages:[{role:`user`,content:{type:`text`,text:f()}}]})),g,_=new Promise(e=>{g=e}),v,y=new Promise(e=>{v=e}),b=()=>v?.(),x=(async()=>{await y;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(),ee.remove();let p=n._registeredTools??{};for(let e of Q)p[e]?.remove();let _=new o(n),v=c(n);Z(n,r,e,t(n),_,v),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 b=n._registeredTools??{};for(let[e,t]of Object.entries(b)){if(nt.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 (${rt/1e3}s).\n\nThe existing index may be temporarily locked. Please retry shortly — indexing will complete automatically.`}]}),rt));return Promise.race([n(...t),a])}}let x=Object.keys(b).length;x!==$.length&&Y.warn(`ALL_TOOL_NAMES count mismatch`,{expectedToolCount:$.length,registeredToolCount:x}),Y.info(`MCP server configured`,{toolCount:$.length,resourceCount:4}),g?.(r)})(),te=async()=>{let t=await _;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`,q(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`,q(e))}}catch(e){Y.error(`Initial index failed; will retry on kb_reindex`,q(e))}},S=process.ppid,C=setInterval(()=>{try{process.kill(S,0)}catch{Y.info(`Parent process died; shutting down`,{parentPid:S}),clearInterval(C),_.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 C.unref(),{server:n,startInit:b,ready:x,runInitialIndex:te}}export{$ as ALL_TOOL_NAMES,at as createLazyServer,et as createMcpServer,tt as createServer,X as initializeKnowledgeBase,Z as registerMcpTools};
@@ -1,5 +1,5 @@
1
- import{getToolMeta as e}from"../tool-metadata.js";import{CompactOutputSchema as t,DeadSymbolsOutputSchema as n,FileSummaryOutputSchema as r,FindOutputSchema as i,ScopeMapOutputSchema as a,SymbolOutputSchema as o}from"../output-schemas.js";import{fanOutSearch as s,openWorkspaceStores as c,resolveWorkspaces as l}from"../cross-workspace.js";import{z as u}from"zod";import{CONTENT_TYPES as d,computePartitionKey as f,createLogger as p,serializeError as m}from"../../../core/dist/index.js";import{compact as h,fileSummary as g,find as _,findDeadSymbols as v,findExamples as y,scopeMap as b,symbol as x,trace as S,truncateToTokenBudget as C}from"../../../tools/dist/index.js";const w=p(`tools:context`);function T(n,r,i){let a=e(`compact`);n.registerTool(`compact`,{title:a.title,description:"Compress text to relevant sections using embedding similarity (no LLM). Provide either `text` or `path` (server reads the file — saves a round-trip). Segments by paragraph/sentence/line.",outputSchema:t,inputSchema:{text:u.string().optional().describe(`The text to compress (provide this OR path, not both)`),path:u.string().optional().describe(`File path to read server-side — avoids read_file round-trip + token doubling (provide this OR text)`),query:u.string().describe(`Focus query — what are you trying to understand?`),max_chars:u.number().min(100).max(5e4).default(3e3).describe(`Target output size in characters`),segmentation:u.enum([`paragraph`,`sentence`,`line`]).default(`paragraph`).describe(`How to split the text for scoring`)},annotations:a.annotations},async({text:e,path:t,query:n,max_chars:a,segmentation:o})=>{try{if(!e&&!t)return{content:[{type:`text`,text:`Error: Either "text" or "path" must be provided.`}],isError:!0};let s=await h(r,{text:e,path:t,query:n,maxChars:a,segmentation:o,cache:i});return{content:[{type:`text`,text:[`Compressed ${s.originalChars} → ${s.compressedChars} chars (${(s.ratio*100).toFixed(0)}%)`,`Kept ${s.segmentsKept}/${s.segmentsTotal} segments`,``,s.text].join(`
2
- `)}],structuredContent:{originalChars:s.originalChars,compressedChars:s.compressedChars,ratio:s.ratio,segmentsKept:s.segmentsKept,segmentsTotal:s.segmentsTotal}}}catch(e){return w.error(`Compact failed`,m(e)),{content:[{type:`text`,text:`Compact failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function E(t,n,r){let i=e(`scope_map`);t.registerTool(`scope_map`,{title:i.title,description:`Generate a task-scoped reading plan. Given a task description, identifies which files and sections are relevant, with estimated token counts and suggested reading order.`,outputSchema:a,inputSchema:{task:u.string().describe(`Description of the task to scope`),max_files:u.number().min(1).max(50).default(15).describe(`Maximum files to include`),content_type:u.enum(d).optional().describe(`Filter by content type`),max_tokens:u.number().min(100).max(5e4).optional().describe(`Maximum token budget for the response. When set, output is truncated to fit.`)},annotations:i.annotations},async({task:e,max_files:t,content_type:i,max_tokens:a})=>{try{let o=await b(n,r,{task:e,maxFiles:t,contentType:i}),s=[`## Scope Map: ${e}`,`Total estimated tokens: ~${o.totalEstimatedTokens}`,``,`### Files (by relevance)`,...o.files.map((e,t)=>`${t+1}. **${e.path}** (~${e.estimatedTokens} tokens, ${(e.relevance*100).toFixed(0)}% relevant)\n ${e.reason}\n Focus: ${e.focusRanges.map(e=>`L${e.start}-${e.end}`).join(`, `)}`),``,`### Suggested Reading Order`,...o.readingOrder.map((e,t)=>`${t+1}. ${e}`),``,`### Suggested Compact Calls`,`_Estimated compressed total: ~${Math.ceil(o.totalEstimatedTokens/5)} tokens_`,...o.compactCommands.map((e,t)=>`${t+1}. ${e}`)].join(`
1
+ import{getToolMeta as e}from"../tool-metadata.js";import{CompactOutputSchema as t,DeadSymbolsOutputSchema as n,FileSummaryOutputSchema as r,FindOutputSchema as i,ScopeMapOutputSchema as a,SymbolOutputSchema as o}from"../output-schemas.js";import{fanOutSearch as s,openWorkspaceStores as c,resolveWorkspaces as l}from"../cross-workspace.js";import{z as u}from"zod";import{CONTENT_TYPES as d,computePartitionKey as f,createLogger as p,serializeError as m}from"../../../core/dist/index.js";import{compact as h,fileSummary as g,find as _,findDeadSymbols as v,findExamples as y,scopeMap as b,symbol as x,trace as S,truncateToTokenBudget as C}from"../../../tools/dist/index.js";const w=p(`tools:context`);function T(n,r,i){let a=e(`compact`);n.registerTool(`compact`,{title:a.title,description:"Compress text to relevant sections using embedding similarity (no LLM). Provide either `text` or `path` (server reads the file — saves a round-trip). Segments by paragraph/sentence/line.",outputSchema:t,inputSchema:{text:u.string().optional().describe(`The text to compress (provide this OR path, not both)`),path:u.string().optional().describe(`File path to read server-side — avoids read_file round-trip + token doubling (provide this OR text)`),query:u.string().describe(`Focus query — what are you trying to understand?`),max_chars:u.number().min(100).max(5e4).default(3e3).describe(`Target output size in characters`),segmentation:u.enum([`paragraph`,`sentence`,`line`]).default(`paragraph`).describe(`How to split the text for scoring`),token_budget:u.number().min(50).max(12500).optional().describe(`Token budget — overrides max_chars (approx 4 chars per token). Use to fit output into a specific context window.`)},annotations:a.annotations},async({text:e,path:t,query:n,max_chars:a,segmentation:o,token_budget:s})=>{try{if(!e&&!t)return{content:[{type:`text`,text:`Error: Either "text" or "path" must be provided.`}],isError:!0};let c=await h(r,{text:e,path:t,query:n,maxChars:a,tokenBudget:s,segmentation:o,cache:i});return{content:[{type:`text`,text:[`Compressed ${c.originalChars} → ${c.compressedChars} chars (${(c.ratio*100).toFixed(0)}%)`,`Kept ${c.segmentsKept}/${c.segmentsTotal} segments`,``,c.text].join(`
2
+ `)}],structuredContent:{originalChars:c.originalChars,compressedChars:c.compressedChars,ratio:c.ratio,segmentsKept:c.segmentsKept,segmentsTotal:c.segmentsTotal}}}catch(e){return w.error(`Compact failed`,m(e)),{content:[{type:`text`,text:`Compact failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function E(t,n,r){let i=e(`scope_map`);t.registerTool(`scope_map`,{title:i.title,description:`Generate a task-scoped reading plan. Given a task description, identifies which files and sections are relevant, with estimated token counts and suggested reading order.`,outputSchema:a,inputSchema:{task:u.string().describe(`Description of the task to scope`),max_files:u.number().min(1).max(50).default(15).describe(`Maximum files to include`),content_type:u.enum(d).optional().describe(`Filter by content type`),max_tokens:u.number().min(100).max(5e4).optional().describe(`Maximum token budget for the response. When set, output is truncated to fit.`)},annotations:i.annotations},async({task:e,max_files:t,content_type:i,max_tokens:a})=>{try{let o=await b(n,r,{task:e,maxFiles:t,contentType:i}),s=[`## Scope Map: ${e}`,`Total estimated tokens: ~${o.totalEstimatedTokens}`,``,`### Files (by relevance)`,...o.files.map((e,t)=>`${t+1}. **${e.path}** (~${e.estimatedTokens} tokens, ${(e.relevance*100).toFixed(0)}% relevant)\n ${e.reason}\n Focus: ${e.focusRanges.map(e=>`L${e.start}-${e.end}`).join(`, `)}`),``,`### Suggested Reading Order`,...o.readingOrder.map((e,t)=>`${t+1}. ${e}`),``,`### Suggested Compact Calls`,`_Estimated compressed total: ~${Math.ceil(o.totalEstimatedTokens/5)} tokens_`,...o.compactCommands.map((e,t)=>`${t+1}. ${e}`)].join(`
3
3
  `)+"\n\n---\n_Next: Use `search` to dive into specific files, or `compact` to compress file contents for context._";return{content:[{type:`text`,text:a?C(s,a):s}],structuredContent:{files:o.files.map(e=>({path:e.path,relevance:e.relevance,estimatedTokens:e.estimatedTokens,...e.focusRanges.length>0?{focusLines:e.focusRanges.map(e=>`L${e.start}-${e.end}`)}:{}})),totalFiles:o.files.length,totalEstimatedTokens:o.totalEstimatedTokens,task:e}}}catch(e){return w.error(`Scope map failed`,m(e)),{content:[{type:`text`,text:`Scope map failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function D(t,n,r){let a=e(`find`);t.registerTool(`find`,{title:a.title,description:`Multi-strategy search combining vector, FTS, glob, and regex. Use for precise queries needing multiple strategies. mode=examples finds real usage of a symbol. For general discovery use search instead.`,outputSchema:i,inputSchema:{query:u.string().optional().describe(`Semantic/keyword search query (required for mode "examples")`),glob:u.string().optional().describe(`File glob pattern (search mode only)`),pattern:u.string().optional().describe(`Regex pattern to match in content (search mode only)`),limit:u.number().min(1).max(50).default(10).describe(`Max results`),content_type:u.enum(d).optional().describe(`Filter by content type`),mode:u.enum([`search`,`examples`]).default(`search`).describe(`Mode: "search" (default) for federated search, "examples" to find usage examples of a symbol/pattern`),max_tokens:u.number().min(100).max(5e4).optional().describe(`Maximum token budget for the response. When set, output is truncated to fit.`),workspaces:u.array(u.string()).optional().describe(`Cross-workspace search: partition names or folder basenames to include. Use ["*"] for all. User-level mode only.`)},annotations:a.annotations},async({query:e,glob:t,pattern:i,limit:a,content_type:o,mode:u,max_tokens:d,workspaces:p})=>{try{if(u===`examples`){if(!e)return{content:[{type:`text`,text:`Error: "query" is required for mode "examples".`}],isError:!0};let t=await y(n,r,{query:e,limit:a,contentType:o}),i=JSON.stringify(t);return{content:[{type:`text`,text:d?C(i,d):i}]}}let m=await _(n,r,{query:e,glob:t,pattern:i,limit:a,contentType:o}),h=``;if(p&&p.length>0&&e){let t=l(p,f(process.cwd()));if(t.length>0){let{stores:r,closeAll:i}=await c(t);try{let i=await s(r,await n.embedQuery(e),{limit:a,contentType:o});for(let e of i)m.results.push({path:`[${e.workspace}] ${e.record.sourcePath}`,score:e.score,source:`cross-workspace`,lineRange:e.record.startLine?{start:e.record.startLine,end:e.record.endLine}:void 0,preview:e.record.content.slice(0,200)});m.results.sort((e,t)=>t.score-e.score),m.results=m.results.slice(0,a),m.totalFound=m.results.length,h=` + ${t.length} workspace(s)`}finally{await i()}}}if(m.results.length===0)return{content:[{type:`text`,text:`No results found.${m.failedStrategies?.length?`\nStrategies attempted: ${m.strategies.join(`, `)}\nFailed: ${m.failedStrategies.map(e=>`${e.strategy} (${e.reason})`).join(`, `)}`:m.strategies.length===0?`
4
4
  No search strategies were activated. Provide at least one of: query, glob, or pattern.`:``}`}],structuredContent:{matches:[],totalMatches:0,pattern:e??t??i??``,truncated:!1}};let g=[`Found ${m.totalFound} results via ${m.strategies.join(` + `)}${h}`,``,...m.results.map(e=>{let t=e.lineRange?`:${e.lineRange.start}-${e.lineRange.end}`:``,n=e.preview?`\n ${e.preview.slice(0,100)}...`:``;return`- [${e.source}] ${e.path}${t} (${(e.score*100).toFixed(0)}%)${n}`})];return{content:[{type:`text`,text:d?C(g.join(`
5
5
  `),d):g.join(`
@@ -3,7 +3,7 @@ import{getToolMeta as e}from"../tool-metadata.js";import{createTaskRunner as t}f
3
3
  `)}]}}case`get`:{if(!t)throw Error(`task_id required for get`);let e=o({action:`get`,taskId:t},m);return e.state?{content:[{type:`text`,text:[`## Evidence Map: ${t} (${e.state.tier})`,``,e.formattedMap??`No entries.`,``,`_${e.state.entries.length} entries — created ${e.state.createdAt}_`].join(`
4
4
  `)}]}:{content:[{type:`text`,text:`Evidence map "${t}" not found.`}]}}case`gate`:{if(!t)throw Error(`task_id required for gate`);let e=o({action:`gate`,taskId:t,retryCount:p},m);if(!e.gate)return{content:[{type:`text`,text:`Evidence map "${t}" not found.`}]};let n=e.gate,r=[`## FORGE Gate: **${n.decision}**`,``,`**Reason:** ${n.reason}`,``,`**Stats:** ${n.stats.verified}V / ${n.stats.assumed}A / ${n.stats.unresolved}U (${n.stats.total} total)`];return n.warnings.length>0&&r.push(``,`**Warnings:**`,...n.warnings.map(e=>`- ⚠️ ${e}`)),n.unresolvedCritical.length>0&&r.push(``,`**Blocking entries:**`,...n.unresolvedCritical.map(e=>`- #${e.id}: ${e.claim} [${e.unknownType??`untyped`}]`)),n.safetyGates&&(r.push(``,`**Safety Gates:**`,`- Provenance: ${n.safetyGates.provenance}`,`- Commitment: ${n.safetyGates.commitment}`,`- Coverage: ${n.safetyGates.coverage}`),n.safetyGates.failures.length>0&&r.push(``,`**Safety failures:**`,...n.safetyGates.failures.map(e=>`- \u{1F6D1} ${e}`))),n.annotation&&r.push(``,`**Annotation:**`,n.annotation),e.formattedMap&&r.push(``,`---`,``,e.formattedMap),r.push(``,`---`,`_Next: ${n.decision===`YIELD`?`Proceed to implementation.`:n.decision===`HOLD`?`Resolve blocking entries, then re-run gate.`:n.decision===`HARD_BLOCK`?`Contract unknowns MUST be resolved. Use search or schema_validate.`:`Proceed with annotation — document unresolved items in delivery.`}_`),{content:[{type:`text`,text:r.join(`
5
5
  `)}]}}case`list`:{let e=o({action:`list`},m);return!e.states||e.states.length===0?{content:[{type:`text`,text:`No evidence maps found.`}]}:{content:[{type:`text`,text:e.states.map(e=>`- **${e.taskId}** (${e.tier}) — ${e.entries.length} entries — ${e.updatedAt}`).join(`
6
- `)}]}}case`delete`:if(!t)throw Error(`task_id required for delete`);return{content:[{type:`text`,text:o({action:`delete`,taskId:t},m).deleted?`Deleted evidence map "${t}".`:`Evidence map "${t}" not found.`}]}}}catch(e){return u.error(`Evidence map error`,i(e)),{content:[{type:`text`,text:`Evidence map error: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function f(t,r){let o=e(`digest`);t.registerTool(`digest`,{title:o.title,description:`Compress multiple text sources (handoffs, debates, phase summaries) into a token-budgeted digest. Jointly ranks across all sources, pins structured fields (status, files, decisions, blockers), and allocates budget by priority weight.`,inputSchema:{sources:n.array(n.object({id:n.string().describe(`Source identifier (e.g., "phase-2-handoff")`),text:n.string().max(5e5).describe(`Source text to compress`),weight:n.number().min(0).default(1).describe(`Priority weight (higher = more budget)`)})).min(1).max(20).describe(`Text sources to compress`),query:n.string().describe(`Focus query — what matters for the next step?`),max_chars:n.number().min(100).max(5e4).default(4e3).describe(`Target budget in characters`),pin_fields:n.array(n.string()).optional().describe(`Key fields to always extract (default: status, files, decisions, blockers, next)`),segmentation:n.enum([`paragraph`,`sentence`,`line`]).default(`paragraph`).describe(`How to split text for scoring`)},annotations:o.annotations},async({sources:e,query:t,max_chars:n,pin_fields:o,segmentation:s})=>{try{let i=await a(r,{sources:e,query:t,maxChars:n,pinFields:o,segmentation:s}),c=[`## Digest (${i.totalOriginalChars} → ${i.totalCompressedChars} chars, ${(i.ratio*100).toFixed(0)}%)`,``],l=Object.keys(i.fields);if(l.length>0){c.push(`### Extracted Fields`);for(let e of l){let t=i.fields[e];c.push(`**${e}:**`);for(let e of t)c.push(` - [${e.sourceId}] ${e.value}`)}c.push(``)}c.push(`### Compressed Content`,``,i.text),c.push(``,`### Source Stats`);for(let e of i.sourceStats)c.push(`- **${e.id}**: ${e.originalChars} → ${e.keptChars} chars (${e.segmentsKept}/${e.segmentsTotal} segments)`);return c.push(``,`---`,"_Next: Use the digest as compressed context for the next phase. Use `stash` to persist it if needed._"),{content:[{type:`text`,text:c.join(`
6
+ `)}]}}case`delete`:if(!t)throw Error(`task_id required for delete`);return{content:[{type:`text`,text:o({action:`delete`,taskId:t},m).deleted?`Deleted evidence map "${t}".`:`Evidence map "${t}" not found.`}]}}}catch(e){return u.error(`Evidence map error`,i(e)),{content:[{type:`text`,text:`Evidence map error: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function f(t,r){let o=e(`digest`);t.registerTool(`digest`,{title:o.title,description:`Compress multiple text sources (handoffs, debates, phase summaries) into a token-budgeted digest. Jointly ranks across all sources, pins structured fields (status, files, decisions, blockers), and allocates budget by priority weight.`,inputSchema:{sources:n.array(n.object({id:n.string().describe(`Source identifier (e.g., "phase-2-handoff")`),text:n.string().max(5e5).describe(`Source text to compress`),weight:n.number().min(0).default(1).describe(`Priority weight (higher = more budget)`)})).min(1).max(20).describe(`Text sources to compress`),query:n.string().describe(`Focus query — what matters for the next step?`),max_chars:n.number().min(100).max(5e4).default(4e3).describe(`Target budget in characters`),pin_fields:n.array(n.string()).optional().describe(`Key fields to always extract (default: status, files, decisions, blockers, next)`),segmentation:n.enum([`paragraph`,`sentence`,`line`]).default(`paragraph`).describe(`How to split text for scoring`),token_budget:n.number().min(50).max(12500).optional().describe(`Token budget — overrides max_chars (approx 4 chars per token). Use to fit output into a specific context window.`)},annotations:o.annotations},async({sources:e,query:t,max_chars:n,pin_fields:o,segmentation:s,token_budget:c})=>{try{let i=await a(r,{sources:e,query:t,maxChars:c?c*4:n,pinFields:o,segmentation:s}),l=[`## Digest (${i.totalOriginalChars} → ${i.totalCompressedChars} chars, ${(i.ratio*100).toFixed(0)}%)`,``],u=Object.keys(i.fields);if(u.length>0){l.push(`### Extracted Fields`);for(let e of u){let t=i.fields[e];l.push(`**${e}:**`);for(let e of t)l.push(` - [${e.sourceId}] ${e.value}`)}l.push(``)}l.push(`### Compressed Content`,``,i.text),l.push(``,`### Source Stats`);for(let e of i.sourceStats)l.push(`- **${e.id}**: ${e.originalChars} → ${e.keptChars} chars (${e.segmentsKept}/${e.segmentsTotal} segments)`);return l.push(``,`---`,"_Next: Use the digest as compressed context for the next phase. Use `stash` to persist it if needed._"),{content:[{type:`text`,text:l.join(`
7
7
  `)}]}}catch(e){return u.error(`Digest failed`,i(e)),{content:[{type:`text`,text:`Digest failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function p(t){let r=e(`forge_classify`);t.registerTool(`forge_classify`,{title:r.title,description:`Classify FORGE tier (Floor/Standard/Critical) from target files and task description. Checks blast radius, cross-package boundaries, schema/contract patterns, and security signals. Returns tier, triggers, typed unknown seeds, and ceremony guidance.`,inputSchema:{files:n.array(n.string()).min(1).max(100).describe(`Files being modified (paths)`),task:n.string().describe(`Task description`),root_path:n.string().describe(`Root path of the codebase`)},annotations:r.annotations},async({files:e,task:t,root_path:n})=>{try{let r=await s({files:e,task:t,rootPath:n}),i=[`## FORGE Classification: **${r.tier.toUpperCase()}**`,``];if(r.triggers.length>0){i.push(`### Triggers`);for(let e of r.triggers)i.push(`- **${e.rule}** (${e.source}): ${e.detail}`);i.push(``)}if(r.packagesCrossed.length>0&&i.push(`**Packages crossed:** ${r.packagesCrossed.join(`, `)}`),r.typedUnknownSeeds.length>0){i.push(``,`### Typed Unknown Seeds`);for(let e of r.typedUnknownSeeds)i.push(`- [${e.type}] ${e.description} → use \`${e.suggestedTool}\``)}i.push(``,`### Ceremony`);let a=r.ceremony;return i.push(`- **Ground:** ${a.ground}`,`- **Build:** ${a.build}`,`- **Break:** ${a.break}`,`- **Evidence Map:** ${a.evidenceMap}`,`- **Gate:** ${a.gate}`),i.push(``,`---`,`_Next: ${r.tier===`floor`?`Proceed directly to implementation.`:"Run `forge_ground` to execute the full Ground phase."}_`),{content:[{type:`text`,text:i.join(`
8
8
  `)}]}}catch(e){return u.error(`FORGE classify failed`,i(e)),{content:[{type:`text`,text:`FORGE classify failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function m(t,r,a){let o=e(`stratum_card`);t.registerTool(`stratum_card`,{title:o.title,description:`Generate context cards from files — a compressed alternative to reading full files (10-100x token reduction). Tier 1 (T1): structure only (~100 tokens/file — imports, exports, functions). Tier 2 (T2): structure + query-relevant content (~300 tokens/file).`,inputSchema:{files:n.array(n.string()).min(1).max(50).describe(`Absolute file paths to generate cards for`),query:n.string().describe(`Current task query — guides relevance scoring`),tier:n.enum([`T1`,`T2`]).default(`T1`).describe(`Card tier: T1 = structural only, T2 = T1 + compressed content`),max_content_chars:n.number().min(100).max(5e3).default(800).describe(`For T2: max chars for compressed content section`)},annotations:o.annotations},async({files:e,query:t,tier:n,max_content_chars:o})=>{try{let i=await l(r,{files:e,query:t,tier:n,maxContentChars:o,cache:a}),s=[`## STRATUM Cards (${n}) — ${i.cards.length} files`,`Total: ~${i.totalTokenEstimate} tokens (was ~${i.totalOriginalTokenEstimate}, ${(i.compressionRatio*100).toFixed(0)}% of original)`,``];for(let e of i.cards)s.push(e.card,``);return s.push(`---`,"_Next: Use these cards as context instead of reading full files. Use `compact` for deeper content extraction on specific files._"),{content:[{type:`text`,text:s.join(`
9
9
  `)}]}}catch(e){return u.error(`STRATUM cards failed`,i(e)),{content:[{type:`text`,text:`STRATUM cards failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function h(r,a,o){let s=e(`forge_ground`);r.registerTool(`forge_ground`,{title:s.title,description:`Execute the complete FORGE Ground phase in a single call. Chains: tier classification → scope map → typed unknown seeds → constraint loading → file summaries → evidence map creation. Replaces 5-15 manual tool calls.`,inputSchema:{task:n.string().describe(`Task description`),files:n.array(n.string()).min(1).max(100).describe(`Target files being modified (absolute paths)`),root_path:n.string().describe(`Root path of the codebase`),max_constraints:n.number().min(0).max(10).default(3).describe(`Max constraint entries to load from KB`),force_tier:n.enum([`floor`,`standard`,`critical`]).optional().describe(`Force a specific tier (skips auto-classification)`),task_id:n.string().optional().describe(`Custom task ID for evidence map (auto-generated if omitted)`)},annotations:s.annotations},async({task:e,files:n,root_path:r,max_constraints:s,force_tier:l,task_id:d},f)=>{try{let i=await c(a,o,{task:e,files:n,rootPath:r,maxConstraints:s,forceTier:l,taskId:d}),u=t(f).createTask(`FORGE Ground`,3);u.progress(0,`Classification: ${i.tier}`),u.progress(1,`Files analyzed: ${i.fileSummaries.length}`),u.progress(2,`Unknowns: ${i.typedUnknownSeeds.length}`),u.complete(`FORGE Ground complete: tier=${i.tier}`);let p=[`## FORGE Ground: **${i.tier.toUpperCase()}**`,`Estimated output: ~${i.estimatedTokens} tokens`,``];if(i.classifyTriggers.length>0){p.push(`### Classification Triggers`);for(let e of i.classifyTriggers)p.push(`- **${e.rule}** (${e.source}): ${e.detail}`);p.push(``)}if(i.fileSummaries.length>0){p.push(`### Target Files`);for(let e of i.fileSummaries)p.push(`- **${e.path}** (${e.lines} lines) — exports: ${e.exports.join(`, `)||`none`} — functions: ${e.functions.join(`, `)||`none`}`);p.push(``)}if(i.typedUnknownSeeds.length>0){p.push(`### Typed Unknown Seeds`);for(let e of i.typedUnknownSeeds)p.push(`- [${e.type}] ${e.description} → \`${e.suggestedTool}\``);p.push(``)}if(i.constraints.length>0){p.push(`### Constraint Seed`);for(let e of i.constraints)p.push(`- **${e.source}** (${(e.relevance*100).toFixed(0)}%): ${e.snippet}`);p.push(``)}if(i.scopeMap){p.push(`### Scope Map: ${i.scopeMap.files.length} files (~${i.scopeMap.totalEstimatedTokens} tokens)`);for(let e of i.scopeMap.files.slice(0,5))p.push(`- ${e.path} (${(e.relevance*100).toFixed(0)}%) — ${e.reason}`);i.scopeMap.files.length>5&&p.push(`- _...and ${i.scopeMap.files.length-5} more_`),p.push(``)}i.evidenceMapTaskId&&(p.push(`**Evidence Map:** \`${i.evidenceMapTaskId}\` (initialized)`),p.push(``)),p.push(`### Ceremony Guidance`);let m=i.ceremony;return p.push(`- **Ground:** ${m.ground}`,`- **Build:** ${m.build}`,`- **Break:** ${m.break}`,`- **Evidence Map:** ${m.evidenceMap}`,`- **Gate:** ${m.gate}`),p.push(``,`---`,`_Next: ${i.tier===`floor`?`Proceed to Build phase.`:"Use `evidence_map` to track claims during Build, then `evidence_map` gate after Break."}_`),{content:[{type:`text`,text:p.join(`
@@ -1 +1 @@
1
- function e(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`)}export{e as escHtml};
1
+ function e(e){return String(e??``).replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`)}export{e as escHtml};
@@ -5,13 +5,14 @@ import{getToolMeta as e}from"../tool-metadata.js";import{escHtml as t}from"./pre
5
5
  - "browser": Rich markdown in chat + serves a themed dashboard on a local URL that auto-opens in your system browser. If openBrowserPage is available, also call it with the returned URL. When actions are provided, browser shows interactive buttons and the tool blocks until user clicks.
6
6
  Use "html" for in-chat display. Use "browser" for visual dashboards and when you need interactive user input back.
7
7
  After calling present with format "browser", extract the URL from the response and call openBrowserPage({ url }) to open it in VS Code.`,annotations:r.annotations,inputSchema:k,_meta:{ui:{resourceUri:w}}},async({format:e,title:t,content:r,actions:i})=>(e??`html`)===`browser`?await N(t,r,i,n):J(t,r,i))}let M=null;process.on(`exit`,()=>{if(M){try{M.close()}catch{}M=null}});async function N(e,t,n,r){let i=P(e,t),a=q(e,t,n),o,s,c=Array.isArray(n)?n:[],l=``;try{M&&=(M.close(),null),c.length>0&&(o=new Promise(e=>{s=e})),l=await new Promise((e,t)=>{let n=_((e,t)=>{if(e.method===`POST`&&e.url===`/callback`){let n=``;e.on(`data`,e=>{n+=e.toString()}),e.on(`end`,()=>{t.writeHead(200,{"Content-Type":`application/json`,"Access-Control-Allow-Origin":`*`}),t.end(`{"ok":true}`);try{let e=JSON.parse(n);s?.(e)}catch{}});return}if(e.method===`OPTIONS`){t.writeHead(204,{"Access-Control-Allow-Origin":`*`,"Access-Control-Allow-Methods":`POST`,"Access-Control-Allow-Headers":`Content-Type`}),t.end();return}t.writeHead(200,{"Content-Type":`text/html; charset=utf-8`}),t.end(a)});n.listen(0,`127.0.0.1`,()=>{let r=n.address();typeof r==`object`&&r?(M=n,e(`http://127.0.0.1:${r.port}`)):t(Error(`Failed to start present server`))}),setTimeout(()=>{n.close(),M===n&&(M=null)},300*1e3).unref()});try{g(process.platform===`win32`?`start "" "${l}"`:process.platform===`darwin`?`open "${l}"`:`xdg-open "${l}"`)}catch{}}catch{}let u=v({uri:`ui://kb/present-static.html`,content:{type:`rawHtml`,htmlString:a},encoding:`text`,adapters:{mcpApps:{enabled:!0}}}),d=l?`${i}\n\n---\n🌐 **Dashboard opened in browser:** ${l}`:i;if(c.length>0&&r?.available&&o)try{let e=await Promise.race([o,new Promise((e,t)=>setTimeout(()=>t(Error(`timeout`)),300*1e3))]);return{content:[{type:`text`,text:`${d}\n\n✅ **Selected:** ${e.actionId} = \`${e.value}\``},u]}}catch{return{content:[{type:`text`,text:`${d}\n\n⚠️ *No selection received (timed out).*`},u]}}return{content:[{type:`text`,text:d},u]}}function P(e,t){let n=[];if(e&&n.push(`# ${e}\n`),typeof t==`string`)n.push(t);else if(Array.isArray(t))if(t.length===0)n.push(`*(empty)*`);else if(Z(t[0]))for(let e of t)n.push(F(e));else if(typeof t[0]==`object`&&t[0]!==null)n.push(I(t));else for(let e of t)n.push(`- ${String(e)}`);else if(typeof t==`object`&&t){let e=t;Array.isArray(e.nodes)&&Array.isArray(e.edges)?n.push(R(e)):Array.isArray(e.metrics)?n.push(L(e.metrics)):n.push(z(e))}else n.push(String(t));return n.join(`
8
- `)}function F(e){let t=[];switch(e.title&&t.push(`## ${e.title}\n`),e.type){case`markdown`:t.push(String(e.value??``));break;case`code`:t.push(`\`\`\`${e.language??``}\n${String(e.value??``)}\n\`\`\``);break;case`mermaid`:t.push(`\`\`\`mermaid\n${String(e.value??``)}\n\`\`\``);break;case`table`:Array.isArray(e.value)&&t.push(I(e.value));break;case`metrics`:Array.isArray(e.value)&&t.push(L(e.value));break;case`graph`:e.value&&typeof e.value==`object`&&t.push(R(e.value));break;case`cards`:if(Array.isArray(e.value))for(let n of e.value)t.push(`### ${n.title??`Card`}`),(n.body||n.description)&&t.push(String(n.body??n.description)),(n.badge||n.status)&&t.push(`> **${n.badge??n.status}**`),t.push(``);break;case`tree`:e.value&&typeof e.value==`object`&&t.push(z(e.value));break;case`chart`:{let n=e.value;n?.data&&Array.isArray(n.data)&&t.push(`*${String(n.chartType??`chart`)} chart — ${n.data.length} data points*`);break}case`timeline`:{let n=e.value;if(n?.items)for(let e of n.items){let n=e.status===`done`?`✅`:e.status===`active`?`🔄`:e.status===`error`?`❌`:`⬜`;t.push(`${n} **${e.title}**${e.description?` — ${e.description}`:``}`)}break}case`checklist`:{let n=e.value;if(n?.items)for(let e of n.items)t.push(`- [${e.checked?`x`:` `}] ${e.label}${e.note?` — ${e.note}`:``}`);break}case`comparison`:{let n=e.value;if(n?.columns&&n.columns.length>0){let e=Math.max(...n.columns.map(e=>e.items?.length??0)),r=n.columns.map(e=>e.title);t.push(`| ${r.join(` | `)} |`),t.push(`| ${r.map(()=>`---`).join(` | `)} |`);for(let r=0;r<e;r++)t.push(`| ${n.columns.map(e=>e.items?.[r]??``).join(` | `)} |`)}break}case`status-board`:{let n=e.value;if(n?.items)for(let e of n.items){let n=e.status===`success`?`🟢`:e.status===`warning`?`🟡`:e.status===`error`?`🔴`:e.status===`info`?`🔵`:`⚪`;t.push(`${n} **${e.label}**${e.detail?` — ${e.detail}`:``}`)}break}case`prompt`:{let n=e.value;n?.question&&(t.push(`> **${n.question}**`),n.context&&t.push(`> ${n.context}`));break}case`progress`:{let n=e.value;if(n?.items)for(let e of n.items){let n=e.max??100,r=n>0?Math.round(e.value/n*100):0,i=`█`.repeat(Math.round(r/5))+`░`.repeat(20-Math.round(r/5));t.push(`${e.label}: ${i} ${r}%`)}break}default:t.push(JSON.stringify(e.value,null,2))}return t.push(``),t.join(`
8
+ `)}function F(e){let t=[];switch(e.title&&t.push(`## ${e.title}\n`),e.type){case`markdown`:t.push(String(e.value??``));break;case`code`:t.push(`\`\`\`${e.language??``}\n${String(e.value??``)}\n\`\`\``);break;case`mermaid`:t.push(`\`\`\`mermaid\n${String(e.value??``)}\n\`\`\``);break;case`table`:Array.isArray(e.value)&&t.push(I(e.value));break;case`metrics`:Array.isArray(e.value)&&t.push(L(e.value));break;case`graph`:e.value&&typeof e.value==`object`&&t.push(R(e.value));break;case`cards`:if(Array.isArray(e.value))for(let n of e.value)t.push(`### ${n.title??`Card`}`),(n.body||n.description)&&t.push(String(n.body??n.description)),(n.badge||n.status)&&t.push(`> **${n.badge??n.status}**`),t.push(``);break;case`tree`:e.value&&typeof e.value==`object`&&t.push(z(e.value));break;case`chart`:{let n=e.value;n?.data&&Array.isArray(n.data)&&t.push(`*${String(n.chartType??`chart`)} chart — ${n.data.length} data points*`);break}case`timeline`:{let n=e.value;if(n?.items)for(let e of n.items){let n=e.status===`done`?`✅`:e.status===`active`?`🔄`:e.status===`error`?`❌`:`⬜`;t.push(`${n} **${e.title}**${e.description?` — ${e.description}`:``}`)}break}case`checklist`:{let n=e.value;if(n?.items)for(let e of n.items)t.push(`- [${e.checked?`x`:` `}] ${e.label}${e.note?` — ${e.note}`:``}`);break}case`comparison`:{let n=e.value;if(n?.columns&&n.columns.length>0){let e=Math.max(...n.columns.map(e=>e.items?.length??0)),r=n.columns.map(e=>e.title);t.push(`| ${r.join(` | `)} |`),t.push(`| ${r.map(()=>`---`).join(` | `)} |`);for(let r=0;r<e;r++)t.push(`| ${n.columns.map(e=>e.items?.[r]??``).join(` | `)} |`)}break}case`status-board`:{let n=e.value;if(n?.items)for(let e of n.items){let n=e.status===`success`?`🟢`:e.status===`warning`?`🟡`:e.status===`error`?`🔴`:e.status===`info`?`🔵`:`⚪`;t.push(`${n} **${e.label}**${e.detail?` — ${e.detail}`:``}`)}break}case`prompt`:{let n=e.value;n?.question&&(t.push(`> **${n.question}**`),n.context&&t.push(`> ${n.context}`));break}case`progress`:{let n=e.value;if(n?.items)for(let e of n.items){let n=e.max??100,r=n>0?Math.round(e.value/n*100):0,i=`█`.repeat(Math.round(r/5))+`░`.repeat(20-Math.round(r/5));t.push(`${e.label}: ${i} ${r}%`)}break}case`text`:t.push(String(e.value??``));break;case`heading`:t.push(`## ${String(e.value??``)}\n`);break;case`separator`:t.push(`---
9
+ `);break;default:t.push(JSON.stringify(e.value,null,2))}return t.push(``),t.join(`
9
10
  `)}function I(e){if(e.length===0)return`*(empty table)*`;let t=Object.keys(e[0]),n=[];n.push(`| ${t.join(` | `)} |`),n.push(`| ${t.map(()=>`---`).join(` | `)} |`);for(let r of e)n.push(`| ${t.map(e=>String(r[e]??``)).join(` | `)} |`);return n.join(`
10
11
  `)}function L(e){return e.map(e=>`- **${e.label}**: ${e.value}`).join(`
11
12
  `)}function R(e){let t=["```mermaid",`graph LR`];for(let n of e.nodes){let e=X(String(n.id??n.name??``)),r=String(n.label??n.name??e);t.push(` ${e}["${r}"]`)}for(let n of e.edges){let e=X(String(n.source??n.from??``)),r=X(String(n.target??n.to??``)),i=n.label?`|${String(n.label)}|`:``;t.push(` ${e} -->${i} ${r}`)}return t.push("```"),t.join(`
12
13
  `)}function z(e,t=0){let n=` `.repeat(t),r=[];for(let[i,a]of Object.entries(e))typeof a==`object`&&a&&!Array.isArray(a)?(r.push(`${n}- **${i}**:`),r.push(z(a,t+1))):r.push(`${n}- **${i}**: ${Y(a)}`);return r.join(`
13
14
  `)}function B(e,n){let r=[];if(e&&r.push(`<h1>${t(e)}</h1>`),typeof n==`string`)r.push(`<div class="md-content">${S.parse(n)}</div>`);else if(Array.isArray(n))if(n.length===0)r.push(`<p><em>empty</em></p>`);else if(Z(n[0]))for(let e of n)r.push(V(e));else typeof n[0]==`object`&&n[0]!==null?r.push(H(n)):r.push(`<ul>${n.map(e=>`<li>${t(String(e))}</li>`).join(``)}</ul>`);else if(typeof n==`object`&&n){let e=n;Array.isArray(e.metrics)?r.push(U(e.metrics)):Array.isArray(e.nodes)&&Array.isArray(e.edges)?(r.push(`<pre class="mermaid">${t(K(e))}</pre>`),r.push(`<script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"><\/script>`),r.push(`<script>mermaid.run();<\/script>`)):r.push(G(e))}else r.push(`<p>${t(String(n))}</p>`);return r.join(`
14
- `)}function V(e){let l=[];switch(e.title&&l.push(`<h2>${t(e.title)}</h2>`),e.type){case`markdown`:l.push(`<div class="md-content">${S.parse(String(e.value??``))}</div>`);break;case`code`:l.push(`<pre><code>${t(String(e.value??``))}</code></pre>`);break;case`mermaid`:l.push(`<pre class="mermaid">${t(String(e.value??``))}</pre>`);break;case`table`:if(Array.isArray(e.value)){let t=e.value;if(t.length>0&&Array.isArray(t[0])){let e=t,n=e[0].map(String),r=e.slice(1).map(e=>Object.fromEntries(n.map((t,n)=>[t,e[n]])));l.push(H(r))}else l.push(H(t))}break;case`metrics`:{let t;Array.isArray(e.value)?t=e.value:e.value&&typeof e.value==`object`&&(t=Object.entries(e.value).map(([e,t])=>({label:e,value:String(t)}))),t&&l.push(U(t))}break;case`cards`:Array.isArray(e.value)&&l.push(W(e.value));break;case`tree`:e.value&&typeof e.value==`object`&&l.push(G(e.value));break;case`graph`:e.value&&typeof e.value==`object`&&l.push(`<pre class="mermaid">${t(K(e.value))}</pre>`);break;case`chart`:{let t=e.value;if(t&&!t.chartType&&t.type&&Array.isArray(t.labels)&&Array.isArray(t.datasets)){let n=t.labels,r=t.datasets,i=r.map((e,t)=>e.label??`series${t+1}`),a=n.map((e,t)=>{let n={_label:e};return r.forEach((e,r)=>{n[i[r]]=e.data[t]??0}),n}),o={type:`chart`,title:e.title,value:{chartType:String(t.type),data:a,xKey:`_label`,yKeys:i}};l.push(c(o))}else l.push(c(e));break}case`timeline`:{let t=e.value;Array.isArray(t)&&(t={items:t.map(e=>({title:String(e.event??e.title??``),phase:e.date==null?e.phase==null?void 0:String(e.phase):String(e.date),description:e.description==null?void 0:String(e.description),status:e.status??`done`}))}),t&&l.push(s(t));break}case`checklist`:e.value&&l.push(n(e.value));break;case`comparison`:e.value&&l.push(r(e.value));break;case`status-board`:e.value&&l.push(o(e.value));break;case`prompt`:e.value&&l.push(a(e.value));break;case`progress`:e.value&&l.push(i(e.value));break;default:l.push(`<pre>${t(JSON.stringify(e.value,null,2))}</pre>`)}return l.join(`
15
+ `)}function V(e){let l=[];switch(e.title&&l.push(`<h2>${t(e.title)}</h2>`),e.type){case`markdown`:l.push(`<div class="md-content">${S.parse(String(e.value??``))}</div>`);break;case`code`:l.push(`<pre><code>${t(String(e.value??``))}</code></pre>`);break;case`mermaid`:l.push(`<pre class="mermaid">${t(String(e.value??``))}</pre>`);break;case`table`:if(Array.isArray(e.value)){let t=e.value;if(t.length>0&&Array.isArray(t[0])){let e=t,n=e[0].map(String),r=e.slice(1).map(e=>Object.fromEntries(n.map((t,n)=>[t,e[n]])));l.push(H(r))}else l.push(H(t))}break;case`metrics`:{let t;Array.isArray(e.value)?t=e.value:e.value&&typeof e.value==`object`&&(t=Object.entries(e.value).map(([e,t])=>({label:e,value:String(t)}))),t&&l.push(U(t))}break;case`cards`:Array.isArray(e.value)&&l.push(W(e.value));break;case`tree`:e.value&&typeof e.value==`object`&&l.push(G(e.value));break;case`graph`:e.value&&typeof e.value==`object`&&l.push(`<pre class="mermaid">${t(K(e.value))}</pre>`);break;case`chart`:{let t=e.value;if(t&&!t.chartType&&t.type&&Array.isArray(t.labels)&&Array.isArray(t.datasets)){let n=t.labels,r=t.datasets,i=r.map((e,t)=>e.label??`series${t+1}`),a=n.map((e,t)=>{let n={_label:e};return r.forEach((e,r)=>{n[i[r]]=e.data[t]??0}),n}),o={type:`chart`,title:e.title,value:{chartType:String(t.type),data:a,xKey:`_label`,yKeys:i}};l.push(c(o))}else l.push(c(e));break}case`timeline`:{let t=e.value;Array.isArray(t)&&(t={items:t.map(e=>({title:String(e.event??e.title??``),phase:e.date==null?e.phase==null?void 0:String(e.phase):String(e.date),description:e.description==null?void 0:String(e.description),status:e.status??`done`}))}),t&&l.push(s(t));break}case`checklist`:e.value&&l.push(n(e.value));break;case`comparison`:e.value&&l.push(r(e.value));break;case`status-board`:e.value&&l.push(o(e.value));break;case`prompt`:e.value&&l.push(a(e.value));break;case`progress`:e.value&&l.push(i(e.value));break;case`text`:l.push(`<div class="md-content">${S.parse(String(e.value??``))}</div>`);break;case`heading`:l.push(`<h2>${t(String(e.value??``))}</h2>`);break;case`separator`:l.push(`<hr class="separator">`);break;default:l.push(`<pre>${t(JSON.stringify(e.value,null,2))}</pre>`)}return l.join(`
15
16
  `)}function H(e){if(e.length===0)return`<p><em>empty table</em></p>`;let n=Object.keys(e[0]);return`<div class="table-wrap"><table><thead><tr>${n.map(e=>`<th>${t(e)}</th>`).join(``)}</tr></thead><tbody>${e.map(e=>`<tr>${n.map(n=>`<td>${t(String(e[n]??``))}</td>`).join(``)}</tr>`).join(`
16
17
  `)}</tbody></table></div>`}function U(e){return`<div class="metric-grid">${e.map(e=>`<div class="metric"><div class="metric-value">${t(String(e.value))}</div><div class="metric-label">${t(e.label)}</div></div>`).join(``)}</div>`}function W(e){return`<div class="card-grid">${e.map(e=>{let n=[`<div class="card">`];return e.title&&n.push(`<div class="card-title">${t(String(e.title))}</div>`),(e.body||e.description)&&n.push(`<div class="card-body">${t(String(e.body??e.description))}</div>`),(e.badge||e.status)&&n.push(`<span class="badge">${t(String(e.badge??e.status))}</span>`),n.push(`</div>`),n.join(``)}).join(``)}</div>`}function G(e){let n=[];for(let[r,i]of Object.entries(e))typeof i==`object`&&i&&!Array.isArray(i)?n.push(`<div class="tree-node"><span class="tree-key">${t(r)}:</span><div class="tree-children">${G(i)}</div></div>`):n.push(`<div class="tree-node"><span class="tree-key">${t(r)}:</span> ${t(Y(i))}</div>`);return n.join(``)}function K(e){let t=[`graph LR`];for(let n of e.nodes){let e=X(String(n.id??n.name??``)),r=String(n.label??n.name??e);t.push(` ${e}["${r}"]`)}for(let n of e.edges){let e=X(String(n.source??n.from??``)),r=X(String(n.target??n.to??``)),i=n.label?`|${String(n.label)}|`:``;t.push(` ${e} -->${i} ${r}`)}return t.join(`
17
18
  `)}function q(e,n,r){let i=B(e,n);return`<!DOCTYPE html>
@@ -1,10 +1,10 @@
1
- import{getToolMeta as e}from"../tool-metadata.js";import{SearchOutputSchema as t}from"../output-schemas.js";import{fanOutFtsSearch as n,fanOutSearch as r,openWorkspaceStores as i,resolveWorkspaces as a}from"../cross-workspace.js";import{curatedResourceLink as o,extractCuratedPath as s}from"../resource-links.js";import{stat as c}from"node:fs/promises";import{z as l}from"zod";import{CONTENT_TYPES as u,KNOWLEDGE_ORIGINS as d,SOURCE_TYPES as f,computePartitionKey as p,createLogger as m,serializeError as h}from"../../../core/dist/index.js";import{graphAugmentSearch as g,truncateToTokenBudget as _}from"../../../tools/dist/index.js";import{mergeResults as v}from"../../../enterprise-bridge/dist/index.js";const y=m(`tools`);async function b(e,t,n,r,i){if(!e||t>=e.config.fallbackThreshold&&n.length>0)return{results:n,triggered:!1,cacheHit:!1};let a=!1;try{let t=e.cache.get(r);return t?a=!0:(t=await e.client.search(r,i),t.length>0&&e.cache.set(r,t)),t.length>0?{results:v(n,t,i).map(e=>({record:{id:`er:${e.sourcePath}`,content:e.content,sourcePath:e.source===`er`?`[ER] ${e.sourcePath}`:e.sourcePath,startLine:e.startLine??0,endLine:e.endLine??0,contentType:e.contentType??`documentation`,headingPath:e.headingPath,origin:e.source===`er`?`curated`:e.origin??`indexed`,category:e.category,tags:e.tags??[],chunkIndex:0,totalChunks:1,fileHash:``,indexedAt:new Date().toISOString(),version:1},score:e.score})),triggered:!0,cacheHit:a}:{results:n,triggered:!0,cacheHit:a}}catch(e){return y.warn(`ER fallback failed`,h(e)),{results:n,triggered:!0,cacheHit:a}}}function x(e,t,n=60){let r=new Map;for(let t=0;t<e.length;t++){let i=e[t];r.set(i.record.id,{record:i.record,score:1/(n+t+1)})}for(let e=0;e<t.length;e++){let i=t[e],a=r.get(i.record.id);a?a.score+=1/(n+e+1):r.set(i.record.id,{record:i.record,score:1/(n+e+1)})}return[...r.values()].sort((e,t)=>t.score-e.score).map(({record:e,score:t})=>({record:e,score:t}))}function S(e,t){let n=t.toLowerCase().split(/\s+/).filter(e=>e.length>=2);return n.length<2?e:e.map(e=>{let t=e.record.content.toLowerCase(),r=n.map(e=>{let n=[],r=t.indexOf(e);for(;r!==-1;)n.push(r),r=t.indexOf(e,r+1);return n});if(r.some(e=>e.length===0))return e;let i=t.length;for(let e of r[0]){let t=e,a=e+n[0].length;for(let i=1;i<r.length;i++){let o=r[i][0],s=Math.abs(o-e);for(let t=1;t<r[i].length;t++){let n=Math.abs(r[i][t]-e);n<s&&(s=n,o=r[i][t])}t=Math.min(t,o),a=Math.max(a,o+n[i].length)}i=Math.min(i,a-t)}let a=1+.25/(1+i/200);return{record:e.record,score:e.score*a}}).sort((e,t)=>t.score-e.score)}function C(e,t,n=8){let r=new Set(t.toLowerCase().split(/\s+/).filter(e=>e.length>=2)),i=new Map,a=e.length;for(let t of e){let e=new Set(t.record.content.split(/[^a-zA-Z0-9_]+/).filter(e=>e.length>=3&&!w.has(e.toLowerCase())));for(let t of e){let e=t.toLowerCase();/[_A-Z]/.test(t)&&i.set(`__id__${e}`,1)}let n=new Set(t.record.content.toLowerCase().split(/[^a-zA-Z0-9_]+/).filter(e=>e.length>=3&&!w.has(e)));for(let e of n)i.set(e,(i.get(e)??0)+1)}let o=[];for(let[e,t]of i){if(e.startsWith(`__id__`)||r.has(e)||t>a*.8)continue;let n=Math.log(a/t),s=i.has(`__id__${e}`)?1:0,c=e.length>8?.5:0;o.push({term:e,score:n+s+c})}return o.sort((e,t)=>t.score-e.score).slice(0,n).map(e=>e.term)}const w=new Set(`the.and.for.are.but.not.you.all.can.had.her.was.one.our.out.has.have.from.this.that.with.they.been.said.each.which.their.will.other.about.many.then.them.these.some.would.make.like.into.could.time.very.when.come.just.know.take.people.also.back.after.only.more.than.over.such.import.export.const.function.return.true.false.null.undefined.string.number.boolean.void.type.interface`.split(`.`));async function T(e,t){try{let n=await e.getStats();if(!n.lastIndexedAt)return;let r=new Date(n.lastIndexedAt).getTime(),i=Date.now(),a=[...new Set(t.map(e=>e.record.sourcePath))].filter(e=>!e.startsWith(`[ER]`)).slice(0,5);if(a.length===0)return;let o=0;for(let e of a)try{(await c(e)).mtimeMs>r&&o++}catch{o++}if(o>0){let e=i-r,t=Math.floor(e/6e4),n=t<1?`<1 min`:`${t} min`;return`> ⚠️ **Index may be stale** — ${o} file(s) modified since last index (${n} ago). Use \`reindex\` to refresh.`}}catch{}}function E(c,m,v,w,E,D,O){let k=e(`search`);c.registerTool(`search`,{title:k.title,description:`Search the knowledge base for code, docs, and prior decisions. Default choice for discovery. Modes: hybrid (default), semantic, keyword. For multi-strategy precision queries use find; for a known file path use lookup.`,outputSchema:t,inputSchema:{query:l.string().max(5e3).describe(`Natural language search query`),limit:l.number().min(1).max(20).default(5).describe(`Maximum results to return`),search_mode:l.enum([`hybrid`,`semantic`,`keyword`]).default(`hybrid`).describe(`Search strategy: hybrid (vector + FTS + RRF fusion, default), semantic (vector only), keyword (FTS only)`),content_type:l.enum(u).optional().describe(`Filter by content type`),source_type:l.enum(f).optional().describe(`Coarse filter: "source" (code only), "documentation" (md, curated), "test", "config". Overrides content_type if both set.`),origin:l.enum(d).optional().describe(`Filter by knowledge origin`),category:l.string().optional().describe(`Filter by category (e.g., decisions, patterns, conventions)`),tags:l.array(l.string()).optional().describe(`Filter by tags (returns results matching ANY of the specified tags)`),min_score:l.number().min(0).max(1).default(.25).describe(`Minimum similarity score`),graph_hops:l.number().min(0).max(3).default(1).describe(`Number of graph hops to augment results with connected entities (0 = disabled, 1 = direct connections, 2-3 = deeper traversal). Default 1 provides module/symbol context automatically.`),max_tokens:l.number().min(100).max(5e4).optional().describe(`Maximum token budget for the response. When set, output is truncated to fit.`),dedup:l.enum([`file`,`chunk`]).default(`chunk`).describe(`Deduplication mode: "chunk" (default, show all matching chunks) or "file" (collapse chunks from same file into single result with merged line ranges)`),workspaces:l.array(l.string()).optional().describe(`Cross-workspace search: partition names or folder basenames to include. Use ["*"] for all registered workspaces. Only works in user-level install mode.`)},annotations:k.annotations},async({query:e,limit:t,search_mode:c,content_type:l,source_type:u,origin:d,category:f,tags:k,min_score:A,graph_hops:j,max_tokens:M,dedup:N,workspaces:P})=>{try{let F={limit:t,minScore:A,contentType:l,sourceType:u,origin:d,category:f,tags:k},I,L=!1,R=!1,z=``;if(c===`keyword`)I=await v.ftsSearch(e,F),I=I.slice(0,t);else if(c===`semantic`){let n=await m.embedQuery(e);I=await v.search(n,F);let r=await b(E,I[0]?.score??0,I,e,t);I=r.results,L=r.triggered,R=r.cacheHit}else{let n=await m.embedQuery(e),[r,i]=await Promise.all([v.search(n,{...F,limit:t*2}),v.ftsSearch(e,{...F,limit:t*2}).catch(()=>[])]);I=x(r,i).slice(0,t);let a=await b(E,r[0]?.score??0,I,e,t);I=a.results,L=a.triggered,R=a.cacheHit}D&&D.recordSearch(e,L,R),I.length>1&&(I=S(I,e));let B=``;if(P&&P.length>0){let o=a(P,p(process.cwd()));if(o.length>0){let{stores:a,closeAll:s}=await i(o);try{let i;i=c===`keyword`?await n(a,e,{...F,limit:t}):await r(a,await m.embedQuery(e),{...F,limit:t});for(let e of i)I.push({record:{...e.record,sourcePath:`[${e.workspace}] ${e.record.sourcePath}`},score:e.score});I=I.sort((e,t)=>t.score-e.score).slice(0,t),B=` + ${o.length} workspace(s)`}finally{await s()}}}if(N===`file`&&I.length>1){let e=new Map;for(let t of I){let n=t.record.sourcePath,r=e.get(n);r?(t.score>r.best.score&&(r.best=t),r.ranges.push({start:t.record.startLine,end:t.record.endLine})):e.set(n,{best:t,ranges:[{start:t.record.startLine,end:t.record.endLine}]})}I=[...e.values()].sort((e,t)=>t.best.score-e.best.score).map(({best:e,ranges:t})=>({record:{...e.record,content:t.length>1?`${e.record.content}\n\n_Matched ${t.length} sections: ${t.sort((e,t)=>e.start-t.start).map(e=>`L${e.start}-${e.end}`).join(`, `)}_`:e.record.content},score:e.score}))}if(I.length===0){if(O?.available)try{let t=(await O.createMessage({prompt:`The search query "${e}" returned 0 results in a code knowledge base. Suggest ONE alternative search query that might find relevant results. Reply with ONLY the alternative query, nothing else.`,systemPrompt:`You are a search query optimizer for a code knowledge base. Generate a single alternative query.`,maxTokens:100})).text.trim().split(`
2
- `)[0].slice(0,500);if(t&&t!==e){let n=await m.embedQuery(t),r=await v.search(n,F);r.length>0&&(I=r,z=`> _Original query "${e}" returned 0 results. Auto-reformulated to "${t}"._\n\n`,y.info(`Smart search fallback succeeded`,{originalQuery:e,altQuery:t,resultCount:r.length}))}}catch(e){y.debug(`Smart search fallback failed`,{error:String(e)})}if(I.length===0)return{content:[{type:`text`,text:`No results found for the given query.`}],structuredContent:{results:[],totalResults:0,searchMode:c,query:e}}}let V,H;if(j>0&&!w&&(H="> **Note:** `graph_hops` was set but no graph store is available. Graph augmentation skipped."),j>0&&w)try{let e=await g(w,I.map(e=>({recordId:e.record.id,score:e.score,sourcePath:e.record.sourcePath})),{hops:j,maxPerHit:5});V=new Map;for(let t of e)if(t.graphContext.nodes.length>0){let e=t.graphContext.nodes.slice(0,5).map(e=>` - **${e.name}** (${e.type})`).join(`
1
+ import{getToolMeta as e}from"../tool-metadata.js";import{SearchOutputSchema as t}from"../output-schemas.js";import{fanOutFtsSearch as n,fanOutSearch as r,openWorkspaceStores as i,resolveWorkspaces as a}from"../cross-workspace.js";import{curatedResourceLink as o,extractCuratedPath as s}from"../resource-links.js";import{basename as c}from"node:path";import{stat as l}from"node:fs/promises";import{z as u}from"zod";import{CONTENT_TYPES as d,KNOWLEDGE_ORIGINS as f,SOURCE_TYPES as p,computePartitionKey as m,createLogger as h,serializeError as g}from"../../../core/dist/index.js";import{bookendReorder as _,graphAugmentSearch as v,stashGet as y,truncateToTokenBudget as ee}from"../../../tools/dist/index.js";import{mergeResults as b}from"../../../enterprise-bridge/dist/index.js";const x=h(`tools`);function S(e){let t=[],n=c(process.cwd());n&&t.push(`[project: ${n}]`);let r=y(`__context_boost`);return r&&t.push(`[focus: ${r.value}]`),t.length===0?e:`${t.join(` `)} ${e}`}async function C(e,t,n,r,i){if(!e||t>=e.config.fallbackThreshold&&n.length>0)return{results:n,triggered:!1,cacheHit:!1};let a=!1;try{let t=e.cache.get(r);return t?a=!0:(t=await e.client.search(r,i),t.length>0&&e.cache.set(r,t)),t.length>0?{results:b(n,t,i).map(e=>({record:{id:`er:${e.sourcePath}`,content:e.content,sourcePath:e.source===`er`?`[ER] ${e.sourcePath}`:e.sourcePath,startLine:e.startLine??0,endLine:e.endLine??0,contentType:e.contentType??`documentation`,headingPath:e.headingPath,origin:e.source===`er`?`curated`:e.origin??`indexed`,category:e.category,tags:e.tags??[],chunkIndex:0,totalChunks:1,fileHash:``,indexedAt:new Date().toISOString(),version:1},score:e.score})),triggered:!0,cacheHit:a}:{results:n,triggered:!0,cacheHit:a}}catch(e){return x.warn(`ER fallback failed`,g(e)),{results:n,triggered:!0,cacheHit:a}}}function te(e,t,n=60){let r=new Map;for(let t=0;t<e.length;t++){let i=e[t];r.set(i.record.id,{record:i.record,score:1/(n+t+1)})}for(let e=0;e<t.length;e++){let i=t[e],a=r.get(i.record.id);a?a.score+=1/(n+e+1):r.set(i.record.id,{record:i.record,score:1/(n+e+1)})}return[...r.values()].sort((e,t)=>t.score-e.score).map(({record:e,score:t})=>({record:e,score:t}))}function w(e,t){let n=t.toLowerCase().split(/\s+/).filter(e=>e.length>=2);return n.length<2?e:e.map(e=>{let t=e.record.content.toLowerCase(),r=n.map(e=>{let n=[],r=t.indexOf(e);for(;r!==-1;)n.push(r),r=t.indexOf(e,r+1);return n});if(r.some(e=>e.length===0))return e;let i=t.length;for(let e of r[0]){let t=e,a=e+n[0].length;for(let i=1;i<r.length;i++){let o=r[i][0],s=Math.abs(o-e);for(let t=1;t<r[i].length;t++){let n=Math.abs(r[i][t]-e);n<s&&(s=n,o=r[i][t])}t=Math.min(t,o),a=Math.max(a,o+n[i].length)}i=Math.min(i,a-t)}let a=1+.25/(1+i/200);return{record:e.record,score:e.score*a}}).sort((e,t)=>t.score-e.score)}function T(e,t,n=8){let r=new Set(t.toLowerCase().split(/\s+/).filter(e=>e.length>=2)),i=new Map,a=e.length;for(let t of e){let e=new Set(t.record.content.split(/[^a-zA-Z0-9_]+/).filter(e=>e.length>=3&&!E.has(e.toLowerCase())));for(let t of e){let e=t.toLowerCase();/[_A-Z]/.test(t)&&i.set(`__id__${e}`,1)}let n=new Set(t.record.content.toLowerCase().split(/[^a-zA-Z0-9_]+/).filter(e=>e.length>=3&&!E.has(e)));for(let e of n)i.set(e,(i.get(e)??0)+1)}let o=[];for(let[e,t]of i){if(e.startsWith(`__id__`)||r.has(e)||t>a*.8)continue;let n=Math.log(a/t),s=i.has(`__id__${e}`)?1:0,c=e.length>8?.5:0;o.push({term:e,score:n+s+c})}return o.sort((e,t)=>t.score-e.score).slice(0,n).map(e=>e.term)}const E=new Set(`the.and.for.are.but.not.you.all.can.had.her.was.one.our.out.has.have.from.this.that.with.they.been.said.each.which.their.will.other.about.many.then.them.these.some.would.make.like.into.could.time.very.when.come.just.know.take.people.also.back.after.only.more.than.over.such.import.export.const.function.return.true.false.null.undefined.string.number.boolean.void.type.interface`.split(`.`));async function D(e,t){try{let n=await e.getStats();if(!n.lastIndexedAt)return;let r=new Date(n.lastIndexedAt).getTime(),i=Date.now(),a=[...new Set(t.map(e=>e.record.sourcePath))].filter(e=>!e.startsWith(`[ER]`)).slice(0,5);if(a.length===0)return;let o=0;for(let e of a)try{(await l(e)).mtimeMs>r&&o++}catch{o++}if(o>0){let e=i-r,t=Math.floor(e/6e4),n=t<1?`<1 min`:`${t} min`;return`> ⚠️ **Index may be stale** — ${o} file(s) modified since last index (${n} ago). Use \`reindex\` to refresh.`}}catch{}}function O(c,l,h,y,b,E,O){let k=e(`search`);c.registerTool(`search`,{title:k.title,description:`Search the knowledge base for code, docs, and prior decisions. Default choice for discovery. Modes: hybrid (default), semantic, keyword. For multi-strategy precision queries use find; for a known file path use lookup.`,outputSchema:t,inputSchema:{query:u.string().max(5e3).describe(`Natural language search query`),limit:u.number().min(1).max(20).default(5).describe(`Maximum results to return`),search_mode:u.enum([`hybrid`,`semantic`,`keyword`]).default(`hybrid`).describe(`Search strategy: hybrid (vector + FTS + RRF fusion, default), semantic (vector only), keyword (FTS only)`),content_type:u.enum(d).optional().describe(`Filter by content type`),source_type:u.enum(p).optional().describe(`Coarse filter: "source" (code only), "documentation" (md, curated), "test", "config". Overrides content_type if both set.`),origin:u.enum(f).optional().describe(`Filter by knowledge origin`),category:u.string().optional().describe(`Filter by category (e.g., decisions, patterns, conventions)`),tags:u.array(u.string()).optional().describe(`Filter by tags (returns results matching ANY of the specified tags)`),min_score:u.number().min(0).max(1).default(.25).describe(`Minimum similarity score`),graph_hops:u.number().min(0).max(3).default(1).describe(`Number of graph hops to augment results with connected entities (0 = disabled, 1 = direct connections, 2-3 = deeper traversal). Default 1 provides module/symbol context automatically.`),max_tokens:u.number().min(100).max(5e4).optional().describe(`Maximum token budget for the response. When set, output is truncated to fit.`),dedup:u.enum([`file`,`chunk`]).default(`chunk`).describe(`Deduplication mode: "chunk" (default, show all matching chunks) or "file" (collapse chunks from same file into single result with merged line ranges)`),workspaces:u.array(u.string()).optional().describe(`Cross-workspace search: partition names or folder basenames to include. Use ["*"] for all registered workspaces. Only works in user-level install mode.`)},annotations:k.annotations},async({query:e,limit:t,search_mode:c,content_type:u,source_type:d,origin:f,category:p,tags:k,min_score:ne,graph_hops:A,max_tokens:j,dedup:M,workspaces:N})=>{try{let P={limit:t,minScore:ne,contentType:u,sourceType:d,origin:f,category:p,tags:k},F,I=!1,L=!1,R=``,z=S(e);if(c===`keyword`)F=await h.ftsSearch(e,P),F=F.slice(0,t);else if(c===`semantic`){let n=await l.embedQuery(z);F=await h.search(n,P);let r=await C(b,F[0]?.score??0,F,e,t);F=r.results,I=r.triggered,L=r.cacheHit}else{let n=await l.embedQuery(z),[r,i]=await Promise.all([h.search(n,{...P,limit:t*2}),h.ftsSearch(e,{...P,limit:t*2}).catch(()=>[])]);F=te(r,i).slice(0,t);let a=await C(b,r[0]?.score??0,F,e,t);F=a.results,I=a.triggered,L=a.cacheHit}E&&E.recordSearch(e,I,L),F.length>1&&(F=w(F,e));let B=``;if(N&&N.length>0){let o=a(N,m(process.cwd()));if(o.length>0){let{stores:a,closeAll:s}=await i(o);try{let i;i=c===`keyword`?await n(a,e,{...P,limit:t}):await r(a,await l.embedQuery(e),{...P,limit:t});for(let e of i)F.push({record:{...e.record,sourcePath:`[${e.workspace}] ${e.record.sourcePath}`},score:e.score});F=F.sort((e,t)=>t.score-e.score).slice(0,t),B=` + ${o.length} workspace(s)`}finally{await s()}}}if(M===`file`&&F.length>1){let e=new Map;for(let t of F){let n=t.record.sourcePath,r=e.get(n);r?(t.score>r.best.score&&(r.best=t),r.ranges.push({start:t.record.startLine,end:t.record.endLine})):e.set(n,{best:t,ranges:[{start:t.record.startLine,end:t.record.endLine}]})}F=[...e.values()].sort((e,t)=>t.best.score-e.best.score).map(({best:e,ranges:t})=>({record:{...e.record,content:t.length>1?`${e.record.content}\n\n_Matched ${t.length} sections: ${t.sort((e,t)=>e.start-t.start).map(e=>`L${e.start}-${e.end}`).join(`, `)}_`:e.record.content},score:e.score}))}if(F.length===0){if(O?.available)try{let t=(await O.createMessage({prompt:`The search query "${e}" returned 0 results in a code knowledge base. Suggest ONE alternative search query that might find relevant results. Reply with ONLY the alternative query, nothing else.`,systemPrompt:`You are a search query optimizer for a code knowledge base. Generate a single alternative query.`,maxTokens:100})).text.trim().split(`
2
+ `)[0].slice(0,500);if(t&&t!==e){let n=await l.embedQuery(t),r=await h.search(n,P);r.length>0&&(F=r,R=`> _Original query "${e}" returned 0 results. Auto-reformulated to "${t}"._\n\n`,x.info(`Smart search fallback succeeded`,{originalQuery:e,altQuery:t,resultCount:r.length}))}}catch(e){x.debug(`Smart search fallback failed`,{error:String(e)})}if(F.length===0)return{content:[{type:`text`,text:`No results found for the given query.`}],structuredContent:{results:[],totalResults:0,searchMode:c,query:e}}}let V,H;if(A>0&&!y&&(H="> **Note:** `graph_hops` was set but no graph store is available. Graph augmentation skipped."),A>0&&y)try{let e=await v(y,F.map(e=>({recordId:e.record.id,score:e.score,sourcePath:e.record.sourcePath})),{hops:A,maxPerHit:5});V=new Map;for(let t of e)if(t.graphContext.nodes.length>0){let e=t.graphContext.nodes.slice(0,5).map(e=>` - **${e.name}** (${e.type})`).join(`
3
3
  `),n=t.graphContext.edges.slice(0,5).map(e=>` - ${e.fromId} —[${e.type}]→ ${e.toId}`).join(`
4
- `),r=[`- **Graph Context** (${j} hop${j>1?`s`:``}):`];e&&r.push(` Entities:\n${e}`),n&&r.push(` Relationships:\n${n}`),V.set(t.recordId,r.join(`
5
- `))}}catch(e){y.warn(`Graph augmentation failed`,h(e)),H=`> **Note:** Graph augmentation failed. Results shown without graph context.`}let U=I.map((e,t)=>{let n=e.record;return`${`### Result ${t+1} (score: ${e.score.toFixed(3)})`}\n${[`- **Source**: ${n.sourcePath}`,n.headingPath?`- **Section**: ${n.headingPath}`:null,`- **Type**: ${n.contentType}`,n.startLine?`- **Lines**: ${n.startLine}-${n.endLine}`:null,n.origin===`indexed`?null:`- **Origin**: ${n.origin}`,n.category?`- **Category**: ${n.category}`:null,n.tags?.length?`- **Tags**: ${n.tags.join(`, `)}`:null,V?.get(n.id)??null].filter(Boolean).join(`
4
+ `),r=[`- **Graph Context** (${A} hop${A>1?`s`:``}):`];e&&r.push(` Entities:\n${e}`),n&&r.push(` Relationships:\n${n}`),V.set(t.recordId,r.join(`
5
+ `))}}catch(e){x.warn(`Graph augmentation failed`,g(e)),H=`> **Note:** Graph augmentation failed. Results shown without graph context.`}let U=Date.now();for(let e of F)if(e.record.origin===`curated`&&e.record.indexedAt){let t=U-new Date(e.record.indexedAt).getTime(),n=Math.max(0,t/864e5);e.score*=.95**n}F.sort((e,t)=>t.score-e.score),F=_(F);let W=F.map((e,t)=>{let n=e.record;return`${`### Result ${t+1} (score: ${e.score.toFixed(3)})`}\n${[`- **Source**: ${n.sourcePath}`,n.headingPath?`- **Section**: ${n.headingPath}`:null,`- **Type**: ${n.contentType}`,n.startLine?`- **Lines**: ${n.startLine}-${n.endLine}`:null,n.origin===`indexed`?null:`- **Origin**: ${n.origin}`,n.category?`- **Category**: ${n.category}`:null,n.tags?.length?`- **Tags**: ${n.tags.join(`, `)}`:null,V?.get(n.id)??null].filter(Boolean).join(`
6
6
  `)}\n\n${n.content}`}).join(`
7
7
 
8
8
  ---
9
9
 
10
- `),W=(c===`hybrid`?`hybrid (vector + keyword RRF)`:c===`keyword`?`keyword (FTS)`:`semantic (vector)`)+B,G=C(I,e),K=G.length>0?`\n_Distinctive terms: ${G.map(e=>`\`${e}\``).join(`, `)}_`:``,q=await T(v,I),J=[];if(I.length===0)J.push("`reindex` — no results found, index may be stale"),J.push("`find` — try federated search with glob/regex");else{let e=I[0]?.record.sourcePath;e&&J.push(`\`lookup\` — see all chunks from \`${e}\``),J.push("`symbol` — resolve a specific symbol from the results"),J.push("`compact` — compress a result file for focused reading")}let Y=[H?`${H}\n\n`:``,q?`${q}\n\n`:``,U,`\n\n---\n_Search mode: ${W} | ${I.length} results_${K}`,`\n_Next: ${J.join(` | `)}_`],X=z+Y.join(``);M&&(X=_(X,M));let Z=new Set,Q=[];for(let e of I){if(e.record.origin!==`curated`||e.record.sourcePath.startsWith(`[`))continue;let t=s(e.record.sourcePath);if(!t)continue;let n=o(t,e.record.headingPath??t);n&&!Z.has(n.uri)&&(Z.add(n.uri),Q.push(n))}return{content:[{type:`text`,text:X},...Q],structuredContent:{results:I.map(e=>({sourcePath:e.record.sourcePath,contentType:e.record.contentType,score:e.score,...e.record.headingPath?{headingPath:e.record.headingPath}:{},...e.record.startLine?{startLine:e.record.startLine}:{},...e.record.endLine?{endLine:e.record.endLine}:{},...e.record.origin===`indexed`?{}:{origin:e.record.origin},...e.record.category?{category:e.record.category}:{},...e.record.tags?.length?{tags:e.record.tags}:{}})),totalResults:I.length,searchMode:c,query:e}}}catch(e){return y.error(`Search failed`,h(e)),{content:[{type:`text`,text:`Search failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}export{E as registerSearchTool};
10
+ `),G=(c===`hybrid`?`hybrid (vector + keyword RRF)`:c===`keyword`?`keyword (FTS)`:`semantic (vector)`)+B,K=T(F,e),q=K.length>0?`\n_Distinctive terms: ${K.map(e=>`\`${e}\``).join(`, `)}_`:``,J=await D(h,F),Y=[];if(F.length===0)Y.push("`reindex` — no results found, index may be stale"),Y.push("`find` — try federated search with glob/regex");else{let e=F[0]?.record.sourcePath;e&&Y.push(`\`lookup\` — see all chunks from \`${e}\``),Y.push("`symbol` — resolve a specific symbol from the results"),Y.push("`compact` — compress a result file for focused reading")}let X=[H?`${H}\n\n`:``,J?`${J}\n\n`:``,W,`\n\n---\n_Search mode: ${G} | ${F.length} results_${q}`,`\n_Next: ${Y.join(` | `)}_`],Z=R+X.join(``);j&&(Z=ee(Z,j));let Q=new Set,$=[];for(let e of F){if(e.record.origin!==`curated`||e.record.sourcePath.startsWith(`[`))continue;let t=s(e.record.sourcePath);if(!t)continue;let n=o(t,e.record.headingPath??t);n&&!Q.has(n.uri)&&(Q.add(n.uri),$.push(n))}return{content:[{type:`text`,text:Z},...$],structuredContent:{results:F.map(e=>({sourcePath:e.record.sourcePath,contentType:e.record.contentType,score:e.score,...e.record.headingPath?{headingPath:e.record.headingPath}:{},...e.record.startLine?{startLine:e.record.startLine}:{},...e.record.endLine?{endLine:e.record.endLine}:{},...e.record.origin===`indexed`?{}:{origin:e.record.origin},...e.record.category?{category:e.record.category}:{},...e.record.tags?.length?{tags:e.record.tags}:{}})),totalResults:F.length,searchMode:c,query:e}}}catch(e){return x.error(`Search failed`,g(e)),{content:[{type:`text`,text:`Search failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}export{O as registerSearchTool};
@@ -8,6 +8,12 @@ interface OnboardState {
8
8
  onboardComplete: boolean;
9
9
  onboardTimestamp?: string;
10
10
  }
11
+ declare function getScaffoldVersion(): string | null;
12
+ /**
13
+ * Lightweight status tool registered during init — returns version info
14
+ * without needing the KB store, graph, or curated manager.
15
+ */
16
+ declare function registerEarlyStatusTool(server: McpServer): void;
11
17
  declare function registerStatusTool(server: McpServer, store: IKnowledgeStore, graphStore?: IGraphStore, curated?: CuratedKnowledgeManager, onboardState?: OnboardState, config?: KBConfig): void;
12
18
  //#endregion
13
- export { OnboardState, registerStatusTool };
19
+ export { OnboardState, getScaffoldVersion, registerEarlyStatusTool, registerStatusTool };
@@ -1,2 +1,3 @@
1
- import{getToolMeta as e}from"../tool-metadata.js";import{StatusOutputSchema as t}from"../output-schemas.js";import{getCurrentVersion as n}from"../version-check.js";import{existsSync as r,readFileSync as i}from"node:fs";import{resolve as a}from"node:path";import{KB_PATHS as o,createLogger as s,serializeError as c}from"../../../core/dist/index.js";import{WasmRuntime as l}from"../../../chunker/dist/index.js";import{homedir as u}from"node:os";const d=s(`tools`);function f(e,t,n,r=4e3){let i,a=new Promise(e=>{i=setTimeout(()=>{d.warn(`Status sub-operation "${n}" timed out after ${r}ms`),e({value:t,timedOut:!0})},r)});return Promise.race([e.then(e=>(clearTimeout(i),{value:e,timedOut:!1}),e=>(clearTimeout(i),d.warn(`Status sub-operation "${n}" failed: ${e instanceof Error?e.message:String(e)}`),{value:t,timedOut:!1})),a])}function p(){try{let e=a(u(),`.copilot`,`.kb-scaffold.json`);return r(e)?JSON.parse(i(e,`utf-8`)).version??null:null}catch{return null}}function m(i,s,u,m,h,g){let _=e(`status`);i.registerTool(`status`,{title:_.title,description:`Get the current status and statistics of the knowledge base index.`,outputSchema:t,annotations:_.annotations},async()=>{let e=[];try{let t=await f(s.getStats(),{totalRecords:0,totalFiles:0,lastIndexedAt:null,contentTypeBreakdown:{}},`store.getStats`),i=t.value;t.timedOut&&e.push(`⚠ Index stats timed out — values may be incomplete`);let c=await f(s.listSourcePaths(),[],`store.listSourcePaths`),d=c.value;c.timedOut&&e.push(`⚠ File listing timed out`);let _=null,v=0,y=[`## Knowledge Base Status`,``,`- **Total Records**: ${i.totalRecords}`,`- **Total Files**: ${i.totalFiles}`,`- **Last Indexed**: ${i.lastIndexedAt??`Never`}`,``,`### Content Types`,...Object.entries(i.contentTypeBreakdown).map(([e,t])=>`- ${e}: ${t}`),``,`### Indexed Files`,...d.slice(0,50).map(e=>`- ${e}`),d.length>50?`\n... and ${d.length-50} more files`:``];if(u)try{let t=await f(u.getStats(),{nodeCount:0,edgeCount:0,nodeTypes:{},edgeTypes:{}},`graphStore.getStats`);if(t.timedOut)e.push(`⚠ Graph stats timed out`),y.push(``,`### Knowledge Graph`,`- Graph stats timed out`);else{let e=t.value;_={nodes:e.nodeCount,edges:e.edgeCount},y.push(``,`### Knowledge Graph`,`- **Nodes**: ${e.nodeCount}`,`- **Edges**: ${e.edgeCount}`,...Object.entries(e.nodeTypes).map(([e,t])=>` - ${e}: ${t}`));try{let e=await f(u.validate(),{valid:!0,danglingEdges:[],orphanNodes:[],stats:{nodeCount:0,edgeCount:0,nodeTypes:{},edgeTypes:{}}},`graphStore.validate`);if(!e.timedOut){let t=e.value;t.valid||y.push(`- **⚠ Integrity Issues**: ${t.danglingEdges.length} dangling edges`),t.orphanNodes.length>0&&y.push(`- **Orphan nodes**: ${t.orphanNodes.length}`)}}catch{}}}catch{y.push(``,`### Knowledge Graph`,`- Graph store unavailable`)}let b=g?.onboardDir??a(process.cwd(),o.aiKb),x=r(b),S=h?.onboardComplete??x;if(y.push(``,`### Onboard Status`,S?`- ✅ Complete${h?.onboardTimestamp?` (last: ${h.onboardTimestamp})`:``}`:'- Not run — call `onboard({ path: "." })` to analyze the codebase',`- **Onboard Directory**: \`${b}\``),m)try{let t=await f(m.list(),[],`curated.list`);if(t.timedOut)e.push(`⚠ Curated knowledge listing timed out`),y.push(``,`### Curated Knowledge`,`- Listing timed out`);else{let e=t.value;v=e.length,y.push(``,`### Curated Knowledge`,e.length>0?`- ${e.length} entries`:"- Empty use `remember()` to persist decisions")}}catch{y.push(``,`### Curated Knowledge`,`- Unable to read curated entries`)}if(i.lastIndexedAt){let e=new Date(i.lastIndexedAt),t=(Date.now()-e.getTime())/(1e3*60*60);y.push(``,`### Index Freshness`,t>24?`- ⚠ Last indexed ${Math.floor(t)}h ago — may be stale. Run \`reindex({})\``:`- ✅ Last indexed ${t<1?`less than 1h`:`${Math.floor(t)}h`} ago`)}y.push(``,`### Runtime`,`- **Tree-sitter (WASM)**: ${l.get()?`✅ Available (AST analysis)`:`⚠ Unavailable (regex fallback)`}`);let C=p(),w=n();C&&C!==w&&y.push(``,`### Upgrade Available`,`- New version available (${w}). Run: \`npx -y @vpxa/kb upgrade\``),e.length>0&&y.push(``,`### ⚠ Warnings`,...e.map(e=>`- ${e}`));let T=y.join(`
2
- `),E={totalRecords:i.totalRecords,totalFiles:i.totalFiles,lastIndexedAt:i.lastIndexedAt??null,onboarded:S,onboardDir:b,contentTypes:i.contentTypeBreakdown,wasmAvailable:!!l.get(),graphStats:_,curatedCount:v,serverVersion:w,scaffoldVersion:C??null,upgradeAvailable:C!=null&&C!==w};return{content:[{type:`text`,text:T+"\n\n---\n_Next: Use `search` to query indexed content, `graph(stats)` to explore the knowledge graph, or `reindex` to refresh the index._"}],structuredContent:E}}catch(e){return d.error(`Status failed`,c(e)),{content:[{type:`text`,text:`Status check failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}export{m as registerStatusTool};
1
+ import{getGcStatus as e}from"../auto-gc.js";import{getToolTelemetry as t}from"../replay-interceptor.js";import{getToolMeta as n}from"../tool-metadata.js";import{StatusOutputSchema as r}from"../output-schemas.js";import{getCurrentVersion as i}from"../version-check.js";import{existsSync as a,readFileSync as o,statSync as s}from"node:fs";import{resolve as c}from"node:path";import{KB_PATHS as l,createLogger as u,serializeError as d}from"../../../core/dist/index.js";import{WasmRuntime as f}from"../../../chunker/dist/index.js";import{homedir as p}from"node:os";const m=u(`tools`);function h(e,t,n,r=4e3){let i,a=new Promise(e=>{i=setTimeout(()=>{m.warn(`Status sub-operation "${n}" timed out after ${r}ms`),e({value:t,timedOut:!0})},r)});return Promise.race([e.then(e=>(clearTimeout(i),{value:e,timedOut:!1}),e=>(clearTimeout(i),m.warn(`Status sub-operation "${n}" failed: ${e instanceof Error?e.message:String(e)}`),{value:t,timedOut:!1})),a])}function g(){try{let e=c(p(),`.copilot`,`.kb-scaffold.json`);return a(e)?JSON.parse(o(e,`utf-8`)).version??null:null}catch{return null}}function _(e){let t=n(`status`);e.registerTool(`status`,{title:t.title,description:`Get the current status and statistics of the knowledge base index.`,outputSchema:r,annotations:t.annotations},async()=>{let e=i(),t=g(),n=t!=null&&t!==e,r=[`## Knowledge Base Status`,``,`⏳ **KB is initializing** index stats will be available shortly.`,``,`### Runtime`,`- **Tree-sitter (WASM)**: ${f.get()?`✅ Available (AST analysis)`:`⚠ Unavailable (regex fallback)`}`,``,`### Version`,`- **Server**: ${e}`,`- **Scaffold**: ${t??`not installed`}`];n&&r.push(``,`### Upgrade Available`,`- Server v${e} scaffold v${t}`,"- **Run `kb upgrade` in the terminal now** to update agents, prompts, and skills.","- _Agent: please run `kb upgrade` in the terminal to apply the update._");let a={totalRecords:0,totalFiles:0,lastIndexedAt:null,onboarded:!1,onboardDir:``,contentTypes:{},wasmAvailable:!!f.get(),graphStats:null,curatedCount:0,serverVersion:e,scaffoldVersion:t??null,upgradeAvailable:n};return{content:[{type:`text`,text:r.join(`
2
+ `)}],structuredContent:a}})}function v(o,u,p,_,v,y){let b=n(`status`);o.registerTool(`status`,{title:b.title,description:`Get the current status and statistics of the knowledge base index.`,outputSchema:r,annotations:b.annotations},async()=>{let n=[];try{let r=await h(u.getStats(),{totalRecords:0,totalFiles:0,lastIndexedAt:null,contentTypeBreakdown:{}},`store.getStats`),o=r.value;r.timedOut&&n.push(`⚠ Index stats timed out — values may be incomplete`);let d=await h(u.listSourcePaths(),[],`store.listSourcePaths`),m=d.value;d.timedOut&&n.push(`⚠ File listing timed out`);let b=null,x=0,S=[`## Knowledge Base Status`,``,`- **Total Records**: ${o.totalRecords}`,`- **Total Files**: ${o.totalFiles}`,`- **Last Indexed**: ${o.lastIndexedAt??`Never`}`,``,`### Content Types`,...Object.entries(o.contentTypeBreakdown).map(([e,t])=>`- ${e}: ${t}`),``,`### Indexed Files`,...m.slice(0,50).map(e=>`- ${e}`),m.length>50?`\n... and ${m.length-50} more files`:``];if(p)try{let e=await h(p.getStats(),{nodeCount:0,edgeCount:0,nodeTypes:{},edgeTypes:{}},`graphStore.getStats`);if(e.timedOut)n.push(`⚠ Graph stats timed out`),S.push(``,`### Knowledge Graph`,`- Graph stats timed out`);else{let t=e.value;b={nodes:t.nodeCount,edges:t.edgeCount},S.push(``,`### Knowledge Graph`,`- **Nodes**: ${t.nodeCount}`,`- **Edges**: ${t.edgeCount}`,...Object.entries(t.nodeTypes).map(([e,t])=>` - ${e}: ${t}`));try{let e=await h(p.validate(),{valid:!0,danglingEdges:[],orphanNodes:[],stats:{nodeCount:0,edgeCount:0,nodeTypes:{},edgeTypes:{}}},`graphStore.validate`);if(!e.timedOut){let t=e.value;t.valid||S.push(`- **⚠ Integrity Issues**: ${t.danglingEdges.length} dangling edges`),t.orphanNodes.length>0&&S.push(`- **Orphan nodes**: ${t.orphanNodes.length}`)}}catch{}}}catch{S.push(``,`### Knowledge Graph`,`- Graph store unavailable`)}let C=y?.onboardDir??c(process.cwd(),l.aiKb),w=a(C),T=v?.onboardComplete??w;if(S.push(``,`### Onboard Status`,T?`- ✅ Complete${v?.onboardTimestamp?` (last: ${v.onboardTimestamp})`:``}`:'- ❌ Not run — call `onboard({ path: "." })` to analyze the codebase',`- **Onboard Directory**: \`${C}\``),_)try{let e=await h(_.list(),[],`curated.list`);if(e.timedOut)n.push(`⚠ Curated knowledge listing timed out`),S.push(``,`### Curated Knowledge`,`- Listing timed out`);else{let t=e.value;x=t.length,S.push(``,`### Curated Knowledge`,t.length>0?`- ${t.length} entries`:"- Empty — use `remember()` to persist decisions")}}catch{S.push(``,`### Curated Knowledge`,`- Unable to read curated entries`)}let E=0;if(o.lastIndexedAt){E=new Date(o.lastIndexedAt).getTime();let e=(Date.now()-E)/(1e3*60*60);S.push(``,`### Index Freshness`,e>24?`- ⚠ Last indexed ${Math.floor(e)}h ago — may be stale. Run \`reindex({})\``:`- ✅ Last indexed ${e<1?`less than 1h`:`${Math.floor(e)}h`} ago`)}{try{let e=c(process.cwd(),l.data,`stash`);if(a(e)){let t=s(e).mtimeMs;t>E&&(E=t)}}catch{}let e=[];if(_)try{let t=x>0?await _.list():[];for(let e of t){let t=new Date(e.updated||e.created).getTime();t>E&&(E=t)}e.push(...t.sort((e,t)=>new Date(t.updated).getTime()-new Date(e.updated).getTime()).slice(0,5))}catch{}let t=E>0?Date.now()-E:0;if(t>=144e5){let n=Math.floor(t/36e5);if(S.push(``,`### 🌅 Session Briefing`,`_${n}+ hours since last activity — here's what to pick up:_`,``),e.length>0){S.push(`**Recent decisions/notes:**`);for(let t of e)S.push(`- **${t.title}** (${t.category??`note`}) — ${(t.contentPreview??``).slice(0,80)}…`)}S.push(``,`**Suggested next steps:**`,'- `search({ query: "SESSION CHECKPOINT", origin: "curated" })` — find your last checkpoint',"- `restore({})` — resume from a saved checkpoint","- `list()` — browse all stored knowledge")}}S.push(``,`### Runtime`,`- **Tree-sitter (WASM)**: ${f.get()?`✅ Available (AST analysis)`:`⚠ Unavailable (regex fallback)`}`);let D=g(),O=i();D&&D!==O&&S.push(``,`### ⬆ Upgrade Available`,`- Server v${O} ≠ scaffold v${D}`,"- **Run `kb upgrade` in the terminal now** to update agents, prompts, and skills.","- _Agent: please run `kb upgrade` in the terminal to apply the update._"),n.length>0&&S.push(``,`### ⚠ Warnings`,...n.map(e=>`- ${e}`));let k=t();if(k.length>0){let e=k.sort((e,t)=>t.callCount-e.callCount);S.push(``,`### Tool Usage This Session`,``),S.push(`| Tool | Calls | Tokens In | Tokens Out | Errors | Avg Latency |`),S.push(`|------|-------|-----------|------------|--------|-------------|`);for(let t of e.slice(0,15)){let e=Math.round(t.totalInputChars/4),n=Math.round(t.totalOutputChars/4),r=Math.round(t.totalDurationMs/t.callCount);S.push(`| ${t.tool} | ${t.callCount} | ${e.toLocaleString()} | ${n.toLocaleString()} | ${t.errorCount} | ${r}ms |`)}}let A=e();if(A.bufferSize>=10){let e=A.state===`healthy`?`🟢`:A.state===`degraded`?`🔴`:`🟡`;S.push(``,`### Auto-GC: ${e} ${A.state}`),S.push(`- p95 latency: ${A.p95}ms | buffer: ${A.bufferSize} samples`),A.gcCount>0&&S.push(`- GC cycles triggered: ${A.gcCount}`)}let j=S.join(`
3
+ `),M={totalRecords:o.totalRecords,totalFiles:o.totalFiles,lastIndexedAt:o.lastIndexedAt??null,onboarded:T,onboardDir:C,contentTypes:o.contentTypeBreakdown,wasmAvailable:!!f.get(),graphStats:b,curatedCount:x,serverVersion:O,scaffoldVersion:D??null,upgradeAvailable:D!=null&&D!==O};return{content:[{type:`text`,text:j+"\n\n---\n_Next: Use `search` to query indexed content, `graph(stats)` to explore the knowledge graph, or `reindex` to refresh the index._"}],structuredContent:M}}catch(e){return m.error(`Status failed`,d(e)),{content:[{type:`text`,text:`Status check failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}export{g as getScaffoldVersion,_ as registerEarlyStatusTool,v as registerStatusTool};
@@ -2,6 +2,7 @@
2
2
  /**
3
3
  * Non-blocking check for newer @vpxa/kb versions on npm.
4
4
  * Logs a warning to stderr if the running version is outdated.
5
+ * Auto-upgrades scaffold files when server version ≠ scaffold version.
5
6
  */
6
7
  declare function getCurrentVersion(): string;
7
8
  /**
@@ -9,5 +10,12 @@ declare function getCurrentVersion(): string;
9
10
  * This is fire-and-forget — it never throws and never blocks startup.
10
11
  */
11
12
  declare function checkForUpdates(): void;
13
+ /**
14
+ * Auto-upgrade scaffold files when the running server version differs from
15
+ * the installed scaffold version. This is fire-and-forget — it never throws
16
+ * and never blocks startup. The upgrade process runs in a detached child so
17
+ * the MCP server stays responsive.
18
+ */
19
+ declare function autoUpgradeScaffold(): void;
12
20
  //#endregion
13
- export { checkForUpdates, getCurrentVersion };
21
+ export { autoUpgradeScaffold, checkForUpdates, getCurrentVersion };
@@ -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}from"../../core/dist/index.js";const a=i(`server`);function o(){let i=n(t(r(import.meta.url)),`..`,`..`,`..`,`package.json`);try{return JSON.parse(e(i,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}function s(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){let t=(n[e]??0)-(r[e]??0);if(t!==0)return t>0?1:-1}return 0}function c(){let e=o();fetch(`https://registry.npmjs.org/@vpxa/kb/latest`,{signal:AbortSignal.timeout(5e3)}).then(e=>{if(e.ok)return e.json()}).then(t=>{if(!t||typeof t!=`object`)return;let n=t.version;n&&s(e,n)<0&&a.warn(`Update available`,{currentVersion:e,latestVersion:n,updateCommand:`npx -y @vpxa/kb upgrade`})}).catch(()=>{})}export{c as checkForUpdates,o as getCurrentVersion};
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{createLogger as a}from"../../core/dist/index.js";import{execFile as o}from"node:child_process";import{homedir as s}from"node:os";const c=a(`server`);function l(){let e=r(n(i(import.meta.url)),`..`,`..`,`..`,`package.json`);try{return JSON.parse(t(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}function u(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){let t=(n[e]??0)-(r[e]??0);if(t!==0)return t>0?1:-1}return 0}function d(){let e=l();fetch(`https://registry.npmjs.org/@vpxa/kb/latest`,{signal:AbortSignal.timeout(5e3)}).then(e=>{if(e.ok)return e.json()}).then(t=>{if(!t||typeof t!=`object`)return;let n=t.version;n&&u(e,n)<0&&c.warn(`Update available`,{currentVersion:e,latestVersion:n,updateCommand:`kb upgrade`})}).catch(()=>{})}function f(){try{let n=r(s(),`.copilot`,`.kb-scaffold.json`);return e(n)?JSON.parse(t(n,`utf-8`)).version??null:null}catch{return null}}function p(){try{let t=l(),a=f();if(a==null||a===t)return;c.info(`Scaffold version mismatch — auto-upgrading`,{serverVersion:t,scaffoldVersion:a});let s=r(n(i(import.meta.url)),`..`,`..`,`..`,`bin`,`kb.mjs`);if(!e(s)){c.warn(`Cannot auto-upgrade: kb CLI binary not found`,{binPath:s});return}o(process.execPath,[s,`upgrade`],{timeout:3e4,windowsHide:!0},(e,t,n)=>{e?c.warn(`Auto-upgrade failed`,{error:e.message,stderr:n?.slice(0,500)}):c.info(`Auto-upgrade complete`,{output:t?.slice(0,500)})}).unref()}catch(e){c.warn(`Auto-upgrade check failed`,{error:e instanceof Error?e.message:String(e)})}}export{p as autoUpgradeScaffold,d as checkForUpdates,l as getCurrentVersion};
@@ -11,6 +11,8 @@ interface CompactOptions {
11
11
  query: string;
12
12
  /** Target output size in characters (default: 3000) */
13
13
  maxChars?: number;
14
+ /** Token budget — when set, overrides maxChars (approx 4 chars per token) */
15
+ tokenBudget?: number;
14
16
  /** Minimum similarity score to include a segment (0-1, default: 0.3) */
15
17
  minScore?: number;
16
18
  /** Segmentation strategy (default: 'paragraph') */
@@ -1,3 +1,3 @@
1
- import{cosineSimilarity as e,segment as t}from"./text-utils.js";import{readFile as n,stat as r}from"node:fs/promises";async function i(i,a){let{query:o,maxChars:s=3e3,minScore:c=.3,segmentation:l=`paragraph`}=a,u;if(a.text)u=a.text;else if(a.path){let e;try{e=await r(a.path)}catch(e){let t=e.code;throw t===`ENOENT`?Error(`File not found: ${a.path}. Check the path and try again.`):t===`EACCES`||t===`EPERM`?Error(`Permission denied reading ${a.path}. The file exists but is not accessible.`):e}if(e.size>1e7)throw Error(`File too large (${(e.size/1e6).toFixed(1)}MB). compact supports files up to 10MB. Consider splitting or using search instead.`);u=a.cache?(await a.cache.get(a.path)).content:await n(a.path,`utf-8`)}else throw Error(`Either "text" or "path" must be provided`);if(u.length<=s)return{text:u,originalChars:u.length,compressedChars:u.length,ratio:1,segmentsKept:1,segmentsTotal:1};let d=t(u,l);if(d.length===0)return{text:``,originalChars:u.length,compressedChars:0,ratio:0,segmentsKept:0,segmentsTotal:0};let f=await i.embed(o),p=[];for(let t=0;t<d.length;t++){let n=e(f,await i.embed(d[t]));p.push({text:d[t],score:n,index:t})}let m=p.filter(e=>e.score>=c).sort((e,t)=>t.score-e.score),h=[],g=0;for(let e of m){if(g+e.text.length>s){g===0&&(h.push({...e,text:e.text.slice(0,s)}),g=s);break}h.push(e),g+=e.text.length+2}h.sort((e,t)=>e.index-t.index);let _=h.map(e=>e.text).join(`
1
+ import{bookendReorder as e,cosineSimilarity as t,segment as n}from"./text-utils.js";import{readFile as r,stat as i}from"node:fs/promises";async function a(a,o){let{query:s,maxChars:c=3e3,minScore:l=.3,segmentation:u=`paragraph`}=o,d=o.tokenBudget?o.tokenBudget*4:c,f;if(o.text)f=o.text;else if(o.path){let e;try{e=await i(o.path)}catch(e){let t=e.code;throw t===`ENOENT`?Error(`File not found: ${o.path}. Check the path and try again.`):t===`EACCES`||t===`EPERM`?Error(`Permission denied reading ${o.path}. The file exists but is not accessible.`):e}if(e.size>1e7)throw Error(`File too large (${(e.size/1e6).toFixed(1)}MB). compact supports files up to 10MB. Consider splitting or using search instead.`);f=o.cache?(await o.cache.get(o.path)).content:await r(o.path,`utf-8`)}else throw Error(`Either "text" or "path" must be provided`);if(f.length<=d)return{text:f,originalChars:f.length,compressedChars:f.length,ratio:1,segmentsKept:1,segmentsTotal:1};let p=n(f,u);if(p.length===0)return{text:``,originalChars:f.length,compressedChars:0,ratio:0,segmentsKept:0,segmentsTotal:0};let m=await a.embed(s),h=[];for(let e=0;e<p.length;e++){let n=t(m,await a.embed(p[e]));h.push({text:p[e],score:n,index:e})}let g=h.filter(e=>e.score>=l).sort((e,t)=>t.score-e.score),_=[],v=0;for(let e of g){if(v+e.text.length>d){v===0&&(_.push({...e,text:e.text.slice(0,d)}),v=d);break}_.push(e),v+=e.text.length+2}let y=e(_.sort((e,t)=>t.score-e.score)).map(e=>e.text).join(`
2
2
 
3
- `);return{text:_,originalChars:u.length,compressedChars:_.length,ratio:_.length/u.length,segmentsKept:h.length,segmentsTotal:d.length}}export{i as compact};
3
+ `);return{text:y,originalChars:f.length,compressedChars:y.length,ratio:y.length/f.length,segmentsKept:_.length,segmentsTotal:p.length}}export{a as compact};
@@ -46,7 +46,7 @@ import { StashEntry, stashClear, stashDelete, stashGet, stashList, stashSet } fr
46
46
  import { StratumCard, StratumCardOptions, StratumCardResult, stratumCard } from "./stratum-card.js";
47
47
  import { SymbolGraphContext, SymbolInfo, SymbolOptions, symbol } from "./symbol.js";
48
48
  import { TestRunOptions, TestRunResult, classifyExitCode, testRun } from "./test-run.js";
49
- import { cosineSimilarity, estimateTokens, segment } from "./text-utils.js";
49
+ import { bookendReorder, cosineSimilarity, estimateTokens, segment } from "./text-utils.js";
50
50
  import { TimeOptions, TimeResult, timeUtils } from "./time-utils.js";
51
51
  import { TraceNode, TraceOptions, TraceResult, trace } from "./trace.js";
52
52
  import { headTailTruncate, paragraphTruncate, truncateToTokenBudget } from "./truncation.js";
@@ -54,4 +54,4 @@ import { WatchEvent, WatchHandle, WatchOptions, watchList, watchStart, watchStop
54
54
  import { WebFetchMode, WebFetchOptions, WebFetchResult, webFetch } from "./web-fetch.js";
55
55
  import { WebSearchOptions, WebSearchResult, WebSearchResultItem, parseSearchResults, webSearch } from "./web-search.js";
56
56
  import { Workset, addToWorkset, deleteWorkset, getWorkset, listWorksets, removeFromWorkset, saveWorkset } from "./workset.js";
57
- export { type AuditCheck, type AuditData, type AuditOptions, type AuditRecommendation, type BatchOperation, type BatchOptions, type BatchResult, type ChangelogEntry, type ChangelogFormat, type ChangelogOptions, type ChangelogResult, type CheckOptions, type CheckResult, type CheckSummaryResult, type Checkpoint, type ClassifyTrigger, type CodemodChange, type CodemodOptions, type CodemodResult, type CodemodRule, type CompactOptions, type CompactResult, type ConstraintRef, type DeadSymbol, type DeadSymbolOptions, type DeadSymbolResult, type DelegateOptions, type DelegateResult, type DiffChange, type DiffFile, type DiffHunk, type DiffParseOptions, type DigestFieldEntry, type DigestOptions, type DigestResult, type DigestSource, type DogfoodLogEntry, type DogfoodLogGroupedEntry, type DogfoodLogOptions, type DogfoodLogResult, type EncodeOperation, type EncodeOptions, type EncodeResult, type EnvInfoOptions, type EnvInfoResult, type EvalOptions, type EvalResult, type EvidenceEntry, type EvidenceMapAction, type EvidenceMapResult, type EvidenceMapState, type EvidenceStatus, type Example, FileCache, type FileCacheEntry, type FileCacheStats, type FileMetrics, type FileSummaryOptions, type FileSummaryResult, type FindExamplesOptions, type FindExamplesResult, type FindOptions, type FindResult, type FindResults, type ForgeClassifyCeremony, type ForgeClassifyOptions, type ForgeClassifyResult, type ForgeGroundOptions, type ForgeGroundResult, type ForgeTier, type GateDecision, type GateResult, type GitContextOptions, type GitContextResult, type GraphAugmentOptions, type GraphAugmentedResult, type GraphQueryOptions, type GraphQueryResult, type GuideRecommendation, type GuideResult, type HealthCheck, type HealthResult, type HttpMethod, type HttpRequestOptions, type HttpRequestResult, type KBError, type KBErrorCode, type KBNextHint, type KBResponse, type KBResponseMeta, type LaneDiffEntry, type LaneDiffResult, type LaneMergeResult, type LaneMeta, type ManagedProcess, type MeasureOptions, type MeasureResult, type OnboardMode, type OnboardOptions, type OnboardResult, type OnboardStepResult, type ParsedError, type ParsedGitStatus, type ParsedOutput, type ParsedTestResult, type ParsedTestSummary, type QueueItem, type QueueState, type RegexTestOptions, type RegexTestResult, type RenameChange, type RenameOptions, type RenameResult, type ReplayEntry, type ReplayOptions, type RestorePoint, type SafetyGate, type SafetyGateResult, type SchemaValidateOptions, type SchemaValidateResult, type ScopeMapEntry, type ScopeMapOptions, type ScopeMapResult, type Snippet, type SnippetAction, type SnippetOptions, type SnippetResult, type StashEntry, type StratumCard, type StratumCardOptions, type StratumCardResult, type SymbolGraphContext, type SymbolInfo, type SymbolOptions, type TestRunOptions, type TestRunResult, type TimeOptions, type TimeResult, type TraceNode, type TraceOptions, type TraceResult, type TransformOptions, type TransformResult, type TypedUnknownSeed, type UnknownType, type ValidationError, type WatchEvent, type WatchHandle, type WatchOptions, type WebFetchMode, type WebFetchOptions, type WebFetchResult, type WebSearchOptions, type WebSearchResult, type WebSearchResultItem, type Workset, addToWorkset, analyzeFile, audit, autoClaimTestFailures, batch, changelog, check, checkpointLatest, checkpointList, checkpointLoad, checkpointSave, classifyExitCode, codemod, compact, cosineSimilarity, createRestorePoint, dataTransform, delegate, delegateListModels, deleteWorkset, diffParse, digest, dogfoodLog, encode, envInfo, errorResponse, escapeRegExp, estimateTokens, evaluate, evidenceMap, fileSummary, find, findDeadSymbols, findExamples, forgeClassify, forgeGround, formatChangelog, getWorkset, gitContext, graphAugmentSearch, graphQuery, guide, headTailTruncate, health, httpRequest, laneCreate, laneDiff, laneDiscard, laneList, laneMerge, laneStatus, listRestorePoints, listWorksets, measure, okResponse, onboard, paragraphTruncate, parseBiome, parseGitStatus, parseOutput, parseSearchResults, parseTsc, parseVitest, processList, processLogs, processStart, processStatus, processStop, queueClear, queueCreate, queueDelete, queueDone, queueFail, queueGet, queueList, queueNext, queuePush, regexTest, removeFromWorkset, rename, replayAppend, replayCapture, replayClear, replayList, replayTrim, resolvePath, restoreFromPoint, saveWorkset, schemaValidate, scopeMap, segment, snippet, stashClear, stashDelete, stashGet, stashList, stashSet, stratumCard, summarizeCheckResult, symbol, testRun, timeUtils, trace, truncateToTokenBudget, watchList, watchStart, watchStop, webFetch, webSearch };
57
+ export { type AuditCheck, type AuditData, type AuditOptions, type AuditRecommendation, type BatchOperation, type BatchOptions, type BatchResult, type ChangelogEntry, type ChangelogFormat, type ChangelogOptions, type ChangelogResult, type CheckOptions, type CheckResult, type CheckSummaryResult, type Checkpoint, type ClassifyTrigger, type CodemodChange, type CodemodOptions, type CodemodResult, type CodemodRule, type CompactOptions, type CompactResult, type ConstraintRef, type DeadSymbol, type DeadSymbolOptions, type DeadSymbolResult, type DelegateOptions, type DelegateResult, type DiffChange, type DiffFile, type DiffHunk, type DiffParseOptions, type DigestFieldEntry, type DigestOptions, type DigestResult, type DigestSource, type DogfoodLogEntry, type DogfoodLogGroupedEntry, type DogfoodLogOptions, type DogfoodLogResult, type EncodeOperation, type EncodeOptions, type EncodeResult, type EnvInfoOptions, type EnvInfoResult, type EvalOptions, type EvalResult, type EvidenceEntry, type EvidenceMapAction, type EvidenceMapResult, type EvidenceMapState, type EvidenceStatus, type Example, FileCache, type FileCacheEntry, type FileCacheStats, type FileMetrics, type FileSummaryOptions, type FileSummaryResult, type FindExamplesOptions, type FindExamplesResult, type FindOptions, type FindResult, type FindResults, type ForgeClassifyCeremony, type ForgeClassifyOptions, type ForgeClassifyResult, type ForgeGroundOptions, type ForgeGroundResult, type ForgeTier, type GateDecision, type GateResult, type GitContextOptions, type GitContextResult, type GraphAugmentOptions, type GraphAugmentedResult, type GraphQueryOptions, type GraphQueryResult, type GuideRecommendation, type GuideResult, type HealthCheck, type HealthResult, type HttpMethod, type HttpRequestOptions, type HttpRequestResult, type KBError, type KBErrorCode, type KBNextHint, type KBResponse, type KBResponseMeta, type LaneDiffEntry, type LaneDiffResult, type LaneMergeResult, type LaneMeta, type ManagedProcess, type MeasureOptions, type MeasureResult, type OnboardMode, type OnboardOptions, type OnboardResult, type OnboardStepResult, type ParsedError, type ParsedGitStatus, type ParsedOutput, type ParsedTestResult, type ParsedTestSummary, type QueueItem, type QueueState, type RegexTestOptions, type RegexTestResult, type RenameChange, type RenameOptions, type RenameResult, type ReplayEntry, type ReplayOptions, type RestorePoint, type SafetyGate, type SafetyGateResult, type SchemaValidateOptions, type SchemaValidateResult, type ScopeMapEntry, type ScopeMapOptions, type ScopeMapResult, type Snippet, type SnippetAction, type SnippetOptions, type SnippetResult, type StashEntry, type StratumCard, type StratumCardOptions, type StratumCardResult, type SymbolGraphContext, type SymbolInfo, type SymbolOptions, type TestRunOptions, type TestRunResult, type TimeOptions, type TimeResult, type TraceNode, type TraceOptions, type TraceResult, type TransformOptions, type TransformResult, type TypedUnknownSeed, type UnknownType, type ValidationError, type WatchEvent, type WatchHandle, type WatchOptions, type WebFetchMode, type WebFetchOptions, type WebFetchResult, type WebSearchOptions, type WebSearchResult, type WebSearchResultItem, type Workset, addToWorkset, analyzeFile, audit, autoClaimTestFailures, batch, bookendReorder, changelog, check, checkpointLatest, checkpointList, checkpointLoad, checkpointSave, classifyExitCode, codemod, compact, cosineSimilarity, createRestorePoint, dataTransform, delegate, delegateListModels, deleteWorkset, diffParse, digest, dogfoodLog, encode, envInfo, errorResponse, escapeRegExp, estimateTokens, evaluate, evidenceMap, fileSummary, find, findDeadSymbols, findExamples, forgeClassify, forgeGround, formatChangelog, getWorkset, gitContext, graphAugmentSearch, graphQuery, guide, headTailTruncate, health, httpRequest, laneCreate, laneDiff, laneDiscard, laneList, laneMerge, laneStatus, listRestorePoints, listWorksets, measure, okResponse, onboard, paragraphTruncate, parseBiome, parseGitStatus, parseOutput, parseSearchResults, parseTsc, parseVitest, processList, processLogs, processStart, processStatus, processStop, queueClear, queueCreate, queueDelete, queueDone, queueFail, queueGet, queueList, queueNext, queuePush, regexTest, removeFromWorkset, rename, replayAppend, replayCapture, replayClear, replayList, replayTrim, resolvePath, restoreFromPoint, saveWorkset, schemaValidate, scopeMap, segment, snippet, stashClear, stashDelete, stashGet, stashList, stashSet, stratumCard, summarizeCheckResult, symbol, testRun, timeUtils, trace, truncateToTokenBudget, watchList, watchStart, watchStop, webFetch, webSearch };
@@ -1 +1 @@
1
- import{parseBiome as e,parseGitStatus as t,parseOutput as n,parseTsc as r,parseVitest as i}from"./parse-output.js";import{check as a,summarizeCheckResult as o}from"./check.js";import{escapeRegExp as s}from"./regex-utils.js";import{findDeadSymbols as c}from"./dead-symbols.js";import{health as l}from"./health.js";import{resolvePath as u}from"./path-resolver.js";import{cosineSimilarity as d,estimateTokens as f,segment as p}from"./text-utils.js";import{errorResponse as m,okResponse as h}from"./response-envelope.js";import{audit as g}from"./audit.js";import{batch as _}from"./batch.js";import{changelog as v,formatChangelog as y}from"./changelog.js";import{checkpointLatest as b,checkpointList as x,checkpointLoad as S,checkpointSave as C}from"./checkpoint.js";import{createRestorePoint as w,listRestorePoints as T,restoreFromPoint as E}from"./restore-points.js";import{codemod as D}from"./codemod.js";import{compact as O}from"./compact.js";import{dataTransform as k}from"./data-transform.js";import{delegate as A,delegateListModels as j}from"./delegate.js";import{diffParse as M}from"./diff-parse.js";import{digest as N}from"./digest.js";import{dogfoodLog as P}from"./dogfood-log.js";import{encode as F}from"./encode.js";import{envInfo as I}from"./env-info.js";import{evaluate as L}from"./eval.js";import{autoClaimTestFailures as R,evidenceMap as z}from"./evidence-map.js";import{FileCache as B}from"./file-cache.js";import{fileSummary as V}from"./file-summary.js";import{findExamples as H}from"./find-examples.js";import{find as U}from"./find.js";import{forgeClassify as W}from"./forge-classify.js";import{scopeMap as G}from"./scope-map.js";import{forgeGround as K}from"./forge-ground.js";import{gitContext as q}from"./git-context.js";import{graphAugmentSearch as J,graphQuery as Y}from"./graph-query.js";import{guide as X}from"./guide.js";import{headTailTruncate as Z,paragraphTruncate as Q,truncateToTokenBudget as $}from"./truncation.js";import{httpRequest as ee}from"./http-request.js";import{laneCreate as te,laneDiff as ne,laneDiscard as re,laneList as ie,laneMerge as ae,laneStatus as oe}from"./lane.js";import{analyzeFile as se,measure as ce}from"./measure.js";import{onboard as le}from"./onboard.js";import{processList as ue,processLogs as de,processStart as fe,processStatus as pe,processStop as me}from"./process-manager.js";import{queueClear as he,queueCreate as ge,queueDelete as _e,queueDone as ve,queueFail as ye,queueGet as be,queueList as xe,queueNext as Se,queuePush as Ce}from"./queue.js";import{regexTest as we}from"./regex-test.js";import{rename as Te}from"./rename.js";import{replayAppend as Ee,replayCapture as De,replayClear as Oe,replayList as ke,replayTrim as Ae}from"./replay.js";import{schemaValidate as je}from"./schema-validate.js";import{snippet as Me}from"./snippet.js";import{stashClear as Ne,stashDelete as Pe,stashGet as Fe,stashList as Ie,stashSet as Le}from"./stash.js";import{stratumCard as Re}from"./stratum-card.js";import{symbol as ze}from"./symbol.js";import{classifyExitCode as Be,testRun as Ve}from"./test-run.js";import{timeUtils as He}from"./time-utils.js";import{trace as Ue}from"./trace.js";import{watchList as We,watchStart as Ge,watchStop as Ke}from"./watch.js";import{webFetch as qe}from"./web-fetch.js";import{parseSearchResults as Je,webSearch as Ye}from"./web-search.js";import{addToWorkset as Xe,deleteWorkset as Ze,getWorkset as Qe,listWorksets as $e,removeFromWorkset as et,saveWorkset as tt}from"./workset.js";export{B as FileCache,Xe as addToWorkset,se as analyzeFile,g as audit,R as autoClaimTestFailures,_ as batch,v as changelog,a as check,b as checkpointLatest,x as checkpointList,S as checkpointLoad,C as checkpointSave,Be as classifyExitCode,D as codemod,O as compact,d as cosineSimilarity,w as createRestorePoint,k as dataTransform,A as delegate,j as delegateListModels,Ze as deleteWorkset,M as diffParse,N as digest,P as dogfoodLog,F as encode,I as envInfo,m as errorResponse,s as escapeRegExp,f as estimateTokens,L as evaluate,z as evidenceMap,V as fileSummary,U as find,c as findDeadSymbols,H as findExamples,W as forgeClassify,K as forgeGround,y as formatChangelog,Qe as getWorkset,q as gitContext,J as graphAugmentSearch,Y as graphQuery,X as guide,Z as headTailTruncate,l as health,ee as httpRequest,te as laneCreate,ne as laneDiff,re as laneDiscard,ie as laneList,ae as laneMerge,oe as laneStatus,T as listRestorePoints,$e as listWorksets,ce as measure,h as okResponse,le as onboard,Q as paragraphTruncate,e as parseBiome,t as parseGitStatus,n as parseOutput,Je as parseSearchResults,r as parseTsc,i as parseVitest,ue as processList,de as processLogs,fe as processStart,pe as processStatus,me as processStop,he as queueClear,ge as queueCreate,_e as queueDelete,ve as queueDone,ye as queueFail,be as queueGet,xe as queueList,Se as queueNext,Ce as queuePush,we as regexTest,et as removeFromWorkset,Te as rename,Ee as replayAppend,De as replayCapture,Oe as replayClear,ke as replayList,Ae as replayTrim,u as resolvePath,E as restoreFromPoint,tt as saveWorkset,je as schemaValidate,G as scopeMap,p as segment,Me as snippet,Ne as stashClear,Pe as stashDelete,Fe as stashGet,Ie as stashList,Le as stashSet,Re as stratumCard,o as summarizeCheckResult,ze as symbol,Ve as testRun,He as timeUtils,Ue as trace,$ as truncateToTokenBudget,We as watchList,Ge as watchStart,Ke as watchStop,qe as webFetch,Ye as webSearch};
1
+ import{parseBiome as e,parseGitStatus as t,parseOutput as n,parseTsc as r,parseVitest as i}from"./parse-output.js";import{check as a,summarizeCheckResult as o}from"./check.js";import{escapeRegExp as s}from"./regex-utils.js";import{findDeadSymbols as c}from"./dead-symbols.js";import{health as l}from"./health.js";import{resolvePath as u}from"./path-resolver.js";import{bookendReorder as d,cosineSimilarity as f,estimateTokens as p,segment as m}from"./text-utils.js";import{errorResponse as h,okResponse as g}from"./response-envelope.js";import{audit as _}from"./audit.js";import{batch as v}from"./batch.js";import{changelog as y,formatChangelog as b}from"./changelog.js";import{checkpointLatest as x,checkpointList as S,checkpointLoad as C,checkpointSave as w}from"./checkpoint.js";import{createRestorePoint as T,listRestorePoints as E,restoreFromPoint as D}from"./restore-points.js";import{codemod as O}from"./codemod.js";import{compact as k}from"./compact.js";import{dataTransform as A}from"./data-transform.js";import{delegate as j,delegateListModels as M}from"./delegate.js";import{diffParse as N}from"./diff-parse.js";import{digest as P}from"./digest.js";import{dogfoodLog as F}from"./dogfood-log.js";import{encode as I}from"./encode.js";import{envInfo as L}from"./env-info.js";import{evaluate as R}from"./eval.js";import{autoClaimTestFailures as z,evidenceMap as B}from"./evidence-map.js";import{FileCache as V}from"./file-cache.js";import{fileSummary as H}from"./file-summary.js";import{findExamples as U}from"./find-examples.js";import{find as W}from"./find.js";import{forgeClassify as G}from"./forge-classify.js";import{scopeMap as K}from"./scope-map.js";import{forgeGround as q}from"./forge-ground.js";import{gitContext as J}from"./git-context.js";import{graphAugmentSearch as Y,graphQuery as X}from"./graph-query.js";import{guide as Z}from"./guide.js";import{headTailTruncate as Q,paragraphTruncate as $,truncateToTokenBudget as ee}from"./truncation.js";import{httpRequest as te}from"./http-request.js";import{laneCreate as ne,laneDiff as re,laneDiscard as ie,laneList as ae,laneMerge as oe,laneStatus as se}from"./lane.js";import{analyzeFile as ce,measure as le}from"./measure.js";import{onboard as ue}from"./onboard.js";import{processList as de,processLogs as fe,processStart as pe,processStatus as me,processStop as he}from"./process-manager.js";import{queueClear as ge,queueCreate as _e,queueDelete as ve,queueDone as ye,queueFail as be,queueGet as xe,queueList as Se,queueNext as Ce,queuePush as we}from"./queue.js";import{regexTest as Te}from"./regex-test.js";import{rename as Ee}from"./rename.js";import{replayAppend as De,replayCapture as Oe,replayClear as ke,replayList as Ae,replayTrim as je}from"./replay.js";import{schemaValidate as Me}from"./schema-validate.js";import{snippet as Ne}from"./snippet.js";import{stashClear as Pe,stashDelete as Fe,stashGet as Ie,stashList as Le,stashSet as Re}from"./stash.js";import{stratumCard as ze}from"./stratum-card.js";import{symbol as Be}from"./symbol.js";import{classifyExitCode as Ve,testRun as He}from"./test-run.js";import{timeUtils as Ue}from"./time-utils.js";import{trace as We}from"./trace.js";import{watchList as Ge,watchStart as Ke,watchStop as qe}from"./watch.js";import{webFetch as Je}from"./web-fetch.js";import{parseSearchResults as Ye,webSearch as Xe}from"./web-search.js";import{addToWorkset as Ze,deleteWorkset as Qe,getWorkset as $e,listWorksets as et,removeFromWorkset as tt,saveWorkset as nt}from"./workset.js";export{V as FileCache,Ze as addToWorkset,ce as analyzeFile,_ as audit,z as autoClaimTestFailures,v as batch,d as bookendReorder,y as changelog,a as check,x as checkpointLatest,S as checkpointList,C as checkpointLoad,w as checkpointSave,Ve as classifyExitCode,O as codemod,k as compact,f as cosineSimilarity,T as createRestorePoint,A as dataTransform,j as delegate,M as delegateListModels,Qe as deleteWorkset,N as diffParse,P as digest,F as dogfoodLog,I as encode,L as envInfo,h as errorResponse,s as escapeRegExp,p as estimateTokens,R as evaluate,B as evidenceMap,H as fileSummary,W as find,c as findDeadSymbols,U as findExamples,G as forgeClassify,q as forgeGround,b as formatChangelog,$e as getWorkset,J as gitContext,Y as graphAugmentSearch,X as graphQuery,Z as guide,Q as headTailTruncate,l as health,te as httpRequest,ne as laneCreate,re as laneDiff,ie as laneDiscard,ae as laneList,oe as laneMerge,se as laneStatus,E as listRestorePoints,et as listWorksets,le as measure,g as okResponse,ue as onboard,$ as paragraphTruncate,e as parseBiome,t as parseGitStatus,n as parseOutput,Ye as parseSearchResults,r as parseTsc,i as parseVitest,de as processList,fe as processLogs,pe as processStart,me as processStatus,he as processStop,ge as queueClear,_e as queueCreate,ve as queueDelete,ye as queueDone,be as queueFail,xe as queueGet,Se as queueList,Ce as queueNext,we as queuePush,Te as regexTest,tt as removeFromWorkset,Ee as rename,De as replayAppend,Oe as replayCapture,ke as replayClear,Ae as replayList,je as replayTrim,u as resolvePath,D as restoreFromPoint,nt as saveWorkset,Me as schemaValidate,K as scopeMap,m as segment,Ne as snippet,Pe as stashClear,Fe as stashDelete,Ie as stashGet,Le as stashList,Re as stashSet,ze as stratumCard,o as summarizeCheckResult,Be as symbol,He as testRun,Ue as timeUtils,We as trace,ee as truncateToTokenBudget,Ge as watchList,Ke as watchStart,qe as watchStop,Je as webFetch,Xe as webSearch};
@@ -14,5 +14,11 @@ declare function segment(text: string, strategy: 'paragraph' | 'sentence' | 'lin
14
14
  * Cosine similarity between two vectors.
15
15
  */
16
16
  declare function cosineSimilarity(a: Float32Array, b: Float32Array): number;
17
+ /**
18
+ * Reorder items using "bookend" strategy (Liu et al. 2023 "Lost in the Middle").
19
+ * Highest-scoring items placed at start and end positions for better LLM attention.
20
+ * Input must already be sorted by score descending.
21
+ */
22
+ declare function bookendReorder<T>(items: T[]): T[];
17
23
  //#endregion
18
- export { cosineSimilarity, estimateTokens, segment };
24
+ export { bookendReorder, cosineSimilarity, estimateTokens, segment };
@@ -1,2 +1,2 @@
1
1
  function e(e){return Math.ceil(e.length/4)}function t(e,t){switch(t){case`paragraph`:return e.split(/\n\s*\n/).map(e=>e.trim()).filter(e=>e.length>0);case`sentence`:return e.split(/(?<=[.!?])\s+/).map(e=>e.trim()).filter(e=>e.length>0);case`line`:return e.split(`
2
- `).map(e=>e.trim()).filter(e=>e.length>0)}}function n(e,t){let n=0,r=0,i=0;for(let a=0;a<e.length;a++)n+=e[a]*t[a],r+=e[a]*e[a],i+=t[a]*t[a];let a=Math.sqrt(r)*Math.sqrt(i);return a===0?0:n/a}export{n as cosineSimilarity,e as estimateTokens,t as segment};
2
+ `).map(e=>e.trim()).filter(e=>e.length>0)}}function n(e,t){let n=0,r=0,i=0;for(let a=0;a<e.length;a++)n+=e[a]*t[a],r+=e[a]*e[a],i+=t[a]*t[a];let a=Math.sqrt(r)*Math.sqrt(i);return a===0?0:n/a}function r(e){if(e.length<=2)return e;let t=Array(e.length),n=0,r=e.length-1;for(let i=0;i<e.length;i++)i%2==0?t[n++]=e[i]:t[r--]=e[i];return t}export{r as bookendReorder,n as cosineSimilarity,e as estimateTokens,t as segment};
@@ -1,2 +1,2 @@
1
1
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
- import{r as e}from"./chunk-D6axbAb-.js";import{t}from"./react-D__J1GQe.js";import{a as n,i as r,n as i,t as a}from"./jsx-runtime-y6Gdq5PZ.js";import{t as o}from"./useKBClient-C35iA4uG.js";import{t as s}from"./StatusPanel-BAbUxyqQ.js";import{t as c}from"./SearchPanel-CpJGczAc.js";import{t as l}from"./CuratedPanel-BIamXLNy.js";import{t as u}from"./LogPanel-D6u6o84n.js";var d=e(t()),f=a();const p=[`status`,`search`,`curated`,`log`];function m({client:e}){let[t,a]=(0,d.useState)(`status`);return i((e,n)=>{n.tab&&a(p[(p.indexOf(t)+1)%p.length]),e===`1`&&a(`status`),e===`2`&&a(`search`),e===`3`&&a(`curated`),e===`4`&&a(`log`)}),(0,f.jsx)(o,{value:e,children:(0,f.jsxs)(n,{flexDirection:`column`,width:`100%`,children:[(0,f.jsxs)(n,{borderStyle:`single`,paddingX:1,children:[(0,f.jsx)(r,{bold:!0,color:`cyan`,children:`KB Dashboard`}),(0,f.jsx)(r,{children:` │ `}),p.map(e=>(0,f.jsxs)(d.Fragment,{children:[(0,f.jsxs)(r,{color:e===t?`green`:`gray`,bold:e===t,children:[`[`,p.indexOf(e)+1,`] `,e]}),(0,f.jsx)(r,{children:` `})]},e)),(0,f.jsx)(r,{color:`gray`,children:` │ Tab: switch │ Ctrl+C: quit`})]}),(0,f.jsxs)(n,{flexGrow:1,minHeight:10,children:[t===`status`&&(0,f.jsx)(s,{}),t===`search`&&(0,f.jsx)(c,{}),t===`curated`&&(0,f.jsx)(l,{}),t===`log`&&(0,f.jsx)(u,{})]})]})})}export{m as t};
2
+ import{r as e}from"./chunk-D6axbAb-.js";import{t}from"./react-D__J1GQe.js";import{a as n,i as r,n as i,t as a}from"./jsx-runtime-y6Gdq5PZ.js";import{t as o}from"./useKBClient-C35iA4uG.js";import{t as s}from"./StatusPanel-BAbUxyqQ.js";import{t as c}from"./SearchPanel-CpJGczAc.js";import{t as l}from"./CuratedPanel-BIamXLNy.js";import{t as u}from"./LogPanel-akibVigF.js";var d=e(t()),f=a();const p=[`status`,`search`,`curated`,`log`];function m({client:e}){let[t,a]=(0,d.useState)(`status`);return i((e,n)=>{n.tab&&a(p[(p.indexOf(t)+1)%p.length]),e===`1`&&a(`status`),e===`2`&&a(`search`),e===`3`&&a(`curated`),e===`4`&&a(`log`)}),(0,f.jsx)(o,{value:e,children:(0,f.jsxs)(n,{flexDirection:`column`,width:`100%`,children:[(0,f.jsxs)(n,{borderStyle:`single`,paddingX:1,children:[(0,f.jsx)(r,{bold:!0,color:`cyan`,children:`KB Dashboard`}),(0,f.jsx)(r,{children:` │ `}),p.map(e=>(0,f.jsxs)(d.Fragment,{children:[(0,f.jsxs)(r,{color:e===t?`green`:`gray`,bold:e===t,children:[`[`,p.indexOf(e)+1,`] `,e]}),(0,f.jsx)(r,{children:` `})]},e)),(0,f.jsx)(r,{color:`gray`,children:` │ Tab: switch │ Ctrl+C: quit`})]}),(0,f.jsxs)(n,{flexGrow:1,minHeight:10,children:[t===`status`&&(0,f.jsx)(s,{}),t===`search`&&(0,f.jsx)(c,{}),t===`curated`&&(0,f.jsx)(l,{}),t===`log`&&(0,f.jsx)(u,{})]})]})})}export{m as t};
@@ -1,2 +1,2 @@
1
1
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
- import{t as e}from"./App-DXY0-tlW.js";export{e as App};
2
+ import{t as e}from"./App-DGdjV2_f.js";export{e as App};
@@ -0,0 +1,3 @@
1
+ import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
+ import{r as e}from"./chunk-D6axbAb-.js";import{t}from"./react-D__J1GQe.js";import{a as n,i as r,t as i}from"./jsx-runtime-y6Gdq5PZ.js";import{exec as a,execFile as o}from"node:child_process";import{appendFileSync as s,existsSync as c,mkdirSync as l,readFileSync as u,readdirSync as d,unlinkSync as f}from"node:fs";import{dirname as p,join as m,resolve as h}from"node:path";import{promisify as g}from"node:util";import{fileURLToPath as _}from"node:url";import"turndown";g(a),m(p(_(import.meta.url)),`..`,`..`,`wasm`),new Set(Object.keys({".ts":`tree-sitter-typescript.wasm`,".tsx":`tree-sitter-typescript.wasm`,".mts":`tree-sitter-typescript.wasm`,".cts":`tree-sitter-typescript.wasm`,".js":`tree-sitter-javascript.wasm`,".jsx":`tree-sitter-javascript.wasm`,".mjs":`tree-sitter-javascript.wasm`,".cjs":`tree-sitter-javascript.wasm`,".py":`tree-sitter-python.wasm`,".go":`tree-sitter-go.wasm`,".rs":`tree-sitter-rust.wasm`,".java":`tree-sitter-java.wasm`,".kt":`tree-sitter-kotlin.wasm`,".kts":`tree-sitter-kotlin.wasm`,".scala":`tree-sitter-scala.wasm`,".sc":`tree-sitter-scala.wasm`,".c":`tree-sitter-c.wasm`,".h":`tree-sitter-c.wasm`,".cpp":`tree-sitter-cpp.wasm`,".cc":`tree-sitter-cpp.wasm`,".cxx":`tree-sitter-cpp.wasm`,".hpp":`tree-sitter-cpp.wasm`,".hxx":`tree-sitter-cpp.wasm`,".cs":`tree-sitter-c_sharp.wasm`,".swift":`tree-sitter-swift.wasm`,".rb":`tree-sitter-ruby.wasm`,".php":`tree-sitter-php.wasm`}));const v={ai:`.ai`,aiKb:`.ai/kb`,aiCurated:`.ai/curated`,restorePoints:`.ai/restore-points`,data:`.kb-data`,state:`.kb-state`,logs:`.kb-state/logs`,brainstorm:`.brainstorm`,handoffs:`.handoffs`};v.data;const y={debug:0,info:1,warn:2,error:3},b=[];let x=process.env.KB_LOG_LEVEL??`info`,S=process.env.KB_LOG_FILE_SINK===`true`||process.env.KB_LOG_FILE_SINK!==`false`&&!process.env.VITEST&&process.env.NODE_ENV!==`test`;function C(){return S?process.env.VITEST||process.env.NODE_ENV===`test`?process.env.KB_LOG_FILE_SINK===`true`:!0:!1}let w;function T(){return w||=h(process.cwd(),v.logs),w}function E(e){let t=e.toISOString().slice(0,10);return m(T(),`${t}.jsonl`)}let D=0;function O(){let e=Date.now();if(!(e-D<36e5)){D=e;try{let t=T(),n=new Date(e-30*864e5).toISOString().slice(0,10);for(let e of d(t))if(e.endsWith(`.jsonl`)&&e.slice(0,10)<n)try{f(m(t,e))}catch{}}catch{}}}function k(e,t){try{l(T(),{recursive:!0}),s(E(t),`${e}\n`),O()}catch{}}function A(e){function t(t,n,r){if(y[t]<y[x])return;let i=new Date,a={ts:i.toISOString(),level:t,component:e,msg:n,...r},o=JSON.stringify(a);console.error(o);for(let i of b)try{i({level:t,component:e,message:n,data:r})}catch{}C()&&(t===`warn`||t===`error`)&&k(o,i)}return{debug:(e,n)=>t(`debug`,e,n),info:(e,n)=>t(`info`,e,n),warn:(e,n)=>t(`warn`,e,n),error:(e,n)=>t(`error`,e,n)}}const j=A(`query-executor`),M=p(_(import.meta.url));function N(){let e=m(M,`..`,`queries`);if(c(e))return e;let t=m(M,`..`,`..`,`src`,`queries`);return c(t)?t:e}const P=N(),F={".ts":`typescript`,".tsx":`typescript`,".mts":`typescript`,".cts":`typescript`,".js":`javascript`,".jsx":`javascript`,".mjs":`javascript`,".cjs":`javascript`,".py":`python`,".go":`go`,".rs":`rust`,".java":`java`};var I=class{queryCache=new Map;scmCache=new Map;execute(e,t,n,r){let i=this.getOrCompile(t,n,r);return i?i.matches(e).map(e=>L(e)):[]}executeCaptures(e,t,n,r){let i=this.getOrCompile(t,n,r);return i?i.captures(e).map(e=>R(e)):[]}executeRaw(e,t,n){return t.query(n).matches(e).map(e=>L(e))}getOrCompile(e,t,n){let r=F[t];if(!r)return null;let i=`${r}:${n}`,a=this.queryCache.get(i);if(a)return a;let o=this.loadScm(r,n);if(!o)return null;try{let t=e.query(o);return this.queryCache.set(i,t),t}catch(e){throw j.warn(`Failed to compile query`,{langDir:r,queryType:n,error:String(e)}),Error(`Failed to compile ${r}/${n}.scm: ${String(e)}`)}}loadScm(e,t){let n=`${e}:${t}`,r=this.scmCache.get(n);if(r!==void 0)return r;let i=m(P,e,`${t}.scm`);try{let e=u(i,`utf-8`);return this.scmCache.set(n,e),e}catch{return j.info(`Query file not found (graceful skip)`,{langDir:e,queryType:t}),null}}dispose(){this.queryCache.clear(),this.scmCache.clear()}static resolveQueryDir(e){return m(P,e)}};function L(e){let t=new Map;for(let n of e.captures)t.set(n.name,R(n));return{pattern:e.pattern,captures:t}}function R(e){let{node:t}=e;return{name:e.name,text:t.text,nodeType:t.type,startLine:t.startPosition.row,endLine:t.endPosition.row,startColumn:t.startPosition.column,endColumn:t.endPosition.column,node:t}}new I,new I,new I,new I,new I,new Set(`.ts,.tsx,.js,.jsx,.mjs,.cjs,.java,.kt,.kts,.scala,.py,.go,.rs,.rb,.php,.swift,.cs,.c,.cpp,.h,.hpp,.sh,.bash,.ps1,.sql,.graphql,.gql,.proto,.json,.yaml,.yml,.toml,.env,.ini,.cfg,.xml,.pom,.gradle,.tf,.hcl,.lock,.mjs`.split(`,`)),`${v.state}`,v.restorePoints,new Set([`node_modules`,`.git`,`dist`,`build`,`coverage`,`.turbo`,`.cache`,`cdk.out`,v.state]),v.state,new Set([`.git`,v.data,v.state,`.turbo`,`.yarn`,`build`,`coverage`,`dist`,`node_modules`]),g(o),`${v.state}`,new Set(`if_statement.for_statement.for_in_statement.while_statement.do_statement.switch_case.catch_clause.ternary_expression.if_statement.for_statement.while_statement.except_clause.list_comprehension.if_statement.for_statement.enhanced_for_statement.while_statement.catch_clause.ternary_expression.if_statement.for_statement.select_statement.if_expression.for_expression.while_expression.match_arm`.split(`.`)),v.state;function z(){return h(process.cwd(),v.state,`replay.jsonl`)}function B(e={}){let t=z(),n;try{n=u(t,`utf-8`)}catch{return[]}let r=n.trim().split(`
3
+ `).filter(Boolean),i=[];for(let e of r)try{i.push(JSON.parse(e))}catch{}if(e.tool&&(i=i.filter(t=>t.tool===e.tool)),e.source&&(i=i.filter(t=>t.source===e.source)),e.since){let t=e.since;i=i.filter(e=>e.ts>=t)}let a=e.last??20;return i.slice(-a)}v.state,g(a),v.data,`script,style,noscript,iframe,svg,nav,footer,header,aside,form,button,input,select,textarea,[role="navigation"],[role="banner"],[role="contentinfo"],[aria-hidden="true"],.sidebar,.nav,.menu,.footer,.header,.ad,.advertisement,.cookie-banner,.popup,.modal`.split(`,`),v.state;var V=e(t()),H=i();function U(){let[e,t]=(0,V.useState)([]);return(0,V.useEffect)(()=>{let e=()=>{t(B({last:30}))};e();let n=setInterval(e,2e3);return()=>clearInterval(n)},[]),(0,H.jsxs)(n,{flexDirection:`column`,borderStyle:`round`,paddingX:1,children:[(0,H.jsx)(r,{bold:!0,color:`cyan`,children:`Activity Log`}),(0,H.jsx)(r,{children:` `}),e.length===0&&(0,H.jsx)(r,{color:`gray`,children:`No activity recorded yet`}),e.slice().reverse().map((e,t)=>{let n=e.ts.split(`T`)[1]?.split(`.`)[0]??e.ts,i=e.status===`ok`?`green`:`red`;return(0,H.jsxs)(r,{children:[(0,H.jsx)(r,{color:`gray`,children:n}),` `,(0,H.jsx)(r,{color:i,children:e.status===`ok`?`✓`:`✗`}),` `,(0,H.jsx)(r,{bold:!0,children:e.tool}),` `,(0,H.jsxs)(r,{color:`gray`,children:[`(`,e.durationMs,`ms)`]})]},`${e.ts}-${t}`)}),(0,H.jsx)(r,{children:` `}),(0,H.jsx)(r,{color:`gray`,children:`Refreshes every 2s │ Showing last 30`})]})}export{U as t};
@@ -1,2 +1,2 @@
1
1
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
- import{r as e}from"./chunk-D6axbAb-.js";import{t}from"./react-D__J1GQe.js";import{r as n}from"./jsx-runtime-y6Gdq5PZ.js";import{t as r}from"./App-DXY0-tlW.js";var i=e(t());function a(e){n(i.createElement(r,{client:e}))}export{a as launch};
2
+ import{r as e}from"./chunk-D6axbAb-.js";import{t}from"./react-D__J1GQe.js";import{r as n}from"./jsx-runtime-y6Gdq5PZ.js";import{t as r}from"./App-DGdjV2_f.js";var i=e(t());function a(e){n(i.createElement(r,{client:e}))}export{a as launch};
@@ -1,2 +1,2 @@
1
1
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
- import{t as e}from"../LogPanel-D6u6o84n.js";export{e as LogPanel};
2
+ import{t as e}from"../LogPanel-akibVigF.js";export{e as LogPanel};
@@ -1,3 +0,0 @@
1
- import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
- import{r as e}from"./chunk-D6axbAb-.js";import{t}from"./react-D__J1GQe.js";import{a as n,i as r,t as i}from"./jsx-runtime-y6Gdq5PZ.js";import{exec as a,execFile as o}from"node:child_process";import{appendFileSync as s,existsSync as c,mkdirSync as l,readFileSync as u,readdirSync as d,unlinkSync as f}from"node:fs";import{dirname as p,join as m,resolve as h}from"node:path";import{promisify as g}from"node:util";import{fileURLToPath as _}from"node:url";import"turndown";g(a),m(p(_(import.meta.url)),`..`,`..`,`wasm`),new Set(Object.keys({".ts":`tree-sitter-typescript.wasm`,".tsx":`tree-sitter-typescript.wasm`,".mts":`tree-sitter-typescript.wasm`,".cts":`tree-sitter-typescript.wasm`,".js":`tree-sitter-javascript.wasm`,".jsx":`tree-sitter-javascript.wasm`,".mjs":`tree-sitter-javascript.wasm`,".cjs":`tree-sitter-javascript.wasm`,".py":`tree-sitter-python.wasm`,".go":`tree-sitter-go.wasm`,".rs":`tree-sitter-rust.wasm`,".java":`tree-sitter-java.wasm`}));const v={ai:`.ai`,aiKb:`.ai/kb`,aiCurated:`.ai/curated`,restorePoints:`.ai/restore-points`,data:`.kb-data`,state:`.kb-state`,logs:`.kb-state/logs`,brainstorm:`.brainstorm`,handoffs:`.handoffs`};v.data;const y={debug:0,info:1,warn:2,error:3},b=[];let x=process.env.KB_LOG_LEVEL??`info`,S=process.env.KB_LOG_FILE_SINK===`true`||process.env.KB_LOG_FILE_SINK!==`false`&&!process.env.VITEST&&process.env.NODE_ENV!==`test`;function C(){return S?process.env.VITEST||process.env.NODE_ENV===`test`?process.env.KB_LOG_FILE_SINK===`true`:!0:!1}let w;function T(){return w||=h(process.cwd(),v.logs),w}function E(e){let t=e.toISOString().slice(0,10);return m(T(),`${t}.jsonl`)}let D=0;function O(){let e=Date.now();if(!(e-D<36e5)){D=e;try{let t=T(),n=new Date(e-30*864e5).toISOString().slice(0,10);for(let e of d(t))if(e.endsWith(`.jsonl`)&&e.slice(0,10)<n)try{f(m(t,e))}catch{}}catch{}}}function k(e,t){try{l(T(),{recursive:!0}),s(E(t),`${e}\n`),O()}catch{}}function A(e){function t(t,n,r){if(y[t]<y[x])return;let i=new Date,a={ts:i.toISOString(),level:t,component:e,msg:n,...r},o=JSON.stringify(a);console.error(o);for(let i of b)try{i({level:t,component:e,message:n,data:r})}catch{}C()&&(t===`warn`||t===`error`)&&k(o,i)}return{debug:(e,n)=>t(`debug`,e,n),info:(e,n)=>t(`info`,e,n),warn:(e,n)=>t(`warn`,e,n),error:(e,n)=>t(`error`,e,n)}}const j=A(`query-executor`),M=p(_(import.meta.url));function N(){let e=m(M,`..`,`queries`);if(c(e))return e;let t=m(M,`..`,`..`,`src`,`queries`);return c(t)?t:e}const P=N(),F={".ts":`typescript`,".tsx":`typescript`,".mts":`typescript`,".cts":`typescript`,".js":`javascript`,".jsx":`javascript`,".mjs":`javascript`,".cjs":`javascript`,".py":`python`,".go":`go`,".rs":`rust`,".java":`java`};var I=class{queryCache=new Map;scmCache=new Map;execute(e,t,n,r){let i=this.getOrCompile(t,n,r);return i?i.matches(e).map(e=>L(e)):[]}executeCaptures(e,t,n,r){let i=this.getOrCompile(t,n,r);return i?i.captures(e).map(e=>R(e)):[]}executeRaw(e,t,n){return t.query(n).matches(e).map(e=>L(e))}getOrCompile(e,t,n){let r=F[t];if(!r)return null;let i=`${r}:${n}`,a=this.queryCache.get(i);if(a)return a;let o=this.loadScm(r,n);if(!o)return null;try{let t=e.query(o);return this.queryCache.set(i,t),t}catch(e){throw j.warn(`Failed to compile query`,{langDir:r,queryType:n,error:String(e)}),Error(`Failed to compile ${r}/${n}.scm: ${String(e)}`)}}loadScm(e,t){let n=`${e}:${t}`,r=this.scmCache.get(n);if(r!==void 0)return r;let i=m(P,e,`${t}.scm`);try{let e=u(i,`utf-8`);return this.scmCache.set(n,e),e}catch{return j.info(`Query file not found (graceful skip)`,{langDir:e,queryType:t}),null}}dispose(){this.queryCache.clear(),this.scmCache.clear()}static resolveQueryDir(e){return m(P,e)}};function L(e){let t=new Map;for(let n of e.captures)t.set(n.name,R(n));return{pattern:e.pattern,captures:t}}function R(e){let{node:t}=e;return{name:e.name,text:t.text,nodeType:t.type,startLine:t.startPosition.row,endLine:t.endPosition.row,startColumn:t.startPosition.column,endColumn:t.endPosition.column,node:t}}new I,new I,new I,new I,new I,new Set(`.ts,.tsx,.js,.jsx,.mjs,.cjs,.java,.kt,.kts,.scala,.py,.go,.rs,.rb,.php,.swift,.cs,.c,.cpp,.h,.hpp,.sh,.bash,.ps1,.sql,.graphql,.gql,.proto,.json,.yaml,.yml,.toml,.env,.ini,.cfg,.xml,.pom,.gradle,.tf,.hcl,.lock,.mjs`.split(`,`)),`${v.state}`,v.restorePoints,new Set([`node_modules`,`.git`,`dist`,`build`,`coverage`,`.turbo`,`.cache`,`cdk.out`,v.state]),v.state,new Set([`.git`,v.data,v.state,`.turbo`,`.yarn`,`build`,`coverage`,`dist`,`node_modules`]),g(o),`${v.state}`,new Set(`if_statement.for_statement.for_in_statement.while_statement.do_statement.switch_case.catch_clause.ternary_expression.if_statement.for_statement.while_statement.except_clause.list_comprehension.if_statement.for_statement.enhanced_for_statement.while_statement.catch_clause.ternary_expression.if_statement.for_statement.select_statement.if_expression.for_expression.while_expression.match_arm`.split(`.`)),v.state;function z(){return h(process.cwd(),v.state,`replay.jsonl`)}function B(e={}){let t=z(),n;try{n=u(t,`utf-8`)}catch{return[]}let r=n.trim().split(`
3
- `).filter(Boolean),i=[];for(let e of r)try{i.push(JSON.parse(e))}catch{}if(e.tool&&(i=i.filter(t=>t.tool===e.tool)),e.source&&(i=i.filter(t=>t.source===e.source)),e.since){let t=e.since;i=i.filter(e=>e.ts>=t)}let a=e.last??20;return i.slice(-a)}v.state,g(a),v.data,`script,style,noscript,iframe,svg,nav,footer,header,aside,form,button,input,select,textarea,[role="navigation"],[role="banner"],[role="contentinfo"],[aria-hidden="true"],.sidebar,.nav,.menu,.footer,.header,.ad,.advertisement,.cookie-banner,.popup,.modal`.split(`,`),v.state;var V=e(t()),H=i();function U(){let[e,t]=(0,V.useState)([]);return(0,V.useEffect)(()=>{let e=()=>{t(B({last:30}))};e();let n=setInterval(e,2e3);return()=>clearInterval(n)},[]),(0,H.jsxs)(n,{flexDirection:`column`,borderStyle:`round`,paddingX:1,children:[(0,H.jsx)(r,{bold:!0,color:`cyan`,children:`Activity Log`}),(0,H.jsx)(r,{children:` `}),e.length===0&&(0,H.jsx)(r,{color:`gray`,children:`No activity recorded yet`}),e.slice().reverse().map((e,t)=>{let n=e.ts.split(`T`)[1]?.split(`.`)[0]??e.ts,i=e.status===`ok`?`green`:`red`;return(0,H.jsxs)(r,{children:[(0,H.jsx)(r,{color:`gray`,children:n}),` `,(0,H.jsx)(r,{color:i,children:e.status===`ok`?`✓`:`✗`}),` `,(0,H.jsx)(r,{bold:!0,children:e.tool}),` `,(0,H.jsxs)(r,{color:`gray`,children:[`(`,e.durationMs,`ms)`]})]},`${e.ts}-${t}`)}),(0,H.jsx)(r,{children:` `}),(0,H.jsx)(r,{color:`gray`,children:`Refreshes every 2s │ Showing last 30`})]})}export{U as t};