@vpxa/kb 0.1.2 → 0.1.4

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 (48) hide show
  1. package/README.md +3 -3
  2. package/package.json +12 -1
  3. package/packages/chunker/dist/code-chunker.js +1 -1
  4. package/packages/chunker/dist/generic-chunker.js +3 -3
  5. package/packages/chunker/dist/markdown-chunker.js +2 -2
  6. package/packages/chunker/dist/treesitter-chunker.js +1 -1
  7. package/packages/cli/dist/commands/analyze.js +1 -1
  8. package/packages/cli/dist/commands/context-cmds.js +1 -1
  9. package/packages/cli/dist/commands/environment.js +1 -1
  10. package/packages/cli/dist/commands/execution.js +1 -1
  11. package/packages/cli/dist/commands/graph.js +1 -1
  12. package/packages/cli/dist/commands/knowledge.js +1 -1
  13. package/packages/cli/dist/commands/search.js +2 -2
  14. package/packages/cli/dist/commands/system.js +2 -2
  15. package/packages/cli/dist/commands/workspace.js +1 -1
  16. package/packages/cli/dist/helpers.js +3 -3
  17. package/packages/cli/dist/index.d.ts +1 -1
  18. package/packages/cli/dist/index.js +1 -1
  19. package/packages/cli/dist/kb-init.js +1 -1
  20. package/packages/embeddings/dist/onnx-embedder.js +1 -1
  21. package/packages/indexer/dist/filesystem-crawler.js +1 -1
  22. package/packages/indexer/dist/graph-extractor.js +1 -1
  23. package/packages/indexer/dist/incremental-indexer.js +1 -1
  24. package/packages/server/dist/config.js +1 -1
  25. package/packages/server/dist/curated-manager.js +3 -3
  26. package/packages/server/dist/replay-interceptor.js +1 -1
  27. package/packages/server/dist/server.js +1 -1
  28. package/packages/server/dist/tools/analyze.tools.js +1 -1
  29. package/packages/server/dist/tools/forge.tools.js +3 -3
  30. package/packages/server/dist/tools/graph.tool.js +1 -1
  31. package/packages/server/dist/tools/onboard.tool.js +1 -1
  32. package/packages/server/dist/tools/produce.tool.js +1 -1
  33. package/packages/server/dist/tools/reindex.tool.js +1 -1
  34. package/packages/server/dist/tools/replay.tool.js +1 -1
  35. package/packages/server/dist/tools/search.tool.js +11 -11
  36. package/packages/server/dist/tools/status.tool.js +2 -2
  37. package/packages/server/dist/tools/toolkit.tools.js +4 -4
  38. package/packages/server/dist/tools/utility.tools.js +1 -1
  39. package/packages/store/dist/lance-store.js +1 -1
  40. package/packages/tools/dist/compact.js +2 -2
  41. package/packages/tools/dist/dead-symbols.js +2 -2
  42. package/packages/tools/dist/digest.js +2 -2
  43. package/packages/tools/dist/find-examples.js +3 -3
  44. package/packages/tools/dist/onboard.js +1 -1
  45. package/packages/tools/dist/scope-map.js +1 -1
  46. package/packages/tools/dist/stratum-card.js +2 -2
  47. package/packages/tools/dist/symbol.js +3 -3
  48. package/packages/tools/dist/trace.js +2 -2
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @anvpx/kb
1
+ # @vpxa/kb
2
2
 
3
3
  Local-first AI developer toolkit — knowledge base, code analysis, context management, and developer tools for LLM agents.
4
4
 
@@ -31,7 +31,7 @@ The KB auto-indexes configured source directories on startup, stores embeddings
31
31
 
32
32
  ```bash
33
33
  # Install
34
- pnpm add -D @anvpx/kb
34
+ pnpm add -D @vpxa/kb
35
35
 
36
36
  # Initialize in your project
37
37
  npx kb init
@@ -285,7 +285,7 @@ kb init [--force]
285
285
  ## Architecture
286
286
 
287
287
  ```text
288
- @anvpx/kb
288
+ @vpxa/kb
289
289
  ├── packages/
290
290
  │ ├── core/ — types, config, logger, constants
291
291
  │ ├── store/ — LanceDB vector store
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vpxa/kb",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
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",
@@ -37,6 +37,17 @@
37
37
  "bin": {
38
38
  "kb": "./bin/kb.mjs"
39
39
  },
40
+ "dependencies": {
41
+ "@huggingface/transformers": "^3.x",
42
+ "@lancedb/lancedb": "^0.x",
43
+ "@modelcontextprotocol/sdk": "^1.x",
44
+ "better-sqlite3": "^12.x",
45
+ "express": "^5.x",
46
+ "linkedom": "^0.x",
47
+ "minimatch": "^10.x",
48
+ "turndown": "^7.x",
49
+ "zod": "^4.x"
50
+ },
40
51
  "devDependencies": {
41
52
  "@biomejs/biome": "^2.x",
42
53
  "@types/node": "^24.x",
@@ -1,4 +1,4 @@
1
- import{CHUNK_SIZES as p}from"@kb/core";class C{maxChunkSize;constructor(e){this.maxChunkSize=e?.maxChunkSize??p.code.max}chunk(e,n){const r=this.findDeclarationBoundaries(e);if(r.length===0)return this.fallbackChunk(e,n);const s=[];for(let t=0;t<r.length;t++){const i=r[t].offset,l=t+1<r.length?r[t+1].offset:e.length;let h=e.slice(i,l).trim();if(h=`// File: ${n.sourcePath}
1
+ import{CHUNK_SIZES as p}from"../../core/dist/index.js";class C{maxChunkSize;constructor(e){this.maxChunkSize=e?.maxChunkSize??p.code.max}chunk(e,n){const r=this.findDeclarationBoundaries(e);if(r.length===0)return this.fallbackChunk(e,n);const s=[];for(let t=0;t<r.length;t++){const i=r[t].offset,l=t+1<r.length?r[t+1].offset:e.length;let h=e.slice(i,l).trim();if(h=`// File: ${n.sourcePath}
2
2
  `+h,h.length>this.maxChunkSize){const u=this.splitByLines(h,this.maxChunkSize);let c=this.getLineNumber(e,i);for(const a of u){const f=a.split(`
3
3
  `).length;s.push({text:a,sourcePath:n.sourcePath,contentType:n.contentType,chunkIndex:s.length,totalChunks:0,startLine:c,endLine:c+f-1}),c+=f}}else{const u=this.getLineNumber(e,i);s.push({text:h,sourcePath:n.sourcePath,contentType:n.contentType,chunkIndex:s.length,totalChunks:0,startLine:u,endLine:u+h.split(`
4
4
  `).length-1})}}if(r[0].offset>0){const t=e.slice(0,r[0].offset).trim();t.length>0&&s.unshift({text:`// File: ${n.sourcePath}
@@ -1,5 +1,5 @@
1
- import{CHUNK_SIZES as p}from"@kb/core";class C{maxChunkSize;overlap;constructor(n){this.maxChunkSize=n?.maxChunkSize??p.default.max,this.overlap=n?.overlap??p.default.overlap}chunk(n,h){if(n.length<=this.maxChunkSize)return[{text:n,sourcePath:h.sourcePath,contentType:h.contentType,chunkIndex:0,totalChunks:1,startLine:1,endLine:n.split(`
1
+ import{CHUNK_SIZES as p}from"../../core/dist/index.js";class C{maxChunkSize;overlap;constructor(n){this.maxChunkSize=n?.maxChunkSize??p.default.max,this.overlap=n?.overlap??p.default.overlap}chunk(n,h){if(n.length<=this.maxChunkSize)return[{text:n,sourcePath:h.sourcePath,contentType:h.contentType,chunkIndex:0,totalChunks:1,startLine:1,endLine:n.split(`
2
2
  `).length}];const c=n.split(`
3
- `),r=[];let e=[],o=0,l=1;for(let u=0;u<c.length;u++){const t=c[u];if(o+t.length+1>this.maxChunkSize&&e.length>0){r.push({text:e.join(`
4
- `),sourcePath:h.sourcePath,contentType:h.contentType,chunkIndex:r.length,totalChunks:0,startLine:l,endLine:l+e.length-1});const s=[];let a=0;for(let i=e.length-1;i>=0&&!(a+e[i].length+1>this.overlap);i--)s.unshift(e[i]),a+=e[i].length+1;l=l+e.length-s.length,e=[...s,t],o=a+t.length+1}else e.push(t),o+=t.length+1}return e.length>0&&r.push({text:e.join(`
3
+ `),r=[];let e=[],s=0,l=1;for(let u=0;u<c.length;u++){const t=c[u];if(s+t.length+1>this.maxChunkSize&&e.length>0){r.push({text:e.join(`
4
+ `),sourcePath:h.sourcePath,contentType:h.contentType,chunkIndex:r.length,totalChunks:0,startLine:l,endLine:l+e.length-1});const o=[];let a=0;for(let i=e.length-1;i>=0&&!(a+e[i].length+1>this.overlap);i--)o.unshift(e[i]),a+=e[i].length+1;l=l+e.length-o.length,e=[...o,t],s=a+t.length+1}else e.push(t),s+=t.length+1}return e.length>0&&r.push({text:e.join(`
5
5
  `),sourcePath:h.sourcePath,contentType:h.contentType,chunkIndex:r.length,totalChunks:0,startLine:l,endLine:l+e.length-1}),r.map((u,t)=>({...u,chunkIndex:t,totalChunks:r.length}))}}export{C as GenericChunker};
@@ -1,4 +1,4 @@
1
- import{CHUNK_SIZES as u}from"@kb/core";class p{maxChunkSize;minChunkSize;constructor(r){this.maxChunkSize=r?.maxChunkSize??u.markdown.max,this.minChunkSize=r?.minChunkSize??u.markdown.min}chunk(r,s){const h=this.splitByHeadings(r),t=[];for(const n of h){if(n.text.trim().length<this.minChunkSize&&t.length>0){const i=t[t.length-1];i.text+=`
1
+ import{CHUNK_SIZES as u}from"../../core/dist/index.js";class k{maxChunkSize;minChunkSize;constructor(r){this.maxChunkSize=r?.maxChunkSize??u.markdown.max,this.minChunkSize=r?.minChunkSize??u.markdown.min}chunk(r,s){const h=this.splitByHeadings(r),t=[];for(const n of h){if(n.text.trim().length<this.minChunkSize&&t.length>0){const i=t[t.length-1];i.text+=`
2
2
 
3
3
  ${n.text}`,i.endLine=n.endLine;continue}if(n.text.length>this.maxChunkSize){const i=this.splitByParagraphs(n.text,this.maxChunkSize);let e=n.startLine;for(const a of i){const o=a.split(`
4
4
  `).length;t.push({text:a,sourcePath:s.sourcePath,contentType:s.contentType,headingPath:n.headingPath,chunkIndex:t.length,totalChunks:0,startLine:e,endLine:e+o-1}),e+=o}}else t.push({text:n.text,sourcePath:s.sourcePath,contentType:s.contentType,headingPath:n.headingPath,chunkIndex:t.length,totalChunks:0,startLine:n.startLine,endLine:n.endLine})}return t.map((n,i)=>({...n,chunkIndex:i,totalChunks:t.length}))}splitByHeadings(r){const s=r.split(`
@@ -7,4 +7,4 @@ ${s[e]}`,t.endLine=e+1):t={text:s[e],headingPath:"(intro)",startLine:e+1,endLine
7
7
 
8
8
  ${i}`.length>s&&n.length>0?(t.push(n.trim()),n=i):n=n?`${n}
9
9
 
10
- ${i}`:i;return n.trim()&&t.push(n.trim()),t}}export{p as MarkdownChunker};
10
+ ${i}`:i;return n.trim()&&t.push(n.trim()),t}}export{k as MarkdownChunker};
@@ -1,4 +1,4 @@
1
- import{extname as m}from"node:path";import{CHUNK_SIZES as k}from"@kb/core";import{CodeChunker as y}from"./code-chunker.js";const f={".ts":{package:"tree-sitter-typescript",subLanguage:"typescript"},".tsx":{package:"tree-sitter-typescript",subLanguage:"tsx"},".mts":{package:"tree-sitter-typescript",subLanguage:"typescript"},".cts":{package:"tree-sitter-typescript",subLanguage:"typescript"},".js":{package:"tree-sitter-javascript"},".jsx":{package:"tree-sitter-javascript"},".mjs":{package:"tree-sitter-javascript"},".cjs":{package:"tree-sitter-javascript"},".py":{package:"tree-sitter-python"},".go":{package:"tree-sitter-go"},".rs":{package:"tree-sitter-rust"},".java":{package:"tree-sitter-java"}},b=new Set(["function_declaration","class_declaration","interface_declaration","type_alias_declaration","enum_declaration","lexical_declaration","export_statement","variable_declaration","abstract_class_declaration","function_definition","class_definition","decorated_definition","function_declaration","method_declaration","type_declaration","function_item","impl_item","struct_item","enum_item","trait_item","mod_item","type_item","class_declaration","interface_declaration","method_declaration","enum_declaration"]);class u{static instance=null;parser=null;languages=new Map;static async initialize(){if(u.instance)return u.instance;const t=new u;return await t.init()?(u.instance=t,t):null}static get(){return u.instance}async init(){try{const t=await import("tree-sitter"),r=t.default??t;this.parser=new r;for(const[c,s]of Object.entries(f))try{const o=await import(s.package),e=o.default??o,n=s.subLanguage?e[s.subLanguage]:e;n&&this.languages.set(c,n)}catch{}const i=this.languages.size>0;return i&&console.error(`[KB] Tree-sitter initialized with ${this.languages.size} languages: ${[...this.languages.keys()].join(", ")}`),i}catch{return!1}}parse(t,r){const i=this.languages.get(r);return i?(this.parser.setLanguage(i),this.parser.parse(t)):null}hasLanguage(t){return this.languages.has(t)}}async function w(){return await u.initialize()!==null}class L{maxChunkSize;runtime;regexFallback;constructor(t,r){this.runtime=t,this.maxChunkSize=r?.maxChunkSize??k.code.max,this.regexFallback=new y(r)}chunk(t,r){const i=m(r.sourcePath).toLowerCase(),c=this.runtime.parse(t,i);if(!c)return this.regexFallback.chunk(t,r);try{return this.chunkFromAst(c,t,r)}catch{return this.regexFallback.chunk(t,r)}}chunkFromAst(t,r,i){const c=t.rootNode,s=[],o=[];for(let e=0;e<c.childCount;e++){const n=c.child(e);if(n&&b.has(n.type)){let h=n.startPosition?n.startIndex:n.startByte??0,l=n.startPosition?.row??0,a=n.previousSibling;for(;a&&(a.type==="comment"||a.type==="line_comment"||a.type==="block_comment"||a.type==="decorator");)h=a.startIndex??a.startByte??h,l=a.startPosition?.row??l,a=a.previousSibling;o.push({startByte:h,endByte:n.endIndex??n.endByte??r.length,startRow:l,endRow:n.endPosition?.row??r.split(`
1
+ import{extname as m}from"node:path";import{CHUNK_SIZES as k}from"../../core/dist/index.js";import{CodeChunker as y}from"./code-chunker.js";const f={".ts":{package:"tree-sitter-typescript",subLanguage:"typescript"},".tsx":{package:"tree-sitter-typescript",subLanguage:"tsx"},".mts":{package:"tree-sitter-typescript",subLanguage:"typescript"},".cts":{package:"tree-sitter-typescript",subLanguage:"typescript"},".js":{package:"tree-sitter-javascript"},".jsx":{package:"tree-sitter-javascript"},".mjs":{package:"tree-sitter-javascript"},".cjs":{package:"tree-sitter-javascript"},".py":{package:"tree-sitter-python"},".go":{package:"tree-sitter-go"},".rs":{package:"tree-sitter-rust"},".java":{package:"tree-sitter-java"}},x=new Set(["function_declaration","class_declaration","interface_declaration","type_alias_declaration","enum_declaration","lexical_declaration","export_statement","variable_declaration","abstract_class_declaration","function_definition","class_definition","decorated_definition","function_declaration","method_declaration","type_declaration","function_item","impl_item","struct_item","enum_item","trait_item","mod_item","type_item","class_declaration","interface_declaration","method_declaration","enum_declaration"]);class u{static instance=null;parser=null;languages=new Map;static async initialize(){if(u.instance)return u.instance;const t=new u;return await t.init()?(u.instance=t,t):null}static get(){return u.instance}async init(){try{const t=await import("tree-sitter"),r=t.default??t;this.parser=new r;for(const[c,s]of Object.entries(f))try{const o=await import(s.package),e=o.default??o,n=s.subLanguage?e[s.subLanguage]:e;n&&this.languages.set(c,n)}catch{}const i=this.languages.size>0;return i&&console.error(`[KB] Tree-sitter initialized with ${this.languages.size} languages: ${[...this.languages.keys()].join(", ")}`),i}catch{return!1}}parse(t,r){const i=this.languages.get(r);return i?(this.parser.setLanguage(i),this.parser.parse(t)):null}hasLanguage(t){return this.languages.has(t)}}async function w(){return await u.initialize()!==null}class L{maxChunkSize;runtime;regexFallback;constructor(t,r){this.runtime=t,this.maxChunkSize=r?.maxChunkSize??k.code.max,this.regexFallback=new y(r)}chunk(t,r){const i=m(r.sourcePath).toLowerCase(),c=this.runtime.parse(t,i);if(!c)return this.regexFallback.chunk(t,r);try{return this.chunkFromAst(c,t,r)}catch{return this.regexFallback.chunk(t,r)}}chunkFromAst(t,r,i){const c=t.rootNode,s=[],o=[];for(let e=0;e<c.childCount;e++){const n=c.child(e);if(n&&x.has(n.type)){let h=n.startPosition?n.startIndex:n.startByte??0,l=n.startPosition?.row??0,a=n.previousSibling;for(;a&&(a.type==="comment"||a.type==="line_comment"||a.type==="block_comment"||a.type==="decorator");)h=a.startIndex??a.startByte??h,l=a.startPosition?.row??l,a=a.previousSibling;o.push({startByte:h,endByte:n.endIndex??n.endByte??r.length,startRow:l,endRow:n.endPosition?.row??r.split(`
2
2
  `).length-1})}}if(o.length===0)return this.regexFallback.chunk(r,i);if(o[0].startByte>0){const e=r.slice(0,o[0].startByte).trim();e.length>0&&s.push({text:`// File: ${i.sourcePath}
3
3
  ${e}`,sourcePath:i.sourcePath,contentType:i.contentType,chunkIndex:0,totalChunks:0,startLine:1,endLine:o[0].startRow+1})}for(const e of o){let n=r.slice(e.startByte,e.endByte).trim();if(n=`// File: ${i.sourcePath}
4
4
  `+n,n.length>this.maxChunkSize){const l=this.splitByLines(n,this.maxChunkSize);let a=e.startRow+1;for(const p of l){const g=p.split(`
@@ -1,3 +1,3 @@
1
- import{resolve as p}from"node:path";const d=[{name:"analyze",description:"Run analyzer output for a path",usage:"kb analyze <type> <path>",run:async r=>{const i=r.shift()?.trim()??"",a=r.shift()?.trim()??"";(!i||!a)&&(console.error("Usage: kb analyze <type> <path>"),console.error("Types: structure, deps, symbols, patterns, entry-points, blast-radius, diagram"),process.exit(1));const{BlastRadiusAnalyzer:l,DependencyAnalyzer:c,DiagramGenerator:m,EntryPointAnalyzer:n,PatternAnalyzer:e,StructureAnalyzer:t,SymbolAnalyzer:u}=await import("@kb/analyzers"),s=p(a);let o;switch(i){case"structure":o=await new t().analyze(s,{format:"markdown"});break;case"deps":case"dependencies":o=await new c().analyze(s,{format:"markdown"});break;case"symbols":o=await new u().analyze(s,{format:"markdown"});break;case"patterns":o=await new e().analyze(s,{format:"markdown"});break;case"entry-points":o=await new n().analyze(s,{format:"markdown"});break;case"blast-radius":o=await new l().analyze(process.cwd(),{files:[a],format:"markdown"});break;case"diagram":o=await new m().analyze(s,{diagramType:"architecture"});break;default:console.error(`Unknown analyze type: ${i}`),console.error("Types: structure, deps, symbols, patterns, entry-points, blast-radius, diagram"),process.exit(1)}console.log(o.output)}},{name:"onboard",description:"Run all analyses for first-time codebase onboarding",usage:"kb onboard <path> [--generate] [--out-dir <dir>]",run:async r=>{const{onboard:i}=await import("@kb/tools");let a="",l="memory",c;for(let e=0;e<r.length;e++){const t=r[e].trim();t==="--generate"?l="generate":t==="--out-dir"&&e+1<r.length?c=r[++e].trim():t.startsWith("--")||(a=t)}a||(a=process.cwd());const m=p(a);console.log(`Onboarding: ${m} (mode: ${l})`),console.log(`Running analyses...
1
+ import{resolve as p}from"node:path";const d=[{name:"analyze",description:"Run analyzer output for a path",usage:"kb analyze <type> <path>",run:async r=>{const i=r.shift()?.trim()??"",a=r.shift()?.trim()??"";(!i||!a)&&(console.error("Usage: kb analyze <type> <path>"),console.error("Types: structure, deps, symbols, patterns, entry-points, blast-radius, diagram"),process.exit(1));const{BlastRadiusAnalyzer:l,DependencyAnalyzer:c,DiagramGenerator:m,EntryPointAnalyzer:n,PatternAnalyzer:e,StructureAnalyzer:t,SymbolAnalyzer:u}=await import("../../../analyzers/dist/index.js"),s=p(a);let o;switch(i){case"structure":o=await new t().analyze(s,{format:"markdown"});break;case"deps":case"dependencies":o=await new c().analyze(s,{format:"markdown"});break;case"symbols":o=await new u().analyze(s,{format:"markdown"});break;case"patterns":o=await new e().analyze(s,{format:"markdown"});break;case"entry-points":o=await new n().analyze(s,{format:"markdown"});break;case"blast-radius":o=await new l().analyze(process.cwd(),{files:[a],format:"markdown"});break;case"diagram":o=await new m().analyze(s,{diagramType:"architecture"});break;default:console.error(`Unknown analyze type: ${i}`),console.error("Types: structure, deps, symbols, patterns, entry-points, blast-radius, diagram"),process.exit(1)}console.log(o.output)}},{name:"onboard",description:"Run all analyses for first-time codebase onboarding",usage:"kb onboard <path> [--generate] [--out-dir <dir>]",run:async r=>{const{onboard:i}=await import("../../../tools/dist/index.js");let a="",l="memory",c;for(let e=0;e<r.length;e++){const t=r[e].trim();t==="--generate"?l="generate":t==="--out-dir"&&e+1<r.length?c=r[++e].trim():t.startsWith("--")||(a=t)}a||(a=process.cwd());const m=p(a);console.log(`Onboarding: ${m} (mode: ${l})`),console.log(`Running analyses...
2
2
  `);const n=await i({path:m,mode:l,outDir:c});for(const e of n.steps){const t=e.status==="success"?"\u2713":"\u2717",u=e.status==="success"?`${e.durationMs}ms, ${e.output.length} chars`:e.error;console.log(` ${t} ${e.name} \u2014 ${u}`)}console.log(`
3
3
  Total: ${n.totalDurationMs}ms`),n.outDir&&console.log(`Output written to: ${n.outDir}`)}}];export{d as analyzeCommands};
@@ -1 +1 @@
1
- import{resolve as p}from"node:path";import{checkpointLatest as d,checkpointList as u,checkpointLoad as f,checkpointSave as m,diffParse as h,fileSummary as k,gitContext as g,parseOutput as b}from"@kb/tools";import{extractBoolFlag as x,extractNumFlag as w,extractStrFlag as i,parseRecordString as v,printCheckpoint as c,printDiffFiles as y,printFileSummary as C,printGitContext as S,printParsedOutput as U,readStdin as a}from"../helpers.js";const P=[{name:"parse-output",description:"Parse build or tool output from stdin",usage:"kb parse-output [--tool tsc|vitest|biome|git-status]",run:async e=>{const s=i(e,"--tool","").trim()||void 0,t=await a();t.trim()||(console.error("Usage: kb parse-output [--tool tsc|vitest|biome|git-status]"),process.exit(1)),U(b(t,s))}},{name:"git",description:"Show git branch, status, recent commits, and optional diff stats",usage:"kb git [--cwd path] [--commit-count N] [--diff]",run:async e=>{const s=i(e,"--cwd","").trim()||void 0,t=w(e,"--commit-count",5),o=x(e,"--diff"),n=await g({cwd:s,commitCount:t,includeDiff:o});S(n)}},{name:"diff",description:"Parse unified diff text from stdin into structured file changes",usage:"git diff | kb diff",run:async()=>{const e=await a();e.trim()||(console.error("Usage: git diff | kb diff"),process.exit(1)),y(h({diff:e}))}},{name:"summarize",description:"Show a structural summary of a file",usage:"kb summarize <path>",run:async e=>{const s=e.shift()?.trim();s||(console.error("Usage: kb summarize <path>"),process.exit(1));const t=await k({path:p(s)});C(t)}},{name:"checkpoint",description:"Save and restore lightweight session checkpoints",usage:"kb checkpoint <save|load|list|latest> [label-or-id] [--data json] [--notes text]",run:async e=>{const s=e.shift()?.trim();switch(s||(console.error("Usage: kb checkpoint <save|load|list|latest> [label-or-id] [--data json] [--notes text]"),process.exit(1)),s){case"save":{const t=e.shift()?.trim(),o=i(e,"--data",""),n=i(e,"--notes","").trim()||void 0,r=o.trim()?"":await a();t||(console.error("Usage: kb checkpoint save <label> [--data json] [--notes text]"),process.exit(1));const l=m(t,v(o||r),{notes:n});c(l);return}case"load":{const t=e.shift()?.trim();t||(console.error("Usage: kb checkpoint load <id>"),process.exit(1));const o=f(t);if(!o){console.log(`No checkpoint found: ${t}`);return}c(o);return}case"list":{const t=u();if(t.length===0){console.log("No checkpoints saved.");return}console.log(`Checkpoints (${t.length})`),console.log("\u2500".repeat(60));for(const o of t)console.log(`${o.id}`),console.log(` Label: ${o.label}`),console.log(` Created: ${o.createdAt}`);return}case"latest":{const t=d();if(!t){console.log("No checkpoints saved.");return}c(t);return}default:console.error(`Unknown checkpoint action: ${s}`),console.error("Actions: save, load, list, latest"),process.exit(1)}}}];export{P as contextCommands};
1
+ import{resolve as p}from"node:path";import{checkpointLatest as d,checkpointList as u,checkpointLoad as f,checkpointSave as m,diffParse as h,fileSummary as k,gitContext as g,parseOutput as b}from"../../../tools/dist/index.js";import{extractBoolFlag as x,extractNumFlag as w,extractStrFlag as i,parseRecordString as v,printCheckpoint as c,printDiffFiles as y,printFileSummary as C,printGitContext as S,printParsedOutput as U,readStdin as a}from"../helpers.js";const P=[{name:"parse-output",description:"Parse build or tool output from stdin",usage:"kb parse-output [--tool tsc|vitest|biome|git-status]",run:async e=>{const s=i(e,"--tool","").trim()||void 0,t=await a();t.trim()||(console.error("Usage: kb parse-output [--tool tsc|vitest|biome|git-status]"),process.exit(1)),U(b(t,s))}},{name:"git",description:"Show git branch, status, recent commits, and optional diff stats",usage:"kb git [--cwd path] [--commit-count N] [--diff]",run:async e=>{const s=i(e,"--cwd","").trim()||void 0,t=w(e,"--commit-count",5),o=x(e,"--diff"),n=await g({cwd:s,commitCount:t,includeDiff:o});S(n)}},{name:"diff",description:"Parse unified diff text from stdin into structured file changes",usage:"git diff | kb diff",run:async()=>{const e=await a();e.trim()||(console.error("Usage: git diff | kb diff"),process.exit(1)),y(h({diff:e}))}},{name:"summarize",description:"Show a structural summary of a file",usage:"kb summarize <path>",run:async e=>{const s=e.shift()?.trim();s||(console.error("Usage: kb summarize <path>"),process.exit(1));const t=await k({path:p(s)});C(t)}},{name:"checkpoint",description:"Save and restore lightweight session checkpoints",usage:"kb checkpoint <save|load|list|latest> [label-or-id] [--data json] [--notes text]",run:async e=>{const s=e.shift()?.trim();switch(s||(console.error("Usage: kb checkpoint <save|load|list|latest> [label-or-id] [--data json] [--notes text]"),process.exit(1)),s){case"save":{const t=e.shift()?.trim(),o=i(e,"--data",""),n=i(e,"--notes","").trim()||void 0,r=o.trim()?"":await a();t||(console.error("Usage: kb checkpoint save <label> [--data json] [--notes text]"),process.exit(1));const l=m(t,v(o||r),{notes:n});c(l);return}case"load":{const t=e.shift()?.trim();t||(console.error("Usage: kb checkpoint load <id>"),process.exit(1));const o=f(t);if(!o){console.log(`No checkpoint found: ${t}`);return}c(o);return}case"list":{const t=u();if(t.length===0){console.log("No checkpoints saved.");return}console.log(`Checkpoints (${t.length})`),console.log("\u2500".repeat(60));for(const o of t)console.log(`${o.id}`),console.log(` Label: ${o.label}`),console.log(` Created: ${o.createdAt}`);return}case"latest":{const t=d();if(!t){console.log("No checkpoints saved.");return}c(t);return}default:console.error(`Unknown checkpoint action: ${s}`),console.error("Actions: save, load, list, latest"),process.exit(1)}}}];export{P as contextCommands};
@@ -1,2 +1,2 @@
1
- import{readFile as h}from"node:fs/promises";import{resolve as d}from"node:path";import{delegate as g,delegateListModels as w,processList as $,processLogs as x,processStart as k,processStatus as y,processStop as b,watchList as S,watchStart as U,watchStop as N}from"@kb/tools";import{extractNumFlag as f,extractStrFlag as l,printManagedProcess as i,readStdin as v}from"../helpers.js";const L=[{name:"proc",description:"Manage in-memory child processes",usage:"kb proc <start|stop|status|list|logs> ...",run:async e=>{const s=e.shift()?.trim()??"";switch(s){case"start":{const o=e.shift()?.trim(),t=e.shift()?.trim();(!o||!t)&&(console.error("Usage: kb proc start <id> <command> [args...]"),process.exit(1)),i(k(o,t,e));return}case"stop":{const o=e.shift()?.trim();o||(console.error("Usage: kb proc stop <id>"),process.exit(1));const t=b(o);if(!t){console.log(`No managed process found: ${o}`);return}i(t);return}case"status":{const o=e.shift()?.trim();o||(console.error("Usage: kb proc status <id>"),process.exit(1));const t=y(o);if(!t){console.log(`No managed process found: ${o}`);return}i(t);return}case"list":{const o=$();if(o.length===0){console.log("No managed processes.");return}for(const t of o)i(t),console.log("");return}case"logs":{const o=f(e,"--tail",50),t=e.shift()?.trim();t||(console.error("Usage: kb proc logs <id> [--tail N]"),process.exit(1));const n=x(t,o);if(n.length===0){console.log(`No logs found for process: ${t}`);return}for(const c of n)console.log(c);return}default:console.error(`Unknown proc action: ${s}`),console.error("Actions: start, stop, status, list, logs"),process.exit(1)}}},{name:"watch",description:"Manage in-memory filesystem watchers",usage:"kb watch <start|stop|list> ...",run:async e=>{const s=e.shift()?.trim()??"";switch(s){case"start":{const o=e.shift()?.trim();o||(console.error("Usage: kb watch start <path>"),process.exit(1));const t=U({path:d(o)});console.log(`Started watcher: ${t.id}`),console.log(` Path: ${t.path}`),console.log(` Status: ${t.status}`);return}case"stop":{const o=e.shift()?.trim();o||(console.error("Usage: kb watch stop <id>"),process.exit(1));const t=N(o);console.log(t?`Stopped watcher: ${o}`:`Watcher not found: ${o}`);return}case"list":{const o=S();if(o.length===0){console.log("No active watchers.");return}for(const t of o)console.log(`${t.id}`),console.log(` Path: ${t.path}`),console.log(` Status: ${t.status}`),console.log(` Events: ${t.eventCount}`);return}default:console.error(`Unknown watch action: ${s}`),console.error("Actions: start, stop, list"),process.exit(1)}}},{name:"delegate",description:"Delegate a task to a local Ollama model",usage:"kb delegate [--model name] [--system prompt] [--temp 0.3] <prompt | --stdin>",run:async e=>{if((e[0]==="models"?e.shift():void 0)==="models"){try{const p=await w();if(p.length===0){console.log("No Ollama models available. Pull one with: ollama pull qwen2.5-coder:7b");return}for(const u of p)console.log(u)}catch{console.error("Ollama is not running. Start it with: ollama serve"),process.exit(1)}return}const o=l(e,"--model",""),t=l(e,"--system",""),n=f(e,"--temp",.3),c=l(e,"--context","");let a=e.join(" ");a||(a=await v()),a||(console.error("Usage: kb delegate [--model name] <prompt>"),process.exit(1));let m;c&&(m=await h(d(c),"utf-8"));const r=await g({prompt:a,model:o||void 0,system:t||void 0,context:m,temperature:n});r.error&&(console.error(`Error: ${r.error}`),process.exit(1)),console.log(r.response),console.error(`
1
+ import{readFile as h}from"node:fs/promises";import{resolve as d}from"node:path";import{delegate as g,delegateListModels as w,processList as $,processLogs as x,processStart as k,processStatus as y,processStop as b,watchList as S,watchStart as U,watchStop as N}from"../../../tools/dist/index.js";import{extractNumFlag as f,extractStrFlag as l,printManagedProcess as i,readStdin as v}from"../helpers.js";const L=[{name:"proc",description:"Manage in-memory child processes",usage:"kb proc <start|stop|status|list|logs> ...",run:async e=>{const s=e.shift()?.trim()??"";switch(s){case"start":{const o=e.shift()?.trim(),t=e.shift()?.trim();(!o||!t)&&(console.error("Usage: kb proc start <id> <command> [args...]"),process.exit(1)),i(k(o,t,e));return}case"stop":{const o=e.shift()?.trim();o||(console.error("Usage: kb proc stop <id>"),process.exit(1));const t=b(o);if(!t){console.log(`No managed process found: ${o}`);return}i(t);return}case"status":{const o=e.shift()?.trim();o||(console.error("Usage: kb proc status <id>"),process.exit(1));const t=y(o);if(!t){console.log(`No managed process found: ${o}`);return}i(t);return}case"list":{const o=$();if(o.length===0){console.log("No managed processes.");return}for(const t of o)i(t),console.log("");return}case"logs":{const o=f(e,"--tail",50),t=e.shift()?.trim();t||(console.error("Usage: kb proc logs <id> [--tail N]"),process.exit(1));const n=x(t,o);if(n.length===0){console.log(`No logs found for process: ${t}`);return}for(const c of n)console.log(c);return}default:console.error(`Unknown proc action: ${s}`),console.error("Actions: start, stop, status, list, logs"),process.exit(1)}}},{name:"watch",description:"Manage in-memory filesystem watchers",usage:"kb watch <start|stop|list> ...",run:async e=>{const s=e.shift()?.trim()??"";switch(s){case"start":{const o=e.shift()?.trim();o||(console.error("Usage: kb watch start <path>"),process.exit(1));const t=U({path:d(o)});console.log(`Started watcher: ${t.id}`),console.log(` Path: ${t.path}`),console.log(` Status: ${t.status}`);return}case"stop":{const o=e.shift()?.trim();o||(console.error("Usage: kb watch stop <id>"),process.exit(1));const t=N(o);console.log(t?`Stopped watcher: ${o}`:`Watcher not found: ${o}`);return}case"list":{const o=S();if(o.length===0){console.log("No active watchers.");return}for(const t of o)console.log(`${t.id}`),console.log(` Path: ${t.path}`),console.log(` Status: ${t.status}`),console.log(` Events: ${t.eventCount}`);return}default:console.error(`Unknown watch action: ${s}`),console.error("Actions: start, stop, list"),process.exit(1)}}},{name:"delegate",description:"Delegate a task to a local Ollama model",usage:"kb delegate [--model name] [--system prompt] [--temp 0.3] <prompt | --stdin>",run:async e=>{if((e[0]==="models"?e.shift():void 0)==="models"){try{const p=await w();if(p.length===0){console.log("No Ollama models available. Pull one with: ollama pull qwen2.5-coder:7b");return}for(const u of p)console.log(u)}catch{console.error("Ollama is not running. Start it with: ollama serve"),process.exit(1)}return}const o=l(e,"--model",""),t=l(e,"--system",""),n=f(e,"--temp",.3),c=l(e,"--context","");let a=e.join(" ");a||(a=await v()),a||(console.error("Usage: kb delegate [--model name] <prompt>"),process.exit(1));let m;c&&(m=await h(d(c),"utf-8"));const r=await g({prompt:a,model:o||void 0,system:t||void 0,context:m,temperature:n});r.error&&(console.error(`Error: ${r.error}`),process.exit(1)),console.log(r.response),console.error(`
2
2
  (${r.model}, ${r.durationMs}ms, ${r.tokenCount??"?"} tokens)`)}}];export{L as environmentCommands};
@@ -1 +1 @@
1
- import{readFile as f}from"node:fs/promises";import{resolve as l}from"node:path";import{codemod as x,dataTransform as g,evaluate as y,rename as h,testRun as w}from"@kb/tools";import{extractBoolFlag as d,extractNumFlag as u,extractStrFlag as a,printTestRunResult as b,readStdin as m,splitCsv as c}from"../helpers.js";const v=[{name:"eval",description:"Evaluate JavaScript or TypeScript in a constrained VM sandbox",usage:"kb eval [code] [--lang js|ts] [--timeout ms]",run:async e=>{const t=a(e,"--lang","js"),s=u(e,"--timeout",5e3),o=e.join(" "),r=o.trim()?"":await m(),n=o||r;n.trim()||(console.error("Usage: kb eval [code] [--lang js|ts] [--timeout ms]"),process.exit(1));const i=y({code:n,lang:t==="ts"?"ts":"js",timeout:s});if(!i.success){console.error(`Eval failed in ${i.durationMs}ms: ${i.error}`),process.exitCode=1;return}console.log(`Eval succeeded in ${i.durationMs}ms`),console.log("\u2500".repeat(60)),console.log(i.output)}},{name:"test",description:"Run Vitest for all tests or a specific subset",usage:"kb test [files...] [--grep pattern] [--cwd path] [--timeout ms]",run:async e=>{const t=a(e,"--grep","").trim()||void 0,s=a(e,"--cwd","").trim()||void 0,o=u(e,"--timeout",6e4),r=e.filter(Boolean),n=await w({files:r.length>0?r:void 0,grep:t,cwd:s,timeout:o});b(n),n.passed||(process.exitCode=1)}},{name:"rename",description:"Rename a symbol across files using whole-word regex matching",usage:"kb rename <old> <new> <path> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]",run:async e=>{const t=e.shift()?.trim()??"",s=e.shift()?.trim()??"",o=e.shift()?.trim()??"";(!t||!s||!o)&&(console.error("Usage: kb rename <old> <new> <path> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]"),process.exit(1));const r=c(a(e,"--extensions","")),n=c(a(e,"--exclude","")),i=await h({oldName:t,newName:s,rootPath:l(o),extensions:r.length>0?r:void 0,exclude:n.length>0?n:void 0,dryRun:d(e,"--dry-run")});console.log(JSON.stringify(i,null,2))}},{name:"codemod",description:"Apply regex-based codemod rules from a JSON file across a path",usage:"kb codemod <path> --rules <file.json> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]",run:async e=>{const t=e.shift()?.trim()??"",s=a(e,"--rules","").trim();(!t||!s)&&(console.error("Usage: kb codemod <path> --rules <file.json> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]"),process.exit(1));const o=await f(l(s),"utf-8"),r=JSON.parse(o);if(!Array.isArray(r))throw new Error("Codemod rules file must contain a JSON array.");const n=c(a(e,"--extensions","")),i=c(a(e,"--exclude","")),p=await x({rootPath:l(t),rules:r,extensions:n.length>0?n:void 0,exclude:i.length>0?i:void 0,dryRun:d(e,"--dry-run")});console.log(JSON.stringify(p,null,2))}},{name:"transform",description:"Apply jq-like transforms to JSON from stdin",usage:"cat data.json | kb transform <expression>",run:async e=>{const t=e.join(" ").trim(),s=await m();(!t||!s.trim())&&(console.error("Usage: cat data.json | kb transform <expression>"),process.exit(1));const o=g({input:s,expression:t});console.log(o.outputString)}}];export{v as executionCommands};
1
+ import{readFile as f}from"node:fs/promises";import{resolve as l}from"node:path";import{codemod as x,dataTransform as g,evaluate as y,rename as h,testRun as w}from"../../../tools/dist/index.js";import{extractBoolFlag as d,extractNumFlag as u,extractStrFlag as a,printTestRunResult as b,readStdin as m,splitCsv as c}from"../helpers.js";const v=[{name:"eval",description:"Evaluate JavaScript or TypeScript in a constrained VM sandbox",usage:"kb eval [code] [--lang js|ts] [--timeout ms]",run:async e=>{const t=a(e,"--lang","js"),s=u(e,"--timeout",5e3),o=e.join(" "),r=o.trim()?"":await m(),n=o||r;n.trim()||(console.error("Usage: kb eval [code] [--lang js|ts] [--timeout ms]"),process.exit(1));const i=y({code:n,lang:t==="ts"?"ts":"js",timeout:s});if(!i.success){console.error(`Eval failed in ${i.durationMs}ms: ${i.error}`),process.exitCode=1;return}console.log(`Eval succeeded in ${i.durationMs}ms`),console.log("\u2500".repeat(60)),console.log(i.output)}},{name:"test",description:"Run Vitest for all tests or a specific subset",usage:"kb test [files...] [--grep pattern] [--cwd path] [--timeout ms]",run:async e=>{const t=a(e,"--grep","").trim()||void 0,s=a(e,"--cwd","").trim()||void 0,o=u(e,"--timeout",6e4),r=e.filter(Boolean),n=await w({files:r.length>0?r:void 0,grep:t,cwd:s,timeout:o});b(n),n.passed||(process.exitCode=1)}},{name:"rename",description:"Rename a symbol across files using whole-word regex matching",usage:"kb rename <old> <new> <path> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]",run:async e=>{const t=e.shift()?.trim()??"",s=e.shift()?.trim()??"",o=e.shift()?.trim()??"";(!t||!s||!o)&&(console.error("Usage: kb rename <old> <new> <path> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]"),process.exit(1));const r=c(a(e,"--extensions","")),n=c(a(e,"--exclude","")),i=await h({oldName:t,newName:s,rootPath:l(o),extensions:r.length>0?r:void 0,exclude:n.length>0?n:void 0,dryRun:d(e,"--dry-run")});console.log(JSON.stringify(i,null,2))}},{name:"codemod",description:"Apply regex-based codemod rules from a JSON file across a path",usage:"kb codemod <path> --rules <file.json> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]",run:async e=>{const t=e.shift()?.trim()??"",s=a(e,"--rules","").trim();(!t||!s)&&(console.error("Usage: kb codemod <path> --rules <file.json> [--dry-run] [--extensions .ts,.tsx] [--exclude dist/**]"),process.exit(1));const o=await f(l(s),"utf-8"),r=JSON.parse(o);if(!Array.isArray(r))throw new Error("Codemod rules file must contain a JSON array.");const n=c(a(e,"--extensions","")),i=c(a(e,"--exclude","")),p=await x({rootPath:l(t),rules:r,extensions:n.length>0?n:void 0,exclude:i.length>0?i:void 0,dryRun:d(e,"--dry-run")});console.log(JSON.stringify(p,null,2))}},{name:"transform",description:"Apply jq-like transforms to JSON from stdin",usage:"cat data.json | kb transform <expression>",run:async e=>{const t=e.join(" ").trim(),s=await m();(!t||!s.trim())&&(console.error("Usage: cat data.json | kb transform <expression>"),process.exit(1));const o=g({input:s,expression:t});console.log(o.outputString)}}];export{v as executionCommands};
@@ -1,4 +1,4 @@
1
- import{graphQuery as u}from"@kb/tools";import{ctx as $}from"../context.js";import{extractNumFlag as r,extractStrFlag as n}from"../helpers.js";const T=[{name:"graph",description:"Query the knowledge graph",usage:`kb graph <action> [options]
1
+ import{graphQuery as u}from"../../../tools/dist/index.js";import{ctx as $}from"../context.js";import{extractNumFlag as r,extractStrFlag as n}from"../helpers.js";const T=[{name:"graph",description:"Query the knowledge graph",usage:`kb graph <action> [options]
2
2
  Actions: stats, find-nodes, find-edges, neighbors, traverse, delete, clear
3
3
  Options: --type, --name, --node-id, --edge-type, --direction, --depth, --limit, --source-path`,run:async t=>{const s=t.shift()?.trim()??"";s||(console.error(`Usage: kb graph <action>
4
4
  Actions: stats, find-nodes, find-edges, neighbors, traverse, delete, clear`),process.exit(1));const{graphStore:a}=await $(),c=n(t,"--type",""),p=n(t,"--name",""),g=n(t,"--node-id",""),l=n(t,"--edge-type",""),f=n(t,"--direction","both"),m=r(t,"--depth",2),h=r(t,"--limit",50),y=n(t,"--source-path",""),i={stats:"stats","find-nodes":"find_nodes","find-edges":"find_edges",neighbors:"neighbors",traverse:"traverse",delete:"delete",clear:"clear"}[s];i||(console.error(`Unknown graph action: ${s}`),console.error("Actions: stats, find-nodes, find-edges, neighbors, traverse, delete, clear"),process.exit(1));const e=await u(a,{action:i,nodeType:c||void 0,namePattern:p||void 0,sourcePath:y||void 0,nodeId:g||void 0,edgeType:l||void 0,direction:f,maxDepth:m,limit:h});if(console.log(e.summary),e.nodes&&e.nodes.length>0){console.log(`
@@ -1 +1 @@
1
- import{compact as m}from"@kb/tools";import{ctx as i}from"../context.js";import{extractNumFlag as p,extractStrFlag as c,readStdin as l,splitCsv as d}from"../helpers.js";const f=[{name:"remember",description:"Store curated knowledge",usage:"kb remember <title> --category <cat> [--tags tag1,tag2]",run:async t=>{const o=c(t,"--category","").trim(),a=d(c(t,"--tags","")),e=t.shift()?.trim()??"",r=await l(),n=r.trim().length>0?r:t.join(" ").trim();(!e||!o||!n.trim())&&(console.error("Usage: kb remember <title> --category <cat> [--tags tag1,tag2]"),process.exit(1));const{curated:s}=await i(),g=await s.remember(e,n,o,a);console.log("Stored curated entry"),console.log(` Path: ${g.path}`),console.log(` Category: ${o}`),a.length>0&&console.log(` Tags: ${a.join(", ")}`)}},{name:"forget",description:"Remove a curated entry",usage:"kb forget <path> --reason <reason>",run:async t=>{const o=c(t,"--reason","").trim(),a=t.shift()?.trim()??"";(!a||!o)&&(console.error("Usage: kb forget <path> --reason <reason>"),process.exit(1));const{curated:e}=await i(),r=await e.forget(a,o);console.log(`Removed curated entry: ${r.path}`)}},{name:"read",description:"Read a curated entry",usage:"kb read <path>",run:async t=>{const o=t.shift()?.trim()??"";o||(console.error("Usage: kb read <path>"),process.exit(1));const{curated:a}=await i(),e=await a.read(o);console.log(e.title),console.log("\u2500".repeat(60)),console.log(`Path: ${e.path}`),console.log(`Category: ${e.category}`),console.log(`Version: ${e.version}`),console.log(`Tags: ${e.tags.length>0?e.tags.join(", "):"None"}`),console.log(""),console.log(e.content)}},{name:"list",description:"List curated entries",usage:"kb list [--category <cat>] [--tag <tag>]",run:async t=>{const o=c(t,"--category","").trim()||void 0,a=c(t,"--tag","").trim()||void 0,{curated:e}=await i(),r=await e.list({category:o,tag:a});if(r.length===0){console.log("No curated entries found.");return}console.log(`Curated entries (${r.length})`),console.log("\u2500".repeat(60));for(const n of r){console.log(n.path),console.log(` ${n.title}`),console.log(` Category: ${n.category} | Version: ${n.version}`),console.log(` Tags: ${n.tags.length>0?n.tags.join(", "):"None"}`);const s=n.contentPreview.replace(/\s+/g," ").trim();s&&console.log(` Preview: ${s}`),console.log("")}}},{name:"update",description:"Update a curated entry",usage:"kb update <path> --reason <reason>",run:async t=>{const o=c(t,"--reason","").trim(),a=t.shift()?.trim()??"",e=await l();(!a||!o||!e.trim())&&(console.error("Usage: kb update <path> --reason <reason>"),process.exit(1));const{curated:r}=await i(),n=await r.update(a,e,o);console.log("Updated curated entry"),console.log(` Path: ${n.path}`),console.log(` Version: ${n.version}`)}},{name:"compact",description:"Compress text for context",usage:"kb compact <query> [--max-chars N] [--segmentation paragraph|sentence|line]",run:async t=>{const o=p(t,"--max-chars",3e3),a=c(t,"--segmentation","paragraph"),e=t.join(" ").trim(),r=await l();(!e||!r.trim())&&(console.error("Usage: kb compact <query> [--max-chars N] [--segmentation paragraph|sentence|line]"),process.exit(1));const{embedder:n}=await i(),s=await m(n,{text:r,query:e,maxChars:o,segmentation:a});console.log(`Compressed ${s.originalChars} chars to ${s.compressedChars} chars`),console.log(`Ratio: ${(s.ratio*100).toFixed(1)}% | Segments: ${s.segmentsKept}/${s.segmentsTotal}`),console.log(""),console.log(s.text)}}];export{f as knowledgeCommands};
1
+ import{compact as m}from"../../../tools/dist/index.js";import{ctx as i}from"../context.js";import{extractNumFlag as p,extractStrFlag as c,readStdin as l,splitCsv as d}from"../helpers.js";const f=[{name:"remember",description:"Store curated knowledge",usage:"kb remember <title> --category <cat> [--tags tag1,tag2]",run:async t=>{const o=c(t,"--category","").trim(),a=d(c(t,"--tags","")),e=t.shift()?.trim()??"",r=await l(),n=r.trim().length>0?r:t.join(" ").trim();(!e||!o||!n.trim())&&(console.error("Usage: kb remember <title> --category <cat> [--tags tag1,tag2]"),process.exit(1));const{curated:s}=await i(),g=await s.remember(e,n,o,a);console.log("Stored curated entry"),console.log(` Path: ${g.path}`),console.log(` Category: ${o}`),a.length>0&&console.log(` Tags: ${a.join(", ")}`)}},{name:"forget",description:"Remove a curated entry",usage:"kb forget <path> --reason <reason>",run:async t=>{const o=c(t,"--reason","").trim(),a=t.shift()?.trim()??"";(!a||!o)&&(console.error("Usage: kb forget <path> --reason <reason>"),process.exit(1));const{curated:e}=await i(),r=await e.forget(a,o);console.log(`Removed curated entry: ${r.path}`)}},{name:"read",description:"Read a curated entry",usage:"kb read <path>",run:async t=>{const o=t.shift()?.trim()??"";o||(console.error("Usage: kb read <path>"),process.exit(1));const{curated:a}=await i(),e=await a.read(o);console.log(e.title),console.log("\u2500".repeat(60)),console.log(`Path: ${e.path}`),console.log(`Category: ${e.category}`),console.log(`Version: ${e.version}`),console.log(`Tags: ${e.tags.length>0?e.tags.join(", "):"None"}`),console.log(""),console.log(e.content)}},{name:"list",description:"List curated entries",usage:"kb list [--category <cat>] [--tag <tag>]",run:async t=>{const o=c(t,"--category","").trim()||void 0,a=c(t,"--tag","").trim()||void 0,{curated:e}=await i(),r=await e.list({category:o,tag:a});if(r.length===0){console.log("No curated entries found.");return}console.log(`Curated entries (${r.length})`),console.log("\u2500".repeat(60));for(const n of r){console.log(n.path),console.log(` ${n.title}`),console.log(` Category: ${n.category} | Version: ${n.version}`),console.log(` Tags: ${n.tags.length>0?n.tags.join(", "):"None"}`);const s=n.contentPreview.replace(/\s+/g," ").trim();s&&console.log(` Preview: ${s}`),console.log("")}}},{name:"update",description:"Update a curated entry",usage:"kb update <path> --reason <reason>",run:async t=>{const o=c(t,"--reason","").trim(),a=t.shift()?.trim()??"",e=await l();(!a||!o||!e.trim())&&(console.error("Usage: kb update <path> --reason <reason>"),process.exit(1));const{curated:r}=await i(),n=await r.update(a,e,o);console.log("Updated curated entry"),console.log(` Path: ${n.path}`),console.log(` Version: ${n.version}`)}},{name:"compact",description:"Compress text for context",usage:"kb compact <query> [--max-chars N] [--segmentation paragraph|sentence|line]",run:async t=>{const o=p(t,"--max-chars",3e3),a=c(t,"--segmentation","paragraph"),e=t.join(" ").trim(),r=await l();(!e||!r.trim())&&(console.error("Usage: kb compact <query> [--max-chars N] [--segmentation paragraph|sentence|line]"),process.exit(1));const{embedder:n}=await i(),s=await m(n,{text:r,query:e,maxChars:o,segmentation:a});console.log(`Compressed ${s.originalChars} chars to ${s.compressedChars} chars`),console.log(`Ratio: ${(s.ratio*100).toFixed(1)}% | Segments: ${s.segmentsKept}/${s.segmentsTotal}`),console.log(""),console.log(s.text)}}];export{f as knowledgeCommands};
@@ -1,6 +1,6 @@
1
- import{find as $,findDeadSymbols as k,findExamples as x,scopeMap as w,symbol as N,trace as R}from"@kb/tools";import{ctx as g}from"../context.js";import{extractNumFlag as p,extractStrFlag as h,formatFocusRanges as T,printDeadSymbolsResult as C,printExamplesResult as F,printSymbolInfo as S,printTraceResult as j,rrf as I}from"../helpers.js";const v=[{name:"search",description:"Search the knowledge base",usage:"kb search <query> [--limit N] [--mode hybrid|semantic|keyword] [--graph-hops 0-3]",run:async o=>{const t=p(o,"--limit",5),r=h(o,"--mode","hybrid"),e=p(o,"--graph-hops",0),s=o.join(" ").trim();s||(console.error("Usage: kb search <query>"),process.exit(1));const{embedder:n,store:a,graphStore:c}=await g(),l=await n.embedQuery(s);let d;if(r==="keyword")d=await a.ftsSearch(s,{limit:t});else if(r==="semantic")d=await a.search(l,{limit:t});else{const[i,f]=await Promise.all([a.search(l,{limit:t*2}),a.ftsSearch(s,{limit:t*2}).catch(()=>[])]);d=I(i,f).slice(0,t)}if(d.length===0){console.log("No results found.");return}for(const{record:i,score:f}of d){console.log(`
1
+ import{find as $,findDeadSymbols as k,findExamples as x,scopeMap as w,symbol as N,trace as R}from"../../../tools/dist/index.js";import{ctx as g}from"../context.js";import{extractNumFlag as p,extractStrFlag as h,formatFocusRanges as T,printDeadSymbolsResult as C,printExamplesResult as F,printSymbolInfo as S,printTraceResult as j,rrf as I}from"../helpers.js";const v=[{name:"search",description:"Search the knowledge base",usage:"kb search <query> [--limit N] [--mode hybrid|semantic|keyword] [--graph-hops 0-3]",run:async o=>{const t=p(o,"--limit",5),r=h(o,"--mode","hybrid"),e=p(o,"--graph-hops",0),s=o.join(" ").trim();s||(console.error("Usage: kb search <query>"),process.exit(1));const{embedder:n,store:a,graphStore:c}=await g(),l=await n.embedQuery(s);let d;if(r==="keyword")d=await a.ftsSearch(s,{limit:t});else if(r==="semantic")d=await a.search(l,{limit:t});else{const[i,f]=await Promise.all([a.search(l,{limit:t*2}),a.ftsSearch(s,{limit:t*2}).catch(()=>[])]);d=I(i,f).slice(0,t)}if(d.length===0){console.log("No results found.");return}for(const{record:i,score:f}of d){console.log(`
2
2
  ${"\u2500".repeat(60)}`),console.log(`[${(f*100).toFixed(1)}%] ${i.sourcePath}:${i.startLine}-${i.endLine}`),console.log(` Type: ${i.contentType} | Origin: ${i.origin}`),i.tags.length>0&&console.log(` Tags: ${i.tags.join(", ")}`),console.log("");const y=i.content.length>500?`${i.content.slice(0,500)}...`:i.content;console.log(y)}if(console.log(`
3
- ${"\u2500".repeat(60)}`),console.log(`${d.length} result(s) found.`),e>0&&d.length>0)try{const{graphAugmentSearch:i}=await import("@kb/tools"),f=d.map(m=>({recordId:m.record.id,score:m.score,sourcePath:m.record.sourcePath})),b=(await i(c,f,{hops:e,maxPerHit:5})).filter(m=>m.graphContext.nodes.length>0);if(b.length>0){console.log(`
3
+ ${"\u2500".repeat(60)}`),console.log(`${d.length} result(s) found.`),e>0&&d.length>0)try{const{graphAugmentSearch:i}=await import("../../../tools/dist/index.js"),f=d.map(m=>({recordId:m.record.id,score:m.score,sourcePath:m.record.sourcePath})),b=(await i(c,f,{hops:e,maxPerHit:5})).filter(m=>m.graphContext.nodes.length>0);if(b.length>0){console.log(`
4
4
  Graph context (${e} hop${e>1?"s":""}):
5
5
  `);for(const m of b){console.log(` ${m.sourcePath}:`);for(const u of m.graphContext.nodes.slice(0,5))console.log(` \u2192 ${u.name} (${u.type})`);for(const u of m.graphContext.edges.slice(0,5))console.log(` \u2192 ${u.fromId} --[${u.type}]--> ${u.toId}`)}}}catch(i){console.error(`[graph] augmentation failed: ${i.message}`)}}},{name:"find",description:"Run federated search across indexed content and files",usage:"kb find [query] [--glob <pattern>] [--pattern <regex>] [--limit N]",run:async o=>{const t=p(o,"--limit",10),r=h(o,"--glob","").trim()||void 0,e=h(o,"--pattern","").trim()||void 0,s=o.join(" ").trim()||void 0;!s&&!r&&!e&&(console.error("Usage: kb find [query] [--glob <pattern>] [--pattern <regex>] [--limit N]"),process.exit(1));const{embedder:n,store:a}=await g(),c=await $(n,a,{query:s,glob:r,pattern:e,limit:t});if(c.results.length===0){console.log("No matches found.");return}console.log(`Strategies: ${c.strategies.join(", ")}`),console.log(`Results: ${c.results.length} shown (${c.totalFound} total)`);for(const l of c.results){const d=l.lineRange?`:${l.lineRange.start}-${l.lineRange.end}`:"";console.log(`
6
6
  [${l.source}] ${l.path}${d}`),console.log(` Score: ${(l.score*100).toFixed(1)}%`),l.preview&&console.log(` ${l.preview.replace(/\s+/g," ").trim()}`)}}},{name:"scope-map",description:"Generate a reading plan for a task",usage:"kb scope-map <task> [--max-files N]",run:async o=>{const t=p(o,"--max-files",15),r=o.join(" ").trim();r||(console.error("Usage: kb scope-map <task> [--max-files N]"),process.exit(1));const{embedder:e,store:s}=await g(),n=await w(e,s,{task:r,maxFiles:t});console.log(`Task: ${n.task}`),console.log(`Files: ${n.files.length}`),console.log(`Estimated tokens: ${n.totalEstimatedTokens}`),console.log(""),console.log("Reading order:");for(const a of n.readingOrder)console.log(` ${a}`);for(const[a,c]of n.files.entries())console.log(`
@@ -1,4 +1,4 @@
1
- import{fork as f}from"node:child_process";import{dirname as m,resolve as h}from"node:path";import{fileURLToPath as g}from"node:url";import{batch as y,check as x,health as k,replayClear as w,replayList as $,replayTrim as b}from"@kb/tools";import{ctx as p}from"../context.js";import{executeCliBatchOperation as I,extractStrFlag as a,parseBatchPayload as R,printCheckResult as N,readInput as T}from"../helpers.js";const C=m(g(import.meta.url)),E=[{name:"status",description:"Show knowledge base index status and statistics",run:async()=>{const{store:e}=await p(),s=await e.getStats(),t=await e.listSourcePaths();console.log("Knowledge Base Status"),console.log("\u2500".repeat(40)),console.log(` Records: ${s.totalRecords}`),console.log(` Files: ${s.totalFiles}`),console.log(` Indexed: ${s.lastIndexedAt??"Never"}`),console.log(` Backend: ${s.storeBackend}`),console.log(` Model: ${s.embeddingModel}`),console.log(""),console.log("Content Types:");for(const[n,o]of Object.entries(s.contentTypeBreakdown))console.log(` ${n}: ${o}`);if(t.length>0){console.log(""),console.log(`Files (${t.length} total):`);for(const n of t.slice(0,20))console.log(` ${n}`);t.length>20&&console.log(` ... and ${t.length-20} more`)}}},{name:"reindex",description:"Re-index the knowledge base from configured sources",usage:"kb reindex [--full]",run:async e=>{const s=e.includes("--full"),{store:t,indexer:n,curated:o,config:i}=await p();console.log("Indexing sources...");const l=r=>{r.phase==="chunking"&&r.currentFile&&process.stdout.write(`\r [${r.filesProcessed+1}/${r.filesTotal}] ${r.currentFile}`),r.phase==="done"&&process.stdout.write(`
1
+ import{fork as f}from"node:child_process";import{dirname as m,resolve as h}from"node:path";import{fileURLToPath as g}from"node:url";import{batch as y,check as x,health as k,replayClear as w,replayList as $,replayTrim as b}from"../../../tools/dist/index.js";import{ctx as p}from"../context.js";import{executeCliBatchOperation as I,extractStrFlag as a,parseBatchPayload as R,printCheckResult as N,readInput as T}from"../helpers.js";const C=m(g(import.meta.url)),E=[{name:"status",description:"Show knowledge base index status and statistics",run:async()=>{const{store:e}=await p(),s=await e.getStats(),t=await e.listSourcePaths();console.log("Knowledge Base Status"),console.log("\u2500".repeat(40)),console.log(` Records: ${s.totalRecords}`),console.log(` Files: ${s.totalFiles}`),console.log(` Indexed: ${s.lastIndexedAt??"Never"}`),console.log(` Backend: ${s.storeBackend}`),console.log(` Model: ${s.embeddingModel}`),console.log(""),console.log("Content Types:");for(const[n,o]of Object.entries(s.contentTypeBreakdown))console.log(` ${n}: ${o}`);if(t.length>0){console.log(""),console.log(`Files (${t.length} total):`);for(const n of t.slice(0,20))console.log(` ${n}`);t.length>20&&console.log(` ... and ${t.length-20} more`)}}},{name:"reindex",description:"Re-index the knowledge base from configured sources",usage:"kb reindex [--full]",run:async e=>{const s=e.includes("--full"),{store:t,indexer:n,curated:o,config:i}=await p();console.log("Indexing sources...");const l=r=>{r.phase==="chunking"&&r.currentFile&&process.stdout.write(`\r [${r.filesProcessed+1}/${r.filesTotal}] ${r.currentFile}`),r.phase==="done"&&process.stdout.write(`
2
2
  `)};let c;s?(console.log("Dropping existing index for full reindex..."),c=await n.reindexAll(i,l)):c=await n.index(i,l),console.log(`Done: ${c.filesProcessed} files, ${c.chunksCreated} chunks in ${(c.durationMs/1e3).toFixed(1)}s`),console.log("Building FTS index..."),await t.createFtsIndex(),console.log("Re-indexing curated entries...");const d=await o.reindexAll();console.log(`Curated: ${d.indexed} entries restored`)}},{name:"serve",description:"Start the MCP server (stdio or HTTP)",usage:"kb serve [--transport stdio|http] [--port N]",run:async e=>{const s=h(C,"..","..","..","server","dist","index.js"),t=a(e,"--transport","stdio"),n=a(e,"--port","3210"),o=f(s,[],{stdio:t==="stdio"?["pipe","pipe","inherit","ipc"]:"inherit",env:{...process.env,KB_TRANSPORT:t,KB_PORT:n}});t==="stdio"&&o.stdin&&o.stdout&&(process.stdin.pipe(o.stdin),o.stdout.pipe(process.stdout)),o.on("exit",i=>process.exit(i??0)),process.on("SIGINT",()=>o.kill("SIGINT")),process.on("SIGTERM",()=>o.kill("SIGTERM")),await new Promise(()=>{})}},{name:"init",description:"Initialize a knowledge base in the current directory",usage:"kb init [--force]",run:async e=>{const s=e.includes("--force"),{initProject:t}=await import("./init.js");await t({force:s})}},{name:"check",description:"Run incremental typecheck and lint",usage:"kb check [--cwd <dir>] [--files f1,f2] [--skip-types] [--skip-lint]",run:async e=>{const s=a(e,"--cwd","").trim()||void 0,n=a(e,"--files","").split(",").map(c=>c.trim()).filter(Boolean);let o=!1;e.includes("--skip-types")&&(e.splice(e.indexOf("--skip-types"),1),o=!0);let i=!1;e.includes("--skip-lint")&&(e.splice(e.indexOf("--skip-lint"),1),i=!0);const l=await x({cwd:s,files:n.length>0?n:void 0,skipTypes:o,skipLint:i});N(l),l.passed||(process.exitCode=1)}},{name:"batch",description:"Execute built-in operations from JSON input",usage:"kb batch [--file path] [--concurrency N]",run:async e=>{const s=a(e,"--file","").trim()||void 0,t=(()=>{const r=e.indexOf("--concurrency");if(r===-1||r+1>=e.length)return 0;const u=Number.parseInt(e.splice(r,2)[1],10);return Number.isNaN(u)?0:u})(),n=await T(s);n.trim()||(console.error("Usage: kb batch [--file path] [--concurrency N]"),process.exit(1));const o=R(n),i=t>0?t:o.concurrency,c=o.operations.some(r=>r.type!=="check")?await p():null,d=await y(o.operations,async r=>I(r,c),{concurrency:i});console.log(JSON.stringify(d,null,2)),d.some(r=>r.status==="error")&&(process.exitCode=1)}},{name:"health",description:"Run project health checks on the current directory",usage:"kb health [path]",run:async e=>{const s=e.shift(),t=k(s);console.log(`Project Health: ${t.path}`),console.log("\u2500".repeat(50));for(const n of t.checks){const o=n.status==="pass"?"+":n.status==="warn"?"~":"X";console.log(` [${o}] ${n.name}: ${n.message}`)}console.log("\u2500".repeat(50)),console.log(`Score: ${t.score}% \u2014 ${t.summary}`)}},{name:"replay",description:"Show recent tool invocation audit trail",usage:"kb replay [--last N] [--tool <name>] [--source mcp|cli]",run:async e=>{const s=Number.parseInt(e[e.indexOf("--last")+1],10)||20,t=e.includes("--tool")?e[e.indexOf("--tool")+1]:void 0,n=e.includes("--source")?e[e.indexOf("--source")+1]:void 0,o=$({last:s,tool:t,source:n});if(o.length===0){console.log("No replay entries. Activity is logged when tools are invoked.");return}console.log(`Replay Log (${o.length} entries)
3
- `);for(const i of o){const l=i.ts.split("T")[1]?.split(".")[0]??i.ts,c=i.status==="ok"?"\u2713":"\u2717";console.log(`${l} ${c} ${i.tool} (${i.durationMs}ms) [${i.source}]`),console.log(` in: ${i.input}`),console.log(` out: ${i.output}`)}b()}},{name:"replay-clear",description:"Clear the replay audit trail",run:async()=>{w(),console.log("Replay log cleared.")}},{name:"tui",description:"Launch interactive terminal dashboard (human monitoring)",run:async()=>{try{const{launch:e}=await import("@kb/tui"),{store:s,embedder:t,config:n}=await p();e({store:s,embedder:t,config:n})}catch(e){throw e.code==="ERR_MODULE_NOT_FOUND"&&(console.error(`TUI requires ink and react. Install them with:
3
+ `);for(const i of o){const l=i.ts.split("T")[1]?.split(".")[0]??i.ts,c=i.status==="ok"?"\u2713":"\u2717";console.log(`${l} ${c} ${i.tool} (${i.durationMs}ms) [${i.source}]`),console.log(` in: ${i.input}`),console.log(` out: ${i.output}`)}b()}},{name:"replay-clear",description:"Clear the replay audit trail",run:async()=>{w(),console.log("Replay log cleared.")}},{name:"tui",description:"Launch interactive terminal dashboard (human monitoring)",run:async()=>{try{const{launch:e}=await import("../../../tui/dist/index.js"),{store:s,embedder:t,config:n}=await p();e({store:s,embedder:t,config:n})}catch(e){throw e.code==="ERR_MODULE_NOT_FOUND"&&(console.error(`TUI requires ink and react. Install them with:
4
4
  pnpm add -D ink react @types/react`),process.exit(1)),e}}}];export{E as systemCommands};
@@ -1,2 +1,2 @@
1
- import{addToWorkset as c,deleteWorkset as d,getWorkset as f,laneCreate as u,laneDiff as g,laneDiscard as m,laneList as k,laneMerge as $,laneStatus as p,listWorksets as h,queueClear as w,queueCreate as b,queueDelete as x,queueDone as y,queueFail as q,queueGet as v,queueList as U,queueNext as N,queuePush as S,removeFromWorkset as C,saveWorkset as M,stashClear as L,stashDelete as D,stashGet as W,stashList as A,stashSet as Q}from"@kb/tools";import{extractStrFlag as i,parseMaybeJsonString as F,printWorkset as a,readStdin as j,splitCsv as V}from"../helpers.js";const G=[{name:"workset",description:"Manage saved file sets",usage:"kb workset <action> [name] [--files f1,f2] [--description desc]",run:async n=>{const r=n.shift()?.trim(),s=V(i(n,"--files","")),e=i(n,"--description","").trim()||void 0,o=n.shift()?.trim();switch(r||(console.error("Usage: kb workset <action> [name] [--files f1,f2] [--description desc]"),console.error("Actions: save, get, list, delete, add, remove"),process.exit(1)),r){case"save":{(!o||s.length===0)&&(console.error("Usage: kb workset save <name> --files f1,f2 [--description desc]"),process.exit(1));const t=M(o,s,{description:e});console.log(`Saved workset: ${t.name}`),a(t);return}case"get":{o||(console.error("Usage: kb workset get <name>"),process.exit(1));const t=f(o);if(!t){console.log(`No workset found: ${o}`);return}a(t);return}case"list":{const t=h();if(t.length===0){console.log("No worksets saved.");return}console.log(`Worksets (${t.length})`),console.log("\u2500".repeat(60));for(const l of t)a(l),console.log("");return}case"delete":{o||(console.error("Usage: kb workset delete <name>"),process.exit(1));const t=d(o);console.log(t?`Deleted workset: ${o}`:`No workset found: ${o}`);return}case"add":{(!o||s.length===0)&&(console.error("Usage: kb workset add <name> --files f1,f2"),process.exit(1));const t=c(o,s);console.log(`Updated workset: ${t.name}`),a(t);return}case"remove":{(!o||s.length===0)&&(console.error("Usage: kb workset remove <name> --files f1,f2"),process.exit(1));const t=C(o,s);if(!t){console.log(`No workset found: ${o}`);return}console.log(`Updated workset: ${t.name}`),a(t);return}default:console.error(`Unknown workset action: ${r}`),console.error("Actions: save, get, list, delete, add, remove"),process.exit(1)}}},{name:"stash",description:"Persist and retrieve named intermediate values",usage:"kb stash <set|get|list|delete|clear> [key] [value]",run:async n=>{const r=n.shift()?.trim(),s=n.shift()?.trim();switch(r||(console.error("Usage: kb stash <set|get|list|delete|clear> [key] [value]"),process.exit(1)),r){case"set":{s||(console.error("Usage: kb stash set <key> <value>"),process.exit(1));const e=n.join(" "),o=e.trim()?"":await j(),l=Q(s,F(e||o));console.log(`Stored stash entry: ${l.key}`),console.log(` Type: ${l.type}`),console.log(` Stored: ${l.storedAt}`);return}case"get":{s||(console.error("Usage: kb stash get <key>"),process.exit(1));const e=W(s);if(!e){console.log(`No stash entry found: ${s}`);return}console.log(JSON.stringify(e,null,2));return}case"list":{const e=A();if(e.length===0){console.log("No stash entries saved.");return}console.log(`Stash entries (${e.length})`),console.log("\u2500".repeat(60));for(const o of e)console.log(`${o.key} (${o.type})`),console.log(` Stored: ${o.storedAt}`);return}case"delete":{s||(console.error("Usage: kb stash delete <key>"),process.exit(1));const e=D(s);console.log(e?`Deleted stash entry: ${s}`:`No stash entry found: ${s}`);return}case"clear":{const e=L();console.log(`Cleared ${e} stash entr${e===1?"y":"ies"}.`);return}default:console.error(`Unknown stash action: ${r}`),console.error("Actions: set, get, list, delete, clear"),process.exit(1)}}},{name:"lane",description:"Manage verified lanes \u2014 isolated file copies for parallel exploration",usage:"kb lane <create|list|status|diff|merge|discard> [name] [--files f1,f2]",run:async n=>{const r=n.shift();if((!r||!["create","list","status","diff","merge","discard"].includes(r))&&(console.error("Usage: kb lane <create|list|status|diff|merge|discard> [name] [--files f1,f2]"),process.exit(1)),r==="list"){const e=k();if(e.length===0){console.log("No active lanes.");return}for(const o of e)console.log(`${o.name} (${o.sourceFiles.length} files, created ${o.createdAt})`);return}const s=n.shift();switch(s||(console.error(`Lane name is required for "${r}".`),process.exit(1)),r){case"create":{const e=i(n,"--files","");e||(console.error("Usage: kb lane create <name> --files file1.ts,file2.ts"),process.exit(1));const o=e.split(",").map(l=>l.trim()),t=u(s,o);console.log(`Lane "${t.name}" created with ${t.sourceFiles.length} files.`);break}case"status":{const e=p(s);console.log(`Lane: ${e.name}`),console.log(`Modified: ${e.modified} | Added: ${e.added} | Deleted: ${e.deleted}`);for(const o of e.entries)console.log(` ${o.status.padEnd(10)} ${o.file}`);break}case"diff":{const e=g(s);console.log(`Lane: ${e.name} \u2014 ${e.modified} modified, ${e.added} added, ${e.deleted} deleted`);for(const o of e.entries)o.diff&&(console.log(`
1
+ import{addToWorkset as c,deleteWorkset as d,getWorkset as f,laneCreate as u,laneDiff as g,laneDiscard as m,laneList as k,laneMerge as $,laneStatus as p,listWorksets as h,queueClear as w,queueCreate as b,queueDelete as x,queueDone as y,queueFail as q,queueGet as v,queueList as U,queueNext as N,queuePush as S,removeFromWorkset as C,saveWorkset as M,stashClear as L,stashDelete as D,stashGet as W,stashList as A,stashSet as Q}from"../../../tools/dist/index.js";import{extractStrFlag as i,parseMaybeJsonString as F,printWorkset as a,readStdin as j,splitCsv as V}from"../helpers.js";const G=[{name:"workset",description:"Manage saved file sets",usage:"kb workset <action> [name] [--files f1,f2] [--description desc]",run:async n=>{const r=n.shift()?.trim(),s=V(i(n,"--files","")),e=i(n,"--description","").trim()||void 0,o=n.shift()?.trim();switch(r||(console.error("Usage: kb workset <action> [name] [--files f1,f2] [--description desc]"),console.error("Actions: save, get, list, delete, add, remove"),process.exit(1)),r){case"save":{(!o||s.length===0)&&(console.error("Usage: kb workset save <name> --files f1,f2 [--description desc]"),process.exit(1));const t=M(o,s,{description:e});console.log(`Saved workset: ${t.name}`),a(t);return}case"get":{o||(console.error("Usage: kb workset get <name>"),process.exit(1));const t=f(o);if(!t){console.log(`No workset found: ${o}`);return}a(t);return}case"list":{const t=h();if(t.length===0){console.log("No worksets saved.");return}console.log(`Worksets (${t.length})`),console.log("\u2500".repeat(60));for(const l of t)a(l),console.log("");return}case"delete":{o||(console.error("Usage: kb workset delete <name>"),process.exit(1));const t=d(o);console.log(t?`Deleted workset: ${o}`:`No workset found: ${o}`);return}case"add":{(!o||s.length===0)&&(console.error("Usage: kb workset add <name> --files f1,f2"),process.exit(1));const t=c(o,s);console.log(`Updated workset: ${t.name}`),a(t);return}case"remove":{(!o||s.length===0)&&(console.error("Usage: kb workset remove <name> --files f1,f2"),process.exit(1));const t=C(o,s);if(!t){console.log(`No workset found: ${o}`);return}console.log(`Updated workset: ${t.name}`),a(t);return}default:console.error(`Unknown workset action: ${r}`),console.error("Actions: save, get, list, delete, add, remove"),process.exit(1)}}},{name:"stash",description:"Persist and retrieve named intermediate values",usage:"kb stash <set|get|list|delete|clear> [key] [value]",run:async n=>{const r=n.shift()?.trim(),s=n.shift()?.trim();switch(r||(console.error("Usage: kb stash <set|get|list|delete|clear> [key] [value]"),process.exit(1)),r){case"set":{s||(console.error("Usage: kb stash set <key> <value>"),process.exit(1));const e=n.join(" "),o=e.trim()?"":await j(),l=Q(s,F(e||o));console.log(`Stored stash entry: ${l.key}`),console.log(` Type: ${l.type}`),console.log(` Stored: ${l.storedAt}`);return}case"get":{s||(console.error("Usage: kb stash get <key>"),process.exit(1));const e=W(s);if(!e){console.log(`No stash entry found: ${s}`);return}console.log(JSON.stringify(e,null,2));return}case"list":{const e=A();if(e.length===0){console.log("No stash entries saved.");return}console.log(`Stash entries (${e.length})`),console.log("\u2500".repeat(60));for(const o of e)console.log(`${o.key} (${o.type})`),console.log(` Stored: ${o.storedAt}`);return}case"delete":{s||(console.error("Usage: kb stash delete <key>"),process.exit(1));const e=D(s);console.log(e?`Deleted stash entry: ${s}`:`No stash entry found: ${s}`);return}case"clear":{const e=L();console.log(`Cleared ${e} stash entr${e===1?"y":"ies"}.`);return}default:console.error(`Unknown stash action: ${r}`),console.error("Actions: set, get, list, delete, clear"),process.exit(1)}}},{name:"lane",description:"Manage verified lanes \u2014 isolated file copies for parallel exploration",usage:"kb lane <create|list|status|diff|merge|discard> [name] [--files f1,f2]",run:async n=>{const r=n.shift();if((!r||!["create","list","status","diff","merge","discard"].includes(r))&&(console.error("Usage: kb lane <create|list|status|diff|merge|discard> [name] [--files f1,f2]"),process.exit(1)),r==="list"){const e=k();if(e.length===0){console.log("No active lanes.");return}for(const o of e)console.log(`${o.name} (${o.sourceFiles.length} files, created ${o.createdAt})`);return}const s=n.shift();switch(s||(console.error(`Lane name is required for "${r}".`),process.exit(1)),r){case"create":{const e=i(n,"--files","");e||(console.error("Usage: kb lane create <name> --files file1.ts,file2.ts"),process.exit(1));const o=e.split(",").map(l=>l.trim()),t=u(s,o);console.log(`Lane "${t.name}" created with ${t.sourceFiles.length} files.`);break}case"status":{const e=p(s);console.log(`Lane: ${e.name}`),console.log(`Modified: ${e.modified} | Added: ${e.added} | Deleted: ${e.deleted}`);for(const o of e.entries)console.log(` ${o.status.padEnd(10)} ${o.file}`);break}case"diff":{const e=g(s);console.log(`Lane: ${e.name} \u2014 ${e.modified} modified, ${e.added} added, ${e.deleted} deleted`);for(const o of e.entries)o.diff&&(console.log(`
2
2
  --- ${o.file} (${o.status})`),console.log(o.diff));break}case"merge":{const e=$(s);console.log(`Merged ${e.filesMerged} files from lane "${e.name}".`);for(const o of e.files)console.log(` ${o}`);break}case"discard":{const e=m(s);console.log(e?`Lane "${s}" discarded.`:`Lane "${s}" not found.`);break}}}},{name:"queue",description:"Manage task queues for sequential agent operations",usage:"kb queue <create|push|next|done|fail|get|list|clear|delete> [name] [args]",run:async n=>{const r=n.shift();if((!r||!["create","push","next","done","fail","get","list","clear","delete"].includes(r))&&(console.error("Usage: kb queue <create|push|next|done|fail|get|list|clear|delete> [name] [args]"),process.exit(1)),r==="list"){const e=U();if(e.length===0){console.log("No queues.");return}for(const o of e)console.log(`${o.name} pending:${o.pending} done:${o.done} failed:${o.failed} total:${o.total}`);return}const s=n.shift();switch(s||(console.error(`Queue name is required for "${r}".`),process.exit(1)),r){case"create":{const e=b(s);console.log(`Queue "${e.name}" created.`);break}case"push":{const e=n.join(" ")||"Untitled task",o=S(s,e);console.log(`Pushed "${o.title}" (${o.id}) to queue "${s}".`);break}case"next":{const e=N(s);console.log(e?`Next: ${e.title} (${e.id})`:`No pending items in queue "${s}".`);break}case"done":{const e=n.shift();e||(console.error("Usage: kb queue done <name> <id>"),process.exit(1));const o=y(s,e);console.log(`Marked "${o.title}" as done.`);break}case"fail":{const e=n.shift(),o=n.join(" ")||"Unknown error";e||(console.error("Usage: kb queue fail <name> <id> [error message]"),process.exit(1));const t=q(s,e,o);console.log(`Marked "${t.title}" as failed: ${o}`);break}case"get":{const e=v(s);if(!e){console.log(`Queue "${s}" not found.`);return}console.log(`Queue: ${e.name} (${e.items.length} items)`);for(const o of e.items){const t=o.error?` \u2014 ${o.error}`:"";console.log(` ${o.status.padEnd(12)} ${o.id} ${o.title}${t}`)}break}case"clear":{const e=w(s);console.log(`Cleared ${e} completed/failed items from queue "${s}".`);break}case"delete":{const e=x(s);console.log(e?`Queue "${s}" deleted.`:`Queue "${s}" not found.`);break}}}}];export{G as workspaceCommands};
@@ -1,3 +1,3 @@
1
- import{readFile as p}from"node:fs/promises";import{resolve as u}from"node:path";import{check as m,find as $}from"@kb/tools";function S(e,o,n){const t=e.indexOf(o);if(t===-1||t+1>=e.length)return n;const s=Number.parseInt(e.splice(t,2)[1],10);return Number.isNaN(s)?n:s}function k(e,o,n){const t=e.indexOf(o);return t===-1||t+1>=e.length?n:e.splice(t,2)[1]}function R(e,o){const n=e.indexOf(o);return n===-1?!1:(e.splice(n,1),!0)}async function y(){if(process.stdin.isTTY)return"";const e=[];for await(const o of process.stdin)e.push(o);return Buffer.concat(e).toString("utf-8")}async function v(e){return e?p(u(e),"utf-8"):y()}function B(e){return e.split(",").map(o=>o.trim()).filter(Boolean)}function A(e){const o=JSON.parse(e);if(Array.isArray(o))return{operations:l(o)};if(o&&typeof o=="object"&&"operations"in o){const n=o;return{operations:l(n.operations),concurrency:typeof n.concurrency=="number"?n.concurrency:void 0}}throw new Error("Batch input must be an array of operations or an object with an operations array.")}function l(e){if(!Array.isArray(e))throw new Error("Batch operations must be an array.");return e.map((o,n)=>{if(!o||typeof o!="object")throw new Error(`Batch operation at index ${n} must be an object.`);const t=o;if(typeof t.id!="string"||t.id.length===0)throw new Error(`Batch operation at index ${n} is missing a valid id.`);if(typeof t.type!="string"||t.type.length===0)throw new Error(`Batch operation ${t.id} is missing a valid type.`);if(!t.args||typeof t.args!="object"||Array.isArray(t.args))throw new Error(`Batch operation ${t.id} must include an args object.`);return{id:t.id,type:t.type,args:t.args}})}function E(e){return e.map(o=>{const n=o.heading?` ${o.heading}`:"";return`${o.start}-${o.end}${n}`}).join(", ")}function T(e){switch(e.tool){case"tsc":case"biome":{console.log(`${e.tool} errors: ${e.errors.length}`);for(const o of e.errors){const n=[o.line,o.column].filter(r=>r!==void 0).join(":"),t=n?`${o.file}:${n}`:o.file,s=o.code?` ${o.code}`:"";console.log(`- ${t} [${o.severity}${s}] ${o.message}`)}return}case"vitest":console.log("Vitest summary"),console.log(` Passed: ${e.summary.passed}`),console.log(` Failed: ${e.summary.failed}`),console.log(` Skipped: ${e.summary.skipped}`),e.summary.duration!==void 0&&console.log(` Duration: ${e.summary.duration}ms`);for(const o of e.summary.tests)o.status==="fail"&&(console.log(`- ${o.name}${o.file?` (${o.file})`:""}`),o.error&&console.log(` ${o.error}`));return;case"git-status":console.log(`Branch: ${e.status.branch??"unknown"}`),console.log(`Staged: ${e.status.staged.length}`);for(const o of e.status.staged)console.log(` ${o.status} ${o.file}`);console.log(`Unstaged: ${e.status.unstaged.length}`);for(const o of e.status.unstaged)console.log(` ${o.status} ${o.file}`);console.log(`Untracked: ${e.status.untracked.length}`);for(const o of e.status.untracked)console.log(` ?? ${o}`);return}}function C(e){console.log(`Overall: ${e.passed?"passed":"failed"}`),d("tsc",e.tsc.passed,e.tsc.errors),d("biome",e.biome.passed,e.biome.errors)}function d(e,o,n){console.log(`${e}: ${o?"passed":`${n.length} issue(s)`}`);for(const t of n){const s=[t.line,t.column].filter(c=>c!==void 0).join(":"),r=s?`${t.file}:${s}`:t.file,i=t.code?` ${t.code}`:"";console.log(` - ${r} [${t.severity}${i}] ${t.message}`)}}function O(e){console.log(`Vitest: ${e.passed?"passed":"failed"}`),console.log(` Duration: ${e.durationMs}ms`),console.log(` Passed: ${e.summary.passed}`),console.log(` Failed: ${e.summary.failed}`),console.log(` Skipped: ${e.summary.skipped}`),e.summary.suites!==void 0&&console.log(` Suites: ${e.summary.suites}`);const o=e.summary.tests.filter(n=>n.status==="fail");if(o.length!==0){console.log("Failed tests:");for(const n of o)console.log(` - ${n.name}${n.file?` (${n.file})`:""}`),n.error&&console.log(` ${n.error}`)}}function P(e){console.log(`Branch: ${e.branch}`),console.log(`Staged: ${e.status.staged.length}`);for(const o of e.status.staged)console.log(` - ${o}`);console.log(`Modified: ${e.status.modified.length}`);for(const o of e.status.modified)console.log(` - ${o}`);console.log(`Untracked: ${e.status.untracked.length}`);for(const o of e.status.untracked)console.log(` - ${o}`);if(console.log(""),console.log("Recent commits:"),e.recentCommits.length===0)console.log(" none");else for(const o of e.recentCommits)console.log(` - ${o.hash} ${o.message}`),console.log(` ${o.author} @ ${o.date}`);e.diff&&(console.log(""),console.log("Diff stat:"),console.log(e.diff))}function N(e){if(e.length===0){console.log("No diff files found.");return}for(const o of e){const n=o.oldPath?` (from ${o.oldPath})`:"";console.log(`${o.path}${n}`),console.log(` Status: ${o.status}`),console.log(` Changes: +${o.additions} -${o.deletions}`),console.log(` Hunks: ${o.hunks.length}`);for(const t of o.hunks){const s=t.header?` ${t.header}`:"";console.log(` @@ -${t.oldStart},${t.oldLines} +${t.newStart},${t.newLines} @@${s}`)}}}function D(e){if(console.log(`Start: ${e.start}`),console.log(`Direction: ${e.direction}`),console.log(`Depth reached: ${e.depth}`),console.log(`Nodes: ${e.nodes.length}`),e.nodes.length===0){console.log("No trace nodes found.");return}for(const o of e.nodes)console.log(` - [${o.relationship}] ${o.path}:${o.line} ${o.symbol}`)}function F(e){if(console.log(`Query: ${e.query}`),console.log(`Examples: ${e.examples.length} shown (${e.totalFound} total)`),e.examples.length===0){console.log("No matching examples found.");return}for(const o of e.examples){console.log(""),console.log(`${o.path}:${o.startLine}-${o.endLine}`),console.log(` Context: ${o.context}`),console.log(` Relevance: ${(o.relevance*100).toFixed(1)}%`);for(const n of o.content.split(`
2
- `))console.log(` ${n}`)}}function I(e){console.log(e.id),console.log(` Command: ${e.command}${e.args.length>0?` ${e.args.join(" ")}`:""}`),console.log(` PID: ${e.pid??"unknown"}`),console.log(` Status: ${e.status}`),console.log(` Started: ${e.startedAt}`),e.exitCode!==void 0&&console.log(` Exit code: ${e.exitCode}`),console.log(` Logs: ${e.logs.length}`)}function q(e){if(console.log(`Exports scanned: ${e.totalExports}`),console.log(`Potentially dead: ${e.totalDead}`),e.deadSymbols.length===0){console.log("No dead symbols found.");return}for(const o of e.deadSymbols)console.log(` - ${o.path}:${o.line} ${o.kind} ${o.name}`)}function j(e){console.log(e.path),console.log(` Language: ${e.language}`),console.log(` Lines: ${e.lines}`),console.log(` Estimated tokens: ~${e.estimatedTokens}`),console.log(""),a("Imports",e.imports),a("Exports",e.exports),a("Functions",e.functions.map(o=>`${o.name} @ line ${o.line}${o.exported?" [exported]":""}`)),a("Classes",e.classes.map(o=>`${o.name} @ line ${o.line}${o.exported?" [exported]":""}`)),a("Interfaces",e.interfaces.map(o=>`${o.name} @ line ${o.line}`)),a("Types",e.types.map(o=>`${o.name} @ line ${o.line}`))}function _(e){if(console.log(`Symbol: ${e.name}`),e.definedIn?console.log(`Defined in: ${e.definedIn.path}:${e.definedIn.line} (${e.definedIn.kind})`):console.log("Defined in: not found"),console.log(""),console.log("Imported by:"),e.importedBy.length===0)console.log(" none");else for(const o of e.importedBy)console.log(` - ${o.path}:${o.line} ${o.importStatement}`);if(console.log(""),console.log("Referenced in:"),e.referencedIn.length===0)console.log(" none");else for(const o of e.referencedIn)console.log(` - ${o.path}:${o.line} ${o.context}`)}function L(e){console.log(e.name),console.log(` Files: ${e.files.length}`),console.log(` Updated: ${e.updated}`),e.description&&console.log(` Description: ${e.description}`);for(const o of e.files)console.log(` - ${o}`)}function M(e){if(console.log(e.id),console.log(` Label: ${e.label}`),console.log(` Created: ${e.createdAt}`),e.notes&&console.log(` Notes: ${e.notes}`),e.files?.length){console.log(` Files: ${e.files.length}`);for(const o of e.files)console.log(` - ${o}`)}console.log(" Data:");for(const o of JSON.stringify(e.data,null,2).split(`
3
- `))console.log(` ${o}`)}function a(e,o){if(console.log(`${e}:`),o.length===0){console.log(" none"),console.log("");return}for(const n of o)console.log(` - ${n}`);console.log("")}function J(e){const o=e.trim();if(!o)return"";try{return JSON.parse(o)}catch{return e}}function U(e){const o=e.trim();if(!o)return{};const n=JSON.parse(o);if(!n||typeof n!="object"||Array.isArray(n))throw new Error("Checkpoint data must be a JSON object.");return n}function h(e,o,n=60){const t=new Map;for(let s=0;s<e.length;s++){const r=e[s];t.set(r.record.id,{record:r.record,score:1/(n+s+1)})}for(let s=0;s<o.length;s++){const r=o[s],i=t.get(r.record.id);i?i.score+=1/(n+s+1):t.set(r.record.id,{record:r.record,score:1/(n+s+1)})}return[...t.values()].sort((s,r)=>r.score-s.score)}async function K(e,o){switch(e.type){case"search":{if(!o)throw new Error("search operation requires knowledge base context");const n=typeof e.args.query=="string"?e.args.query.trim():"";if(!n)throw new Error("search operation requires a query");const t=typeof e.args.limit=="number"?e.args.limit:5,s=e.args.search_mode==="semantic"||e.args.search_mode==="keyword"?e.args.search_mode:"hybrid",r=typeof e.args.content_type=="string"?e.args.content_type:void 0,i=typeof e.args.min_score=="number"?e.args.min_score:.25;if(s==="keyword")return(await o.store.ftsSearch(n,{limit:t,contentType:r,minScore:i})).slice(0,t);const c=await o.embedder.embedQuery(n);if(s==="semantic")return o.store.search(c,{limit:t,contentType:r,minScore:i});const[f,g]=await Promise.all([o.store.search(c,{limit:t*2,contentType:r,minScore:i}),o.store.ftsSearch(n,{limit:t*2,contentType:r,minScore:i}).catch(()=>[])]);return h(f,g).slice(0,t)}case"find":{if(!o)throw new Error("find operation requires knowledge base context");const n=typeof e.args.query=="string"?e.args.query:void 0,t=typeof e.args.glob=="string"?e.args.glob:void 0,s=typeof e.args.pattern=="string"?e.args.pattern:void 0,r=typeof e.args.limit=="number"?e.args.limit:10,i=typeof e.args.content_type=="string"?e.args.content_type:void 0,c=typeof e.args.cwd=="string"?e.args.cwd:void 0;if(!n&&!t&&!s)throw new Error("find operation requires query, glob, or pattern");return $(o.embedder,o.store,{query:n,glob:t,pattern:s,limit:r,contentType:i,cwd:c})}case"check":{const n=Array.isArray(e.args.files)?e.args.files.filter(i=>typeof i=="string"):void 0,t=typeof e.args.cwd=="string"?e.args.cwd:void 0,s=e.args.skip_types===!0,r=e.args.skip_lint===!0;return m({files:n,cwd:t,skipTypes:s,skipLint:r})}default:throw new Error(`Unsupported batch operation type: ${e.type}`)}}export{K as executeCliBatchOperation,R as extractBoolFlag,S as extractNumFlag,k as extractStrFlag,E as formatFocusRanges,A as parseBatchPayload,J as parseMaybeJsonString,U as parseRecordString,C as printCheckResult,d as printCheckSection,M as printCheckpoint,q as printDeadSymbolsResult,N as printDiffFiles,F as printExamplesResult,j as printFileSummary,P as printGitContext,I as printManagedProcess,T as printParsedOutput,a as printSection,_ as printSymbolInfo,O as printTestRunResult,D as printTraceResult,L as printWorkset,v as readInput,y as readStdin,h as rrf,B as splitCsv,l as validateBatchOperations};
1
+ import{readFile as p}from"node:fs/promises";import{resolve as u}from"node:path";import{check as m,find as $}from"../../tools/dist/index.js";function S(e,o,n){const t=e.indexOf(o);if(t===-1||t+1>=e.length)return n;const s=Number.parseInt(e.splice(t,2)[1],10);return Number.isNaN(s)?n:s}function k(e,o,n){const t=e.indexOf(o);return t===-1||t+1>=e.length?n:e.splice(t,2)[1]}function R(e,o){const n=e.indexOf(o);return n===-1?!1:(e.splice(n,1),!0)}async function y(){if(process.stdin.isTTY)return"";const e=[];for await(const o of process.stdin)e.push(o);return Buffer.concat(e).toString("utf-8")}async function v(e){return e?p(u(e),"utf-8"):y()}function B(e){return e.split(",").map(o=>o.trim()).filter(Boolean)}function A(e){const o=JSON.parse(e);if(Array.isArray(o))return{operations:l(o)};if(o&&typeof o=="object"&&"operations"in o){const n=o;return{operations:l(n.operations),concurrency:typeof n.concurrency=="number"?n.concurrency:void 0}}throw new Error("Batch input must be an array of operations or an object with an operations array.")}function l(e){if(!Array.isArray(e))throw new Error("Batch operations must be an array.");return e.map((o,n)=>{if(!o||typeof o!="object")throw new Error(`Batch operation at index ${n} must be an object.`);const t=o;if(typeof t.id!="string"||t.id.length===0)throw new Error(`Batch operation at index ${n} is missing a valid id.`);if(typeof t.type!="string"||t.type.length===0)throw new Error(`Batch operation ${t.id} is missing a valid type.`);if(!t.args||typeof t.args!="object"||Array.isArray(t.args))throw new Error(`Batch operation ${t.id} must include an args object.`);return{id:t.id,type:t.type,args:t.args}})}function E(e){return e.map(o=>{const n=o.heading?` ${o.heading}`:"";return`${o.start}-${o.end}${n}`}).join(", ")}function T(e){switch(e.tool){case"tsc":case"biome":{console.log(`${e.tool} errors: ${e.errors.length}`);for(const o of e.errors){const n=[o.line,o.column].filter(r=>r!==void 0).join(":"),t=n?`${o.file}:${n}`:o.file,s=o.code?` ${o.code}`:"";console.log(`- ${t} [${o.severity}${s}] ${o.message}`)}return}case"vitest":console.log("Vitest summary"),console.log(` Passed: ${e.summary.passed}`),console.log(` Failed: ${e.summary.failed}`),console.log(` Skipped: ${e.summary.skipped}`),e.summary.duration!==void 0&&console.log(` Duration: ${e.summary.duration}ms`);for(const o of e.summary.tests)o.status==="fail"&&(console.log(`- ${o.name}${o.file?` (${o.file})`:""}`),o.error&&console.log(` ${o.error}`));return;case"git-status":console.log(`Branch: ${e.status.branch??"unknown"}`),console.log(`Staged: ${e.status.staged.length}`);for(const o of e.status.staged)console.log(` ${o.status} ${o.file}`);console.log(`Unstaged: ${e.status.unstaged.length}`);for(const o of e.status.unstaged)console.log(` ${o.status} ${o.file}`);console.log(`Untracked: ${e.status.untracked.length}`);for(const o of e.status.untracked)console.log(` ?? ${o}`);return}}function C(e){console.log(`Overall: ${e.passed?"passed":"failed"}`),d("tsc",e.tsc.passed,e.tsc.errors),d("biome",e.biome.passed,e.biome.errors)}function d(e,o,n){console.log(`${e}: ${o?"passed":`${n.length} issue(s)`}`);for(const t of n){const s=[t.line,t.column].filter(c=>c!==void 0).join(":"),r=s?`${t.file}:${s}`:t.file,i=t.code?` ${t.code}`:"";console.log(` - ${r} [${t.severity}${i}] ${t.message}`)}}function O(e){console.log(`Vitest: ${e.passed?"passed":"failed"}`),console.log(` Duration: ${e.durationMs}ms`),console.log(` Passed: ${e.summary.passed}`),console.log(` Failed: ${e.summary.failed}`),console.log(` Skipped: ${e.summary.skipped}`),e.summary.suites!==void 0&&console.log(` Suites: ${e.summary.suites}`);const o=e.summary.tests.filter(n=>n.status==="fail");if(o.length!==0){console.log("Failed tests:");for(const n of o)console.log(` - ${n.name}${n.file?` (${n.file})`:""}`),n.error&&console.log(` ${n.error}`)}}function P(e){console.log(`Branch: ${e.branch}`),console.log(`Staged: ${e.status.staged.length}`);for(const o of e.status.staged)console.log(` - ${o}`);console.log(`Modified: ${e.status.modified.length}`);for(const o of e.status.modified)console.log(` - ${o}`);console.log(`Untracked: ${e.status.untracked.length}`);for(const o of e.status.untracked)console.log(` - ${o}`);if(console.log(""),console.log("Recent commits:"),e.recentCommits.length===0)console.log(" none");else for(const o of e.recentCommits)console.log(` - ${o.hash} ${o.message}`),console.log(` ${o.author} @ ${o.date}`);e.diff&&(console.log(""),console.log("Diff stat:"),console.log(e.diff))}function N(e){if(e.length===0){console.log("No diff files found.");return}for(const o of e){const n=o.oldPath?` (from ${o.oldPath})`:"";console.log(`${o.path}${n}`),console.log(` Status: ${o.status}`),console.log(` Changes: +${o.additions} -${o.deletions}`),console.log(` Hunks: ${o.hunks.length}`);for(const t of o.hunks){const s=t.header?` ${t.header}`:"";console.log(` @@ -${t.oldStart},${t.oldLines} +${t.newStart},${t.newLines} @@${s}`)}}}function D(e){if(console.log(`Start: ${e.start}`),console.log(`Direction: ${e.direction}`),console.log(`Depth reached: ${e.depth}`),console.log(`Nodes: ${e.nodes.length}`),e.nodes.length===0){console.log("No trace nodes found.");return}for(const o of e.nodes)console.log(` - [${o.relationship}] ${o.path}:${o.line} ${o.symbol}`)}function F(e){if(console.log(`Query: ${e.query}`),console.log(`Examples: ${e.examples.length} shown (${e.totalFound} total)`),e.examples.length===0){console.log("No matching examples found.");return}for(const o of e.examples){console.log(""),console.log(`${o.path}:${o.startLine}-${o.endLine}`),console.log(` Context: ${o.context}`),console.log(` Relevance: ${(o.relevance*100).toFixed(1)}%`);for(const n of o.content.split(`
2
+ `))console.log(` ${n}`)}}function I(e){console.log(e.id),console.log(` Command: ${e.command}${e.args.length>0?` ${e.args.join(" ")}`:""}`),console.log(` PID: ${e.pid??"unknown"}`),console.log(` Status: ${e.status}`),console.log(` Started: ${e.startedAt}`),e.exitCode!==void 0&&console.log(` Exit code: ${e.exitCode}`),console.log(` Logs: ${e.logs.length}`)}function j(e){if(console.log(`Exports scanned: ${e.totalExports}`),console.log(`Potentially dead: ${e.totalDead}`),e.deadSymbols.length===0){console.log("No dead symbols found.");return}for(const o of e.deadSymbols)console.log(` - ${o.path}:${o.line} ${o.kind} ${o.name}`)}function q(e){console.log(e.path),console.log(` Language: ${e.language}`),console.log(` Lines: ${e.lines}`),console.log(` Estimated tokens: ~${e.estimatedTokens}`),console.log(""),a("Imports",e.imports),a("Exports",e.exports),a("Functions",e.functions.map(o=>`${o.name} @ line ${o.line}${o.exported?" [exported]":""}`)),a("Classes",e.classes.map(o=>`${o.name} @ line ${o.line}${o.exported?" [exported]":""}`)),a("Interfaces",e.interfaces.map(o=>`${o.name} @ line ${o.line}`)),a("Types",e.types.map(o=>`${o.name} @ line ${o.line}`))}function _(e){if(console.log(`Symbol: ${e.name}`),e.definedIn?console.log(`Defined in: ${e.definedIn.path}:${e.definedIn.line} (${e.definedIn.kind})`):console.log("Defined in: not found"),console.log(""),console.log("Imported by:"),e.importedBy.length===0)console.log(" none");else for(const o of e.importedBy)console.log(` - ${o.path}:${o.line} ${o.importStatement}`);if(console.log(""),console.log("Referenced in:"),e.referencedIn.length===0)console.log(" none");else for(const o of e.referencedIn)console.log(` - ${o.path}:${o.line} ${o.context}`)}function L(e){console.log(e.name),console.log(` Files: ${e.files.length}`),console.log(` Updated: ${e.updated}`),e.description&&console.log(` Description: ${e.description}`);for(const o of e.files)console.log(` - ${o}`)}function M(e){if(console.log(e.id),console.log(` Label: ${e.label}`),console.log(` Created: ${e.createdAt}`),e.notes&&console.log(` Notes: ${e.notes}`),e.files?.length){console.log(` Files: ${e.files.length}`);for(const o of e.files)console.log(` - ${o}`)}console.log(" Data:");for(const o of JSON.stringify(e.data,null,2).split(`
3
+ `))console.log(` ${o}`)}function a(e,o){if(console.log(`${e}:`),o.length===0){console.log(" none"),console.log("");return}for(const n of o)console.log(` - ${n}`);console.log("")}function J(e){const o=e.trim();if(!o)return"";try{return JSON.parse(o)}catch{return e}}function U(e){const o=e.trim();if(!o)return{};const n=JSON.parse(o);if(!n||typeof n!="object"||Array.isArray(n))throw new Error("Checkpoint data must be a JSON object.");return n}function h(e,o,n=60){const t=new Map;for(let s=0;s<e.length;s++){const r=e[s];t.set(r.record.id,{record:r.record,score:1/(n+s+1)})}for(let s=0;s<o.length;s++){const r=o[s],i=t.get(r.record.id);i?i.score+=1/(n+s+1):t.set(r.record.id,{record:r.record,score:1/(n+s+1)})}return[...t.values()].sort((s,r)=>r.score-s.score)}async function K(e,o){switch(e.type){case"search":{if(!o)throw new Error("search operation requires knowledge base context");const n=typeof e.args.query=="string"?e.args.query.trim():"";if(!n)throw new Error("search operation requires a query");const t=typeof e.args.limit=="number"?e.args.limit:5,s=e.args.search_mode==="semantic"||e.args.search_mode==="keyword"?e.args.search_mode:"hybrid",r=typeof e.args.content_type=="string"?e.args.content_type:void 0,i=typeof e.args.min_score=="number"?e.args.min_score:.25;if(s==="keyword")return(await o.store.ftsSearch(n,{limit:t,contentType:r,minScore:i})).slice(0,t);const c=await o.embedder.embedQuery(n);if(s==="semantic")return o.store.search(c,{limit:t,contentType:r,minScore:i});const[f,g]=await Promise.all([o.store.search(c,{limit:t*2,contentType:r,minScore:i}),o.store.ftsSearch(n,{limit:t*2,contentType:r,minScore:i}).catch(()=>[])]);return h(f,g).slice(0,t)}case"find":{if(!o)throw new Error("find operation requires knowledge base context");const n=typeof e.args.query=="string"?e.args.query:void 0,t=typeof e.args.glob=="string"?e.args.glob:void 0,s=typeof e.args.pattern=="string"?e.args.pattern:void 0,r=typeof e.args.limit=="number"?e.args.limit:10,i=typeof e.args.content_type=="string"?e.args.content_type:void 0,c=typeof e.args.cwd=="string"?e.args.cwd:void 0;if(!n&&!t&&!s)throw new Error("find operation requires query, glob, or pattern");return $(o.embedder,o.store,{query:n,glob:t,pattern:s,limit:r,contentType:i,cwd:c})}case"check":{const n=Array.isArray(e.args.files)?e.args.files.filter(i=>typeof i=="string"):void 0,t=typeof e.args.cwd=="string"?e.args.cwd:void 0,s=e.args.skip_types===!0,r=e.args.skip_lint===!0;return m({files:n,cwd:t,skipTypes:s,skipLint:r})}default:throw new Error(`Unsupported batch operation type: ${e.type}`)}}export{K as executeCliBatchOperation,R as extractBoolFlag,S as extractNumFlag,k as extractStrFlag,E as formatFocusRanges,A as parseBatchPayload,J as parseMaybeJsonString,U as parseRecordString,C as printCheckResult,d as printCheckSection,M as printCheckpoint,j as printDeadSymbolsResult,N as printDiffFiles,F as printExamplesResult,q as printFileSummary,P as printGitContext,I as printManagedProcess,T as printParsedOutput,a as printSection,_ as printSymbolInfo,O as printTestRunResult,D as printTraceResult,L as printWorkset,v as readInput,y as readStdin,h as rrf,B as splitCsv,l as validateBatchOperations};
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @anvpx/kb CLI — command-line interface for the knowledge base toolkit.
2
+ * @vpxa/kb CLI — command-line interface for the knowledge base toolkit.
3
3
  *
4
4
  * Thin adapter: arg parsing + output formatting.
5
5
  * All core logic lives in @kb/core, @kb/store, @kb/embeddings, etc.
@@ -1,3 +1,3 @@
1
- import{analyzeCommands as a}from"./commands/analyze.js";import{contextCommands as i}from"./commands/context-cmds.js";import{environmentCommands as c}from"./commands/environment.js";import{executionCommands as l}from"./commands/execution.js";import{graphCommands as p}from"./commands/graph.js";import{knowledgeCommands as d}from"./commands/knowledge.js";import{searchCommands as f}from"./commands/search.js";import{systemCommands as g}from"./commands/system.js";import{workspaceCommands as h}from"./commands/workspace.js";import{getCtx as C}from"./context.js";const e=[...f,...d,...a,...p,...g,...l,...i,...h,...c];e.push({name:"help",description:"Show available commands",run:async()=>{r()}});async function U(s){const o=[...s],n=o.shift();if(!n||n==="--help"||n==="-h"){r();return}if(n==="--version"||n==="-v"){console.log("0.1.0");return}const t=e.find(m=>m.name===n);t||(console.error(`Unknown command: ${n}`),r(),process.exit(1));try{await t.run(o)}finally{const m=C();m&&await m.store.close()}}function r(){console.log(`@anvpx/kb \u2014 Local-first AI developer toolkit
1
+ import{analyzeCommands as a}from"./commands/analyze.js";import{contextCommands as i}from"./commands/context-cmds.js";import{environmentCommands as c}from"./commands/environment.js";import{executionCommands as l}from"./commands/execution.js";import{graphCommands as p}from"./commands/graph.js";import{knowledgeCommands as d}from"./commands/knowledge.js";import{searchCommands as f}from"./commands/search.js";import{systemCommands as g}from"./commands/system.js";import{workspaceCommands as h}from"./commands/workspace.js";import{getCtx as C}from"./context.js";const e=[...f,...d,...a,...p,...g,...l,...i,...h,...c];e.push({name:"help",description:"Show available commands",run:async()=>{r()}});async function U(s){const o=[...s],n=o.shift();if(!n||n==="--help"||n==="-h"){r();return}if(n==="--version"||n==="-v"){console.log("0.1.0");return}const t=e.find(m=>m.name===n);t||(console.error(`Unknown command: ${n}`),r(),process.exit(1));try{await t.run(o)}finally{const m=C();m&&await m.store.close()}}function r(){console.log(`@vpxa/kb \u2014 Local-first AI developer toolkit
2
2
  `),console.log(`Usage: kb <command> [options]
3
3
  `),console.log("Commands:");const s=Math.max(...e.map(o=>o.name.length));for(const o of e)console.log(` ${o.name.padEnd(s+2)}${o.description}`);console.log(""),console.log("Options:"),console.log(" --help, -h Show this help"),console.log(" --version, -v Show version")}export{U as run};
@@ -1 +1 @@
1
- import{existsSync as d,readFileSync as g}from"node:fs";import{dirname as p,resolve as o}from"node:path";import{initializeTreeSitter as m}from"@kb/chunker";import{OnnxEmbedder as l}from"@kb/embeddings";import{IncrementalIndexer as u}from"@kb/indexer";import{createStore as f,SqliteGraphStore as h}from"@kb/store";function y(){const t=process.env.KB_CONFIG_PATH??(d(o(process.cwd(),"kb.config.json"))?o(process.cwd(),"kb.config.json"):null);t||(console.error("No kb.config.json found in current directory."),console.error("Run `kb init` to create one, or set KB_CONFIG_PATH."),process.exit(1));const r=g(t,"utf-8"),e=JSON.parse(r),n=p(t);return e.sources=e.sources.map(s=>({...s,path:o(n,s.path)})),e.store.path=o(n,e.store.path),e.curated=e.curated??{path:"curated"},e.curated.path=o(n,e.curated.path),e}async function x(){const t=y(),r=new l({model:t.embedding.model,dimensions:t.embedding.dimensions});await r.initialize();const e=await f({backend:t.store.backend,path:t.store.path});await e.initialize();const n=new u(r,e),{CuratedKnowledgeManager:s}=await import("@kb/server/curated-manager"),c=new s(t.curated.path,e,r);let i;try{const a=new h({path:t.store.path});await a.initialize(),i=a,n.setGraphStore(i)}catch(a){console.error(`[kb] Graph store init failed (non-fatal): ${a.message}`),i={initialize:async()=>{},upsertNode:async()=>{},upsertEdge:async()=>{},upsertNodes:async()=>{},upsertEdges:async()=>{},getNode:async()=>null,getNeighbors:async()=>({nodes:[],edges:[]}),traverse:async()=>({nodes:[],edges:[]}),findNodes:async()=>[],findEdges:async()=>[],deleteNode:async()=>{},deleteBySourcePath:async()=>0,clear:async()=>{},getStats:async()=>({nodeCount:0,edgeCount:0,nodeTypes:{},edgeTypes:{}}),close:async()=>{}}}return await m().catch(()=>{}),{config:t,embedder:r,store:e,graphStore:i,indexer:n,curated:c}}export{x as initKB};
1
+ import{existsSync as d,readFileSync as g}from"node:fs";import{dirname as p,resolve as o}from"node:path";import{initializeTreeSitter as m}from"../../chunker/dist/index.js";import{OnnxEmbedder as l}from"../../embeddings/dist/index.js";import{IncrementalIndexer as u}from"../../indexer/dist/index.js";import{createStore as f,SqliteGraphStore as h}from"../../store/dist/index.js";function y(){const t=process.env.KB_CONFIG_PATH??(d(o(process.cwd(),"kb.config.json"))?o(process.cwd(),"kb.config.json"):null);t||(console.error("No kb.config.json found in current directory."),console.error("Run `kb init` to create one, or set KB_CONFIG_PATH."),process.exit(1));const r=g(t,"utf-8"),e=JSON.parse(r),n=p(t);return e.sources=e.sources.map(s=>({...s,path:o(n,s.path)})),e.store.path=o(n,e.store.path),e.curated=e.curated??{path:"curated"},e.curated.path=o(n,e.curated.path),e}async function x(){const t=y(),r=new l({model:t.embedding.model,dimensions:t.embedding.dimensions});await r.initialize();const e=await f({backend:t.store.backend,path:t.store.path});await e.initialize();const n=new u(r,e),{CuratedKnowledgeManager:s}=await import("../../server/dist/curated-manager.js"),c=new s(t.curated.path,e,r);let i;try{const a=new h({path:t.store.path});await a.initialize(),i=a,n.setGraphStore(i)}catch(a){console.error(`[kb] Graph store init failed (non-fatal): ${a.message}`),i={initialize:async()=>{},upsertNode:async()=>{},upsertEdge:async()=>{},upsertNodes:async()=>{},upsertEdges:async()=>{},getNode:async()=>null,getNeighbors:async()=>({nodes:[],edges:[]}),traverse:async()=>({nodes:[],edges:[]}),findNodes:async()=>[],findEdges:async()=>[],deleteNode:async()=>{},deleteBySourcePath:async()=>0,clear:async()=>{},getStats:async()=>({nodeCount:0,edgeCount:0,nodeTypes:{},edgeTypes:{}}),close:async()=>{}}}return await m().catch(()=>{}),{config:t,embedder:r,store:e,graphStore:i,indexer:n,curated:c}}export{x as initKB};
@@ -1 +1 @@
1
- import{pipeline as m}from"@huggingface/transformers";import{EMBEDDING_DEFAULTS as l}from"@kb/core";class h{pipe=null;dimensions;modelId;queryPrefix;constructor(e){this.modelId=e?.model??l.model,this.dimensions=e?.dimensions??l.dimensions,this.queryPrefix=e?.queryPrefix??this.detectQueryPrefix(this.modelId)}detectQueryPrefix(e){const i=e.toLowerCase();return i.includes("bge")||i.includes("mxbai-embed")?"Represent this sentence for searching relevant passages: ":i.includes("/e5-")||i.includes("multilingual-e5")?"query: ":""}async initialize(){if(!this.pipe)try{this.pipe=await m("feature-extraction",this.modelId,{dtype:"fp32"})}catch(e){throw new Error(`Failed to initialize embedding model "${this.modelId}": ${e.message}`)}}async shutdown(){this.pipe=null}async embed(e){this.pipe||await this.initialize();const i=await this.pipe?.(e,{pooling:"mean",normalize:!0});if(!i)throw new Error("Embedding pipeline returned no output");return new Float32Array(i.data)}async embedQuery(e){return this.embed(this.queryPrefix+e)}async embedBatch(e){if(e.length===0)return[];this.pipe||await this.initialize();const i=[],a=32;for(let r=0;r<e.length;r+=a){const t=e.slice(r,r+a),n=await this.pipe?.(t,{pooling:"mean",normalize:!0});if(!n)throw new Error("Embedding pipeline returned no output");if(t.length===1)i.push(new Float32Array(n.data));else for(let s=0;s<t.length;s++){const o=s*this.dimensions,d=n.data.slice(o,o+this.dimensions);i.push(new Float32Array(d))}}return i}}export{h as OnnxEmbedder};
1
+ import{pipeline as m}from"@huggingface/transformers";import{EMBEDDING_DEFAULTS as l}from"../../core/dist/index.js";class h{pipe=null;dimensions;modelId;queryPrefix;constructor(e){this.modelId=e?.model??l.model,this.dimensions=e?.dimensions??l.dimensions,this.queryPrefix=e?.queryPrefix??this.detectQueryPrefix(this.modelId)}detectQueryPrefix(e){const i=e.toLowerCase();return i.includes("bge")||i.includes("mxbai-embed")?"Represent this sentence for searching relevant passages: ":i.includes("/e5-")||i.includes("multilingual-e5")?"query: ":""}async initialize(){if(!this.pipe)try{this.pipe=await m("feature-extraction",this.modelId,{dtype:"fp32"})}catch(e){throw new Error(`Failed to initialize embedding model "${this.modelId}": ${e.message}`)}}async shutdown(){this.pipe=null}async embed(e){this.pipe||await this.initialize();const i=await this.pipe?.(e,{pooling:"mean",normalize:!0});if(!i)throw new Error("Embedding pipeline returned no output");return new Float32Array(i.data)}async embedQuery(e){return this.embed(this.queryPrefix+e)}async embedBatch(e){if(e.length===0)return[];this.pipe||await this.initialize();const i=[],a=32;for(let r=0;r<e.length;r+=a){const t=e.slice(r,r+a),n=await this.pipe?.(t,{pooling:"mean",normalize:!0});if(!n)throw new Error("Embedding pipeline returned no output");if(t.length===1)i.push(new Float32Array(n.data));else for(let s=0;s<t.length;s++){const o=s*this.dimensions,d=n.data.slice(o,o+this.dimensions);i.push(new Float32Array(d))}}return i}}export{h as OnnxEmbedder};
@@ -1 +1 @@
1
- import{lstat as u,readdir as w,readFile as d,stat as g}from"node:fs/promises";import{extname as h,join as x,relative as S}from"node:path";import{FILE_LIMITS as y}from"@kb/core";import{minimatch as E}from"minimatch";class p{static BINARY_EXTENSIONS=new Set([".node",".so",".dylib",".dll",".wasm",".bin",".exe",".png",".jpg",".jpeg",".gif",".bmp",".ico",".webp",".svg",".mp3",".mp4",".wav",".avi",".mov",".flac",".zip",".gz",".tar",".bz2",".7z",".rar",".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".ttf",".otf",".woff",".woff2",".eot",".pyc",".class",".o",".obj",".a",".lib"]);async crawl(e){const i=[],n=new Set;return await this.walkDir(e.rootDir,e.rootDir,e.excludePatterns,i,n),i}async walkDir(e,i,n,s,o){let c;try{c=await w(e,{withFileTypes:!0})}catch(r){const t=r.code;(t==="EACCES"||t==="EPERM")&&console.error(`[KB] Permission denied, skipping directory: ${e}`);return}for(const r of c){const t=x(e,r.name),l=S(i,t).replace(/\\/g,"/");if(!this.isExcluded(l,n)){if(r.isDirectory()){if(r.name.startsWith("."))continue;try{if((await u(t)).isSymbolicLink())continue}catch{continue}const a=t;if(o.has(a))continue;o.add(a),await this.walkDir(t,i,n,s,o)}else if(r.isFile()){const a=h(r.name).toLowerCase();if(p.BINARY_EXTENSIONS.has(a))continue;try{if((await g(t)).size>y.maxFileSizeBytes)continue;const f=await d(t,"utf-8");if(f.includes("\0"))continue;s.push({relativePath:l,absolutePath:t,content:f,extension:a})}catch{}}}}}isExcluded(e,i){return i.some(n=>E(e,n,{dot:!0}))}}export{p as FilesystemCrawler};
1
+ import{lstat as u,readdir as w,readFile as d,stat as g}from"node:fs/promises";import{extname as h,join as x,relative as S}from"node:path";import{FILE_LIMITS as y}from"../../core/dist/index.js";import{minimatch as E}from"minimatch";class p{static BINARY_EXTENSIONS=new Set([".node",".so",".dylib",".dll",".wasm",".bin",".exe",".png",".jpg",".jpeg",".gif",".bmp",".ico",".webp",".svg",".mp3",".mp4",".wav",".avi",".mov",".flac",".zip",".gz",".tar",".bz2",".7z",".rar",".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".ttf",".otf",".woff",".woff2",".eot",".pyc",".class",".o",".obj",".a",".lib"]);async crawl(e){const i=[],n=new Set;return await this.walkDir(e.rootDir,e.rootDir,e.excludePatterns,i,n),i}async walkDir(e,i,n,s,o){let c;try{c=await w(e,{withFileTypes:!0})}catch(r){const t=r.code;(t==="EACCES"||t==="EPERM")&&console.error(`[KB] Permission denied, skipping directory: ${e}`);return}for(const r of c){const t=x(e,r.name),l=S(i,t).replace(/\\/g,"/");if(!this.isExcluded(l,n)){if(r.isDirectory()){if(r.name.startsWith("."))continue;try{if((await u(t)).isSymbolicLink())continue}catch{continue}const a=t;if(o.has(a))continue;o.add(a),await this.walkDir(t,i,n,s,o)}else if(r.isFile()){const a=h(r.name).toLowerCase();if(p.BINARY_EXTENSIONS.has(a))continue;try{if((await g(t)).size>y.maxFileSizeBytes)continue;const f=await d(t,"utf-8");if(f.includes("\0"))continue;s.push({relativePath:l,absolutePath:t,content:f,extension:a})}catch{}}}}}isExcluded(e,i){return i.some(n=>E(e,n,{dot:!0}))}}export{p as FilesystemCrawler};
@@ -1 +1 @@
1
- import{createHash as y}from"node:crypto";import{dirname as k,extname as I,join as j}from"node:path";const S=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs"]),$=[{pattern:/^export\s+(?:async\s+)?function\s+(\w+)/gm,kind:"function",exported:!0},{pattern:/^export\s+(?:default\s+)?class\s+(\w+)/gm,kind:"class",exported:!0},{pattern:/^export\s+interface\s+(\w+)/gm,kind:"interface",exported:!0},{pattern:/^export\s+type\s+(\w+)/gm,kind:"type",exported:!0},{pattern:/^export\s+(?:const|let)\s+(\w+)/gm,kind:"const",exported:!0},{pattern:/^export\s+enum\s+(\w+)/gm,kind:"enum",exported:!0},{pattern:/^(?:async\s+)?function\s+(\w+)/gm,kind:"function",exported:!1},{pattern:/^class\s+(\w+)/gm,kind:"class",exported:!1},{pattern:/^interface\s+(\w+)/gm,kind:"interface",exported:!1},{pattern:/^type\s+(\w+)/gm,kind:"type",exported:!1},{pattern:/^enum\s+(\w+)/gm,kind:"enum",exported:!1}],G=[/import\s+(?:(?:type\s+)?(?:(?:\{[^}]*\}|[\w*]+)\s+from\s+)?)['"]([^'"]+)['"]/g,/import\(\s*['"]([^'"]+)['"]\s*\)/g,/require\(\s*['"]([^'"]+)['"]\s*\)/g];function x(t,e,s){return y("sha256").update(`${t}:${e}:${s}`).digest("hex").slice(0,16)}function E(t,e,s){return y("sha256").update(`${t}-${s}-${e}`).digest("hex").slice(0,16)}function R(t,e){const s=k(e);return j(s,t).replace(/\\/g,"/").replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,"")}function N(t){return t.replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,"")}function b(t,e){const s=I(e).toLowerCase();if(!S.has(s))return{nodes:[],edges:[]};const c=[],g=[],l=new Date().toISOString(),u=new Set,f=N(e),o=x("module",f,f);c.push({id:o,type:"module",name:e,properties:{ext:s},sourcePath:e,createdAt:l});for(const{pattern:p,kind:i,exported:d}of $){const n=new RegExp(p.source,p.flags);let a;for(;(a=n.exec(t))!==null;){const r=a[1],h=`${i}:${r}`;if(u.has(h))continue;u.add(h);const m=x(i,r,e);c.push({id:m,type:i,name:r,properties:{exported:d},sourcePath:e,createdAt:l}),g.push({id:E(o,m,"defines"),fromId:o,toId:m,type:"defines",weight:d?1:.5})}}const w=new Set;for(const p of G){const i=new RegExp(p.source,p.flags);let d;for(;(d=i.exec(t))!==null;){const n=d[1];if(!n.startsWith(".")||w.has(n))continue;w.add(n);const a=R(n,e),r=x("module",a,a);g.push({id:E(o,r,"imports"),fromId:o,toId:r,type:"imports",properties:{source:n}})}}return{nodes:c,edges:g}}export{b as extractGraph};
1
+ import{createHash as y}from"node:crypto";import{dirname as k,extname as j,join as I}from"node:path";const S=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs"]),$=[{pattern:/^export\s+(?:async\s+)?function\s+(\w+)/gm,kind:"function",exported:!0},{pattern:/^export\s+(?:default\s+)?class\s+(\w+)/gm,kind:"class",exported:!0},{pattern:/^export\s+interface\s+(\w+)/gm,kind:"interface",exported:!0},{pattern:/^export\s+type\s+(\w+)/gm,kind:"type",exported:!0},{pattern:/^export\s+(?:const|let)\s+(\w+)/gm,kind:"const",exported:!0},{pattern:/^export\s+enum\s+(\w+)/gm,kind:"enum",exported:!0},{pattern:/^(?:async\s+)?function\s+(\w+)/gm,kind:"function",exported:!1},{pattern:/^class\s+(\w+)/gm,kind:"class",exported:!1},{pattern:/^interface\s+(\w+)/gm,kind:"interface",exported:!1},{pattern:/^type\s+(\w+)/gm,kind:"type",exported:!1},{pattern:/^enum\s+(\w+)/gm,kind:"enum",exported:!1}],G=[/import\s+(?:(?:type\s+)?(?:(?:\{[^}]*\}|[\w*]+)\s+from\s+)?)['"]([^'"]+)['"]/g,/import\(\s*['"]([^'"]+)['"]\s*\)/g,/require\(\s*['"]([^'"]+)['"]\s*\)/g];function x(t,e,s){return y("sha256").update(`${t}:${e}:${s}`).digest("hex").slice(0,16)}function E(t,e,s){return y("sha256").update(`${t}-${s}-${e}`).digest("hex").slice(0,16)}function R(t,e){const s=k(e);return I(s,t).replace(/\\/g,"/").replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,"")}function N(t){return t.replace(/\.(js|jsx|ts|tsx|mjs|cjs)$/,"")}function O(t,e){const s=j(e).toLowerCase();if(!S.has(s))return{nodes:[],edges:[]};const c=[],g=[],l=new Date().toISOString(),u=new Set,f=N(e),o=x("module",f,f);c.push({id:o,type:"module",name:e,properties:{ext:s},sourcePath:e,createdAt:l});for(const{pattern:i,kind:p,exported:d}of $){const n=new RegExp(i.source,i.flags);let a;for(;(a=n.exec(t))!==null;){const r=a[1],h=`${p}:${r}`;if(u.has(h))continue;u.add(h);const m=x(p,r,e);c.push({id:m,type:p,name:r,properties:{exported:d},sourcePath:e,createdAt:l}),g.push({id:E(o,m,"defines"),fromId:o,toId:m,type:"defines",weight:d?1:.5})}}const w=new Set;for(const i of G){const p=new RegExp(i.source,i.flags);let d;for(;(d=p.exec(t))!==null;){const n=d[1];if(!n.startsWith(".")||w.has(n))continue;w.add(n);const a=R(n,e),r=x("module",a,a);g.push({id:E(o,r,"imports"),fromId:o,toId:r,type:"imports",properties:{source:n}})}}return{nodes:c,edges:g}}export{O as extractGraph};
@@ -1 +1 @@
1
- import{availableParallelism as G}from"node:os";import{createChunker as F}from"@kb/chunker";import{detectContentType as B}from"@kb/core";import{generateRecordId as K,hashContent as b}from"./file-hasher.js";import{FilesystemCrawler as H}from"./filesystem-crawler.js";import{extractGraph as A}from"./graph-extractor.js";async function S(c,s,r,o){let g=0;async function l(){for(;g<c.length;){const d=g++;try{await s(c[d])}catch(a){o?.(c[d],a)}}}await Promise.all(Array.from({length:Math.min(r,c.length)},()=>l()))}const L=Math.max(1,Math.floor(G()/2));class V{constructor(s,r){this.embedder=s;this.store=r;this.crawler=new H}crawler;indexing=!1;graphStore;setGraphStore(s){this.graphStore=s}async index(s,r){if(this.indexing)throw new Error("Indexing is already in progress");this.indexing=!0;try{return await this.doIndex(s,r,{})}finally{this.indexing=!1}}async doIndex(s,r,o={}){const g=Date.now();let l=0,d=0,a=0,C=0;const w=s.indexing.concurrency??L;r?.({phase:"crawling",filesTotal:0,filesProcessed:0,chunksTotal:0,chunksProcessed:0});const y=(await Promise.all(s.sources.map(e=>this.crawler.crawl({rootDir:e.path,excludePatterns:e.excludePatterns})))).flat();let p,f;if(o.skipHashCheck)p=y,f=[];else{const e=await this.store.listSourcePaths(),h=new Set(y.map(n=>n.relativePath));f=e.filter(n=>!h.has(n)&&!n.startsWith("curated/")),p=[],await S(y,async n=>{const i=b(n.content),P=await this.store.getBySourcePath(n.relativePath);if(P.length>0&&P[0].fileHash===i){d++;return}p.push(n)},w,(n,i)=>console.error(`[indexer] hash check failed for ${n.relativePath}:`,i))}const u=p.length,I=50;let m=[],x=[],k=0;const v=async()=>{if(this.graphStore){try{m.length>0&&await this.graphStore.upsertNodes(m),x.length>0&&await this.graphStore.upsertEdges(x)}catch(e){console.error("[indexer] graph batch flush failed:",e)}m=[],x=[],k=0}};return await S(p,async e=>{r?.({phase:"chunking",filesTotal:u,filesProcessed:l,chunksTotal:a,chunksProcessed:a,currentFile:e.relativePath});const h=B(e.relativePath),i=F(e.extension).chunk(e.content,{sourcePath:e.relativePath,contentType:h});if(i.length===0)return;r?.({phase:"embedding",filesTotal:u,filesProcessed:l,chunksTotal:a+i.length,chunksProcessed:a,currentFile:e.relativePath});const P=await this.embedder.embedBatch(i.map(t=>t.text)),T=b(e.content),R=i.map((t,E)=>({id:K(e.relativePath,E),content:t.text,sourcePath:t.sourcePath,contentType:t.contentType,headingPath:t.headingPath,chunkIndex:t.chunkIndex,totalChunks:t.totalChunks,startLine:t.startLine,endLine:t.endLine,fileHash:T,indexedAt:new Date().toISOString(),origin:"indexed",tags:[],version:1}));if(r?.({phase:"storing",filesTotal:u,filesProcessed:l,chunksTotal:a+i.length,chunksProcessed:a,currentFile:e.relativePath}),await this.store.upsert(R,P),this.graphStore)try{o.graphCleared||await this.graphStore.deleteBySourcePath(e.relativePath);const t=A(e.content,e.relativePath);t.nodes.length>0&&m.push(...t.nodes),t.edges.length>0&&x.push(...t.edges),k++,k>=I&&await v()}catch(t){console.error(`[indexer] graph extraction failed for ${e.relativePath}:`,t)}l++,a+=i.length},w,(e,h)=>console.error(`[indexer] processing failed for ${e.relativePath}:`,h)),await v(),f.length>0&&(r?.({phase:"cleanup",filesTotal:u,filesProcessed:l,chunksTotal:a,chunksProcessed:a}),await S(f,async e=>{await this.store.deleteBySourcePath(e),this.graphStore&&await this.graphStore.deleteBySourcePath(e).catch(h=>console.error(`[indexer] graph cleanup failed for ${e}:`,h)),C++},w,(e,h)=>console.error(`[indexer] cleanup failed for ${e}:`,h))),r?.({phase:"done",filesTotal:u,filesProcessed:l,chunksTotal:a,chunksProcessed:a}),{filesProcessed:l,filesSkipped:d,chunksCreated:a,filesRemoved:C,durationMs:Date.now()-g}}async reindexAll(s,r){if(await this.store.dropTable(),this.graphStore)try{const o=await this.graphStore.getStats();o.nodeCount>0&&(await this.graphStore.clear(),console.error(`[indexer] Graph store cleared (was ${o.nodeCount} nodes, ${o.edgeCount} edges)`))}catch(o){console.error("[indexer] Graph store clear failed:",o)}return this.doReindex(s,r)}async doReindex(s,r){if(this.indexing)throw new Error("Indexing is already in progress");this.indexing=!0;try{return await this.doIndex(s,r,{skipHashCheck:!0,graphCleared:!0})}finally{this.indexing=!1}}async getStats(){return this.store.getStats()}}export{V as IncrementalIndexer};
1
+ import{availableParallelism as G}from"node:os";import{createChunker as F}from"../../chunker/dist/index.js";import{detectContentType as B}from"../../core/dist/index.js";import{generateRecordId as K,hashContent as I}from"./file-hasher.js";import{FilesystemCrawler as H}from"./filesystem-crawler.js";import{extractGraph as A}from"./graph-extractor.js";async function S(c,s,r,o){let g=0;async function l(){for(;g<c.length;){const d=g++;try{await s(c[d])}catch(a){o?.(c[d],a)}}}await Promise.all(Array.from({length:Math.min(r,c.length)},()=>l()))}const L=Math.max(1,Math.floor(G()/2));class O{constructor(s,r){this.embedder=s;this.store=r;this.crawler=new H}crawler;indexing=!1;graphStore;setGraphStore(s){this.graphStore=s}async index(s,r){if(this.indexing)throw new Error("Indexing is already in progress");this.indexing=!0;try{return await this.doIndex(s,r,{})}finally{this.indexing=!1}}async doIndex(s,r,o={}){const g=Date.now();let l=0,d=0,a=0,C=0;const w=s.indexing.concurrency??L;r?.({phase:"crawling",filesTotal:0,filesProcessed:0,chunksTotal:0,chunksProcessed:0});const y=(await Promise.all(s.sources.map(e=>this.crawler.crawl({rootDir:e.path,excludePatterns:e.excludePatterns})))).flat();let p,f;if(o.skipHashCheck)p=y,f=[];else{const e=await this.store.listSourcePaths(),h=new Set(y.map(n=>n.relativePath));f=e.filter(n=>!h.has(n)&&!n.startsWith("curated/")),p=[],await S(y,async n=>{const i=I(n.content),P=await this.store.getBySourcePath(n.relativePath);if(P.length>0&&P[0].fileHash===i){d++;return}p.push(n)},w,(n,i)=>console.error(`[indexer] hash check failed for ${n.relativePath}:`,i))}const u=p.length,b=50;let m=[],x=[],k=0;const v=async()=>{if(this.graphStore){try{m.length>0&&await this.graphStore.upsertNodes(m),x.length>0&&await this.graphStore.upsertEdges(x)}catch(e){console.error("[indexer] graph batch flush failed:",e)}m=[],x=[],k=0}};return await S(p,async e=>{r?.({phase:"chunking",filesTotal:u,filesProcessed:l,chunksTotal:a,chunksProcessed:a,currentFile:e.relativePath});const h=B(e.relativePath),i=F(e.extension).chunk(e.content,{sourcePath:e.relativePath,contentType:h});if(i.length===0)return;r?.({phase:"embedding",filesTotal:u,filesProcessed:l,chunksTotal:a+i.length,chunksProcessed:a,currentFile:e.relativePath});const P=await this.embedder.embedBatch(i.map(t=>t.text)),T=I(e.content),R=i.map((t,E)=>({id:K(e.relativePath,E),content:t.text,sourcePath:t.sourcePath,contentType:t.contentType,headingPath:t.headingPath,chunkIndex:t.chunkIndex,totalChunks:t.totalChunks,startLine:t.startLine,endLine:t.endLine,fileHash:T,indexedAt:new Date().toISOString(),origin:"indexed",tags:[],version:1}));if(r?.({phase:"storing",filesTotal:u,filesProcessed:l,chunksTotal:a+i.length,chunksProcessed:a,currentFile:e.relativePath}),await this.store.upsert(R,P),this.graphStore)try{o.graphCleared||await this.graphStore.deleteBySourcePath(e.relativePath);const t=A(e.content,e.relativePath);t.nodes.length>0&&m.push(...t.nodes),t.edges.length>0&&x.push(...t.edges),k++,k>=b&&await v()}catch(t){console.error(`[indexer] graph extraction failed for ${e.relativePath}:`,t)}l++,a+=i.length},w,(e,h)=>console.error(`[indexer] processing failed for ${e.relativePath}:`,h)),await v(),f.length>0&&(r?.({phase:"cleanup",filesTotal:u,filesProcessed:l,chunksTotal:a,chunksProcessed:a}),await S(f,async e=>{await this.store.deleteBySourcePath(e),this.graphStore&&await this.graphStore.deleteBySourcePath(e).catch(h=>console.error(`[indexer] graph cleanup failed for ${e}:`,h)),C++},w,(e,h)=>console.error(`[indexer] cleanup failed for ${e}:`,h))),r?.({phase:"done",filesTotal:u,filesProcessed:l,chunksTotal:a,chunksProcessed:a}),{filesProcessed:l,filesSkipped:d,chunksCreated:a,filesRemoved:C,durationMs:Date.now()-g}}async reindexAll(s,r){if(await this.store.dropTable(),this.graphStore)try{const o=await this.graphStore.getStats();o.nodeCount>0&&(await this.graphStore.clear(),console.error(`[indexer] Graph store cleared (was ${o.nodeCount} nodes, ${o.edgeCount} edges)`))}catch(o){console.error("[indexer] Graph store clear failed:",o)}return this.doReindex(s,r)}async doReindex(s,r){if(this.indexing)throw new Error("Indexing is already in progress");this.indexing=!0;try{return await this.doIndex(s,r,{skipHashCheck:!0,graphCleared:!0})}finally{this.indexing=!1}}async getStats(){return this.store.getStats()}}export{O as IncrementalIndexer};
@@ -1 +1 @@
1
- import{existsSync as i,readFileSync as d}from"node:fs";import{dirname as c,resolve as e}from"node:path";import{fileURLToPath as u}from"node:url";const p=c(u(import.meta.url));function a(r,n,o){const t=e(r),s=e(n);if(!t.startsWith(s))throw new Error(`Config ${o} path escapes workspace root: ${r} is not under ${n}`);return t}function l(){const r=process.env.KB_CONFIG_PATH??(i(e(process.cwd(),"kb.config.json"))?e(process.cwd(),"kb.config.json"):e(p,"..","..","..","kb.config.json"));try{const n=d(r,"utf-8"),o=JSON.parse(n);if(!o.sources||!Array.isArray(o.sources)||o.sources.length===0)throw new Error("Config must have at least one source");if(!o.store?.path)throw new Error("Config must specify store.path");const t=c(r);return o.sources=o.sources.map(s=>({...s,path:a(e(t,s.path),t,"source")})),o.store.path=a(e(t,o.store.path),t,"store"),o.curated=o.curated??{path:"curated"},o.curated.path=a(e(t,o.curated.path),t,"curated"),o}catch(n){const o=n instanceof Error?n.message:String(n);return console.error(`[KB] Failed to load config from ${r}: ${o}`),console.error("[KB] Falling back to default configuration"),f()}}function f(){const r=process.env.KB_WORKSPACE_ROOT??process.cwd();return{sources:[{path:r,excludePatterns:["node_modules/**","dist/**",".git/**","coverage/**","*.lock","pnpm-lock.yaml"]}],indexing:{chunkSize:1500,chunkOverlap:200,minChunkSize:100},embedding:{model:"mixedbread-ai/mxbai-embed-large-v1",dimensions:1024},store:{backend:"lancedb",path:e(r,".kb-data")},curated:{path:e(r,"curated")}}}export{l as loadConfig};
1
+ import{existsSync as i,readFileSync as d}from"node:fs";import{dirname as c,resolve as r}from"node:path";import{fileURLToPath as u}from"node:url";const p=c(u(import.meta.url));function a(e,n,o){const t=r(e),s=r(n);if(!t.startsWith(s))throw new Error(`Config ${o} path escapes workspace root: ${e} is not under ${n}`);return t}function l(){const e=process.env.KB_CONFIG_PATH??(i(r(process.cwd(),"kb.config.json"))?r(process.cwd(),"kb.config.json"):r(p,"..","..","..","kb.config.json"));try{const n=d(e,"utf-8"),o=JSON.parse(n);if(!o.sources||!Array.isArray(o.sources)||o.sources.length===0)throw new Error("Config must have at least one source");if(!o.store?.path)throw new Error("Config must specify store.path");const t=c(e);return o.sources=o.sources.map(s=>({...s,path:a(r(t,s.path),t,"source")})),o.store.path=a(r(t,o.store.path),t,"store"),o.curated=o.curated??{path:"curated"},o.curated.path=a(r(t,o.curated.path),t,"curated"),o}catch(n){const o=n instanceof Error?n.message:String(n);return console.error(`[KB] Failed to load config from ${e}: ${o}`),console.error("[KB] Falling back to default configuration"),f()}}function f(){const e=process.env.KB_WORKSPACE_ROOT??process.cwd();return{sources:[{path:e,excludePatterns:["node_modules/**","dist/**",".git/**","coverage/**","*.lock","pnpm-lock.yaml"]}],indexing:{chunkSize:1500,chunkOverlap:200,minChunkSize:100},embedding:{model:"mixedbread-ai/mxbai-embed-large-v1",dimensions:1024},store:{backend:"lancedb",path:r(e,".kb-data")},curated:{path:r(e,"curated")}}}export{l as loadConfig};
@@ -1,10 +1,10 @@
1
- import{createHash as C}from"node:crypto";import{mkdir as b,readdir as f,readFile as m,stat as y,unlink as P,writeFile as v}from"node:fs/promises";import{dirname as F,isAbsolute as I,join as u}from"node:path";const w=50*1024;class E{constructor(t,e,n){this.curatedDir=t;this.store=e;this.embedder=n}async remember(t,e,n,r=[]){this.validateCategoryName(n),this.validateContentSize(e);const a=this.slugify(t),s=await this.uniqueRelativePath(n,a),i=u(this.curatedDir,s),g=new Date().toISOString(),c={title:t,category:n,tags:r,created:g,updated:g,version:1,origin:"curated",changelog:[{version:1,date:g,reason:"Initial creation"}]},d=this.serializeFile(e,c);return await b(F(i),{recursive:!0}),await v(i,d,"utf-8"),await this.indexCuratedFile(s,e,c),{path:s}}async update(t,e,n){this.guardPath(t),this.validateContentSize(e);const r=u(this.curatedDir,t),a=await m(r,"utf-8"),{frontmatter:s}=this.parseFile(a),i=(s.version??1)+1,g=new Date().toISOString();s.version=i,s.updated=g,s.changelog=[...s.changelog??[],{version:i,date:g,reason:n}];const c=this.serializeFile(e,s);return await v(r,c,"utf-8"),await this.indexCuratedFile(t,e,s),{path:t,version:i}}async forget(t,e){this.guardPath(t);const n=u(this.curatedDir,t),r=`curated/${t}`;return await this.store.deleteBySourcePath(r),await P(n),{path:t}}async read(t){this.guardPath(t);const e=u(this.curatedDir,t),n=await m(e,"utf-8"),{frontmatter:r,content:a}=this.parseFile(n),s=t.split("/")[0];return{path:t,title:r.title??t,category:s,tags:r.tags??[],version:r.version??1,created:r.created??"",updated:r.updated??"",contentPreview:a.slice(0,200),content:a}}async list(t){const e=[],n=t?.category?[t.category]:await this.discoverCategories();for(const r of n){const a=u(this.curatedDir,r);try{const s=await f(a);for(const i of s){if(!i.endsWith(".md"))continue;const g=u(a,i),c=await m(g,"utf-8"),{frontmatter:d,content:h}=this.parseFile(c);t?.tag&&!(d.tags??[]).includes(t.tag)||e.push({path:`${r}/${i}`,title:d.title??i,category:r,tags:d.tags??[],version:d.version??1,created:d.created??"",updated:d.updated??"",contentPreview:h.slice(0,200)})}}catch{}}return e}async reindexAll(){const t=await this.discoverCategories(),e=[],n=[];for(const i of t){const g=u(this.curatedDir,i);let c;try{c=(await f(g)).filter(d=>d.endsWith(".md"))}catch{continue}for(const d of c){const h=`${i}/${d}`,p=u(g,d);try{const o=await m(p,"utf-8"),{frontmatter:l,content:$}=this.parseFile(o);n.push({relativePath:h,content:$,frontmatter:l})}catch(o){e.push(`${h}: ${o.message}`)}}}if(n.length===0)return{indexed:0,errors:e};const r=await this.embedder.embedBatch(n.map(i=>i.content)),a=new Date().toISOString(),s=n.map(i=>{const g=`curated/${i.relativePath}`;return{id:this.hashId(g,0),content:i.content,sourcePath:g,contentType:"curated-knowledge",headingPath:i.frontmatter.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:i.content.split(`
1
+ import{createHash as C}from"node:crypto";import{mkdir as b,readdir as f,readFile as m,stat as y,unlink as P,writeFile as v}from"node:fs/promises";import{dirname as x,isAbsolute as F,join as u}from"node:path";const w=50*1024;class k{constructor(t,e,n){this.curatedDir=t;this.store=e;this.embedder=n}async remember(t,e,n,r=[]){this.validateCategoryName(n),this.validateContentSize(e);const a=this.slugify(t),s=await this.uniqueRelativePath(n,a),i=u(this.curatedDir,s),g=new Date().toISOString(),c={title:t,category:n,tags:r,created:g,updated:g,version:1,origin:"curated",changelog:[{version:1,date:g,reason:"Initial creation"}]},d=this.serializeFile(e,c);return await b(x(i),{recursive:!0}),await v(i,d,"utf-8"),await this.indexCuratedFile(s,e,c),{path:s}}async update(t,e,n){this.guardPath(t),this.validateContentSize(e);const r=u(this.curatedDir,t),a=await m(r,"utf-8"),{frontmatter:s}=this.parseFile(a),i=(s.version??1)+1,g=new Date().toISOString();s.version=i,s.updated=g,s.changelog=[...s.changelog??[],{version:i,date:g,reason:n}];const c=this.serializeFile(e,s);return await v(r,c,"utf-8"),await this.indexCuratedFile(t,e,s),{path:t,version:i}}async forget(t,e){this.guardPath(t);const n=u(this.curatedDir,t),r=`curated/${t}`;return await this.store.deleteBySourcePath(r),await P(n),{path:t}}async read(t){this.guardPath(t);const e=u(this.curatedDir,t),n=await m(e,"utf-8"),{frontmatter:r,content:a}=this.parseFile(n),s=t.split("/")[0];return{path:t,title:r.title??t,category:s,tags:r.tags??[],version:r.version??1,created:r.created??"",updated:r.updated??"",contentPreview:a.slice(0,200),content:a}}async list(t){const e=[],n=t?.category?[t.category]:await this.discoverCategories();for(const r of n){const a=u(this.curatedDir,r);try{const s=await f(a);for(const i of s){if(!i.endsWith(".md"))continue;const g=u(a,i),c=await m(g,"utf-8"),{frontmatter:d,content:h}=this.parseFile(c);t?.tag&&!(d.tags??[]).includes(t.tag)||e.push({path:`${r}/${i}`,title:d.title??i,category:r,tags:d.tags??[],version:d.version??1,created:d.created??"",updated:d.updated??"",contentPreview:h.slice(0,200)})}}catch{}}return e}async reindexAll(){const t=await this.discoverCategories(),e=[],n=[];for(const i of t){const g=u(this.curatedDir,i);let c;try{c=(await f(g)).filter(d=>d.endsWith(".md"))}catch{continue}for(const d of c){const h=`${i}/${d}`,p=u(g,d);try{const o=await m(p,"utf-8"),{frontmatter:l,content:$}=this.parseFile(o);n.push({relativePath:h,content:$,frontmatter:l})}catch(o){e.push(`${h}: ${o.message}`)}}}if(n.length===0)return{indexed:0,errors:e};const r=await this.embedder.embedBatch(n.map(i=>i.content)),a=new Date().toISOString(),s=n.map(i=>{const g=`curated/${i.relativePath}`;return{id:this.hashId(g,0),content:i.content,sourcePath:g,contentType:"curated-knowledge",headingPath:i.frontmatter.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:i.content.split(`
2
2
  `).length,fileHash:this.hash(i.content),indexedAt:a,origin:"curated",tags:i.frontmatter.tags,category:i.frontmatter.category,version:i.frontmatter.version}});return await this.store.upsert(s,r),{indexed:n.length,errors:e}}async indexCuratedFile(t,e,n){const r=await this.embedder.embed(e),a=`curated/${t}`,s=new Date().toISOString(),i={id:this.hashId(a,0),content:e,sourcePath:a,contentType:"curated-knowledge",headingPath:n.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:e.split(`
3
- `).length,fileHash:this.hash(e),indexedAt:s,origin:"curated",tags:n.tags,category:n.category,version:n.version};await this.store.upsert([i],[r])}async discoverCategories(){try{return(await f(this.curatedDir,{withFileTypes:!0})).filter(e=>e.isDirectory()&&/^[a-z][a-z0-9-]*$/.test(e.name)).map(e=>e.name)}catch{return[]}}guardPath(t){if(t.includes("..")||I(t))throw new Error(`Invalid path: ${t}. Must be relative within curated/ directory.`);const e=t.split("/")[0];this.validateCategoryName(e)}validateCategoryName(t){if(!/^[a-z][a-z0-9-]*$/.test(t))throw new Error(`Invalid category name: "${t}". Must be lowercase kebab-case (e.g., "decisions", "api-contracts").`)}validateContentSize(t){if(Buffer.byteLength(t,"utf-8")>w)throw new Error(`Content exceeds maximum size of ${w/1024}KB`)}slugify(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"").slice(0,80)}async uniqueRelativePath(t,e){const n=`${t}/${e}.md`,r=u(this.curatedDir,n);try{await y(r)}catch{return n}for(let a=2;a<=100;a++){const s=`${t}/${e}-${a}.md`;try{await y(u(this.curatedDir,s))}catch{return s}}throw new Error(`Too many entries with slug "${e}" in category "${t}"`)}hash(t){return C("sha256").update(t).digest("hex").slice(0,16)}hashId(t,e){return this.hash(`${t}::${e}`)}serializeFile(t,e){return`${["---",`title: "${e.title.replace(/"/g,'\\"')}"`,`category: ${e.category}`,`tags: [${e.tags.map(r=>`"${r}"`).join(", ")}]`,`created: ${e.created}`,`updated: ${e.updated}`,`version: ${e.version}`,`origin: ${e.origin}`,"changelog:",...e.changelog.map(r=>` - version: ${r.version}
3
+ `).length,fileHash:this.hash(e),indexedAt:s,origin:"curated",tags:n.tags,category:n.category,version:n.version};await this.store.upsert([i],[r])}async discoverCategories(){try{return(await f(this.curatedDir,{withFileTypes:!0})).filter(e=>e.isDirectory()&&/^[a-z][a-z0-9-]*$/.test(e.name)).map(e=>e.name)}catch{return[]}}guardPath(t){if(t.includes("..")||F(t))throw new Error(`Invalid path: ${t}. Must be relative within curated/ directory.`);const e=t.split("/")[0];this.validateCategoryName(e)}validateCategoryName(t){if(!/^[a-z][a-z0-9-]*$/.test(t))throw new Error(`Invalid category name: "${t}". Must be lowercase kebab-case (e.g., "decisions", "api-contracts").`)}validateContentSize(t){if(Buffer.byteLength(t,"utf-8")>w)throw new Error(`Content exceeds maximum size of ${w/1024}KB`)}slugify(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"").slice(0,80)}async uniqueRelativePath(t,e){const n=`${t}/${e}.md`,r=u(this.curatedDir,n);try{await y(r)}catch{return n}for(let a=2;a<=100;a++){const s=`${t}/${e}-${a}.md`;try{await y(u(this.curatedDir,s))}catch{return s}}throw new Error(`Too many entries with slug "${e}" in category "${t}"`)}hash(t){return C("sha256").update(t).digest("hex").slice(0,16)}hashId(t,e){return this.hash(`${t}::${e}`)}serializeFile(t,e){return`${["---",`title: "${e.title.replace(/"/g,'\\"')}"`,`category: ${e.category}`,`tags: [${e.tags.map(r=>`"${r}"`).join(", ")}]`,`created: ${e.created}`,`updated: ${e.updated}`,`version: ${e.version}`,`origin: ${e.origin}`,"changelog:",...e.changelog.map(r=>` - version: ${r.version}
4
4
  date: ${r.date}
5
5
  reason: "${r.reason.replace(/"/g,'\\"')}"`),"---"].join(`
6
6
  `)}
7
7
 
8
8
  ${t}
9
9
  `}parseFile(t){const e=t.match(/^---\n([\s\S]*?)\n---\n\n?([\s\S]*)$/);if(!e)return{frontmatter:{title:"Untitled",category:"notes",tags:[],created:"",updated:"",version:1,origin:"curated",changelog:[]},content:t};const n=e[1],r=e[2].trim(),a={},s=[],i=n.split(`
10
- `);let g=!1,c={};for(const d of i){if(/^changelog:\s*$/.test(d)){g=!0;continue}if(g){const p=d.match(/^\s+-\s+version:\s*(\d+)$/);if(p){c.version!=null&&s.push(c),c={version:parseInt(p[1],10)};continue}const o=d.match(/^\s+date:\s*(.+)$/);if(o){c.date=o[1].trim();continue}const l=d.match(/^\s+reason:\s*"?(.*?)"?\s*$/);if(l){c.reason=l[1];continue}/^\w/.test(d)&&(g=!1,c.version!=null&&s.push(c),c={});continue}const h=d.match(/^(\w+):\s*(.*)$/);if(h){const p=h[1];let o=h[2];typeof o=="string"&&o.startsWith("[")&&o.endsWith("]")?o=o.slice(1,-1).split(",").map(l=>l.trim().replace(/^"|"$/g,"")).filter(l=>l.length>0):typeof o=="string"&&/^\d+$/.test(o)?o=parseInt(o,10):typeof o=="string"&&o.startsWith('"')&&o.endsWith('"')&&(o=o.slice(1,-1)),a[p]=o}}return c.version!=null&&s.push(c),{frontmatter:{title:a.title??"Untitled",category:a.category??"notes",tags:a.tags??[],created:a.created??"",updated:a.updated??"",version:a.version??1,origin:"curated",changelog:s},content:r}}}export{E as CuratedKnowledgeManager};
10
+ `);let g=!1,c={};for(const d of i){if(/^changelog:\s*$/.test(d)){g=!0;continue}if(g){const p=d.match(/^\s+-\s+version:\s*(\d+)$/);if(p){c.version!=null&&s.push(c),c={version:parseInt(p[1],10)};continue}const o=d.match(/^\s+date:\s*(.+)$/);if(o){c.date=o[1].trim();continue}const l=d.match(/^\s+reason:\s*"?(.*?)"?\s*$/);if(l){c.reason=l[1];continue}/^\w/.test(d)&&(g=!1,c.version!=null&&s.push(c),c={});continue}const h=d.match(/^(\w+):\s*(.*)$/);if(h){const p=h[1];let o=h[2];typeof o=="string"&&o.startsWith("[")&&o.endsWith("]")?o=o.slice(1,-1).split(",").map(l=>l.trim().replace(/^"|"$/g,"")).filter(l=>l.length>0):typeof o=="string"&&/^\d+$/.test(o)?o=parseInt(o,10):typeof o=="string"&&o.startsWith('"')&&o.endsWith('"')&&(o=o.slice(1,-1)),a[p]=o}}return c.version!=null&&s.push(c),{frontmatter:{title:a.title??"Untitled",category:a.category??"notes",tags:a.tags??[],created:a.created??"",updated:a.updated??"",version:a.version??1,origin:"curated",changelog:s},content:r}}}export{k as CuratedKnowledgeManager};
@@ -1 +1 @@
1
- import{replayAppend as s}from"@kb/tools";function w(n){const i=n.registerTool.bind(n);n.registerTool=(o,a,p)=>i(o,a,async(r,c)=>{const e=Date.now();try{const t=await p(r,c);return s({ts:new Date().toISOString(),source:"mcp",tool:o,input:JSON.stringify(r),durationMs:Date.now()-e,status:"ok",output:JSON.stringify(t).slice(0,200)}),t}catch(t){throw s({ts:new Date().toISOString(),source:"mcp",tool:o,input:JSON.stringify(r),durationMs:Date.now()-e,status:"error",output:t instanceof Error?t.message:String(t)}),t}})}export{w as installReplayInterceptor};
1
+ import{replayAppend as s}from"../../tools/dist/index.js";function w(n){const i=n.registerTool.bind(n);n.registerTool=(o,a,p)=>i(o,a,async(r,c)=>{const e=Date.now();try{const t=await p(r,c);return s({ts:new Date().toISOString(),source:"mcp",tool:o,input:JSON.stringify(r),durationMs:Date.now()-e,status:"ok",output:JSON.stringify(t).slice(0,200)}),t}catch(t){throw s({ts:new Date().toISOString(),source:"mcp",tool:o,input:JSON.stringify(r),durationMs:Date.now()-e,status:"error",output:t instanceof Error?t.message:String(t)}),t}})}export{w as installReplayInterceptor};
@@ -1 +1 @@
1
- import{initializeTreeSitter as c}from"@kb/chunker";import{OnnxEmbedder as m}from"@kb/embeddings";import{IncrementalIndexer as g}from"@kb/indexer";import{createStore as p,SqliteGraphStore as T}from"@kb/store";import{McpServer as u}from"@modelcontextprotocol/sdk/server/mcp.js";import{CuratedKnowledgeManager as f}from"./curated-manager.js";import{installReplayInterceptor as h}from"./replay-interceptor.js";import{registerResources as S}from"./resources/resources.js";import{registerAnalyzeDependenciesTool as x,registerAnalyzeDiagramTool as w,registerAnalyzeEntryPointsTool as K,registerAnalyzePatternsTool as y,registerAnalyzeStructureTool as B,registerAnalyzeSymbolsTool as C,registerBlastRadiusTool as I}from"./tools/analyze.tools.js";import{registerDigestTool as v,registerEvidenceMapTool as P,registerForgeClassifyTool as z,registerForgeGroundTool as R,registerStratumCardTool as E}from"./tools/forge.tools.js";import{registerForgetTool as F}from"./tools/forget.tool.js";import{registerGraphTool as M}from"./tools/graph.tool.js";import{registerListTool as $}from"./tools/list.tool.js";import{registerLookupTool as G}from"./tools/lookup.tool.js";import{registerOnboardTool as A}from"./tools/onboard.tool.js";import{registerProduceKnowledgeTool as D}from"./tools/produce.tool.js";import{registerReadTool as O}from"./tools/read.tool.js";import{registerReindexTool as W}from"./tools/reindex.tool.js";import{registerRememberTool as L}from"./tools/remember.tool.js";import{registerReplayTool as H}from"./tools/replay.tool.js";import{registerSearchTool as j}from"./tools/search.tool.js";import{registerStatusTool as q}from"./tools/status.tool.js";import{registerBatchTool as N,registerCheckpointTool as Q,registerCheckTool as U,registerCodemodTool as V,registerCompactTool as _,registerDataTransformTool as J,registerDeadSymbolsTool as X,registerDelegateTool as Y,registerDiffParseTool as Z,registerEvalTool as b,registerFileSummaryTool as k,registerFindExamplesTool as ee,registerFindTool as re,registerGitContextTool as oe,registerHealthTool as te,registerLaneTool as se,registerParseOutputTool as ie,registerProcessTool as ne,registerQueueTool as ae,registerRenameTool as le,registerScopeMapTool as de,registerStashTool as ce,registerSymbolTool as me,registerTestRunTool as ge,registerTraceTool as pe,registerWatchTool as Te,registerWebFetchTool as ue,registerWorksetTool as fe}from"./tools/toolkit.tools.js";import{registerUpdateTool as he}from"./tools/update.tool.js";import{registerChangelogTool as Se,registerEncodeTool as xe,registerEnvTool as we,registerHttpTool as Ke,registerMeasureTool as ye,registerRegexTestTool as Be,registerSchemaValidateTool as Ce,registerSnippetTool as Ie,registerTimeTool as ve,registerWebSearchTool as Pe}from"./tools/utility.tools.js";async function ze(r){console.error("[KB] Initializing knowledge base components...");const t=new m({model:r.embedding.model,dimensions:r.embedding.dimensions});await t.initialize(),console.error(`[KB] Embedder loaded: ${t.modelId} (${t.dimensions}d)`);const e=await p({backend:r.store.backend,path:r.store.path});await e.initialize(),console.error("[KB] Store initialized");const a=new g(t,e),i=r.curated.path,d=new f(i,e,t),s=new T({path:r.store.path});await s.initialize(),console.error("[KB] Graph store initialized"),a.setGraphStore(s);const n=await c();return console.error(n?"[KB] Tree-sitter chunking enabled":"[KB] Tree-sitter not available \u2014 using regex-based code chunking"),{embedder:t,store:e,indexer:a,curated:d,graphStore:s}}function Re(r,t){const e=new u({name:"kb",version:"0.1.0"});return h(e),j(e,r.embedder,r.store,r.graphStore),G(e,r.store),q(e,r.store,r.graphStore),W(e,r.indexer,t,r.curated,r.store),L(e,r.curated),he(e,r.curated),F(e,r.curated),O(e,r.curated),$(e,r.curated),B(e,r.store,r.embedder),x(e,r.store,r.embedder),C(e,r.store,r.embedder),y(e,r.store,r.embedder),K(e,r.store,r.embedder),w(e,r.store,r.embedder),I(e,r.store,r.embedder),D(e),A(e,r.store,r.embedder),M(e,r.graphStore),_(e,r.embedder),de(e,r.embedder,r.store),re(e,r.embedder,r.store),ie(e),fe(e),U(e),N(e,r.embedder,r.store),me(e,r.embedder,r.store),b(e),ge(e),ce(e),oe(e),Z(e),le(e),V(e),k(e),Q(e),J(e),pe(e,r.embedder,r.store),ee(e,r.embedder,r.store),ne(e),Te(e),X(e,r.embedder,r.store),Y(e),te(e),se(e),ae(e),ue(e),P(e),v(e,r.embedder),z(e),E(e,r.embedder),R(e,r.embedder,r.store),Pe(e),Ke(e),Be(e),xe(e),ye(e),Se(e),Ce(e),Ie(e),we(e),ve(e),S(e,r.store),H(e),e}async function rr(r){const t=await ze(r),e=Re(t,r);console.error("[KB] MCP server configured with 64 tools and 2 resources");const a=async()=>{try{const n=r.sources.map(o=>o.path).join(", ");console.error(`[KB] Running initial index for sources: ${n}`);const l=await t.indexer.index(r,o=>{o.phase==="crawling"||o.phase==="done"||(o.phase==="chunking"&&o.currentFile&&console.error(`[KB] [${o.filesProcessed+1}/${o.filesTotal}] ${o.currentFile}`),o.phase==="cleanup"&&console.error(`[KB] cleanup: removing ${o.filesTotal-o.filesProcessed} stale entries`))});console.error(`[KB] Indexed ${l.filesProcessed} files (${l.filesSkipped} skipped, ${l.chunksCreated} chunks) in ${(l.durationMs/1e3).toFixed(1)}s`);try{await t.store.createFtsIndex()}catch(o){console.error("[KB] FTS index creation failed (non-fatal):",o)}try{const o=await t.curated.reindexAll();console.error(`[KB] Curated re-index: ${o.indexed} entries restored to vector store`)}catch(o){console.error("[KB] Curated re-index failed:",o)}}catch(n){console.error("[KB] Initial index failed (will retry on kb_reindex):",n)}},i=async()=>{console.error("[KB] Shutting down..."),await t.graphStore.close().catch(()=>{}),await t.store.close(),process.exit(0)};process.on("SIGINT",i),process.on("SIGTERM",i);const d=process.ppid,s=setInterval(()=>{try{process.kill(d,0)}catch{console.error("[KB] Parent process died \u2014 orphan detected, shutting down..."),clearInterval(s),i()}},5e3);return s.unref(),{server:e,runInitialIndex:a}}export{Re as createMcpServer,rr as createServer,ze as initializeKnowledgeBase};
1
+ import{initializeTreeSitter as c}from"../../chunker/dist/index.js";import{OnnxEmbedder as m}from"../../embeddings/dist/index.js";import{IncrementalIndexer as g}from"../../indexer/dist/index.js";import{createStore as p,SqliteGraphStore as T}from"../../store/dist/index.js";import{McpServer as u}from"@modelcontextprotocol/sdk/server/mcp.js";import{CuratedKnowledgeManager as f}from"./curated-manager.js";import{installReplayInterceptor as h}from"./replay-interceptor.js";import{registerResources as S}from"./resources/resources.js";import{registerAnalyzeDependenciesTool as x,registerAnalyzeDiagramTool as w,registerAnalyzeEntryPointsTool as K,registerAnalyzePatternsTool as y,registerAnalyzeStructureTool as B,registerAnalyzeSymbolsTool as C,registerBlastRadiusTool as I}from"./tools/analyze.tools.js";import{registerDigestTool as v,registerEvidenceMapTool as P,registerForgeClassifyTool as z,registerForgeGroundTool as R,registerStratumCardTool as E}from"./tools/forge.tools.js";import{registerForgetTool as F}from"./tools/forget.tool.js";import{registerGraphTool as M}from"./tools/graph.tool.js";import{registerListTool as $}from"./tools/list.tool.js";import{registerLookupTool as G}from"./tools/lookup.tool.js";import{registerOnboardTool as A}from"./tools/onboard.tool.js";import{registerProduceKnowledgeTool as D}from"./tools/produce.tool.js";import{registerReadTool as O}from"./tools/read.tool.js";import{registerReindexTool as W}from"./tools/reindex.tool.js";import{registerRememberTool as j}from"./tools/remember.tool.js";import{registerReplayTool as L}from"./tools/replay.tool.js";import{registerSearchTool as H}from"./tools/search.tool.js";import{registerStatusTool as q}from"./tools/status.tool.js";import{registerBatchTool as N,registerCheckpointTool as Q,registerCheckTool as U,registerCodemodTool as V,registerCompactTool as _,registerDataTransformTool as J,registerDeadSymbolsTool as X,registerDelegateTool as Y,registerDiffParseTool as Z,registerEvalTool as b,registerFileSummaryTool as k,registerFindExamplesTool as ee,registerFindTool as re,registerGitContextTool as oe,registerHealthTool as te,registerLaneTool as se,registerParseOutputTool as ie,registerProcessTool as ne,registerQueueTool as ae,registerRenameTool as le,registerScopeMapTool as de,registerStashTool as ce,registerSymbolTool as me,registerTestRunTool as ge,registerTraceTool as pe,registerWatchTool as Te,registerWebFetchTool as ue,registerWorksetTool as fe}from"./tools/toolkit.tools.js";import{registerUpdateTool as he}from"./tools/update.tool.js";import{registerChangelogTool as Se,registerEncodeTool as xe,registerEnvTool as we,registerHttpTool as Ke,registerMeasureTool as ye,registerRegexTestTool as Be,registerSchemaValidateTool as Ce,registerSnippetTool as Ie,registerTimeTool as ve,registerWebSearchTool as Pe}from"./tools/utility.tools.js";async function ze(r){console.error("[KB] Initializing knowledge base components...");const t=new m({model:r.embedding.model,dimensions:r.embedding.dimensions});await t.initialize(),console.error(`[KB] Embedder loaded: ${t.modelId} (${t.dimensions}d)`);const e=await p({backend:r.store.backend,path:r.store.path});await e.initialize(),console.error("[KB] Store initialized");const a=new g(t,e),i=r.curated.path,d=new f(i,e,t),s=new T({path:r.store.path});await s.initialize(),console.error("[KB] Graph store initialized"),a.setGraphStore(s);const n=await c();return console.error(n?"[KB] Tree-sitter chunking enabled":"[KB] Tree-sitter not available \u2014 using regex-based code chunking"),{embedder:t,store:e,indexer:a,curated:d,graphStore:s}}function Re(r,t){const e=new u({name:"kb",version:"0.1.0"});return h(e),H(e,r.embedder,r.store,r.graphStore),G(e,r.store),q(e,r.store,r.graphStore),W(e,r.indexer,t,r.curated,r.store),j(e,r.curated),he(e,r.curated),F(e,r.curated),O(e,r.curated),$(e,r.curated),B(e,r.store,r.embedder),x(e,r.store,r.embedder),C(e,r.store,r.embedder),y(e,r.store,r.embedder),K(e,r.store,r.embedder),w(e,r.store,r.embedder),I(e,r.store,r.embedder),D(e),A(e,r.store,r.embedder),M(e,r.graphStore),_(e,r.embedder),de(e,r.embedder,r.store),re(e,r.embedder,r.store),ie(e),fe(e),U(e),N(e,r.embedder,r.store),me(e,r.embedder,r.store),b(e),ge(e),ce(e),oe(e),Z(e),le(e),V(e),k(e),Q(e),J(e),pe(e,r.embedder,r.store),ee(e,r.embedder,r.store),ne(e),Te(e),X(e,r.embedder,r.store),Y(e),te(e),se(e),ae(e),ue(e),P(e),v(e,r.embedder),z(e),E(e,r.embedder),R(e,r.embedder,r.store),Pe(e),Ke(e),Be(e),xe(e),ye(e),Se(e),Ce(e),Ie(e),we(e),ve(e),S(e,r.store),L(e),e}async function rr(r){const t=await ze(r),e=Re(t,r);console.error("[KB] MCP server configured with 64 tools and 2 resources");const a=async()=>{try{const n=r.sources.map(o=>o.path).join(", ");console.error(`[KB] Running initial index for sources: ${n}`);const l=await t.indexer.index(r,o=>{o.phase==="crawling"||o.phase==="done"||(o.phase==="chunking"&&o.currentFile&&console.error(`[KB] [${o.filesProcessed+1}/${o.filesTotal}] ${o.currentFile}`),o.phase==="cleanup"&&console.error(`[KB] cleanup: removing ${o.filesTotal-o.filesProcessed} stale entries`))});console.error(`[KB] Indexed ${l.filesProcessed} files (${l.filesSkipped} skipped, ${l.chunksCreated} chunks) in ${(l.durationMs/1e3).toFixed(1)}s`);try{await t.store.createFtsIndex()}catch(o){console.error("[KB] FTS index creation failed (non-fatal):",o)}try{const o=await t.curated.reindexAll();console.error(`[KB] Curated re-index: ${o.indexed} entries restored to vector store`)}catch(o){console.error("[KB] Curated re-index failed:",o)}}catch(n){console.error("[KB] Initial index failed (will retry on kb_reindex):",n)}},i=async()=>{console.error("[KB] Shutting down..."),await t.graphStore.close().catch(()=>{}),await t.store.close(),process.exit(0)};process.on("SIGINT",i),process.on("SIGTERM",i);const d=process.ppid,s=setInterval(()=>{try{process.kill(d,0)}catch{console.error("[KB] Parent process died \u2014 orphan detected, shutting down..."),clearInterval(s),i()}},5e3);return s.unref(),{server:e,runInitialIndex:a}}export{Re as createMcpServer,rr as createServer,ze as initializeKnowledgeBase};