@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
@@ -1 +1 @@
1
- import{createHash as y}from"node:crypto";import{BlastRadiusAnalyzer as f,DependencyAnalyzer as x,DiagramGenerator as b,EntryPointAnalyzer as w,PatternAnalyzer as z,StructureAnalyzer as _,SymbolAnalyzer as v}from"@kb/analyzers";import{z as a}from"zod";async function d(s,o,r,i,e){try{const t=y("sha256").update(i).digest("hex").slice(0,12),n=`produced/analysis/${r}/${t}.md`,c=y("sha256").update(e).digest("hex").slice(0,16),l=new Date().toISOString(),m=e.length>2e3?e.split(/(?=^## )/m).filter(p=>p.trim().length>0):[e],u=m.map((p,g)=>({id:y("sha256").update(`${n}::${g}`).digest("hex").slice(0,16),content:p.trim(),sourcePath:n,contentType:"produced-knowledge",chunkIndex:g,totalChunks:m.length,startLine:0,endLine:0,fileHash:c,indexedAt:l,origin:"produced",tags:["analysis",r],category:"analysis",version:1})),h=await o.embedBatch(u.map(p=>p.content));await s.upsert(u,h),console.error(`[KB] Auto-persisted ${r} analysis (${u.length} chunks)`)}catch(t){console.error(`[KB] Auto-persist ${r} failed:`,t)}}function K(s,o,r){const i=new _;s.registerTool("analyze_structure",{description:"Analyze the file/directory structure of a codebase. Returns an annotated tree with language stats.",inputSchema:{path:a.string().describe("Root path to analyze"),max_depth:a.number().min(1).max(10).default(6).describe("Maximum directory depth"),format:a.enum(["json","markdown"]).default("markdown").describe("Output format")}},async({path:e,max_depth:t,format:n})=>{try{const c=await i.analyze(e,{format:n,maxDepth:t});return d(o,r,"structure",e,c.output),{content:[{type:"text",text:c.output+"\n\n---\n_Analysis auto-saved to KB. Next: Use `analyze_dependencies` for import graphs, or `analyze_patterns` to detect architecture patterns._"}]}}catch(c){return{content:[{type:"text",text:`Analysis failed: ${c.message}`}],isError:!0}}})}function k(s,o,r){const i=new x;s.registerTool("analyze_dependencies",{description:"Analyze import/require dependencies across a codebase. Shows external packages and internal module graph.",inputSchema:{path:a.string().describe("Root path to analyze"),format:a.enum(["json","markdown","mermaid"]).default("markdown").describe("Output format")}},async({path:e,format:t})=>{try{const n=await i.analyze(e,{format:t});return d(o,r,"dependencies",e,n.output),{content:[{type:"text",text:n.output+"\n\n---\n_Analysis auto-saved to KB. Next: Use `analyze_symbols` to explore exported symbols, or `analyze_diagram` for visual representation._"}]}}catch(n){return{content:[{type:"text",text:`Analysis failed: ${n.message}`}],isError:!0}}})}function I(s,o,r){const i=new v;s.registerTool("analyze_symbols",{description:"Extract exported and local symbols (functions, classes, interfaces, types, constants) from a codebase.",inputSchema:{path:a.string().describe("Root path to analyze"),filter:a.string().optional().describe("Filter symbols by name substring"),format:a.enum(["json","markdown"]).default("markdown").describe("Output format")}},async({path:e,filter:t,format:n})=>{try{const c=await i.analyze(e,{format:n,filter:t});return d(o,r,"symbols",e,c.output),{content:[{type:"text",text:c.output+"\n\n---\n_Analysis auto-saved to KB. Next: Use `analyze_dependencies` to see import relationships, or `search` to find usage patterns._"}]}}catch(c){return{content:[{type:"text",text:`Analysis failed: ${c.message}`}],isError:!0}}})}function T(s,o,r){const i=new z;s.registerTool("analyze_patterns",{description:"Detect architectural patterns, frameworks, and conventions in a codebase using directory structure and code heuristics.",inputSchema:{path:a.string().describe("Root path to analyze")}},async({path:e})=>{try{const t=await i.analyze(e);return d(o,r,"patterns",e,t.output),{content:[{type:"text",text:t.output+"\n\n---\n_Analysis auto-saved to KB. Next: Use `analyze_entry_points` to find Lambda handlers and main exports, or `produce_knowledge` for full analysis._"}]}}catch(t){return{content:[{type:"text",text:`Analysis failed: ${t.message}`}],isError:!0}}})}function $(s,o,r){const i=new w;s.registerTool("analyze_entry_points",{description:"Find entry points: Lambda handlers, main exports, CLI bins, and server start scripts.",inputSchema:{path:a.string().describe("Root path to analyze")}},async({path:e})=>{try{const t=await i.analyze(e);return d(o,r,"entry-points",e,t.output),{content:[{type:"text",text:t.output+"\n\n---\n_Analysis auto-saved to KB. Next: Use `analyze_dependencies` to see what each entry point imports, or `produce_knowledge` for comprehensive analysis._"}]}}catch(t){return{content:[{type:"text",text:`Analysis failed: ${t.message}`}],isError:!0}}})}function B(s,o,r){const i=new b;s.registerTool("analyze_diagram",{description:"Generate a Mermaid diagram of the codebase architecture or dependency graph.",inputSchema:{path:a.string().describe("Root path to analyze"),diagram_type:a.enum(["architecture","dependencies"]).default("architecture").describe("Type of diagram")}},async({path:e,diagram_type:t})=>{try{const n=await i.analyze(e,{diagramType:t});return d(o,r,"diagram",e,n.output),{content:[{type:"text",text:n.output+"\n\n---\n_Analysis auto-saved to KB. Next: Use `analyze_structure` for detailed file tree, or `produce_knowledge` for comprehensive analysis._"}]}}catch(n){return{content:[{type:"text",text:`Diagram generation failed: ${n.message}`}],isError:!0}}})}function R(s,o,r){const i=new f;s.registerTool("blast_radius",{description:"Given a list of changed files, trace the dependency graph to find all affected files (direct + transitive importers) and their tests. Useful for scoping code reviews and impact analysis.",inputSchema:{path:a.string().describe("Root path of the codebase"),files:a.array(a.string()).min(1).describe("Changed file paths (relative to root)"),max_depth:a.number().min(1).max(20).default(5).describe("Maximum transitive dependency depth"),format:a.enum(["json","markdown"]).default("markdown").describe("Output format")}},async({path:e,files:t,max_depth:n,format:c})=>{try{const l=await i.analyze(e,{files:t,maxDepth:n,format:c});return d(o,r,"blast-radius",e,l.output),{content:[{type:"text",text:l.output+"\n\n---\n_Analysis auto-saved to KB. Next: Use `analyze_dependencies` to see the full import graph, or `analyze_symbols` to inspect affected exports._"}]}}catch(l){return{content:[{type:"text",text:`Blast radius analysis failed: ${l.message}`}],isError:!0}}})}export{k as registerAnalyzeDependenciesTool,B as registerAnalyzeDiagramTool,$ as registerAnalyzeEntryPointsTool,T as registerAnalyzePatternsTool,K as registerAnalyzeStructureTool,I as registerAnalyzeSymbolsTool,R as registerBlastRadiusTool};
1
+ import{createHash as y}from"node:crypto";import{BlastRadiusAnalyzer as f,DependencyAnalyzer as x,DiagramGenerator as b,EntryPointAnalyzer as w,PatternAnalyzer as z,StructureAnalyzer as _,SymbolAnalyzer as v}from"../../../analyzers/dist/index.js";import{z as a}from"zod";async function d(s,o,r,i,e){try{const t=y("sha256").update(i).digest("hex").slice(0,12),n=`produced/analysis/${r}/${t}.md`,c=y("sha256").update(e).digest("hex").slice(0,16),l=new Date().toISOString(),m=e.length>2e3?e.split(/(?=^## )/m).filter(p=>p.trim().length>0):[e],u=m.map((p,g)=>({id:y("sha256").update(`${n}::${g}`).digest("hex").slice(0,16),content:p.trim(),sourcePath:n,contentType:"produced-knowledge",chunkIndex:g,totalChunks:m.length,startLine:0,endLine:0,fileHash:c,indexedAt:l,origin:"produced",tags:["analysis",r],category:"analysis",version:1})),h=await o.embedBatch(u.map(p=>p.content));await s.upsert(u,h),console.error(`[KB] Auto-persisted ${r} analysis (${u.length} chunks)`)}catch(t){console.error(`[KB] Auto-persist ${r} failed:`,t)}}function K(s,o,r){const i=new _;s.registerTool("analyze_structure",{description:"Analyze the file/directory structure of a codebase. Returns an annotated tree with language stats.",inputSchema:{path:a.string().describe("Root path to analyze"),max_depth:a.number().min(1).max(10).default(6).describe("Maximum directory depth"),format:a.enum(["json","markdown"]).default("markdown").describe("Output format")}},async({path:e,max_depth:t,format:n})=>{try{const c=await i.analyze(e,{format:n,maxDepth:t});return d(o,r,"structure",e,c.output),{content:[{type:"text",text:c.output+"\n\n---\n_Analysis auto-saved to KB. Next: Use `analyze_dependencies` for import graphs, or `analyze_patterns` to detect architecture patterns._"}]}}catch(c){return{content:[{type:"text",text:`Analysis failed: ${c.message}`}],isError:!0}}})}function I(s,o,r){const i=new x;s.registerTool("analyze_dependencies",{description:"Analyze import/require dependencies across a codebase. Shows external packages and internal module graph.",inputSchema:{path:a.string().describe("Root path to analyze"),format:a.enum(["json","markdown","mermaid"]).default("markdown").describe("Output format")}},async({path:e,format:t})=>{try{const n=await i.analyze(e,{format:t});return d(o,r,"dependencies",e,n.output),{content:[{type:"text",text:n.output+"\n\n---\n_Analysis auto-saved to KB. Next: Use `analyze_symbols` to explore exported symbols, or `analyze_diagram` for visual representation._"}]}}catch(n){return{content:[{type:"text",text:`Analysis failed: ${n.message}`}],isError:!0}}})}function T(s,o,r){const i=new v;s.registerTool("analyze_symbols",{description:"Extract exported and local symbols (functions, classes, interfaces, types, constants) from a codebase.",inputSchema:{path:a.string().describe("Root path to analyze"),filter:a.string().optional().describe("Filter symbols by name substring"),format:a.enum(["json","markdown"]).default("markdown").describe("Output format")}},async({path:e,filter:t,format:n})=>{try{const c=await i.analyze(e,{format:n,filter:t});return d(o,r,"symbols",e,c.output),{content:[{type:"text",text:c.output+"\n\n---\n_Analysis auto-saved to KB. Next: Use `analyze_dependencies` to see import relationships, or `search` to find usage patterns._"}]}}catch(c){return{content:[{type:"text",text:`Analysis failed: ${c.message}`}],isError:!0}}})}function k(s,o,r){const i=new z;s.registerTool("analyze_patterns",{description:"Detect architectural patterns, frameworks, and conventions in a codebase using directory structure and code heuristics.",inputSchema:{path:a.string().describe("Root path to analyze")}},async({path:e})=>{try{const t=await i.analyze(e);return d(o,r,"patterns",e,t.output),{content:[{type:"text",text:t.output+"\n\n---\n_Analysis auto-saved to KB. Next: Use `analyze_entry_points` to find Lambda handlers and main exports, or `produce_knowledge` for full analysis._"}]}}catch(t){return{content:[{type:"text",text:`Analysis failed: ${t.message}`}],isError:!0}}})}function $(s,o,r){const i=new w;s.registerTool("analyze_entry_points",{description:"Find entry points: Lambda handlers, main exports, CLI bins, and server start scripts.",inputSchema:{path:a.string().describe("Root path to analyze")}},async({path:e})=>{try{const t=await i.analyze(e);return d(o,r,"entry-points",e,t.output),{content:[{type:"text",text:t.output+"\n\n---\n_Analysis auto-saved to KB. Next: Use `analyze_dependencies` to see what each entry point imports, or `produce_knowledge` for comprehensive analysis._"}]}}catch(t){return{content:[{type:"text",text:`Analysis failed: ${t.message}`}],isError:!0}}})}function B(s,o,r){const i=new b;s.registerTool("analyze_diagram",{description:"Generate a Mermaid diagram of the codebase architecture or dependency graph.",inputSchema:{path:a.string().describe("Root path to analyze"),diagram_type:a.enum(["architecture","dependencies"]).default("architecture").describe("Type of diagram")}},async({path:e,diagram_type:t})=>{try{const n=await i.analyze(e,{diagramType:t});return d(o,r,"diagram",e,n.output),{content:[{type:"text",text:n.output+"\n\n---\n_Analysis auto-saved to KB. Next: Use `analyze_structure` for detailed file tree, or `produce_knowledge` for comprehensive analysis._"}]}}catch(n){return{content:[{type:"text",text:`Diagram generation failed: ${n.message}`}],isError:!0}}})}function R(s,o,r){const i=new f;s.registerTool("blast_radius",{description:"Given a list of changed files, trace the dependency graph to find all affected files (direct + transitive importers) and their tests. Useful for scoping code reviews and impact analysis.",inputSchema:{path:a.string().describe("Root path of the codebase"),files:a.array(a.string()).min(1).describe("Changed file paths (relative to root)"),max_depth:a.number().min(1).max(20).default(5).describe("Maximum transitive dependency depth"),format:a.enum(["json","markdown"]).default("markdown").describe("Output format")}},async({path:e,files:t,max_depth:n,format:c})=>{try{const l=await i.analyze(e,{files:t,maxDepth:n,format:c});return d(o,r,"blast-radius",e,l.output),{content:[{type:"text",text:l.output+"\n\n---\n_Analysis auto-saved to KB. Next: Use `analyze_dependencies` to see the full import graph, or `analyze_symbols` to inspect affected exports._"}]}}catch(l){return{content:[{type:"text",text:`Blast radius analysis failed: ${l.message}`}],isError:!0}}})}export{I as registerAnalyzeDependenciesTool,B as registerAnalyzeDiagramTool,$ as registerAnalyzeEntryPointsTool,k as registerAnalyzePatternsTool,K as registerAnalyzeStructureTool,T as registerAnalyzeSymbolsTool,R as registerBlastRadiusTool};
@@ -1,4 +1,4 @@
1
- import{digest as y,evidenceMap as g,forgeClassify as x,forgeGround as b,stratumCard as v}from"@kb/tools";import{z as t}from"zod";function T(m){m.registerTool("evidence_map",{description:"FORGE Evidence Map \u2014 track critical-path claims as Verified/Assumed/Unresolved with receipts. Supports CRUD operations and deterministic Gate evaluation (YIELD/HOLD/HARD_BLOCK/FORCED_DELIVERY). Persists across tool calls.",inputSchema:{action:t.enum(["create","add","update","get","gate","list","delete"]).describe("Operation to perform"),task_id:t.string().optional().describe("Task identifier (required for all except list)"),tier:t.enum(["floor","standard","critical"]).optional().describe("FORGE tier (required for create)"),claim:t.string().optional().describe("Critical-path claim text (for add)"),status:t.enum(["V","A","U"]).optional().describe("Evidence status: V=Verified, A=Assumed, U=Unresolved"),receipt:t.string().optional().describe("Evidence receipt: tool\u2192ref for V, reasoning for A, attempts for U"),id:t.number().optional().describe("Entry ID (for update)"),critical_path:t.boolean().default(!0).describe("Whether this claim is on the critical path"),unknown_type:t.enum(["contract","convention","freshness","runtime","data-flow","impact"]).optional().describe("Typed unknown classification"),retry_count:t.number().default(0).describe("Retry count for gate evaluation (0 = first attempt)"),cwd:t.string().optional().describe("Working directory for evidence map storage (default: server cwd). Use root_path from forge_ground to match.")}},async({action:h,task_id:s,tier:l,claim:c,status:i,receipt:d,id:o,critical_path:p,unknown_type:n,retry_count:r,cwd:u})=>{try{switch(h){case"create":{if(!s)throw new Error("task_id required for create");if(!l)throw new Error("tier required for create");return g({action:"create",taskId:s,tier:l},u),{content:[{type:"text",text:`Created evidence map "${s}" (tier: ${l}).
1
+ import{digest as x,evidenceMap as g,forgeClassify as y,forgeGround as b,stratumCard as v}from"../../../tools/dist/index.js";import{z as t}from"zod";function T(m){m.registerTool("evidence_map",{description:"FORGE Evidence Map \u2014 track critical-path claims as Verified/Assumed/Unresolved with receipts. Supports CRUD operations and deterministic Gate evaluation (YIELD/HOLD/HARD_BLOCK/FORCED_DELIVERY). Persists across tool calls.",inputSchema:{action:t.enum(["create","add","update","get","gate","list","delete"]).describe("Operation to perform"),task_id:t.string().optional().describe("Task identifier (required for all except list)"),tier:t.enum(["floor","standard","critical"]).optional().describe("FORGE tier (required for create)"),claim:t.string().optional().describe("Critical-path claim text (for add)"),status:t.enum(["V","A","U"]).optional().describe("Evidence status: V=Verified, A=Assumed, U=Unresolved"),receipt:t.string().optional().describe("Evidence receipt: tool\u2192ref for V, reasoning for A, attempts for U"),id:t.number().optional().describe("Entry ID (for update)"),critical_path:t.boolean().default(!0).describe("Whether this claim is on the critical path"),unknown_type:t.enum(["contract","convention","freshness","runtime","data-flow","impact"]).optional().describe("Typed unknown classification"),retry_count:t.number().default(0).describe("Retry count for gate evaluation (0 = first attempt)"),cwd:t.string().optional().describe("Working directory for evidence map storage (default: server cwd). Use root_path from forge_ground to match.")}},async({action:h,task_id:s,tier:l,claim:c,status:i,receipt:d,id:o,critical_path:p,unknown_type:n,retry_count:r,cwd:u})=>{try{switch(h){case"create":{if(!s)throw new Error("task_id required for create");if(!l)throw new Error("tier required for create");return g({action:"create",taskId:s,tier:l},u),{content:[{type:"text",text:`Created evidence map "${s}" (tier: ${l}).
2
2
 
3
3
  ---
4
4
  _Next: Use \`evidence_map\` with action "add" to record critical-path claims._`}]}}case"add":{if(!s)throw new Error("task_id required for add");if(!c)throw new Error("claim required for add");if(!i)throw new Error("status required for add");const e=g({action:"add",taskId:s,claim:c,status:i,receipt:d??"",criticalPath:p,unknownType:n},u),a=[`Added entry #${e.entry?.id} to "${s}": [${i}] ${c}`];return e.formattedMap&&a.push("",e.formattedMap),{content:[{type:"text",text:a.join(`
@@ -6,8 +6,8 @@ _Next: Use \`evidence_map\` with action "add" to record critical-path claims._`}
6
6
  `)}]}}case"get":{if(!s)throw new Error("task_id required for get");const e=g({action:"get",taskId:s},u);return e.state?{content:[{type:"text",text:[`## Evidence Map: ${s} (${e.state.tier})`,"",e.formattedMap??"No entries.","",`_${e.state.entries.length} entries \u2014 created ${e.state.createdAt}_`].join(`
7
7
  `)}]}:{content:[{type:"text",text:`Evidence map "${s}" not found.`}]}}case"gate":{if(!s)throw new Error("task_id required for gate");const e=g({action:"gate",taskId:s,retryCount:r},u);if(!e.gate)return{content:[{type:"text",text:`Evidence map "${s}" not found.`}]};const a=e.gate,f=[`## FORGE Gate: **${a.decision}**`,"",`**Reason:** ${a.reason}`,"",`**Stats:** ${a.stats.verified}V / ${a.stats.assumed}A / ${a.stats.unresolved}U (${a.stats.total} total)`];return a.warnings.length>0&&f.push("","**Warnings:**",...a.warnings.map($=>`- \u26A0\uFE0F ${$}`)),a.unresolvedCritical.length>0&&f.push("","**Blocking entries:**",...a.unresolvedCritical.map($=>`- #${$.id}: ${$.claim} [${$.unknownType??"untyped"}]`)),a.annotation&&f.push("","**Annotation:**",a.annotation),e.formattedMap&&f.push("","---","",e.formattedMap),f.push("","---",`_Next: ${a.decision==="YIELD"?"Proceed to implementation.":a.decision==="HOLD"?"Resolve blocking entries, then re-run gate.":a.decision==="HARD_BLOCK"?"Contract unknowns MUST be resolved. Use search or schema_validate.":"Proceed with annotation \u2014 document unresolved items in delivery."}_`),{content:[{type:"text",text:f.join(`
8
8
  `)}]}}case"list":{const e=g({action:"list"},u);return!e.states||e.states.length===0?{content:[{type:"text",text:"No evidence maps found."}]}:{content:[{type:"text",text:e.states.map(f=>`- **${f.taskId}** (${f.tier}) \u2014 ${f.entries.length} entries \u2014 ${f.updatedAt}`).join(`
9
- `)}]}}case"delete":{if(!s)throw new Error("task_id required for delete");return{content:[{type:"text",text:g({action:"delete",taskId:s},u).deleted?`Deleted evidence map "${s}".`:`Evidence map "${s}" not found.`}]}}}}catch(e){return{content:[{type:"text",text:`Evidence map error: ${e.message}`}],isError:!0}}})}function w(m,h){m.registerTool("digest",{description:"Compress multiple text sources (handoffs, debates, phase summaries) into a token-budgeted digest. Jointly ranks across all sources, pins structured fields (status, files, decisions, blockers), and allocates budget by priority weight.",inputSchema:{sources:t.array(t.object({id:t.string().describe('Source identifier (e.g., "phase-2-handoff")'),text:t.string().describe("Source text to compress"),weight:t.number().min(0).default(1).describe("Priority weight (higher = more budget)")})).min(1).describe("Text sources to compress"),query:t.string().describe("Focus query \u2014 what matters for the next step?"),max_chars:t.number().min(100).max(5e4).default(4e3).describe("Target budget in characters"),pin_fields:t.array(t.string()).optional().describe("Key fields to always extract (default: status, files, decisions, blockers, next)"),segmentation:t.enum(["paragraph","sentence","line"]).default("paragraph").describe("How to split text for scoring")}},async({sources:s,query:l,max_chars:c,pin_fields:i,segmentation:d})=>{try{const o=await y(h,{sources:s,query:l,maxChars:c,pinFields:i,segmentation:d}),p=[`## Digest (${o.totalOriginalChars} \u2192 ${o.totalCompressedChars} chars, ${(o.ratio*100).toFixed(0)}%)`,""],n=Object.keys(o.fields);if(n.length>0){p.push("### Extracted Fields");for(const r of n){const u=o.fields[r];p.push(`**${r}:**`);for(const e of u)p.push(` - [${e.sourceId}] ${e.value}`)}p.push("")}p.push("### Compressed Content","",o.text),p.push("","### Source Stats");for(const r of o.sourceStats)p.push(`- **${r.id}**: ${r.originalChars} \u2192 ${r.keptChars} chars (${r.segmentsKept}/${r.segmentsTotal} segments)`);return p.push("","---","_Next: Use the digest as compressed context for the next phase. Use `stash` to persist it if needed._"),{content:[{type:"text",text:p.join(`
10
- `)}]}}catch(o){return{content:[{type:"text",text:`Digest failed: ${o.message}`}],isError:!0}}})}function C(m){m.registerTool("forge_classify",{description:"Classify FORGE tier (Floor/Standard/Critical) from target files and task description. Checks blast radius, cross-package boundaries, schema/contract patterns, and security signals. Returns tier, triggers, typed unknown seeds, and ceremony guidance.",inputSchema:{files:t.array(t.string()).min(1).describe("Files being modified (paths)"),task:t.string().describe("Task description"),root_path:t.string().describe("Root path of the codebase")}},async({files:h,task:s,root_path:l})=>{try{const c=await x({files:h,task:s,rootPath:l}),i=[`## FORGE Classification: **${c.tier.toUpperCase()}**`,""];if(c.triggers.length>0){i.push("### Triggers");for(const o of c.triggers)i.push(`- **${o.rule}** (${o.source}): ${o.detail}`);i.push("")}if(c.packagesCrossed.length>0&&i.push(`**Packages crossed:** ${c.packagesCrossed.join(", ")}`),c.typedUnknownSeeds.length>0){i.push("","### Typed Unknown Seeds");for(const o of c.typedUnknownSeeds)i.push(`- [${o.type}] ${o.description} \u2192 use \`${o.suggestedTool}\``)}i.push("","### Ceremony");const d=c.ceremony;return i.push(`- **Ground:** ${d.ground}`,`- **Build:** ${d.build}`,`- **Break:** ${d.break}`,`- **Evidence Map:** ${d.evidenceMap}`,`- **Gate:** ${d.gate}`),i.push("","---",`_Next: ${c.tier==="floor"?"Proceed directly to implementation.":"Run `forge_ground` to execute the full Ground phase."}_`),{content:[{type:"text",text:i.join(`
9
+ `)}]}}case"delete":{if(!s)throw new Error("task_id required for delete");return{content:[{type:"text",text:g({action:"delete",taskId:s},u).deleted?`Deleted evidence map "${s}".`:`Evidence map "${s}" not found.`}]}}}}catch(e){return{content:[{type:"text",text:`Evidence map error: ${e.message}`}],isError:!0}}})}function w(m,h){m.registerTool("digest",{description:"Compress multiple text sources (handoffs, debates, phase summaries) into a token-budgeted digest. Jointly ranks across all sources, pins structured fields (status, files, decisions, blockers), and allocates budget by priority weight.",inputSchema:{sources:t.array(t.object({id:t.string().describe('Source identifier (e.g., "phase-2-handoff")'),text:t.string().describe("Source text to compress"),weight:t.number().min(0).default(1).describe("Priority weight (higher = more budget)")})).min(1).describe("Text sources to compress"),query:t.string().describe("Focus query \u2014 what matters for the next step?"),max_chars:t.number().min(100).max(5e4).default(4e3).describe("Target budget in characters"),pin_fields:t.array(t.string()).optional().describe("Key fields to always extract (default: status, files, decisions, blockers, next)"),segmentation:t.enum(["paragraph","sentence","line"]).default("paragraph").describe("How to split text for scoring")}},async({sources:s,query:l,max_chars:c,pin_fields:i,segmentation:d})=>{try{const o=await x(h,{sources:s,query:l,maxChars:c,pinFields:i,segmentation:d}),p=[`## Digest (${o.totalOriginalChars} \u2192 ${o.totalCompressedChars} chars, ${(o.ratio*100).toFixed(0)}%)`,""],n=Object.keys(o.fields);if(n.length>0){p.push("### Extracted Fields");for(const r of n){const u=o.fields[r];p.push(`**${r}:**`);for(const e of u)p.push(` - [${e.sourceId}] ${e.value}`)}p.push("")}p.push("### Compressed Content","",o.text),p.push("","### Source Stats");for(const r of o.sourceStats)p.push(`- **${r.id}**: ${r.originalChars} \u2192 ${r.keptChars} chars (${r.segmentsKept}/${r.segmentsTotal} segments)`);return p.push("","---","_Next: Use the digest as compressed context for the next phase. Use `stash` to persist it if needed._"),{content:[{type:"text",text:p.join(`
10
+ `)}]}}catch(o){return{content:[{type:"text",text:`Digest failed: ${o.message}`}],isError:!0}}})}function C(m){m.registerTool("forge_classify",{description:"Classify FORGE tier (Floor/Standard/Critical) from target files and task description. Checks blast radius, cross-package boundaries, schema/contract patterns, and security signals. Returns tier, triggers, typed unknown seeds, and ceremony guidance.",inputSchema:{files:t.array(t.string()).min(1).describe("Files being modified (paths)"),task:t.string().describe("Task description"),root_path:t.string().describe("Root path of the codebase")}},async({files:h,task:s,root_path:l})=>{try{const c=await y({files:h,task:s,rootPath:l}),i=[`## FORGE Classification: **${c.tier.toUpperCase()}**`,""];if(c.triggers.length>0){i.push("### Triggers");for(const o of c.triggers)i.push(`- **${o.rule}** (${o.source}): ${o.detail}`);i.push("")}if(c.packagesCrossed.length>0&&i.push(`**Packages crossed:** ${c.packagesCrossed.join(", ")}`),c.typedUnknownSeeds.length>0){i.push("","### Typed Unknown Seeds");for(const o of c.typedUnknownSeeds)i.push(`- [${o.type}] ${o.description} \u2192 use \`${o.suggestedTool}\``)}i.push("","### Ceremony");const d=c.ceremony;return i.push(`- **Ground:** ${d.ground}`,`- **Build:** ${d.build}`,`- **Break:** ${d.break}`,`- **Evidence Map:** ${d.evidenceMap}`,`- **Gate:** ${d.gate}`),i.push("","---",`_Next: ${c.tier==="floor"?"Proceed directly to implementation.":"Run `forge_ground` to execute the full Ground phase."}_`),{content:[{type:"text",text:i.join(`
11
11
  `)}]}}catch(c){return{content:[{type:"text",text:`FORGE classify failed: ${c.message}`}],isError:!0}}})}function M(m,h){m.registerTool("stratum_card",{description:"Generate STRATUM context cards from files. T1 = structural metadata (~100 tokens/file). T2 = T1 + compressed content (~300 tokens/file). Replaces reading full files \u2014 10-100x token reduction.",inputSchema:{files:t.array(t.string()).min(1).describe("Absolute file paths to generate cards for"),query:t.string().describe("Current task query \u2014 guides relevance scoring"),tier:t.enum(["T1","T2"]).default("T1").describe("Card tier: T1 = structural only, T2 = T1 + compressed content"),max_content_chars:t.number().min(100).max(5e3).default(800).describe("For T2: max chars for compressed content section")}},async({files:s,query:l,tier:c,max_content_chars:i})=>{try{const d=await v(h,{files:s,query:l,tier:c,maxContentChars:i}),o=[`## STRATUM Cards (${c}) \u2014 ${d.cards.length} files`,`Total: ~${d.totalTokenEstimate} tokens (was ~${d.totalOriginalTokenEstimate}, ${(d.compressionRatio*100).toFixed(0)}% of original)`,""];for(const p of d.cards)o.push(p.card,"");return o.push("---","_Next: Use these cards as context instead of reading full files. Use `compact` for deeper content extraction on specific files._"),{content:[{type:"text",text:o.join(`
12
12
  `)}]}}catch(d){return{content:[{type:"text",text:`STRATUM cards failed: ${d.message}`}],isError:!0}}})}function S(m,h,s){m.registerTool("forge_ground",{description:"Execute the complete FORGE Ground phase in a single call. Chains: tier classification \u2192 scope map \u2192 typed unknown seeds \u2192 constraint loading \u2192 file summaries \u2192 evidence map creation. Replaces 5-15 manual tool calls.",inputSchema:{task:t.string().describe("Task description"),files:t.array(t.string()).min(1).describe("Target files being modified (absolute paths)"),root_path:t.string().describe("Root path of the codebase"),max_constraints:t.number().min(0).max(10).default(3).describe("Max constraint entries to load from KB"),force_tier:t.enum(["floor","standard","critical"]).optional().describe("Force a specific tier (skips auto-classification)"),task_id:t.string().optional().describe("Custom task ID for evidence map (auto-generated if omitted)")}},async({task:l,files:c,root_path:i,max_constraints:d,force_tier:o,task_id:p})=>{try{const n=await b(h,s,{task:l,files:c,rootPath:i,maxConstraints:d,forceTier:o,taskId:p}),r=[`## FORGE Ground: **${n.tier.toUpperCase()}**`,`Estimated output: ~${n.estimatedTokens} tokens`,""];if(n.classifyTriggers.length>0){r.push("### Classification Triggers");for(const e of n.classifyTriggers)r.push(`- **${e.rule}** (${e.source}): ${e.detail}`);r.push("")}if(n.fileSummaries.length>0){r.push("### Target Files");for(const e of n.fileSummaries)r.push(`- **${e.path}** (${e.lines} lines) \u2014 exports: ${e.exports.join(", ")||"none"} \u2014 functions: ${e.functions.join(", ")||"none"}`);r.push("")}if(n.typedUnknownSeeds.length>0){r.push("### Typed Unknown Seeds");for(const e of n.typedUnknownSeeds)r.push(`- [${e.type}] ${e.description} \u2192 \`${e.suggestedTool}\``);r.push("")}if(n.constraints.length>0){r.push("### Constraint Seed");for(const e of n.constraints)r.push(`- **${e.source}** (${(e.relevance*100).toFixed(0)}%): ${e.snippet}`);r.push("")}if(n.scopeMap){r.push(`### Scope Map: ${n.scopeMap.files.length} files (~${n.scopeMap.totalEstimatedTokens} tokens)`);for(const e of n.scopeMap.files.slice(0,5))r.push(`- ${e.path} (${(e.relevance*100).toFixed(0)}%) \u2014 ${e.reason}`);n.scopeMap.files.length>5&&r.push(`- _...and ${n.scopeMap.files.length-5} more_`),r.push("")}n.evidenceMapTaskId&&(r.push(`**Evidence Map:** \`${n.evidenceMapTaskId}\` (initialized)`),r.push("")),r.push("### Ceremony Guidance");const u=n.ceremony;return r.push(`- **Ground:** ${u.ground}`,`- **Build:** ${u.build}`,`- **Break:** ${u.break}`,`- **Evidence Map:** ${u.evidenceMap}`,`- **Gate:** ${u.gate}`),r.push("","---",`_Next: ${n.tier==="floor"?"Proceed to Build phase.":"Use `evidence_map` to track claims during Build, then `evidence_map` gate after Break."}_`),{content:[{type:"text",text:r.join(`
13
13
  `)}]}}catch(n){return{content:[{type:"text",text:`FORGE Ground failed: ${n.message}`}],isError:!0}}})}export{w as registerDigestTool,T as registerEvidenceMapTool,C as registerForgeClassifyTool,S as registerForgeGroundTool,M as registerStratumCardTool};
@@ -1,4 +1,4 @@
1
- import{graphQuery as a}from"@kb/tools";import{z as e}from"zod";const p=e.object({id:e.string().optional().describe("Node ID (auto-generated if omitted)"),type:e.string().describe("Node type (entity, service, api, concept, decision)"),name:e.string().describe("Display name"),properties:e.record(e.string(),e.unknown()).optional().describe("Arbitrary properties"),sourceRecordId:e.string().optional().describe("Back-link to knowledge record ID"),sourcePath:e.string().optional().describe("Source file path")}),c=e.object({id:e.string().optional().describe("Edge ID (auto-generated if omitted)"),fromId:e.string().describe("Source node ID"),toId:e.string().describe("Target node ID"),type:e.string().describe("Relationship type (depends-on, implements, calls, affects)"),weight:e.number().min(0).max(1).optional().describe("Relationship weight"),properties:e.record(e.string(),e.unknown()).optional().describe("Arbitrary properties")});function h(n,s){n.registerTool("graph",{description:"Query and manage the knowledge graph. Find nodes/edges, traverse connections, add entities and relationships. The graph captures structural relationships between concepts discovered in the codebase.",inputSchema:{action:e.enum(["find_nodes","find_edges","neighbors","traverse","stats","add","delete","clear"]).describe("Action: find_nodes (search nodes), find_edges (search edges), neighbors (direct connections), traverse (multi-hop), stats (graph overview), add (insert nodes/edges), delete (remove nodes), clear (remove all)"),node_type:e.string().optional().describe("Node type filter (for find_nodes)"),name_pattern:e.string().optional().describe("Name substring match (for find_nodes)"),source_path:e.string().optional().describe("Source path filter"),node_id:e.string().optional().describe("Node ID (for neighbors, traverse, delete)"),edge_type:e.string().optional().describe("Edge type filter"),from_id:e.string().optional().describe("Source node ID (for find_edges)"),to_id:e.string().optional().describe("Target node ID (for find_edges)"),direction:e.enum(["outgoing","incoming","both"]).default("both").describe("Traversal direction"),max_depth:e.number().min(1).max(5).default(2).describe("Max traversal depth"),limit:e.number().min(1).max(100).default(50).describe("Max results"),nodes:e.array(p).optional().describe("Nodes to add (for action=add)"),edges:e.array(c).optional().describe("Edges to add (for action=add)")}},async t=>{try{const r=await a(s,{action:t.action,nodeType:t.node_type,namePattern:t.name_pattern,sourcePath:t.source_path,nodeId:t.node_id,edgeType:t.edge_type,fromId:t.from_id,toId:t.to_id,direction:t.direction,maxDepth:t.max_depth,limit:t.limit,nodes:t.nodes,edges:t.edges}),i=[r.summary];if(r.nodes&&r.nodes.length>0){i.push(`
1
+ import{graphQuery as a}from"../../../tools/dist/index.js";import{z as e}from"zod";const p=e.object({id:e.string().optional().describe("Node ID (auto-generated if omitted)"),type:e.string().describe("Node type (entity, service, api, concept, decision)"),name:e.string().describe("Display name"),properties:e.record(e.string(),e.unknown()).optional().describe("Arbitrary properties"),sourceRecordId:e.string().optional().describe("Back-link to knowledge record ID"),sourcePath:e.string().optional().describe("Source file path")}),c=e.object({id:e.string().optional().describe("Edge ID (auto-generated if omitted)"),fromId:e.string().describe("Source node ID"),toId:e.string().describe("Target node ID"),type:e.string().describe("Relationship type (depends-on, implements, calls, affects)"),weight:e.number().min(0).max(1).optional().describe("Relationship weight"),properties:e.record(e.string(),e.unknown()).optional().describe("Arbitrary properties")});function h(n,s){n.registerTool("graph",{description:"Query and manage the knowledge graph. Find nodes/edges, traverse connections, add entities and relationships. The graph captures structural relationships between concepts discovered in the codebase.",inputSchema:{action:e.enum(["find_nodes","find_edges","neighbors","traverse","stats","add","delete","clear"]).describe("Action: find_nodes (search nodes), find_edges (search edges), neighbors (direct connections), traverse (multi-hop), stats (graph overview), add (insert nodes/edges), delete (remove nodes), clear (remove all)"),node_type:e.string().optional().describe("Node type filter (for find_nodes)"),name_pattern:e.string().optional().describe("Name substring match (for find_nodes)"),source_path:e.string().optional().describe("Source path filter"),node_id:e.string().optional().describe("Node ID (for neighbors, traverse, delete)"),edge_type:e.string().optional().describe("Edge type filter"),from_id:e.string().optional().describe("Source node ID (for find_edges)"),to_id:e.string().optional().describe("Target node ID (for find_edges)"),direction:e.enum(["outgoing","incoming","both"]).default("both").describe("Traversal direction"),max_depth:e.number().min(1).max(5).default(2).describe("Max traversal depth"),limit:e.number().min(1).max(100).default(50).describe("Max results"),nodes:e.array(p).optional().describe("Nodes to add (for action=add)"),edges:e.array(c).optional().describe("Edges to add (for action=add)")}},async t=>{try{const r=await a(s,{action:t.action,nodeType:t.node_type,namePattern:t.name_pattern,sourcePath:t.source_path,nodeId:t.node_id,edgeType:t.edge_type,fromId:t.from_id,toId:t.to_id,direction:t.direction,maxDepth:t.max_depth,limit:t.limit,nodes:t.nodes,edges:t.edges}),i=[r.summary];if(r.nodes&&r.nodes.length>0){i.push(`
2
2
  ### Nodes`);for(const o of r.nodes){const d=Object.keys(o.properties).length>0?` \u2014 ${JSON.stringify(o.properties)}`:"";i.push(`- **${o.name}** (${o.type}, id: \`${o.id}\`)${d}`)}}if(r.edges&&r.edges.length>0){i.push(`
3
3
  ### Edges`);for(const o of r.edges)i.push(`- \`${o.fromId}\` \u2014[${o.type}]\u2192 \`${o.toId}\`${o.weight!==1?` (weight: ${o.weight})`:""}`)}return r.stats&&(i.push(`
4
4
  Node types: ${JSON.stringify(r.stats.nodeTypes)}`),i.push(`Edge types: ${JSON.stringify(r.stats.edgeTypes)}`)),i.push("\n---\n_Next: Use `graph(traverse)` to explore connections, `graph(add)` to insert entities, or `search` with graph-augmented results._"),{content:[{type:"text",text:i.join(`
@@ -1,2 +1,2 @@
1
- import{createHash as m}from"node:crypto";import{onboard as g}from"@kb/tools";import{z as l}from"zod";async function b(c,p,d){for(const t of d.steps)if(!(t.status!=="success"||!t.output))try{const s=m("sha256").update(d.path).digest("hex").slice(0,12),u=`produced/onboard/${t.name}/${s}.md`,e=m("sha256").update(t.output).digest("hex").slice(0,16),r=new Date().toISOString(),a=t.output.length>2e3?t.output.split(/(?=^## )/m).filter(i=>i.trim().length>0):[t.output],n=a.map((i,h)=>({id:m("sha256").update(`${u}::${h}`).digest("hex").slice(0,16),content:i.trim(),sourcePath:u,contentType:"produced-knowledge",chunkIndex:h,totalChunks:a.length,startLine:0,endLine:0,fileHash:e,indexedAt:r,origin:"produced",tags:["onboard",t.name],category:"analysis",version:1})),o=await p.embedBatch(n.map(i=>i.content));await c.upsert(n,o)}catch(s){console.error(`[KB] Auto-persist onboard/${t.name} failed:`,s)}}function w(c,p,d){c.registerTool("onboard",{description:"First-time codebase onboarding: runs all analysis tools (structure, dependencies, entry-points, symbols, patterns, diagram) in one command. Results are auto-persisted to KB. Use mode=generate to also write structured output to .ai/kb/ directory.",inputSchema:{path:l.string().describe("Root path of the codebase to onboard"),mode:l.enum(["memory","generate"]).default("memory").describe("Output mode: memory = KB vector store only; generate = also write to .ai/kb/ directory"),out_dir:l.string().optional().describe("Custom output directory for generate mode (default: <path>/.ai/kb)")}},async({path:t,mode:s,out_dir:u})=>{try{console.error(`[KB] Starting onboard for: ${t} (mode: ${s})`);const e=await g({path:t,mode:s,outDir:u});b(p,d,e);const r=["## Onboard Complete","",`**Path:** \`${e.path}\``,`**Mode:** ${e.mode}`,`**Duration:** ${e.totalDurationMs}ms`,""];e.outDir&&(r.push(`**Output directory:** \`${e.outDir}\``),r.push("")),r.push("### Analysis Results","");const a=[],n=[];for(const o of e.steps)o.status==="success"?a.push(`- \u2713 **${o.name}** (${o.durationMs}ms) \u2014 ${o.output.length} chars`):n.push(`- \u2717 **${o.name}** \u2014 ${o.error}`);r.push(...a),n.length>0&&r.push("","### Failed","",...n),r.push("","---","");for(const o of e.steps)o.status==="success"&&r.push(`### ${o.name}`,"",o.output,"","---","");return r.push("_All results auto-saved to KB.",e.mode==="generate"?` Files written to \`${e.outDir}\`.`:""," Next: Use `search` to query the knowledge, or `remember` to add custom insights._"),{content:[{type:"text",text:r.join(`
1
+ import{createHash as m}from"node:crypto";import{onboard as g}from"../../../tools/dist/index.js";import{z as l}from"zod";async function f(c,p,d){for(const t of d.steps)if(!(t.status!=="success"||!t.output))try{const r=m("sha256").update(d.path).digest("hex").slice(0,12),u=`produced/onboard/${t.name}/${r}.md`,e=m("sha256").update(t.output).digest("hex").slice(0,16),s=new Date().toISOString(),a=t.output.length>2e3?t.output.split(/(?=^## )/m).filter(i=>i.trim().length>0):[t.output],n=a.map((i,h)=>({id:m("sha256").update(`${u}::${h}`).digest("hex").slice(0,16),content:i.trim(),sourcePath:u,contentType:"produced-knowledge",chunkIndex:h,totalChunks:a.length,startLine:0,endLine:0,fileHash:e,indexedAt:s,origin:"produced",tags:["onboard",t.name],category:"analysis",version:1})),o=await p.embedBatch(n.map(i=>i.content));await c.upsert(n,o)}catch(r){console.error(`[KB] Auto-persist onboard/${t.name} failed:`,r)}}function w(c,p,d){c.registerTool("onboard",{description:"First-time codebase onboarding: runs all analysis tools (structure, dependencies, entry-points, symbols, patterns, diagram) in one command. Results are auto-persisted to KB. Use mode=generate to also write structured output to .ai/kb/ directory.",inputSchema:{path:l.string().describe("Root path of the codebase to onboard"),mode:l.enum(["memory","generate"]).default("memory").describe("Output mode: memory = KB vector store only; generate = also write to .ai/kb/ directory"),out_dir:l.string().optional().describe("Custom output directory for generate mode (default: <path>/.ai/kb)")}},async({path:t,mode:r,out_dir:u})=>{try{console.error(`[KB] Starting onboard for: ${t} (mode: ${r})`);const e=await g({path:t,mode:r,outDir:u});f(p,d,e);const s=["## Onboard Complete","",`**Path:** \`${e.path}\``,`**Mode:** ${e.mode}`,`**Duration:** ${e.totalDurationMs}ms`,""];e.outDir&&(s.push(`**Output directory:** \`${e.outDir}\``),s.push("")),s.push("### Analysis Results","");const a=[],n=[];for(const o of e.steps)o.status==="success"?a.push(`- \u2713 **${o.name}** (${o.durationMs}ms) \u2014 ${o.output.length} chars`):n.push(`- \u2717 **${o.name}** \u2014 ${o.error}`);s.push(...a),n.length>0&&s.push("","### Failed","",...n),s.push("","---","");for(const o of e.steps)o.status==="success"&&s.push(`### ${o.name}`,"",o.output,"","---","");return s.push("_All results auto-saved to KB.",e.mode==="generate"?` Files written to \`${e.outDir}\`.`:""," Next: Use `search` to query the knowledge, or `remember` to add custom insights._"),{content:[{type:"text",text:s.join(`
2
2
  `)}]}}catch(e){return console.error("[KB] Onboard failed:",e),{content:[{type:"text",text:`Onboard failed: ${e.message}`}],isError:!0}}})}export{w as registerOnboardTool};
@@ -1,4 +1,4 @@
1
- import{DependencyAnalyzer as c,DiagramGenerator as d,EntryPointAnalyzer as l,KnowledgeProducer as u,PatternAnalyzer as p,StructureAnalyzer as y,SymbolAnalyzer as m}from"@kb/analyzers";import{z as n}from"zod";function h(o){const s={structure:new y,dependencies:new c,symbols:new m,patterns:new p,entryPoints:new l,diagrams:new d},r=new u(s);o.registerTool("produce_knowledge",{description:"Run automated codebase analysis and produce synthesis instructions. Executes Tier 1 deterministic analyzers, then returns structured baselines and instructions for you to synthesize knowledge using remember.",inputSchema:{scope:n.string().optional().describe("Root path to analyze (defaults to workspace root)"),aspects:n.array(n.enum(["all","structure","dependencies","symbols","patterns","entry-points","diagrams"])).default(["all"]).describe("Which analysis aspects to run")}},async({scope:i,aspects:t})=>{try{const e=i??".";console.error(`[KB] Running knowledge production for: ${e}, aspects: ${t.join(", ")}`);const a=await r.runExtraction(e,t);return{content:[{type:"text",text:r.buildSynthesisInstructions(a,t)+`
1
+ import{DependencyAnalyzer as c,DiagramGenerator as d,EntryPointAnalyzer as l,KnowledgeProducer as u,PatternAnalyzer as p,StructureAnalyzer as y,SymbolAnalyzer as m}from"../../../analyzers/dist/index.js";import{z as n}from"zod";function h(o){const s={structure:new y,dependencies:new c,symbols:new m,patterns:new p,entryPoints:new l,diagrams:new d},r=new u(s);o.registerTool("produce_knowledge",{description:"Run automated codebase analysis and produce synthesis instructions. Executes Tier 1 deterministic analyzers, then returns structured baselines and instructions for you to synthesize knowledge using remember.",inputSchema:{scope:n.string().optional().describe("Root path to analyze (defaults to workspace root)"),aspects:n.array(n.enum(["all","structure","dependencies","symbols","patterns","entry-points","diagrams"])).default(["all"]).describe("Which analysis aspects to run")}},async({scope:i,aspects:t})=>{try{const e=i??".";console.error(`[KB] Running knowledge production for: ${e}, aspects: ${t.join(", ")}`);const a=await r.runExtraction(e,t);return{content:[{type:"text",text:r.buildSynthesisInstructions(a,t)+`
2
2
 
3
3
  ---
4
4
  _Next: Review the baselines above and use \`remember\` to store synthesized knowledge entries._`}]}}catch(e){return console.error("[KB] Knowledge production failed:",e),{content:[{type:"text",text:`Knowledge production failed: ${e.message}`}],isError:!0}}})}export{h as registerProduceKnowledgeTool};
@@ -1,2 +1,2 @@
1
- import{z as u}from"zod";function f(l,s,i,c,d){l.registerTool("reindex",{description:"Trigger re-indexing of the knowledge base. Can do incremental (only changed files) or full re-index.",inputSchema:{full:u.boolean().default(!1).describe("If true, force full re-index ignoring file hashes")}},async({full:a})=>{try{console.error(`[KB] Starting ${a?"full":"incremental"} re-index...`);const r=e=>o=>{o.phase==="chunking"&&o.currentFile&&console.error(`[KB] ${e} [${o.filesProcessed+1}/${o.filesTotal}] ${o.currentFile}`)},t=a?await s.reindexAll(i,r("Reindex")):await s.index(i,r("Index")),n=["## Re-index Complete","",`- **Files Processed**: ${t.filesProcessed}`,`- **Files Skipped** (unchanged): ${t.filesSkipped}`,`- **Chunks Created**: ${t.chunksCreated}`,`- **Files Removed**: ${t.filesRemoved}`,`- **Duration**: ${(t.durationMs/1e3).toFixed(1)}s`];if(d)try{await d.createFtsIndex()}catch(e){n.push("",`- **FTS Index Failed**: ${e.message}`)}try{const e=await c.reindexAll();n.push("",`- **Curated Entries Re-indexed**: ${e.indexed}`),e.errors.length>0&&n.push(`- **Curated Errors**: ${e.errors.length}`),console.error(`[KB] Curated re-index: ${e.indexed} entries`)}catch(e){n.push("",`- **Curated Re-index Failed**: ${e.message}`),console.error("[KB] Curated re-index failed:",e)}return{content:[{type:"text",text:n.join(`
1
+ import{z as u}from"zod";function f(l,i,o,c,d){l.registerTool("reindex",{description:"Trigger re-indexing of the knowledge base. Can do incremental (only changed files) or full re-index.",inputSchema:{full:u.boolean().default(!1).describe("If true, force full re-index ignoring file hashes")}},async({full:a})=>{try{console.error(`[KB] Starting ${a?"full":"incremental"} re-index...`);const r=e=>s=>{s.phase==="chunking"&&s.currentFile&&console.error(`[KB] ${e} [${s.filesProcessed+1}/${s.filesTotal}] ${s.currentFile}`)},t=a?await i.reindexAll(o,r("Reindex")):await i.index(o,r("Index")),n=["## Re-index Complete","",`- **Files Processed**: ${t.filesProcessed}`,`- **Files Skipped** (unchanged): ${t.filesSkipped}`,`- **Chunks Created**: ${t.chunksCreated}`,`- **Files Removed**: ${t.filesRemoved}`,`- **Duration**: ${(t.durationMs/1e3).toFixed(1)}s`];if(d)try{await d.createFtsIndex()}catch(e){n.push("",`- **FTS Index Failed**: ${e.message}`)}try{const e=await c.reindexAll();n.push("",`- **Curated Entries Re-indexed**: ${e.indexed}`),e.errors.length>0&&n.push(`- **Curated Errors**: ${e.errors.length}`),console.error(`[KB] Curated re-index: ${e.indexed} entries`)}catch(e){n.push("",`- **Curated Re-index Failed**: ${e.message}`),console.error("[KB] Curated re-index failed:",e)}return{content:[{type:"text",text:n.join(`
2
2
  `)+"\n\n---\n_Next: Use `search` to query the refreshed index, or `status` to verify index stats._"}]}}catch(r){return console.error("[KB] Reindex failed:",r),{content:[{type:"text",text:`Reindex failed: ${r.message}`}],isError:!0}}})}export{f as registerReindexTool};
@@ -1,4 +1,4 @@
1
- import{replayClear as u,replayList as d,replayTrim as m}from"@kb/tools";import{z as o}from"zod";function f(n){n.registerTool("replay_list",{description:"View the audit trail of recent MCP tool and CLI invocations. Shows tool name, duration, status, and input/output summaries. Useful for debugging agent behavior and understanding what happened.",inputSchema:{last:o.number().optional().describe("Number of entries to return (default: 20)"),tool:o.string().optional().describe('Filter by tool name (e.g., "search")'),source:o.enum(["mcp","cli"]).optional().describe('Filter by source: "mcp" or "cli"'),since:o.string().optional().describe("ISO timestamp \u2014 only show entries after this time")}},async({last:r,tool:s,source:i,since:a})=>{try{const e=d({last:r,tool:s,source:i,since:a});if(e.length===0)return{content:[{type:"text",text:"No replay entries found. Activity is logged when tools are invoked via MCP or CLI."}]};const l=e.map(t=>{const c=t.ts.split("T")[1]?.split(".")[0]??t.ts,p=t.status==="ok"?"\u2713":"\u2717";return`${c} ${p} ${t.tool} (${t.durationMs}ms) [${t.source}]
1
+ import{replayClear as u,replayList as d,replayTrim as m}from"../../../tools/dist/index.js";import{z as o}from"zod";function f(n){n.registerTool("replay_list",{description:"View the audit trail of recent MCP tool and CLI invocations. Shows tool name, duration, status, and input/output summaries. Useful for debugging agent behavior and understanding what happened.",inputSchema:{last:o.number().optional().describe("Number of entries to return (default: 20)"),tool:o.string().optional().describe('Filter by tool name (e.g., "search")'),source:o.enum(["mcp","cli"]).optional().describe('Filter by source: "mcp" or "cli"'),since:o.string().optional().describe("ISO timestamp \u2014 only show entries after this time")}},async({last:r,tool:s,source:i,since:a})=>{try{const e=d({last:r,tool:s,source:i,since:a});if(e.length===0)return{content:[{type:"text",text:"No replay entries found. Activity is logged when tools are invoked via MCP or CLI."}]};const l=e.map(t=>{const c=t.ts.split("T")[1]?.split(".")[0]??t.ts,p=t.status==="ok"?"\u2713":"\u2717";return`${c} ${p} ${t.tool} (${t.durationMs}ms) [${t.source}]
2
2
  in: ${t.input}
3
3
  out: ${t.output}`});return m(),{content:[{type:"text",text:`**Replay Log** (${e.length} entries)
4
4
 
@@ -1,21 +1,21 @@
1
- import{graphAugmentSearch as F}from"@kb/tools";import{z as f}from"zod";function j(m,y,a=60){const o=new Map;for(let e=0;e<m.length;e++){const t=m[e];o.set(t.record.id,{record:t.record,score:1/(a+e+1)})}for(let e=0;e<y.length;e++){const t=y[e],l=o.get(t.record.id);l?l.score+=1/(a+e+1):o.set(t.record.id,{record:t.record,score:1/(a+e+1)})}return[...o.values()].sort((e,t)=>t.score-e.score).map(({record:e,score:t})=>({record:e,score:t}))}function L(m,y){const a=y.toLowerCase().split(/\s+/).filter(o=>o.length>=2);return a.length<2?m:m.map(o=>{const e=o.record.content.toLowerCase(),t=a.map(i=>{const h=[];let r=e.indexOf(i);for(;r!==-1;)h.push(r),r=e.indexOf(i,r+1);return h});if(t.some(i=>i.length===0))return o;let l=e.length;for(const i of t[0]){let h=i,r=i+a[0].length;for(let d=1;d<t.length;d++){let g=t[d][0],p=Math.abs(g-i);for(let c=1;c<t[d].length;c++){const w=Math.abs(t[d][c]-i);w<p&&(p=w,g=t[d][c])}h=Math.min(h,g),r=Math.max(r,g+a[d].length)}l=Math.min(l,r-h)}const s=1+.25/(1+l/200);return{record:o.record,score:o.score*s}}).sort((o,e)=>e.score-o.score)}function I(m,y,a=8){const o=new Set(y.toLowerCase().split(/\s+/).filter(s=>s.length>=2)),e=new Map,t=m.length;for(const s of m){const i=new Set(s.record.content.split(/[^a-zA-Z0-9_]+/).filter(r=>r.length>=3&&!_.has(r.toLowerCase())));for(const r of i){const d=r.toLowerCase();/[_A-Z]/.test(r)&&e.set(`__id__${d}`,1)}const h=new Set(s.record.content.toLowerCase().split(/[^a-zA-Z0-9_]+/).filter(r=>r.length>=3&&!_.has(r)));for(const r of h)e.set(r,(e.get(r)??0)+1)}const l=[];for(const[s,i]of e){if(s.startsWith("__id__")||o.has(s)||i>t*.8)continue;const h=Math.log(t/i),r=e.has(`__id__${s}`)?1:0,d=s.length>8?.5:0;l.push({term:s,score:h+r+d})}return l.sort((s,i)=>i.score-s.score).slice(0,a).map(s=>s.term)}const _=new Set(["the","and","for","are","but","not","you","all","can","had","her","was","one","our","out","has","have","from","this","that","with","they","been","said","each","which","their","will","other","about","many","then","them","these","some","would","make","like","into","could","time","very","when","come","just","know","take","people","also","back","after","only","more","than","over","such","import","export","const","function","return","true","false","null","undefined","string","number","boolean","void","type","interface"]);function O(m,y,a,o){m.registerTool("search",{description:"Search the knowledge base with hybrid vector + keyword matching (BM25 + RRF fusion). Best for finding code, docs, and prior decisions. Supports semantic, keyword, and hybrid modes.",inputSchema:{query:f.string().describe("Natural language search query"),limit:f.number().min(1).max(20).default(5).describe("Maximum results to return"),search_mode:f.enum(["hybrid","semantic","keyword"]).default("hybrid").describe("Search strategy: hybrid (vector + FTS + RRF fusion, default), semantic (vector only), keyword (FTS only)"),content_type:f.enum(["markdown","code-typescript","code-javascript","code-python","config-json","config-yaml","config-toml","config-dotenv","infrastructure","documentation","test","script","curated-knowledge","produced-knowledge","other"]).optional().describe("Filter by content type"),origin:f.enum(["indexed","curated","produced"]).optional().describe("Filter by knowledge origin"),category:f.string().optional().describe("Filter by category (e.g., decisions, patterns, conventions)"),tags:f.array(f.string()).optional().describe("Filter by tags (returns results matching ANY of the specified tags)"),min_score:f.number().min(0).max(1).default(.25).describe("Minimum similarity score"),graph_hops:f.number().min(0).max(3).default(0).describe("Number of graph hops to augment results with (0 = no graph context, 1-3 = enrich results with connected entities)")}},async({query:e,limit:t,search_mode:l,content_type:s,origin:i,category:h,tags:r,min_score:d,graph_hops:g})=>{try{const p={limit:t,minScore:d,contentType:s,origin:i,category:h,tags:r};let c;if(l==="keyword")c=await a.ftsSearch(e,p),c=c.slice(0,t);else if(l==="semantic"){const u=await y.embedQuery(e);c=await a.search(u,p)}else{const u=await y.embedQuery(e),[S,n]=await Promise.all([a.search(u,{...p,limit:t*2}),a.ftsSearch(e,{...p,limit:t*2}).catch(()=>[])]);c=j(S,n).slice(0,t)}if(c.length>1&&(c=L(c,e)),c.length===0)return{content:[{type:"text",text:"No results found for the given query."}]};let w,$;if(g>0&&!o&&($="> **Note:** `graph_hops` was set but no graph store is available. Graph augmentation skipped."),g>0&&o)try{const u=c.map(n=>({recordId:n.record.id,score:n.score,sourcePath:n.record.sourcePath})),S=await F(o,u,{hops:g,maxPerHit:5});w=new Map;for(const n of S)if(n.graphContext.nodes.length>0){const x=n.graphContext.nodes.slice(0,5).map(b=>` - **${b.name}** (${b.type})`).join(`
2
- `),k=n.graphContext.edges.slice(0,5).map(b=>` - ${b.fromId} \u2014[${b.type}]\u2192 ${b.toId}`).join(`
3
- `),v=[`- **Graph Context** (${g} hop${g>1?"s":""}):`];x&&v.push(` Entities:
4
- ${x}`),k&&v.push(` Relationships:
5
- ${k}`),w.set(n.recordId,v.join(`
6
- `))}}catch(u){console.error("[KB] Graph augmentation failed (non-fatal):",u),$="> **Note:** Graph augmentation failed. Results shown without graph context."}const M=c.map((u,S)=>{const n=u.record,x=`### Result ${S+1} (score: ${u.score.toFixed(3)})`,k=[`- **Source**: ${n.sourcePath}`,n.headingPath?`- **Section**: ${n.headingPath}`:null,`- **Type**: ${n.contentType}`,n.startLine?`- **Lines**: ${n.startLine}-${n.endLine}`:null,n.origin!=="indexed"?`- **Origin**: ${n.origin}`:null,n.category?`- **Category**: ${n.category}`:null,n.tags?.length?`- **Tags**: ${n.tags.join(", ")}`:null,w?.get(n.id)??null].filter(Boolean).join(`
7
- `);return`${x}
8
- ${k}
1
+ import{graphAugmentSearch as C}from"../../../tools/dist/index.js";import{z as f}from"zod";function F(m,y,a=60){const o=new Map;for(let e=0;e<m.length;e++){const t=m[e];o.set(t.record.id,{record:t.record,score:1/(a+e+1)})}for(let e=0;e<y.length;e++){const t=y[e],d=o.get(t.record.id);d?d.score+=1/(a+e+1):o.set(t.record.id,{record:t.record,score:1/(a+e+1)})}return[...o.values()].sort((e,t)=>t.score-e.score).map(({record:e,score:t})=>({record:e,score:t}))}function L(m,y){const a=y.toLowerCase().split(/\s+/).filter(o=>o.length>=2);return a.length<2?m:m.map(o=>{const e=o.record.content.toLowerCase(),t=a.map(i=>{const h=[];let r=e.indexOf(i);for(;r!==-1;)h.push(r),r=e.indexOf(i,r+1);return h});if(t.some(i=>i.length===0))return o;let d=e.length;for(const i of t[0]){let h=i,r=i+a[0].length;for(let l=1;l<t.length;l++){let g=t[l][0],p=Math.abs(g-i);for(let c=1;c<t[l].length;c++){const w=Math.abs(t[l][c]-i);w<p&&(p=w,g=t[l][c])}h=Math.min(h,g),r=Math.max(r,g+a[l].length)}d=Math.min(d,r-h)}const s=1+.25/(1+d/200);return{record:o.record,score:o.score*s}}).sort((o,e)=>e.score-o.score)}function I(m,y,a=8){const o=new Set(y.toLowerCase().split(/\s+/).filter(s=>s.length>=2)),e=new Map,t=m.length;for(const s of m){const i=new Set(s.record.content.split(/[^a-zA-Z0-9_]+/).filter(r=>r.length>=3&&!_.has(r.toLowerCase())));for(const r of i){const l=r.toLowerCase();/[_A-Z]/.test(r)&&e.set(`__id__${l}`,1)}const h=new Set(s.record.content.toLowerCase().split(/[^a-zA-Z0-9_]+/).filter(r=>r.length>=3&&!_.has(r)));for(const r of h)e.set(r,(e.get(r)??0)+1)}const d=[];for(const[s,i]of e){if(s.startsWith("__id__")||o.has(s)||i>t*.8)continue;const h=Math.log(t/i),r=e.has(`__id__${s}`)?1:0,l=s.length>8?.5:0;d.push({term:s,score:h+r+l})}return d.sort((s,i)=>i.score-s.score).slice(0,a).map(s=>s.term)}const _=new Set(["the","and","for","are","but","not","you","all","can","had","her","was","one","our","out","has","have","from","this","that","with","they","been","said","each","which","their","will","other","about","many","then","them","these","some","would","make","like","into","could","time","very","when","come","just","know","take","people","also","back","after","only","more","than","over","such","import","export","const","function","return","true","false","null","undefined","string","number","boolean","void","type","interface"]);function O(m,y,a,o){m.registerTool("search",{description:"Search the knowledge base with hybrid vector + keyword matching (BM25 + RRF fusion). Best for finding code, docs, and prior decisions. Supports semantic, keyword, and hybrid modes.",inputSchema:{query:f.string().describe("Natural language search query"),limit:f.number().min(1).max(20).default(5).describe("Maximum results to return"),search_mode:f.enum(["hybrid","semantic","keyword"]).default("hybrid").describe("Search strategy: hybrid (vector + FTS + RRF fusion, default), semantic (vector only), keyword (FTS only)"),content_type:f.enum(["markdown","code-typescript","code-javascript","code-python","config-json","config-yaml","config-toml","config-dotenv","infrastructure","documentation","test","script","curated-knowledge","produced-knowledge","other"]).optional().describe("Filter by content type"),origin:f.enum(["indexed","curated","produced"]).optional().describe("Filter by knowledge origin"),category:f.string().optional().describe("Filter by category (e.g., decisions, patterns, conventions)"),tags:f.array(f.string()).optional().describe("Filter by tags (returns results matching ANY of the specified tags)"),min_score:f.number().min(0).max(1).default(.25).describe("Minimum similarity score"),graph_hops:f.number().min(0).max(3).default(0).describe("Number of graph hops to augment results with (0 = no graph context, 1-3 = enrich results with connected entities)")}},async({query:e,limit:t,search_mode:d,content_type:s,origin:i,category:h,tags:r,min_score:l,graph_hops:g})=>{try{const p={limit:t,minScore:l,contentType:s,origin:i,category:h,tags:r};let c;if(d==="keyword")c=await a.ftsSearch(e,p),c=c.slice(0,t);else if(d==="semantic"){const u=await y.embedQuery(e);c=await a.search(u,p)}else{const u=await y.embedQuery(e),[S,n]=await Promise.all([a.search(u,{...p,limit:t*2}),a.ftsSearch(e,{...p,limit:t*2}).catch(()=>[])]);c=F(S,n).slice(0,t)}if(c.length>1&&(c=L(c,e)),c.length===0)return{content:[{type:"text",text:"No results found for the given query."}]};let w,x;if(g>0&&!o&&(x="> **Note:** `graph_hops` was set but no graph store is available. Graph augmentation skipped."),g>0&&o)try{const u=c.map(n=>({recordId:n.record.id,score:n.score,sourcePath:n.record.sourcePath})),S=await C(o,u,{hops:g,maxPerHit:5});w=new Map;for(const n of S)if(n.graphContext.nodes.length>0){const $=n.graphContext.nodes.slice(0,5).map(b=>` - **${b.name}** (${b.type})`).join(`
2
+ `),v=n.graphContext.edges.slice(0,5).map(b=>` - ${b.fromId} \u2014[${b.type}]\u2192 ${b.toId}`).join(`
3
+ `),k=[`- **Graph Context** (${g} hop${g>1?"s":""}):`];$&&k.push(` Entities:
4
+ ${$}`),v&&k.push(` Relationships:
5
+ ${v}`),w.set(n.recordId,k.join(`
6
+ `))}}catch(u){console.error("[KB] Graph augmentation failed (non-fatal):",u),x="> **Note:** Graph augmentation failed. Results shown without graph context."}const M=c.map((u,S)=>{const n=u.record,$=`### Result ${S+1} (score: ${u.score.toFixed(3)})`,v=[`- **Source**: ${n.sourcePath}`,n.headingPath?`- **Section**: ${n.headingPath}`:null,`- **Type**: ${n.contentType}`,n.startLine?`- **Lines**: ${n.startLine}-${n.endLine}`:null,n.origin!=="indexed"?`- **Origin**: ${n.origin}`:null,n.category?`- **Category**: ${n.category}`:null,n.tags?.length?`- **Tags**: ${n.tags.join(", ")}`:null,w?.get(n.id)??null].filter(Boolean).join(`
7
+ `);return`${$}
8
+ ${v}
9
9
 
10
10
  ${n.content}`}).join(`
11
11
 
12
12
  ---
13
13
 
14
- `),T=l==="hybrid"?"hybrid (vector + keyword RRF)":l==="keyword"?"keyword (FTS)":"semantic (vector)",R=I(c,e),C=R.length>0?`
15
- _Distinctive terms: ${R.map(u=>`\`${u}\``).join(", ")}_`:"";return{content:[{type:"text",text:`${$?`${$}
14
+ `),T=d==="hybrid"?"hybrid (vector + keyword RRF)":d==="keyword"?"keyword (FTS)":"semantic (vector)",R=I(c,e),j=R.length>0?`
15
+ _Distinctive terms: ${R.map(u=>`\`${u}\``).join(", ")}_`:"";return{content:[{type:"text",text:`${x?`${x}
16
16
 
17
17
  `:""}${M}
18
18
 
19
19
  ---
20
- _Search mode: ${T} | ${c.length} results_${C}
20
+ _Search mode: ${T} | ${c.length} results_${j}
21
21
  _Next: Use \`lookup\` to see all chunks from a specific file, or \`analyze_structure\` to understand the codebase layout._`}]}}catch(p){return console.error("[KB] Search failed:",p),{content:[{type:"text",text:`Search failed: ${p.message}`}],isError:!0}}})}export{O as registerSearchTool};
@@ -1,3 +1,3 @@
1
- function p(c,n,a){c.registerTool("status",{description:"Get the current status and statistics of the knowledge base index."},async()=>{try{const e=await n.getStats(),o=await n.listSourcePaths(),s=["## Knowledge Base Status","",`- **Total Records**: ${e.totalRecords}`,`- **Total Files**: ${e.totalFiles}`,`- **Last Indexed**: ${e.lastIndexedAt??"Never"}`,"","### Content Types",...Object.entries(e.contentTypeBreakdown).map(([t,r])=>`- ${t}: ${r}`),"","### Indexed Files",...o.slice(0,50).map(t=>`- ${t}`),o.length>50?`
2
- ... and ${o.length-50} more files`:""];if(a)try{const t=await a.getStats();s.push("","### Knowledge Graph",`- **Nodes**: ${t.nodeCount}`,`- **Edges**: ${t.edgeCount}`,...Object.entries(t.nodeTypes).map(([r,d])=>` - ${r}: ${d}`))}catch{s.push("","### Knowledge Graph","- Graph store unavailable")}return{content:[{type:"text",text:s.join(`
1
+ function p(d,n,a){d.registerTool("status",{description:"Get the current status and statistics of the knowledge base index."},async()=>{try{const e=await n.getStats(),o=await n.listSourcePaths(),s=["## Knowledge Base Status","",`- **Total Records**: ${e.totalRecords}`,`- **Total Files**: ${e.totalFiles}`,`- **Last Indexed**: ${e.lastIndexedAt??"Never"}`,"","### Content Types",...Object.entries(e.contentTypeBreakdown).map(([t,r])=>`- ${t}: ${r}`),"","### Indexed Files",...o.slice(0,50).map(t=>`- ${t}`),o.length>50?`
2
+ ... and ${o.length-50} more files`:""];if(a)try{const t=await a.getStats();s.push("","### Knowledge Graph",`- **Nodes**: ${t.nodeCount}`,`- **Edges**: ${t.edgeCount}`,...Object.entries(t.nodeTypes).map(([r,c])=>` - ${r}: ${c}`))}catch{s.push("","### Knowledge Graph","- Graph store unavailable")}return{content:[{type:"text",text:s.join(`
3
3
  `)+"\n\n---\n_Next: Use `search` to query indexed content, `graph(stats)` to explore the knowledge graph, or `reindex` to refresh the index._"}]}}catch(e){return console.error("[KB] Status failed:",e),{content:[{type:"text",text:`Status check failed: ${e.message}`}],isError:!0}}})}export{p as registerStatusTool};
@@ -1,4 +1,4 @@
1
- import{addToWorkset as x,batch as b,check as m,checkpointLatest as w,checkpointList as S,checkpointLoad as $,checkpointSave as k,codemod as E,compact as v,dataTransform as T,delegate as q,delegateListModels as O,deleteWorkset as M,diffParse as N,evaluate as _,fileSummary as R,find as g,findDeadSymbols as I,findExamples as J,getWorkset as C,gitContext as L,health as j,laneCreate as F,laneDiff as D,laneDiscard as A,laneList as P,laneMerge as W,laneStatus as K,listWorksets as U,parseOutput as B,processList as z,processLogs as G,processStart as Q,processStatus as H,processStop as V,queueClear as X,queueCreate as Y,queueDelete as Z,queueDone as ee,queueFail as te,queueGet as re,queueList as ne,queueNext as oe,queuePush as se,removeFromWorkset as ie,rename as ae,saveWorkset as ce,scopeMap as le,stashClear as de,stashDelete as ue,stashGet as pe,stashList as fe,stashSet as me,symbol as ge,testRun as he,trace as ye,watchList as xe,watchStart as be,watchStop as we,webFetch as Se}from"@kb/tools";import{z as r}from"zod";function je(t,n){t.registerTool("compact",{description:"Compress text to relevant sections using embedding similarity (no LLM). Ideal for reducing file contents before context injection. Segments by paragraph/sentence/line.",inputSchema:{text:r.string().describe("The text to compress"),query:r.string().describe("Focus query \u2014 what are you trying to understand?"),max_chars:r.number().min(100).max(5e4).default(3e3).describe("Target output size in characters"),segmentation:r.enum(["paragraph","sentence","line"]).default("paragraph").describe("How to split the text for scoring")}},async({text:e,query:s,max_chars:o,segmentation:i})=>{try{const a=await v(n,{text:e,query:s,maxChars:o,segmentation:i});return{content:[{type:"text",text:[`Compressed ${a.originalChars} \u2192 ${a.compressedChars} chars (${(a.ratio*100).toFixed(0)}%)`,`Kept ${a.segmentsKept}/${a.segmentsTotal} segments`,"",a.text].join(`
1
+ import{addToWorkset as x,batch as b,check as m,checkpointLatest as w,checkpointList as S,checkpointLoad as $,checkpointSave as k,codemod as E,compact as v,dataTransform as T,delegate as q,delegateListModels as O,deleteWorkset as M,diffParse as N,evaluate as _,fileSummary as R,find as g,findDeadSymbols as I,findExamples as J,getWorkset as C,gitContext as j,health as L,laneCreate as F,laneDiff as D,laneDiscard as A,laneList as P,laneMerge as W,laneStatus as K,listWorksets as U,parseOutput as B,processList as z,processLogs as G,processStart as Q,processStatus as H,processStop as V,queueClear as X,queueCreate as Y,queueDelete as Z,queueDone as ee,queueFail as te,queueGet as re,queueList as ne,queueNext as oe,queuePush as se,removeFromWorkset as ie,rename as ae,saveWorkset as ce,scopeMap as le,stashClear as de,stashDelete as ue,stashGet as pe,stashList as fe,stashSet as me,symbol as ge,testRun as he,trace as ye,watchList as xe,watchStart as be,watchStop as we,webFetch as Se}from"../../../tools/dist/index.js";import{z as r}from"zod";function Le(t,n){t.registerTool("compact",{description:"Compress text to relevant sections using embedding similarity (no LLM). Ideal for reducing file contents before context injection. Segments by paragraph/sentence/line.",inputSchema:{text:r.string().describe("The text to compress"),query:r.string().describe("Focus query \u2014 what are you trying to understand?"),max_chars:r.number().min(100).max(5e4).default(3e3).describe("Target output size in characters"),segmentation:r.enum(["paragraph","sentence","line"]).default("paragraph").describe("How to split the text for scoring")}},async({text:e,query:s,max_chars:o,segmentation:i})=>{try{const a=await v(n,{text:e,query:s,maxChars:o,segmentation:i});return{content:[{type:"text",text:[`Compressed ${a.originalChars} \u2192 ${a.compressedChars} chars (${(a.ratio*100).toFixed(0)}%)`,`Kept ${a.segmentsKept}/${a.segmentsTotal} segments`,"",a.text].join(`
2
2
  `)}]}}catch(a){return{content:[{type:"text",text:`Compact failed: ${a.message}`}],isError:!0}}})}function Fe(t,n,e){t.registerTool("scope_map",{description:"Generate a task-scoped reading plan. Given a task description, identifies which files and sections are relevant, with estimated token counts and suggested reading order.",inputSchema:{task:r.string().describe("Description of the task to scope"),max_files:r.number().min(1).max(50).default(15).describe("Maximum files to include"),content_type:r.string().optional().describe("Filter by content type")}},async({task:s,max_files:o,content_type:i})=>{try{const a=await le(n,e,{task:s,maxFiles:o,contentType:i});return{content:[{type:"text",text:[`## Scope Map: ${s}`,`Total estimated tokens: ~${a.totalEstimatedTokens}`,"","### Files (by relevance)",...a.files.map((c,u)=>`${u+1}. **${c.path}** (~${c.estimatedTokens} tokens, ${(c.relevance*100).toFixed(0)}% relevant)
3
3
  ${c.reason}
4
4
  Focus: ${c.focusRanges.map(d=>`L${d.start}-${d.end}`).join(", ")}`),"","### Suggested Reading Order",...a.readingOrder.map((c,u)=>`${u+1}. ${c}`)].join(`
@@ -9,13 +9,13 @@ import{addToWorkset as x,batch as b,check as m,checkpointLatest as w,checkpointL
9
9
  `)}]}}case"delete":{if(!e)throw new Error("name required for delete");return{content:[{type:"text",text:M(e)?`Deleted workset "${e}".`:`Workset "${e}" not found.`}]}}case"add":{if(!e||!s)throw new Error("name and files required for add");const i=x(e,s);return{content:[{type:"text",text:`Added to workset "${i.name}": now ${i.files.length} files.`}]}}case"remove":{if(!e||!s)throw new Error("name and files required for remove");const i=ie(e,s);return i?{content:[{type:"text",text:`Removed from workset "${i.name}": now ${i.files.length} files.`}]}:{content:[{type:"text",text:`Workset "${e}" not found.`}]}}}}catch(i){return{content:[{type:"text",text:`Workset operation failed: ${i.message}`}],isError:!0}}})}function We(t){t.registerTool("check",{description:"Run incremental typecheck (tsc) and lint (biome) on the project or specific files. Returns structured error and warning lists.",inputSchema:{files:r.array(r.string()).optional().describe("Specific files to check (if omitted, checks all)"),cwd:r.string().optional().describe("Working directory"),skip_types:r.boolean().default(!1).describe("Skip TypeScript typecheck"),skip_lint:r.boolean().default(!1).describe("Skip Biome lint")}},async({files:n,cwd:e,skip_types:s,skip_lint:o})=>{try{const i=await m({files:n,cwd:e,skipTypes:s,skipLint:o});return{content:[{type:"text",text:JSON.stringify(i,null,2)}]}}catch(i){return{content:[{type:"text",text:`Check failed: ${i.message}`}],isError:!0}}})}function Ke(t,n,e){t.registerTool("batch",{description:"Execute multiple built-in operations in parallel with concurrency control. Supported operation types: search, find, and check.",inputSchema:{operations:r.array(r.object({id:r.string().describe("Unique ID for this operation"),type:r.enum(["search","find","check"]).describe("Built-in operation type"),args:r.record(r.string(),r.unknown()).describe("Arguments for the operation")})).min(1).describe("Operations to execute"),concurrency:r.number().min(1).max(20).default(4).describe("Max concurrent operations")}},async({operations:s,concurrency:o})=>{try{const i=await b(s,async a=>ve(a,n,e),{concurrency:o});return{content:[{type:"text",text:JSON.stringify(i,null,2)}]}}catch(i){return{content:[{type:"text",text:`Batch failed: ${i.message}`}],isError:!0}}})}function Ue(t,n,e){t.registerTool("symbol",{description:"Resolve a symbol: find where it is defined, who imports it, and where it is referenced. Works on TypeScript and JavaScript codebases.",inputSchema:{name:r.string().describe("Symbol name to look up (function, class, type, etc.)"),limit:r.number().min(1).max(50).default(20).describe("Max results per category")}},async({name:s,limit:o})=>{try{const i=await ge(n,e,{name:s,limit:o});return{content:[{type:"text",text:Oe(i)}]}}catch(i){return{content:[{type:"text",text:`Symbol lookup failed: ${i.message}`}],isError:!0}}})}function Be(t){t.registerTool("eval",{description:"Execute a JavaScript or TypeScript snippet in a constrained VM sandbox with a timeout. Captures console output and returned values.",inputSchema:{code:r.string().describe("Code snippet to execute"),lang:r.enum(["js","ts"]).default("js").optional().describe("Language mode: js executes directly, ts strips common type syntax first"),timeout:r.number().min(1).max(6e4).default(5e3).optional().describe("Execution timeout in milliseconds")}},async({code:n,lang:e,timeout:s})=>{try{const o=_({code:n,lang:e,timeout:s});return o.success?{content:[{type:"text",text:`Eval succeeded in ${o.durationMs}ms
10
10
 
11
11
  ${o.output}`}]}:{content:[{type:"text",text:`Eval failed in ${o.durationMs}ms: ${o.error??"Unknown error"}`}],isError:!0}}catch(o){return console.error("[KB] Eval failed:",o),{content:[{type:"text",text:`Eval failed: ${o.message}`}],isError:!0}}})}function ze(t){t.registerTool("test_run",{description:"Run Vitest for the current project or a subset of files, then return a structured summary of passing and failing tests.",inputSchema:{files:r.array(r.string()).optional().describe("Specific test files or patterns to run"),grep:r.string().optional().describe("Only run tests whose names match this pattern"),cwd:r.string().optional().describe("Working directory for the test run")}},async({files:n,grep:e,cwd:s})=>{try{const o=await he({files:n,grep:e,cwd:s});return{content:[{type:"text",text:Me(o)}],isError:!o.passed}}catch(o){return{content:[{type:"text",text:`Test run failed: ${o.message}`}],isError:!0}}})}function Ge(t){t.registerTool("stash",{description:"Persist and retrieve named values in .kb-state/stash.json for intermediate results between tool calls.",inputSchema:{action:r.enum(["set","get","list","delete","clear"]).describe("Operation to perform on the stash"),key:r.string().optional().describe("Entry key for set/get/delete operations"),value:r.string().optional().describe("String or JSON value for set operations")}},async({action:n,key:e,value:s})=>{try{switch(n){case"set":{if(!e)throw new Error("key required for set");const o=me(e,Ie(s??""));return{content:[{type:"text",text:`Stored stash entry "${o.key}" (${o.type}) at ${o.storedAt}.`}]}}case"get":{if(!e)throw new Error("key required for get");const o=pe(e);return{content:[{type:"text",text:o?JSON.stringify(o,null,2):`Stash entry "${e}" not found.`}]}}case"list":{const o=fe();return{content:[{type:"text",text:o.length===0?"Stash is empty.":o.map(i=>`- ${i.key} (${i.type}) \u2014 ${i.storedAt}`).join(`
12
- `)}]}}case"delete":{if(!e)throw new Error("key required for delete");return{content:[{type:"text",text:ue(e)?`Deleted stash entry "${e}".`:`Stash entry "${e}" not found.`}]}}case"clear":{const o=de();return{content:[{type:"text",text:`Cleared ${o} stash entr${o===1?"y":"ies"}.`}]}}}}catch(o){return{content:[{type:"text",text:`Stash operation failed: ${o.message}`}],isError:!0}}})}function Qe(t){t.registerTool("git_context",{description:"Summarize the current Git branch, working tree state, recent commits, and optional diff statistics for the repository.",inputSchema:{cwd:r.string().optional().describe("Repository root or working directory"),commit_count:r.number().min(1).max(50).default(5).optional().describe("How many recent commits to include"),include_diff:r.boolean().default(!1).optional().describe("Include diff stat for working tree changes")}},async({cwd:n,commit_count:e,include_diff:s})=>{try{const o=await L({cwd:n,commitCount:e,includeDiff:s});return{content:[{type:"text",text:Ne(o)}]}}catch(o){return{content:[{type:"text",text:`Git context failed: ${o.message}`}],isError:!0}}})}function He(t){t.registerTool("diff_parse",{description:"Parse raw unified diff text into file-level and hunk-level structural changes.",inputSchema:{diff:r.string().describe("Raw unified diff text")}},async({diff:n})=>{try{const e=n.replace(/\\n/g,`
12
+ `)}]}}case"delete":{if(!e)throw new Error("key required for delete");return{content:[{type:"text",text:ue(e)?`Deleted stash entry "${e}".`:`Stash entry "${e}" not found.`}]}}case"clear":{const o=de();return{content:[{type:"text",text:`Cleared ${o} stash entr${o===1?"y":"ies"}.`}]}}}}catch(o){return{content:[{type:"text",text:`Stash operation failed: ${o.message}`}],isError:!0}}})}function Qe(t){t.registerTool("git_context",{description:"Summarize the current Git branch, working tree state, recent commits, and optional diff statistics for the repository.",inputSchema:{cwd:r.string().optional().describe("Repository root or working directory"),commit_count:r.number().min(1).max(50).default(5).optional().describe("How many recent commits to include"),include_diff:r.boolean().default(!1).optional().describe("Include diff stat for working tree changes")}},async({cwd:n,commit_count:e,include_diff:s})=>{try{const o=await j({cwd:n,commitCount:e,includeDiff:s});return{content:[{type:"text",text:Ne(o)}]}}catch(o){return{content:[{type:"text",text:`Git context failed: ${o.message}`}],isError:!0}}})}function He(t){t.registerTool("diff_parse",{description:"Parse raw unified diff text into file-level and hunk-level structural changes.",inputSchema:{diff:r.string().describe("Raw unified diff text")}},async({diff:n})=>{try{const e=n.replace(/\\n/g,`
13
13
  `).replace(/\\t/g," "),s=N({diff:e});return{content:[{type:"text",text:_e(s)}]}}catch(e){return{content:[{type:"text",text:`Diff parse failed: ${e.message}`}],isError:!0}}})}function Ve(t){t.registerTool("rename",{description:"Rename a symbol across files using whole-word regex matching for exports, imports, and general usage references.",inputSchema:{old_name:r.string().describe("Existing symbol name to replace"),new_name:r.string().describe("New symbol name to use"),root_path:r.string().describe("Root directory to search within"),extensions:r.array(r.string()).optional().describe("Optional file extensions to include, such as .ts,.tsx,.js,.jsx"),dry_run:r.boolean().default(!0).describe("Preview changes without writing files")}},async({old_name:n,new_name:e,root_path:s,extensions:o,dry_run:i})=>{try{const a=await ae({oldName:n,newName:e,rootPath:s,extensions:o,dryRun:i});return{content:[{type:"text",text:JSON.stringify(a,null,2)}]}}catch(a){return{content:[{type:"text",text:`Rename failed: ${a.message}`}],isError:!0}}})}function Xe(t){t.registerTool("codemod",{description:"Apply regex-based codemod rules across files and return structured before/after changes for each affected line.",inputSchema:{root_path:r.string().describe("Root directory to transform within"),rules:r.array(r.object({description:r.string().describe("What the codemod rule does"),pattern:r.string().describe("Regex pattern in string form"),replacement:r.string().describe("Replacement string with optional capture groups")})).min(1).describe("Codemod rules to apply"),dry_run:r.boolean().default(!0).describe("Preview changes without writing files")}},async({root_path:n,rules:e,dry_run:s})=>{try{const o=await E({rootPath:n,rules:e,dryRun:s});return{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}catch(o){return{content:[{type:"text",text:`Codemod failed: ${o.message}`}],isError:!0}}})}function Ye(t){t.registerTool("file_summary",{description:"Create a concise structural summary of a source file: imports, exports, functions, classes, interfaces, and types.",inputSchema:{path:r.string().describe("Absolute path to the file to summarize")}},async({path:n})=>{try{const e=await R({path:n});return{content:[{type:"text",text:Re(e)}]}}catch(e){return{content:[{type:"text",text:`File summary failed: ${e.message}`}],isError:!0}}})}function Ze(t){t.registerTool("checkpoint",{description:"Save and restore lightweight session checkpoints in .kb-state/checkpoints for cross-session continuity.",inputSchema:{action:r.enum(["save","load","list","latest"]).describe("Checkpoint action to perform"),label:r.string().optional().describe("Checkpoint label for save, or checkpoint id for load"),data:r.string().optional().describe("JSON object string for save actions"),notes:r.string().optional().describe("Optional notes for save actions")}},async({action:n,label:e,data:s,notes:o})=>{try{switch(n){case"save":{if(!e)throw new Error("label required for save");const i=k(e,Je(s),{notes:o});return{content:[{type:"text",text:f(i)}]}}case"load":{if(!e)throw new Error("label required for load");const i=$(e);return{content:[{type:"text",text:i?f(i):`Checkpoint "${e}" not found.`}]}}case"list":{const i=S();return{content:[{type:"text",text:i.length===0?"No checkpoints saved.":i.map(a=>`- ${a.id} \u2014 ${a.label} (${a.createdAt})`).join(`
14
- `)}]}}case"latest":{const i=w();return{content:[{type:"text",text:i?f(i):"No checkpoints saved."}]}}}}catch(i){return{content:[{type:"text",text:`Checkpoint failed: ${i.message}`}],isError:!0}}})}function et(t){t.registerTool("data_transform",{description:"Apply small jq-like transforms to JSON input for filtering, projection, grouping, and path extraction.",inputSchema:{input:r.string().describe("Input JSON string"),expression:r.string().describe("Transform expression to apply")}},async({input:n,expression:e})=>{try{return{content:[{type:"text",text:T({input:n,expression:e}).outputString}]}}catch(s){return{content:[{type:"text",text:`Data transform failed: ${s.message}`}],isError:!0}}})}function tt(t,n,e){t.registerTool("trace",{description:"Trace data flow through a codebase by following imports, call sites, and references from a starting symbol or file location.",inputSchema:{start:r.string().describe("Starting point \u2014 symbol name or file:line reference"),direction:r.enum(["forward","backward","both"]).describe("Which direction to trace relationships"),max_depth:r.number().min(1).max(10).default(3).optional().describe("Maximum trace depth")}},async({start:s,direction:o,max_depth:i})=>{try{const a=await ye(n,e,{start:s,direction:o,maxDepth:i});return{content:[{type:"text",text:JSON.stringify(a,null,2)}]}}catch(a){return{content:[{type:"text",text:`Trace failed: ${a.message}`}],isError:!0}}})}function rt(t,n,e){t.registerTool("find_examples",{description:"Find real usage examples of a function, class, or pattern in the indexed codebase.",inputSchema:{query:r.string().describe("Symbol or pattern to find examples of"),limit:r.number().min(1).max(20).default(5).optional().describe("Maximum examples to return"),content_type:r.string().optional().describe("Filter by content type")}},async({query:s,limit:o,content_type:i})=>{try{const a=await J(n,e,{query:s,limit:o,contentType:i});return{content:[{type:"text",text:JSON.stringify(a,null,2)}]}}catch(a){return{content:[{type:"text",text:`Find examples failed: ${a.message}`}],isError:!0}}})}function nt(t){t.registerTool("process",{description:"Start, stop, inspect, list, and tail logs for in-memory managed child processes.",inputSchema:{action:r.enum(["start","stop","status","list","logs"]).describe("Process action to perform"),id:r.string().optional().describe("Managed process ID"),command:r.string().optional().describe("Executable to start"),args:r.array(r.string()).optional().describe("Arguments for start actions"),tail:r.number().min(1).max(500).optional().describe("Log lines to return for logs actions")}},async({action:n,id:e,command:s,args:o,tail:i})=>{try{switch(n){case"start":{if(!e||!s)throw new Error("id and command are required for start");return{content:[{type:"text",text:JSON.stringify(Q(e,s,o??[]),null,2)}]}}case"stop":{if(!e)throw new Error("id is required for stop");return{content:[{type:"text",text:JSON.stringify(V(e)??null,null,2)}]}}case"status":{if(!e)throw new Error("id is required for status");return{content:[{type:"text",text:JSON.stringify(H(e)??null,null,2)}]}}case"list":return{content:[{type:"text",text:JSON.stringify(z(),null,2)}]};case"logs":{if(!e)throw new Error("id is required for logs");return{content:[{type:"text",text:JSON.stringify(G(e,i),null,2)}]}}}}catch(a){return{content:[{type:"text",text:`Process action failed: ${a.message}`}],isError:!0}}})}function ot(t){t.registerTool("watch",{description:"Start, stop, and list in-memory filesystem watchers for a directory.",inputSchema:{action:r.enum(["start","stop","list"]).describe("Watch action to perform"),path:r.string().optional().describe("Directory path to watch for start actions"),id:r.string().optional().describe("Watcher ID for stop actions")}},async({action:n,path:e,id:s})=>{try{switch(n){case"start":{if(!e)throw new Error("path is required for start");return{content:[{type:"text",text:JSON.stringify(be({path:e}),null,2)}]}}case"stop":{if(!s)throw new Error("id is required for stop");return{content:[{type:"text",text:JSON.stringify({stopped:we(s)},null,2)}]}}case"list":return{content:[{type:"text",text:JSON.stringify(xe(),null,2)}]}}}catch(o){return{content:[{type:"text",text:`Watch action failed: ${o.message}`}],isError:!0}}})}function st(t,n,e){t.registerTool("dead_symbols",{description:"Find exported symbols that appear to be unused because they are never imported or re-exported.",inputSchema:{limit:r.number().min(1).max(500).default(100).optional().describe("Maximum exported symbols to scan")}},async({limit:s})=>{try{const o=await I(n,e,{limit:s});return{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}catch(o){return{content:[{type:"text",text:`Dead symbol scan failed: ${o.message}`}],isError:!0}}})}function it(t){t.registerTool("delegate",{description:"Delegate a subtask to a local Ollama model. Use for summarization, classification, naming, or any task that can offload work from the host agent. Fails fast if Ollama is not running.",inputSchema:{prompt:r.string().describe("The task or question to send to the local model"),model:r.string().optional().describe("Ollama model name (default: first available model)"),system:r.string().optional().describe("System prompt for the model"),context:r.string().optional().describe("Context text to include before the prompt (e.g. file contents)"),temperature:r.number().min(0).max(2).default(.3).optional().describe("Sampling temperature (0=deterministic, default 0.3)"),timeout:r.number().min(1e3).max(6e5).default(12e4).optional().describe("Timeout in milliseconds (default 120000)"),action:r.enum(["generate","list_models"]).default("generate").optional().describe("Action: generate a response or list available models")}},async({prompt:n,model:e,system:s,context:o,temperature:i,timeout:a,action:l})=>{try{if(l==="list_models"){const u=await O();return{content:[{type:"text",text:JSON.stringify({models:u,count:u.length,_Next:"Use delegate with a model name"},null,2)}]}}const c=await q({prompt:n,model:e,system:s,context:o,temperature:i,timeout:a});return c.error?{content:[{type:"text",text:JSON.stringify({error:c.error,model:c.model,durationMs:c.durationMs},null,2)}],isError:!0}:{content:[{type:"text",text:JSON.stringify({model:c.model,response:c.response,durationMs:c.durationMs,tokenCount:c.tokenCount,_Next:"Use the response in your workflow. stash to save it."},null,2)}]}}catch(c){return{content:[{type:"text",text:`Delegate failed: ${c.message}`}],isError:!0}}})}function at(t){t.registerTool("lane",{description:"Manage verified lanes \u2014 isolated file copies for parallel exploration. Create a lane, make changes, diff, merge back, or discard.",inputSchema:{action:r.enum(["create","list","status","diff","merge","discard"]).describe("Lane action to perform"),name:r.string().optional().describe("Lane name (required for create/status/diff/merge/discard)"),files:r.array(r.string()).optional().describe("File paths to copy into the lane (required for create)")}},async({action:n,name:e,files:s})=>{try{switch(n){case"create":{if(!e)throw new Error("name is required for create");if(!s||s.length===0)throw new Error("files are required for create");const o=F(e,s);return{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}case"list":return{content:[{type:"text",text:JSON.stringify(P(),null,2)}]};case"status":{if(!e)throw new Error("name is required for status");return{content:[{type:"text",text:JSON.stringify(K(e),null,2)}]}}case"diff":{if(!e)throw new Error("name is required for diff");return{content:[{type:"text",text:JSON.stringify(D(e),null,2)}]}}case"merge":{if(!e)throw new Error("name is required for merge");return{content:[{type:"text",text:JSON.stringify(W(e),null,2)}]}}case"discard":{if(!e)throw new Error("name is required for discard");return{content:[{type:"text",text:JSON.stringify({discarded:A(e)},null,2)}]}}}}catch(o){return{content:[{type:"text",text:`Lane action failed: ${o.message}`}],isError:!0}}})}function ct(t){t.registerTool("health",{description:"Run project health checks \u2014 verifies package.json, tsconfig, scripts, lockfile, README, LICENSE, .gitignore.",inputSchema:{path:r.string().optional().describe("Root directory to check (defaults to cwd)")}},async({path:n})=>{try{const e=j(n);return{content:[{type:"text",text:JSON.stringify(e,null,2)}]}}catch(e){return{content:[{type:"text",text:`Health check failed: ${e.message}`}],isError:!0}}})}function lt(t){t.registerTool("queue",{description:"Manage task queues for sequential agent operations. Push items, take next, mark done/failed, list queues.",inputSchema:{action:r.enum(["create","push","next","done","fail","get","list","clear","delete"]).describe("Queue action"),name:r.string().optional().describe("Queue name (required for most actions)"),title:r.string().optional().describe("Item title (required for push)"),id:r.string().optional().describe("Item ID (required for done/fail)"),data:r.unknown().optional().describe("Arbitrary data to attach to a queue item"),error:r.string().optional().describe("Error message (required for fail)")}},async({action:n,name:e,title:s,id:o,data:i,error:a})=>{try{switch(n){case"create":{if(!e)throw new Error("name is required for create");return{content:[{type:"text",text:JSON.stringify(Y(e),null,2)}]}}case"push":{if(!e)throw new Error("name is required for push");if(!s)throw new Error("title is required for push");return{content:[{type:"text",text:JSON.stringify(se(e,s,i),null,2)}]}}case"next":{if(!e)throw new Error("name is required for next");const l=oe(e);return{content:[{type:"text",text:JSON.stringify(l,null,2)}]}}case"done":{if(!e)throw new Error("name is required for done");if(!o)throw new Error("id is required for done");return{content:[{type:"text",text:JSON.stringify(ee(e,o),null,2)}]}}case"fail":{if(!e)throw new Error("name is required for fail");if(!o)throw new Error("id is required for fail");if(!a)throw new Error("error is required for fail");return{content:[{type:"text",text:JSON.stringify(te(e,o,a),null,2)}]}}case"get":{if(!e)throw new Error("name is required for get");return{content:[{type:"text",text:JSON.stringify(re(e),null,2)}]}}case"list":return{content:[{type:"text",text:JSON.stringify(ne(),null,2)}]};case"clear":{if(!e)throw new Error("name is required for clear");return{content:[{type:"text",text:JSON.stringify({cleared:X(e)},null,2)}]}}case"delete":{if(!e)throw new Error("name is required for delete");return{content:[{type:"text",text:JSON.stringify({deleted:Z(e)},null,2)}]}}}}catch(l){return{content:[{type:"text",text:`Queue action failed: ${l.message}`}],isError:!0}}})}const $e=r.object({query:r.string(),limit:r.number().min(1).max(20).default(5).optional(),search_mode:r.enum(["hybrid","semantic","keyword"]).default("hybrid").optional(),content_type:r.string().optional(),origin:r.enum(["indexed","curated","produced"]).optional(),category:r.string().optional(),tags:r.array(r.string()).optional(),min_score:r.number().min(0).max(1).default(.25).optional()}),ke=r.object({query:r.string().optional(),glob:r.string().optional(),pattern:r.string().optional(),limit:r.number().min(1).max(50).default(10).optional(),content_type:r.string().optional(),cwd:r.string().optional()}),Ee=r.object({files:r.array(r.string()).optional(),cwd:r.string().optional(),skip_types:r.boolean().optional(),skip_lint:r.boolean().optional()});async function ve(t,n,e){switch(t.type){case"search":{const s=$e.parse(t.args);return Te(n,e,s)}case"find":{const s=ke.parse(t.args);if(!s.query&&!s.glob&&!s.pattern)throw new Error("find operation requires query, glob, or pattern");return g(n,e,{query:s.query,glob:s.glob,pattern:s.pattern,limit:s.limit,contentType:s.content_type,cwd:s.cwd})}case"check":{const s=Ee.parse(t.args);return m({files:s.files,cwd:s.cwd,skipTypes:s.skip_types,skipLint:s.skip_lint})}default:throw new Error(`Unsupported batch operation type: ${t.type}`)}}async function Te(t,n,e){const s=e.limit??5,o={limit:s,minScore:e.min_score??.25,contentType:e.content_type,origin:e.origin,category:e.category,tags:e.tags},i=t.embedQuery?.bind(t)??t.embed.bind(t);if(e.search_mode==="keyword")return(await n.ftsSearch(e.query,o)).slice(0,s);const a=await i(e.query);if(e.search_mode==="semantic")return n.search(a,o);const[l,c]=await Promise.all([n.search(a,{...o,limit:s*2}),n.ftsSearch(e.query,{...o,limit:s*2})]);return qe(l,c).slice(0,s)}function qe(t,n,e=60){const s=new Map;for(let o=0;o<t.length;o++){const i=t[o];s.set(i.record.id,{record:i.record,score:1/(e+o+1)})}for(let o=0;o<n.length;o++){const i=n[o],a=s.get(i.record.id);if(a){a.score+=1/(e+o+1);continue}s.set(i.record.id,{record:i.record,score:1/(e+o+1)})}return[...s.values()].sort((o,i)=>i.score-o.score)}function Oe(t){const n=[`Symbol: ${t.name}`];if(t.definedIn?n.push(`Defined in: ${t.definedIn.path}:${t.definedIn.line} (${t.definedIn.kind})`):n.push("Defined in: not found"),n.push("","Imported by:"),t.importedBy.length===0)n.push(" none");else for(const e of t.importedBy)n.push(` - ${e.path}:${e.line} ${e.importStatement}`);if(n.push("","Referenced in:"),t.referencedIn.length===0)n.push(" none");else for(const e of t.referencedIn)n.push(` - ${e.path}:${e.line} ${e.context}`);return n.join(`
14
+ `)}]}}case"latest":{const i=w();return{content:[{type:"text",text:i?f(i):"No checkpoints saved."}]}}}}catch(i){return{content:[{type:"text",text:`Checkpoint failed: ${i.message}`}],isError:!0}}})}function et(t){t.registerTool("data_transform",{description:"Apply small jq-like transforms to JSON input for filtering, projection, grouping, and path extraction.",inputSchema:{input:r.string().describe("Input JSON string"),expression:r.string().describe("Transform expression to apply")}},async({input:n,expression:e})=>{try{return{content:[{type:"text",text:T({input:n,expression:e}).outputString}]}}catch(s){return{content:[{type:"text",text:`Data transform failed: ${s.message}`}],isError:!0}}})}function tt(t,n,e){t.registerTool("trace",{description:"Trace data flow through a codebase by following imports, call sites, and references from a starting symbol or file location.",inputSchema:{start:r.string().describe("Starting point \u2014 symbol name or file:line reference"),direction:r.enum(["forward","backward","both"]).describe("Which direction to trace relationships"),max_depth:r.number().min(1).max(10).default(3).optional().describe("Maximum trace depth")}},async({start:s,direction:o,max_depth:i})=>{try{const a=await ye(n,e,{start:s,direction:o,maxDepth:i});return{content:[{type:"text",text:JSON.stringify(a,null,2)}]}}catch(a){return{content:[{type:"text",text:`Trace failed: ${a.message}`}],isError:!0}}})}function rt(t,n,e){t.registerTool("find_examples",{description:"Find real usage examples of a function, class, or pattern in the indexed codebase.",inputSchema:{query:r.string().describe("Symbol or pattern to find examples of"),limit:r.number().min(1).max(20).default(5).optional().describe("Maximum examples to return"),content_type:r.string().optional().describe("Filter by content type")}},async({query:s,limit:o,content_type:i})=>{try{const a=await J(n,e,{query:s,limit:o,contentType:i});return{content:[{type:"text",text:JSON.stringify(a,null,2)}]}}catch(a){return{content:[{type:"text",text:`Find examples failed: ${a.message}`}],isError:!0}}})}function nt(t){t.registerTool("process",{description:"Start, stop, inspect, list, and tail logs for in-memory managed child processes.",inputSchema:{action:r.enum(["start","stop","status","list","logs"]).describe("Process action to perform"),id:r.string().optional().describe("Managed process ID"),command:r.string().optional().describe("Executable to start"),args:r.array(r.string()).optional().describe("Arguments for start actions"),tail:r.number().min(1).max(500).optional().describe("Log lines to return for logs actions")}},async({action:n,id:e,command:s,args:o,tail:i})=>{try{switch(n){case"start":{if(!e||!s)throw new Error("id and command are required for start");return{content:[{type:"text",text:JSON.stringify(Q(e,s,o??[]),null,2)}]}}case"stop":{if(!e)throw new Error("id is required for stop");return{content:[{type:"text",text:JSON.stringify(V(e)??null,null,2)}]}}case"status":{if(!e)throw new Error("id is required for status");return{content:[{type:"text",text:JSON.stringify(H(e)??null,null,2)}]}}case"list":return{content:[{type:"text",text:JSON.stringify(z(),null,2)}]};case"logs":{if(!e)throw new Error("id is required for logs");return{content:[{type:"text",text:JSON.stringify(G(e,i),null,2)}]}}}}catch(a){return{content:[{type:"text",text:`Process action failed: ${a.message}`}],isError:!0}}})}function ot(t){t.registerTool("watch",{description:"Start, stop, and list in-memory filesystem watchers for a directory.",inputSchema:{action:r.enum(["start","stop","list"]).describe("Watch action to perform"),path:r.string().optional().describe("Directory path to watch for start actions"),id:r.string().optional().describe("Watcher ID for stop actions")}},async({action:n,path:e,id:s})=>{try{switch(n){case"start":{if(!e)throw new Error("path is required for start");return{content:[{type:"text",text:JSON.stringify(be({path:e}),null,2)}]}}case"stop":{if(!s)throw new Error("id is required for stop");return{content:[{type:"text",text:JSON.stringify({stopped:we(s)},null,2)}]}}case"list":return{content:[{type:"text",text:JSON.stringify(xe(),null,2)}]}}}catch(o){return{content:[{type:"text",text:`Watch action failed: ${o.message}`}],isError:!0}}})}function st(t,n,e){t.registerTool("dead_symbols",{description:"Find exported symbols that appear to be unused because they are never imported or re-exported.",inputSchema:{limit:r.number().min(1).max(500).default(100).optional().describe("Maximum exported symbols to scan")}},async({limit:s})=>{try{const o=await I(n,e,{limit:s});return{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}catch(o){return{content:[{type:"text",text:`Dead symbol scan failed: ${o.message}`}],isError:!0}}})}function it(t){t.registerTool("delegate",{description:"Delegate a subtask to a local Ollama model. Use for summarization, classification, naming, or any task that can offload work from the host agent. Fails fast if Ollama is not running.",inputSchema:{prompt:r.string().describe("The task or question to send to the local model"),model:r.string().optional().describe("Ollama model name (default: first available model)"),system:r.string().optional().describe("System prompt for the model"),context:r.string().optional().describe("Context text to include before the prompt (e.g. file contents)"),temperature:r.number().min(0).max(2).default(.3).optional().describe("Sampling temperature (0=deterministic, default 0.3)"),timeout:r.number().min(1e3).max(6e5).default(12e4).optional().describe("Timeout in milliseconds (default 120000)"),action:r.enum(["generate","list_models"]).default("generate").optional().describe("Action: generate a response or list available models")}},async({prompt:n,model:e,system:s,context:o,temperature:i,timeout:a,action:l})=>{try{if(l==="list_models"){const u=await O();return{content:[{type:"text",text:JSON.stringify({models:u,count:u.length,_Next:"Use delegate with a model name"},null,2)}]}}const c=await q({prompt:n,model:e,system:s,context:o,temperature:i,timeout:a});return c.error?{content:[{type:"text",text:JSON.stringify({error:c.error,model:c.model,durationMs:c.durationMs},null,2)}],isError:!0}:{content:[{type:"text",text:JSON.stringify({model:c.model,response:c.response,durationMs:c.durationMs,tokenCount:c.tokenCount,_Next:"Use the response in your workflow. stash to save it."},null,2)}]}}catch(c){return{content:[{type:"text",text:`Delegate failed: ${c.message}`}],isError:!0}}})}function at(t){t.registerTool("lane",{description:"Manage verified lanes \u2014 isolated file copies for parallel exploration. Create a lane, make changes, diff, merge back, or discard.",inputSchema:{action:r.enum(["create","list","status","diff","merge","discard"]).describe("Lane action to perform"),name:r.string().optional().describe("Lane name (required for create/status/diff/merge/discard)"),files:r.array(r.string()).optional().describe("File paths to copy into the lane (required for create)")}},async({action:n,name:e,files:s})=>{try{switch(n){case"create":{if(!e)throw new Error("name is required for create");if(!s||s.length===0)throw new Error("files are required for create");const o=F(e,s);return{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}case"list":return{content:[{type:"text",text:JSON.stringify(P(),null,2)}]};case"status":{if(!e)throw new Error("name is required for status");return{content:[{type:"text",text:JSON.stringify(K(e),null,2)}]}}case"diff":{if(!e)throw new Error("name is required for diff");return{content:[{type:"text",text:JSON.stringify(D(e),null,2)}]}}case"merge":{if(!e)throw new Error("name is required for merge");return{content:[{type:"text",text:JSON.stringify(W(e),null,2)}]}}case"discard":{if(!e)throw new Error("name is required for discard");return{content:[{type:"text",text:JSON.stringify({discarded:A(e)},null,2)}]}}}}catch(o){return{content:[{type:"text",text:`Lane action failed: ${o.message}`}],isError:!0}}})}function ct(t){t.registerTool("health",{description:"Run project health checks \u2014 verifies package.json, tsconfig, scripts, lockfile, README, LICENSE, .gitignore.",inputSchema:{path:r.string().optional().describe("Root directory to check (defaults to cwd)")}},async({path:n})=>{try{const e=L(n);return{content:[{type:"text",text:JSON.stringify(e,null,2)}]}}catch(e){return{content:[{type:"text",text:`Health check failed: ${e.message}`}],isError:!0}}})}function lt(t){t.registerTool("queue",{description:"Manage task queues for sequential agent operations. Push items, take next, mark done/failed, list queues.",inputSchema:{action:r.enum(["create","push","next","done","fail","get","list","clear","delete"]).describe("Queue action"),name:r.string().optional().describe("Queue name (required for most actions)"),title:r.string().optional().describe("Item title (required for push)"),id:r.string().optional().describe("Item ID (required for done/fail)"),data:r.unknown().optional().describe("Arbitrary data to attach to a queue item"),error:r.string().optional().describe("Error message (required for fail)")}},async({action:n,name:e,title:s,id:o,data:i,error:a})=>{try{switch(n){case"create":{if(!e)throw new Error("name is required for create");return{content:[{type:"text",text:JSON.stringify(Y(e),null,2)}]}}case"push":{if(!e)throw new Error("name is required for push");if(!s)throw new Error("title is required for push");return{content:[{type:"text",text:JSON.stringify(se(e,s,i),null,2)}]}}case"next":{if(!e)throw new Error("name is required for next");const l=oe(e);return{content:[{type:"text",text:JSON.stringify(l,null,2)}]}}case"done":{if(!e)throw new Error("name is required for done");if(!o)throw new Error("id is required for done");return{content:[{type:"text",text:JSON.stringify(ee(e,o),null,2)}]}}case"fail":{if(!e)throw new Error("name is required for fail");if(!o)throw new Error("id is required for fail");if(!a)throw new Error("error is required for fail");return{content:[{type:"text",text:JSON.stringify(te(e,o,a),null,2)}]}}case"get":{if(!e)throw new Error("name is required for get");return{content:[{type:"text",text:JSON.stringify(re(e),null,2)}]}}case"list":return{content:[{type:"text",text:JSON.stringify(ne(),null,2)}]};case"clear":{if(!e)throw new Error("name is required for clear");return{content:[{type:"text",text:JSON.stringify({cleared:X(e)},null,2)}]}}case"delete":{if(!e)throw new Error("name is required for delete");return{content:[{type:"text",text:JSON.stringify({deleted:Z(e)},null,2)}]}}}}catch(l){return{content:[{type:"text",text:`Queue action failed: ${l.message}`}],isError:!0}}})}const $e=r.object({query:r.string(),limit:r.number().min(1).max(20).default(5).optional(),search_mode:r.enum(["hybrid","semantic","keyword"]).default("hybrid").optional(),content_type:r.string().optional(),origin:r.enum(["indexed","curated","produced"]).optional(),category:r.string().optional(),tags:r.array(r.string()).optional(),min_score:r.number().min(0).max(1).default(.25).optional()}),ke=r.object({query:r.string().optional(),glob:r.string().optional(),pattern:r.string().optional(),limit:r.number().min(1).max(50).default(10).optional(),content_type:r.string().optional(),cwd:r.string().optional()}),Ee=r.object({files:r.array(r.string()).optional(),cwd:r.string().optional(),skip_types:r.boolean().optional(),skip_lint:r.boolean().optional()});async function ve(t,n,e){switch(t.type){case"search":{const s=$e.parse(t.args);return Te(n,e,s)}case"find":{const s=ke.parse(t.args);if(!s.query&&!s.glob&&!s.pattern)throw new Error("find operation requires query, glob, or pattern");return g(n,e,{query:s.query,glob:s.glob,pattern:s.pattern,limit:s.limit,contentType:s.content_type,cwd:s.cwd})}case"check":{const s=Ee.parse(t.args);return m({files:s.files,cwd:s.cwd,skipTypes:s.skip_types,skipLint:s.skip_lint})}default:throw new Error(`Unsupported batch operation type: ${t.type}`)}}async function Te(t,n,e){const s=e.limit??5,o={limit:s,minScore:e.min_score??.25,contentType:e.content_type,origin:e.origin,category:e.category,tags:e.tags},i=t.embedQuery?.bind(t)??t.embed.bind(t);if(e.search_mode==="keyword")return(await n.ftsSearch(e.query,o)).slice(0,s);const a=await i(e.query);if(e.search_mode==="semantic")return n.search(a,o);const[l,c]=await Promise.all([n.search(a,{...o,limit:s*2}),n.ftsSearch(e.query,{...o,limit:s*2})]);return qe(l,c).slice(0,s)}function qe(t,n,e=60){const s=new Map;for(let o=0;o<t.length;o++){const i=t[o];s.set(i.record.id,{record:i.record,score:1/(e+o+1)})}for(let o=0;o<n.length;o++){const i=n[o],a=s.get(i.record.id);if(a){a.score+=1/(e+o+1);continue}s.set(i.record.id,{record:i.record,score:1/(e+o+1)})}return[...s.values()].sort((o,i)=>i.score-o.score)}function Oe(t){const n=[`Symbol: ${t.name}`];if(t.definedIn?n.push(`Defined in: ${t.definedIn.path}:${t.definedIn.line} (${t.definedIn.kind})`):n.push("Defined in: not found"),n.push("","Imported by:"),t.importedBy.length===0)n.push(" none");else for(const e of t.importedBy)n.push(` - ${e.path}:${e.line} ${e.importStatement}`);if(n.push("","Referenced in:"),t.referencedIn.length===0)n.push(" none");else for(const e of t.referencedIn)n.push(` - ${e.path}:${e.line} ${e.context}`);return n.join(`
15
15
  `)}function Me(t){const n=[`Vitest run: ${t.passed?"passed":"failed"}`,`Duration: ${t.durationMs}ms`,`Passed: ${t.summary.passed}`,`Failed: ${t.summary.failed}`,`Skipped: ${t.summary.skipped}`];t.summary.suites!==void 0&&n.push(`Suites: ${t.summary.suites}`);const e=t.summary.tests.filter(s=>s.status==="fail");if(e.length>0){n.push("","Failed tests:");for(const s of e)n.push(`- ${s.name}${s.file?` (${s.file})`:""}`),s.error&&n.push(` ${s.error}`)}return n.join(`
16
16
  `)}function Ne(t){const n=[`Branch: ${t.branch}`,`Staged: ${t.status.staged.length}`,...t.status.staged.map(e=>` - ${e}`),`Modified: ${t.status.modified.length}`,...t.status.modified.map(e=>` - ${e}`),`Untracked: ${t.status.untracked.length}`,...t.status.untracked.map(e=>` - ${e}`),"","Recent commits:"];if(t.recentCommits.length===0)n.push(" none");else for(const e of t.recentCommits)n.push(` - ${e.hash} ${e.message}`),n.push(` ${e.author} @ ${e.date}`);return t.diff&&n.push("","Diff stat:",t.diff),n.join(`
17
17
  `)}function _e(t){if(t.length===0)return"No diff files found.";const n=[];for(const e of t){const s=e.oldPath?` (from ${e.oldPath})`:"";n.push(`${e.path}${s} [${e.status}] +${e.additions} -${e.deletions} (${e.hunks.length} hunks)`);for(const o of e.hunks){const i=o.header?` ${o.header}`:"";n.push(` @@ -${o.oldStart},${o.oldLines} +${o.newStart},${o.newLines} @@${i}`)}}return n.join(`
18
18
  `)}function Re(t){return[t.path,`Language: ${t.language}`,`Lines: ${t.lines}`,`Estimated tokens: ~${t.estimatedTokens}`,"",`Imports (${t.imports.length}):`,...p(t.imports),"",`Exports (${t.exports.length}):`,...p(t.exports),"",`Functions (${t.functions.length}):`,...p(t.functions.map(e=>`${e.name} @ line ${e.line}${e.exported?" [exported]":""}`)),"",`Classes (${t.classes.length}):`,...p(t.classes.map(e=>`${e.name} @ line ${e.line}${e.exported?" [exported]":""}`)),"",`Interfaces (${t.interfaces.length}):`,...p(t.interfaces.map(e=>`${e.name} @ line ${e.line}`)),"",`Types (${t.types.length}):`,...p(t.types.map(e=>`${e.name} @ line ${e.line}`))].join(`
19
19
  `)}function f(t){const n=[t.id,`Label: ${t.label}`,`Created: ${t.createdAt}`];if(t.notes&&n.push(`Notes: ${t.notes}`),t.files?.length){n.push(`Files: ${t.files.length}`);for(const e of t.files)n.push(` - ${e}`)}return n.push("","Data:",JSON.stringify(t.data,null,2)),n.join(`
20
20
  `)}function p(t){return t.length===0?[" none"]:t.map(n=>` - ${n}`)}function Ie(t){const n=t.trim();if(!n)return"";try{return JSON.parse(n)}catch{return t}}function Je(t){const n=t?.trim();if(!n)return{};const e=JSON.parse(n);if(!e||typeof e!="object"||Array.isArray(e))throw new Error("data must be a JSON object string");return e}function dt(t){t.registerTool("web_fetch",{description:"PREFERRED web fetcher \u2014 fetch any URL and convert to LLM-optimized markdown. Supports CSS selectors, 4 output modes (markdown/raw/links/outline), smart paragraph-boundary truncation. Strips scripts/styles/nav automatically.",inputSchema:{url:r.string().url().describe("URL to fetch (http/https only)"),mode:r.enum(["markdown","raw","links","outline"]).default("markdown").describe("Output mode: markdown (clean content), raw (HTML), links (extracted URLs), outline (heading hierarchy)"),selector:r.string().optional().describe("CSS selector to extract a specific element instead of auto-detecting main content"),max_length:r.number().min(500).max(1e5).default(15e3).describe("Max characters in output \u2014 truncates at paragraph boundaries"),include_metadata:r.boolean().default(!0).describe("Include page title, description, and URL as a header"),include_links:r.boolean().default(!1).describe("Append extracted links list at the end"),include_images:r.boolean().default(!1).describe("Include image alt texts inline"),timeout:r.number().min(1e3).max(6e4).default(15e3).describe("Request timeout in milliseconds")}},async({url:n,mode:e,selector:s,max_length:o,include_metadata:i,include_links:a,include_images:l,timeout:c})=>{try{const u=await Se({url:n,mode:e,selector:s,maxLength:o,includeMetadata:i,includeLinks:a,includeImages:l,timeout:c}),d=[`## ${u.title||"Web Page"}`,"",u.content];return u.truncated&&d.push("",`_Original length: ${u.originalLength.toLocaleString()} chars_`),d.push("","---","_Next: Use `remember` to save key findings, or `web_fetch` with a `selector` to extract a specific section._"),{content:[{type:"text",text:d.join(`
21
- `)}]}}catch(u){return{content:[{type:"text",text:`Web fetch failed: ${u.message}`}],isError:!0}}})}export{Ke as registerBatchTool,We as registerCheckTool,Ze as registerCheckpointTool,Xe as registerCodemodTool,je as registerCompactTool,et as registerDataTransformTool,st as registerDeadSymbolsTool,it as registerDelegateTool,He as registerDiffParseTool,Be as registerEvalTool,Ye as registerFileSummaryTool,rt as registerFindExamplesTool,De as registerFindTool,Qe as registerGitContextTool,ct as registerHealthTool,at as registerLaneTool,Ae as registerParseOutputTool,nt as registerProcessTool,lt as registerQueueTool,Ve as registerRenameTool,Fe as registerScopeMapTool,Ge as registerStashTool,Ue as registerSymbolTool,ze as registerTestRunTool,tt as registerTraceTool,ot as registerWatchTool,dt as registerWebFetchTool,Pe as registerWorksetTool};
21
+ `)}]}}catch(u){return{content:[{type:"text",text:`Web fetch failed: ${u.message}`}],isError:!0}}})}export{Ke as registerBatchTool,We as registerCheckTool,Ze as registerCheckpointTool,Xe as registerCodemodTool,Le as registerCompactTool,et as registerDataTransformTool,st as registerDeadSymbolsTool,it as registerDelegateTool,He as registerDiffParseTool,Be as registerEvalTool,Ye as registerFileSummaryTool,rt as registerFindExamplesTool,De as registerFindTool,Qe as registerGitContextTool,ct as registerHealthTool,at as registerLaneTool,Ae as registerParseOutputTool,nt as registerProcessTool,lt as registerQueueTool,Ve as registerRenameTool,Fe as registerScopeMapTool,Ge as registerStashTool,Ue as registerSymbolTool,ze as registerTestRunTool,tt as registerTraceTool,ot as registerWatchTool,dt as registerWebFetchTool,Pe as registerWorksetTool};
@@ -1,4 +1,4 @@
1
- import{changelog as g,encode as f,envInfo as h,httpRequest as y,measure as x,regexTest as $,schemaValidate as b,snippet as S,timeUtils as v,webSearch as T}from"@kb/tools";import{z as e}from"zod";function _(c){c.registerTool("web_search",{description:"PREFERRED web search \u2014 search the web via DuckDuckGo (no API key). Returns structured results with title, URL, and snippet.",inputSchema:{query:e.string().describe("Search query"),limit:e.number().min(1).max(20).default(5).describe("Max results to return"),site:e.string().optional().describe('Restrict to domain (e.g., "docs.aws.amazon.com")')}},async({query:a,limit:i,site:r})=>{try{const s=await T({query:a,limit:i,site:r}),t=[`## Search: ${s.query}`,""];if(s.results.length===0)t.push("No results found.");else for(const n of s.results)t.push(`### [${n.title}](${n.url})`,n.snippet,"");return t.push("---","_Next: Use `web_fetch` to read any of these pages in full._"),{content:[{type:"text",text:t.join(`
1
+ import{changelog as g,encode as f,envInfo as h,httpRequest as y,measure as x,regexTest as $,schemaValidate as b,snippet as S,timeUtils as v,webSearch as T}from"../../../tools/dist/index.js";import{z as e}from"zod";function _(c){c.registerTool("web_search",{description:"PREFERRED web search \u2014 search the web via DuckDuckGo (no API key). Returns structured results with title, URL, and snippet.",inputSchema:{query:e.string().describe("Search query"),limit:e.number().min(1).max(20).default(5).describe("Max results to return"),site:e.string().optional().describe('Restrict to domain (e.g., "docs.aws.amazon.com")')}},async({query:a,limit:i,site:r})=>{try{const s=await T({query:a,limit:i,site:r}),t=[`## Search: ${s.query}`,""];if(s.results.length===0)t.push("No results found.");else for(const n of s.results)t.push(`### [${n.title}](${n.url})`,n.snippet,"");return t.push("---","_Next: Use `web_fetch` to read any of these pages in full._"),{content:[{type:"text",text:t.join(`
2
2
  `)}]}}catch(s){return{content:[{type:"text",text:`Web search failed: ${s.message}`}],isError:!0}}})}function M(c){c.registerTool("http",{description:"Make HTTP requests (GET/POST/PUT/PATCH/DELETE/HEAD) for API testing. Returns status, headers, and formatted body with timing info.",inputSchema:{url:e.string().url().describe("Request URL (http/https only)"),method:e.enum(["GET","POST","PUT","PATCH","DELETE","HEAD"]).default("GET").describe("HTTP method"),headers:e.record(e.string(),e.string()).optional().describe("Request headers as key-value pairs"),body:e.string().optional().describe("Request body (for POST/PUT/PATCH)"),timeout:e.number().min(1e3).max(6e4).default(15e3).describe("Timeout in milliseconds")}},async({url:a,method:i,headers:r,body:s,timeout:t})=>{try{const n=await y({url:a,method:i,headers:r,body:s,timeout:t}),o=[`## ${i} ${a}`,"",`**Status:** ${n.status} ${n.statusText}`,`**Time:** ${n.durationMs}ms`,`**Size:** ${n.sizeBytes} bytes`,`**Content-Type:** ${n.contentType}`,"","### Headers","```json",JSON.stringify(n.headers,null,2),"```","","### Body",n.contentType.includes("json")?"```json":"```",n.body,"```"];return n.truncated&&o.push("",`_Response truncated \u2014 total size: ${n.sizeBytes} bytes_`),{content:[{type:"text",text:o.join(`
3
3
  `)}]}}catch(n){return{content:[{type:"text",text:`HTTP request failed: ${n.message}`}],isError:!0}}})}function R(c){c.registerTool("regex_test",{description:"Test a regex pattern against sample strings. Supports match, replace, and split modes.",inputSchema:{pattern:e.string().describe("Regex pattern (without delimiters)"),flags:e.string().default("").describe("Regex flags (g, i, m, s, etc.)"),test_strings:e.array(e.string()).describe("Strings to test the pattern against"),mode:e.enum(["match","replace","split"]).default("match").describe("Test mode"),replacement:e.string().optional().describe("Replacement string (for replace mode)")}},async({pattern:a,flags:i,test_strings:r,mode:s,replacement:t})=>{const n=$({pattern:a,flags:i,testStrings:r,mode:s,replacement:t});if(!n.valid)return{content:[{type:"text",text:`Invalid regex: ${n.error}`}],isError:!0};const o=[`## Regex: \`/${n.pattern}/${n.flags}\``,"",`Mode: ${s}`,""];for(const d of n.results){if(o.push(`**Input:** \`${d.input}\``),o.push(`**Matched:** ${d.matched}`),d.matches)for(const p of d.matches){const l=p.groups.length>0?` groups: [${p.groups.join(", ")}]`:"";o.push(` - "${p.full}" at index ${p.index}${l}`)}d.replaced!==void 0&&o.push(`**Result:** \`${d.replaced}\``),d.split&&o.push(`**Split:** ${JSON.stringify(d.split)}`),o.push("")}return{content:[{type:"text",text:o.join(`
4
4
  `)}]}})}function j(c){c.registerTool("encode",{description:"Encode, decode, or hash text. Supports base64, URL encoding, SHA-256, MD5, JWT decode, hex.",inputSchema:{operation:e.enum(["base64_encode","base64_decode","url_encode","url_decode","sha256","md5","jwt_decode","hex_encode","hex_decode"]).describe("Operation to perform"),input:e.string().describe("Input text")}},async({operation:a,input:i})=>{try{const r=f({operation:a,input:i});return{content:[{type:"text",text:`## ${a}
@@ -1 +1 @@
1
- import{EMBEDDING_DEFAULTS as h,SEARCH_DEFAULTS as d,STORE_DEFAULTS as u}from"@kb/core";import{connect as g,Index as m}from"@lancedb/lancedb";const b=/^[\w.\-/ ]+$/;function s(l,e){if(!b.test(l))throw new Error(`Invalid ${e} filter value: contains disallowed characters`);return l.replace(/'/g,"''")}class p{db=null;table=null;dbPath;tableName;constructor(e){this.dbPath=e?.path??u.path,this.tableName=e?.tableName??u.tableName}async initialize(){this.db=await g(this.dbPath),(await this.db.tableNames()).includes(this.tableName)&&(this.table=await this.db.openTable(this.tableName),await this.createFtsIndex())}async upsert(e,n){if(e.length===0)return;if(e.length!==n.length)throw new Error(`Record count (${e.length}) does not match vector count (${n.length})`);const a=e.map((t,i)=>({id:t.id,vector:Array.from(n[i]),content:t.content,sourcePath:t.sourcePath,contentType:t.contentType,headingPath:t.headingPath??"",chunkIndex:t.chunkIndex,totalChunks:t.totalChunks,startLine:t.startLine,endLine:t.endLine,fileHash:t.fileHash,indexedAt:t.indexedAt,origin:t.origin,tags:JSON.stringify(t.tags),category:t.category??"",version:t.version}));if(this.table){const t=[...new Set(e.map(i=>i.sourcePath))];for(const i of t)try{await this.table.delete(`sourcePath = '${s(i,"sourcePath")}'`)}catch{}await this.table.add(a)}else try{this.table=await this.db?.createTable(this.tableName,a)??null}catch(t){if(String(t).includes("already exists")&&this.db)this.table=await this.db.openTable(this.tableName),await this.table.add(a);else throw t}}async search(e,n){if(!this.table)return[];const a=n?.limit??d.maxResults,t=n?.minScore??d.minScore;let i=this.table.search(e).limit(a*2);const o=this.buildFilterString(n);return o&&(i=i.where(o)),(await i.toArray()).map(c=>({record:this.fromLanceRecord(c),score:1-(c._distance??1)})).filter(c=>c.score>=t).slice(0,a)}async createFtsIndex(){if(this.table)try{await this.table.createIndex("content",{config:m.fts()}),console.error("[KB] FTS index created on content column")}catch(e){String(e).includes("already exists")||console.error("[KB] FTS index creation failed (non-fatal):",e)}}async ftsSearch(e,n){if(!this.table)return[];const a=n?.limit??d.maxResults;try{let t=this.table.search(e).limit(a*2);const i=this.buildFilterString(n);return i&&(t=t.where(i)),(await t.toArray()).map(r=>({record:this.fromLanceRecord(r),score:r._score??r._relevance_score??0}))}catch(t){return console.error("[KB] FTS search failed (non-fatal):",t),[]}}async getById(e){if(!this.table)return null;const n=await this.table.query().where(`id = '${s(e,"id")}'`).limit(1).toArray();return n.length===0?null:this.fromLanceRecord(n[0])}async deleteBySourcePath(e){if(!this.table)return 0;const n=await this.getBySourcePath(e);return n.length===0?0:(await this.table.delete(`sourcePath = '${s(e,"sourcePath")}'`),n.length)}async deleteById(e){return!this.table||!await this.getById(e)?!1:(await this.table.delete(`id = '${s(e,"id")}'`),!0)}async getBySourcePath(e){return this.table?(await this.table.query().where(`sourcePath = '${s(e,"sourcePath")}'`).limit(1e3).toArray()).map(a=>this.fromLanceRecord(a)):[]}async getStats(){if(!this.table)return{totalRecords:0,totalFiles:0,contentTypeBreakdown:{},lastIndexedAt:null,storeBackend:"lancedb",embeddingModel:h.model};const e=await this.table.countRows(),n=await this.table.query().select(["sourcePath","contentType","indexedAt"]).limit(1e5).toArray(),a={},t=new Set;let i=null;for(const o of n){const r=o;a[r.contentType]=(a[r.contentType]??0)+1,t.add(r.sourcePath),(!i||r.indexedAt>i)&&(i=r.indexedAt)}return{totalRecords:e,totalFiles:t.size,contentTypeBreakdown:a,lastIndexedAt:i,storeBackend:"lancedb",embeddingModel:h.model}}async listSourcePaths(){if(!this.table)return[];const e=await this.table.query().select(["sourcePath"]).limit(1e5).toArray();return[...new Set(e.map(n=>n.sourcePath))]}async dropTable(){if(this.db&&(await this.db.tableNames()).includes(this.tableName))for(let a=1;a<=3;a++)try{await this.db.dropTable(this.tableName);break}catch(t){if(a===3)throw t;const i=a*500;console.error(`[KB] dropTable attempt ${a} failed, retrying in ${i}ms...`),await new Promise(o=>setTimeout(o,i))}this.table=null}async close(){try{this.db&&typeof this.db.close=="function"&&await this.db.close()}catch{}this.table=null,this.db=null}buildFilterString(e){const n=[];if(e?.contentType&&n.push(`contentType = '${s(e.contentType,"contentType")}'`),e?.origin&&n.push(`origin = '${s(e.origin,"origin")}'`),e?.category&&n.push(`category = '${s(e.category,"category")}'`),e?.tags&&e.tags.length>0){const a=e.tags.map(t=>`tags LIKE '%${s(t,"tag")}%'`);n.push(`(${a.join(" OR ")})`)}return n.length>0?n.join(" AND "):null}fromLanceRecord(e){return{id:e.id,content:e.content,sourcePath:e.sourcePath,contentType:e.contentType,headingPath:e.headingPath||void 0,chunkIndex:e.chunkIndex,totalChunks:e.totalChunks,startLine:e.startLine,endLine:e.endLine,fileHash:e.fileHash,indexedAt:e.indexedAt,origin:e.origin,tags:JSON.parse(e.tags||"[]"),category:e.category||void 0,version:e.version}}}export{p as LanceStore};
1
+ import{EMBEDDING_DEFAULTS as h,SEARCH_DEFAULTS as d,STORE_DEFAULTS as u}from"../../core/dist/index.js";import{connect as g,Index as m}from"@lancedb/lancedb";const b=/^[\w.\-/ ]+$/;function r(l,e){if(!b.test(l))throw new Error(`Invalid ${e} filter value: contains disallowed characters`);return l.replace(/'/g,"''")}class p{db=null;table=null;dbPath;tableName;constructor(e){this.dbPath=e?.path??u.path,this.tableName=e?.tableName??u.tableName}async initialize(){this.db=await g(this.dbPath),(await this.db.tableNames()).includes(this.tableName)&&(this.table=await this.db.openTable(this.tableName),await this.createFtsIndex())}async upsert(e,n){if(e.length===0)return;if(e.length!==n.length)throw new Error(`Record count (${e.length}) does not match vector count (${n.length})`);const a=e.map((t,i)=>({id:t.id,vector:Array.from(n[i]),content:t.content,sourcePath:t.sourcePath,contentType:t.contentType,headingPath:t.headingPath??"",chunkIndex:t.chunkIndex,totalChunks:t.totalChunks,startLine:t.startLine,endLine:t.endLine,fileHash:t.fileHash,indexedAt:t.indexedAt,origin:t.origin,tags:JSON.stringify(t.tags),category:t.category??"",version:t.version}));if(this.table){const t=[...new Set(e.map(i=>i.sourcePath))];for(const i of t)try{await this.table.delete(`sourcePath = '${r(i,"sourcePath")}'`)}catch{}await this.table.add(a)}else try{this.table=await this.db?.createTable(this.tableName,a)??null}catch(t){if(String(t).includes("already exists")&&this.db)this.table=await this.db.openTable(this.tableName),await this.table.add(a);else throw t}}async search(e,n){if(!this.table)return[];const a=n?.limit??d.maxResults,t=n?.minScore??d.minScore;let i=this.table.search(e).limit(a*2);const o=this.buildFilterString(n);return o&&(i=i.where(o)),(await i.toArray()).map(c=>({record:this.fromLanceRecord(c),score:1-(c._distance??1)})).filter(c=>c.score>=t).slice(0,a)}async createFtsIndex(){if(this.table)try{await this.table.createIndex("content",{config:m.fts()}),console.error("[KB] FTS index created on content column")}catch(e){String(e).includes("already exists")||console.error("[KB] FTS index creation failed (non-fatal):",e)}}async ftsSearch(e,n){if(!this.table)return[];const a=n?.limit??d.maxResults;try{let t=this.table.search(e).limit(a*2);const i=this.buildFilterString(n);return i&&(t=t.where(i)),(await t.toArray()).map(s=>({record:this.fromLanceRecord(s),score:s._score??s._relevance_score??0}))}catch(t){return console.error("[KB] FTS search failed (non-fatal):",t),[]}}async getById(e){if(!this.table)return null;const n=await this.table.query().where(`id = '${r(e,"id")}'`).limit(1).toArray();return n.length===0?null:this.fromLanceRecord(n[0])}async deleteBySourcePath(e){if(!this.table)return 0;const n=await this.getBySourcePath(e);return n.length===0?0:(await this.table.delete(`sourcePath = '${r(e,"sourcePath")}'`),n.length)}async deleteById(e){return!this.table||!await this.getById(e)?!1:(await this.table.delete(`id = '${r(e,"id")}'`),!0)}async getBySourcePath(e){return this.table?(await this.table.query().where(`sourcePath = '${r(e,"sourcePath")}'`).limit(1e3).toArray()).map(a=>this.fromLanceRecord(a)):[]}async getStats(){if(!this.table)return{totalRecords:0,totalFiles:0,contentTypeBreakdown:{},lastIndexedAt:null,storeBackend:"lancedb",embeddingModel:h.model};const e=await this.table.countRows(),n=await this.table.query().select(["sourcePath","contentType","indexedAt"]).limit(1e5).toArray(),a={},t=new Set;let i=null;for(const o of n){const s=o;a[s.contentType]=(a[s.contentType]??0)+1,t.add(s.sourcePath),(!i||s.indexedAt>i)&&(i=s.indexedAt)}return{totalRecords:e,totalFiles:t.size,contentTypeBreakdown:a,lastIndexedAt:i,storeBackend:"lancedb",embeddingModel:h.model}}async listSourcePaths(){if(!this.table)return[];const e=await this.table.query().select(["sourcePath"]).limit(1e5).toArray();return[...new Set(e.map(n=>n.sourcePath))]}async dropTable(){if(this.db&&(await this.db.tableNames()).includes(this.tableName))for(let a=1;a<=3;a++)try{await this.db.dropTable(this.tableName);break}catch(t){if(a===3)throw t;const i=a*500;console.error(`[KB] dropTable attempt ${a} failed, retrying in ${i}ms...`),await new Promise(o=>setTimeout(o,i))}this.table=null}async close(){try{this.db&&typeof this.db.close=="function"&&await this.db.close()}catch{}this.table=null,this.db=null}buildFilterString(e){const n=[];if(e?.contentType&&n.push(`contentType = '${r(e.contentType,"contentType")}'`),e?.origin&&n.push(`origin = '${r(e.origin,"origin")}'`),e?.category&&n.push(`category = '${r(e.category,"category")}'`),e?.tags&&e.tags.length>0){const a=e.tags.map(t=>`tags LIKE '%${r(t,"tag")}%'`);n.push(`(${a.join(" OR ")})`)}return n.length>0?n.join(" AND "):null}fromLanceRecord(e){return{id:e.id,content:e.content,sourcePath:e.sourcePath,contentType:e.contentType,headingPath:e.headingPath||void 0,chunkIndex:e.chunkIndex,totalChunks:e.totalChunks,startLine:e.startLine,endLine:e.endLine,fileHash:e.fileHash,indexedAt:e.indexedAt,origin:e.origin,tags:JSON.parse(e.tags||"[]"),category:e.category||void 0,version:e.version}}}export{p as LanceStore};
@@ -1,3 +1,3 @@
1
- import{cosineSimilarity as b,segment as C}from"./text-utils.js";async function S(m,g){const{text:t,query:l,maxChars:o=3e3,minScore:h=.3,segmentation:p="paragraph"}=g;if(t.length<=o)return{text:t,originalChars:t.length,compressedChars:t.length,ratio:1,segmentsKept:1,segmentsTotal:1};const n=C(t,p);if(n.length===0)return{text:"",originalChars:t.length,compressedChars:0,ratio:0,segmentsKept:0,segmentsTotal:0};const x=await m.embed(l),c=[];for(let e=0;e<n.length;e++){const s=await m.embed(n[e]),u=b(x,s);c.push({text:n[e],score:u,index:e})}const d=c.filter(e=>e.score>=h).sort((e,s)=>s.score-e.score),r=[];let a=0;for(const e of d){if(a+e.text.length>o){a===0&&(r.push({...e,text:e.text.slice(0,o)}),a=o);break}r.push(e),a+=e.text.length+2}r.sort((e,s)=>e.index-s.index);const i=r.map(e=>e.text).join(`
1
+ import{cosineSimilarity as C,segment as b}from"./text-utils.js";async function S(m,g){const{text:t,query:l,maxChars:o=3e3,minScore:h=.3,segmentation:p="paragraph"}=g;if(t.length<=o)return{text:t,originalChars:t.length,compressedChars:t.length,ratio:1,segmentsKept:1,segmentsTotal:1};const n=b(t,p);if(n.length===0)return{text:"",originalChars:t.length,compressedChars:0,ratio:0,segmentsKept:0,segmentsTotal:0};const d=await m.embed(l),c=[];for(let e=0;e<n.length;e++){const s=await m.embed(n[e]),u=C(d,s);c.push({text:n[e],score:u,index:e})}const x=c.filter(e=>e.score>=h).sort((e,s)=>s.score-e.score),r=[];let i=0;for(const e of x){if(i+e.text.length>o){i===0&&(r.push({...e,text:e.text.slice(0,o)}),i=o);break}r.push(e),i+=e.text.length+2}r.sort((e,s)=>e.index-s.index);const a=r.map(e=>e.text).join(`
2
2
 
3
- `);return{text:i,originalChars:t.length,compressedChars:i.length,ratio:i.length/t.length,segmentsKept:r.length,segmentsTotal:n.length}}export{S as compact};
3
+ `);return{text:a,originalChars:t.length,compressedChars:a.length,ratio:a.length/t.length,segmentsKept:r.length,segmentsTotal:n.length}}export{S as compact};
@@ -1,2 +1,2 @@
1
- async function w(o,r,n={}){const{rootPath:a,limit:f=100}=n,x=await o.embed("export function class const type interface enum"),y=await r.search(x,{limit:f*3}),u=/^export\s+(?:async\s+)?(?:function|class|const|let|interface|type|enum)\s+(\w+)/gm,h=[];for(const t of y){if(!D(t.record.sourcePath,a))continue;const e=t.record.content;u.lastIndex=0;for(const m of e.matchAll(u)){const p=m.index??0,l=e.slice(0,p).split(`
2
- `).length-1,d=e.slice(p).match(/export\s+(?:async\s+)?(\w+)/);h.push({name:m[1],path:t.record.sourcePath,line:t.record.startLine+l,kind:d?.[1]??"unknown"})}}const c=new Map;for(const t of h){const e=`${t.path}:${t.name}`;c.has(e)||c.set(e,t)}const i=[];for(const t of c.values()){const e=S(t.name),m=new RegExp(`import\\s+.*\\b${e}\\b.*from`,"m"),p=new RegExp(`export\\s+\\{[^}]*\\b${e}\\b`,"m"),l=await r.ftsSearch(`import ${t.name}`,{limit:10}),d=l.some(s=>s.record.sourcePath!==t.path&&m.test(s.record.content)),g=l.some(s=>s.record.sourcePath!==t.path&&p.test(s.record.content));!d&&!g&&i.push(t)}return i.sort((t,e)=>t.path===e.path?t.line-e.line:t.path.localeCompare(e.path)),{deadSymbols:i,totalExports:c.size,totalDead:i.length}}function S(o){return o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function D(o,r){if(!r)return!0;const n=b(r).replace(/\/+$/,"");if(/^[A-Za-z]:\//.test(n)||n.startsWith("/"))return!0;const a=b(o);return a===n||a.startsWith(`${n}/`)}function b(o){return o.replace(/\\/g,"/").replace(/^\.\//,"")}export{w as findDeadSymbols};
1
+ async function w(o,r,n={}){const{rootPath:a,limit:b=100}=n,x=await o.embed("export function class const type interface enum"),y=await r.search(x,{limit:b*3}),u=/^export\s+(?:async\s+)?(?:function|class|const|let|interface|type|enum)\s+(\w+)/gm,h=[];for(const t of y){if(!D(t.record.sourcePath,a))continue;const e=t.record.content;u.lastIndex=0;for(const m of e.matchAll(u)){const p=m.index??0,d=e.slice(0,p).split(`
2
+ `).length-1,l=e.slice(p).match(/export\s+(?:async\s+)?(\w+)/);h.push({name:m[1],path:t.record.sourcePath,line:t.record.startLine+d,kind:l?.[1]??"unknown"})}}const c=new Map;for(const t of h){const e=`${t.path}:${t.name}`;c.has(e)||c.set(e,t)}const i=[];for(const t of c.values()){const e=S(t.name),m=new RegExp(`import\\s+.*\\b${e}\\b.*from`,"m"),p=new RegExp(`export\\s+\\{[^}]*\\b${e}\\b`,"m"),d=await r.ftsSearch(`import ${t.name}`,{limit:10}),l=d.some(s=>s.record.sourcePath!==t.path&&m.test(s.record.content)),g=d.some(s=>s.record.sourcePath!==t.path&&p.test(s.record.content));!l&&!g&&i.push(t)}return i.sort((t,e)=>t.path===e.path?t.line-e.line:t.path.localeCompare(e.path)),{deadSymbols:i,totalExports:c.size,totalDead:i.length}}function S(o){return o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function D(o,r){if(!r)return!0;const n=f(r).replace(/\/+$/,"");if(/^[A-Za-z]:\//.test(n)||n.startsWith("/"))return!0;const a=f(o);return a===n||a.startsWith(`${n}/`)}function f(o){return o.replace(/\\/g,"/").replace(/^\.\//,"")}export{w as findDeadSymbols};
@@ -1,7 +1,7 @@
1
1
  import{cosineSimilarity as I,estimateTokens as k,segment as N}from"./text-utils.js";const L=["status","files","decisions","blockers","artifacts","next"],O={status:/\b(?:status|result)\s*[:=]/i,files:/\b(?:files?|modified|created|deleted)\s*[:=]/i,artifacts:/\b(?:artifacts?)\s*[:=]/i,decisions:/\b(?:decisions?|decided|chose|selected)\s*[:=]/i,blockers:/\b(?:blockers?|blocked|blocking)\s*[:=]/i,next:/\b(?:next\s*(?:steps?|actions?)|todo|follow.up)\s*[:=]/i},$={status:/(?:^|\b)(?:status|result)\s*[:=]\s*(.+)$/i,files:/(?:^|\b)(?:files?|modified|created|deleted)\s*[:=]\s*(.+)$/i,artifacts:/(?:^|\b)(?:artifacts?)\s*[:=]\s*(.+)$/i,decisions:/(?:^|\b)(?:decisions?|decided|chose|selected)\s*[:=]\s*(.+)$/i,blockers:/(?:^|\b)(?:blockers?|blocked|blocking)\s*[:=]\s*(.+)$/i,next:/(?:^|\b)(?:next\s*(?:steps?|actions?)|todo|follow.up)\s*[:=]\s*(.+)$/i},R=/\b(?:APPROVED|NEEDS_REVISION|BLOCKED|SUCCESS|PARTIAL|FAILED|ESCALATE)\b/i,b=.01;function M(e){const n=e??[...L];return[...new Set(n.map(r=>r.toLowerCase()))]}function _(e){return typeof e!="number"||!Number.isFinite(e)||e<=0?1:e}function K(e,n){const r=new Set;for(const i of n)O[i]?.test(e)&&r.add(i);return n.includes("status")&&R.test(e)&&r.add("status"),[...r]}function V(e,n){const r=n.split(`
2
- `).map(i=>i.trim()).filter(i=>i.length>0);for(const i of r){const g=$[e]?.exec(i);if(g?.[1])return g[1].trim();if(e==="status"){const m=i.match(R);if(m)return m[0]}}return n.trim()}function q(e,n,r,i){e[n]||(e[n]=[]),e[n].push({sourceId:r,value:i})}function U(e,n,r,i){return e.map(c=>{const g=N(c.text,n).map((s,o)=>{const l=K(s,r);for(const h of l)q(i,h,c.id,V(h,s));return{index:o,text:s,pinnedFields:l,score:0}}),m=g.filter(s=>s.pinnedFields.length>0).reduce((s,o)=>s+o.text.length,0),f=g.filter(s=>s.pinnedFields.length===0).reduce((s,o)=>s+o.text.length,0);return{id:c.id,originalText:c.text,weight:_(c.weight),segments:g,pinnedChars:m,nonPinnedChars:f}})}function j(e,n){const r=new Map(e.map(g=>[g.id,0]));let i=Math.max(0,n),c=e.filter(g=>g.nonPinnedChars>0);for(;i>b&&c.length>0;){const g=c.reduce((s,o)=>s+o.weight,0);let m=0;const f=[];for(const s of c){const o=r.get(s.id)??0,l=s.nonPinnedChars-o;if(l<=b)continue;const h=i*(s.weight/g),x=Math.min(h,l);r.set(s.id,o+x),m+=x,l-x>b&&f.push(s)}if(m<=b)break;i-=m,c=f}return r}function A(e){return e.map(n=>`[${n.id}]
2
+ `).map(i=>i.trim()).filter(i=>i.length>0);for(const i of r){const g=$[e]?.exec(i);if(g?.[1])return g[1].trim();if(e==="status"){const m=i.match(R);if(m)return m[0]}}return n.trim()}function q(e,n,r,i){e[n]||(e[n]=[]),e[n].push({sourceId:r,value:i})}function U(e,n,r,i){return e.map(d=>{const g=N(d.text,n).map((s,o)=>{const l=K(s,r);for(const h of l)q(i,h,d.id,V(h,s));return{index:o,text:s,pinnedFields:l,score:0}}),m=g.filter(s=>s.pinnedFields.length>0).reduce((s,o)=>s+o.text.length,0),f=g.filter(s=>s.pinnedFields.length===0).reduce((s,o)=>s+o.text.length,0);return{id:d.id,originalText:d.text,weight:_(d.weight),segments:g,pinnedChars:m,nonPinnedChars:f}})}function j(e,n){const r=new Map(e.map(g=>[g.id,0]));let i=Math.max(0,n),d=e.filter(g=>g.nonPinnedChars>0);for(;i>b&&d.length>0;){const g=d.reduce((s,o)=>s+o.weight,0);let m=0;const f=[];for(const s of d){const o=r.get(s.id)??0,l=s.nonPinnedChars-o;if(l<=b)continue;const h=i*(s.weight/g),x=Math.min(h,l);r.set(s.id,o+x),m+=x,l-x>b&&f.push(s)}if(m<=b)break;i-=m,d=f}return r}function A(e){return e.map(n=>`[${n.id}]
3
3
  ${n.text}`).join(`
4
4
 
5
- `)}function B(e,n){return e===0?0:n/e}async function z(e,n){const{sources:r,query:i,maxChars:c=4e3,pinFields:g,segmentation:m="paragraph"}=n,f={},s=M(g),o=U(r,m,s,f),l=r.reduce((d,u)=>d+u.text.length,0);if(l<=c){const d=o.filter(a=>a.originalText.trim().length>0).map(a=>({id:a.id,text:a.originalText})),u=o.map(a=>({id:a.id,originalChars:a.originalText.length,keptChars:a.originalText.length,segmentsKept:a.segments.length,segmentsTotal:a.segments.length}));return{text:A(d),fields:f,sourceStats:u,totalOriginalChars:l,totalCompressedChars:l,ratio:l===0?0:1}}const h=await e.embedQuery(i);for(const d of o)for(const u of d.segments){if(u.pinnedFields.length>0)continue;const a=await e.embed(u.text);u.score=I(h,a)}const x=o.reduce((d,u)=>d+u.pinnedChars,0),w=j(o,c-x),T=[],y=[];let P=0;for(const d of o){const u=w.get(d.id)??0,a=new Map;let C=0;const v=d.segments.filter(t=>t.pinnedFields.length===0).sort((t,p)=>p.score-t.score||k(t.text)-k(p.text)||t.index-p.index);let S;for(const t of v){const p=u-C;if(p<=b)break;if(t.text.length<=p+b){a.set(t.index,t.text),C+=t.text.length;continue}S||(S=t)}const F=Math.floor(u-C);if(S&&F>0){const t=S.text.slice(0,F).trimEnd();t.length>0&&(a.set(S.index,t),C+=t.length)}const E=d.segments.filter(t=>t.pinnedFields.length>0||a.has(t.index)).map(t=>({index:t.index,text:a.get(t.index)??t.text})),D=E.reduce((t,p)=>t+p.text.length,0);T.push({id:d.id,originalChars:d.originalText.length,keptChars:D,segmentsKept:E.length,segmentsTotal:d.segments.length}),P+=D,E.length!==0&&y.push({id:d.id,text:E.map(t=>t.text).join(`
5
+ `)}function B(e,n){return e===0?0:n/e}async function z(e,n){const{sources:r,query:i,maxChars:d=4e3,pinFields:g,segmentation:m="paragraph"}=n,f={},s=M(g),o=U(r,m,s,f),l=r.reduce((c,u)=>c+u.text.length,0);if(l<=d){const c=o.filter(a=>a.originalText.trim().length>0).map(a=>({id:a.id,text:a.originalText})),u=o.map(a=>({id:a.id,originalChars:a.originalText.length,keptChars:a.originalText.length,segmentsKept:a.segments.length,segmentsTotal:a.segments.length}));return{text:A(c),fields:f,sourceStats:u,totalOriginalChars:l,totalCompressedChars:l,ratio:l===0?0:1}}const h=await e.embedQuery(i);for(const c of o)for(const u of c.segments){if(u.pinnedFields.length>0)continue;const a=await e.embed(u.text);u.score=I(h,a)}const x=o.reduce((c,u)=>c+u.pinnedChars,0),w=j(o,d-x),T=[],y=[];let P=0;for(const c of o){const u=w.get(c.id)??0,a=new Map;let C=0;const v=c.segments.filter(t=>t.pinnedFields.length===0).sort((t,p)=>p.score-t.score||k(t.text)-k(p.text)||t.index-p.index);let S;for(const t of v){const p=u-C;if(p<=b)break;if(t.text.length<=p+b){a.set(t.index,t.text),C+=t.text.length;continue}S||(S=t)}const F=Math.floor(u-C);if(S&&F>0){const t=S.text.slice(0,F).trimEnd();t.length>0&&(a.set(S.index,t),C+=t.length)}const E=c.segments.filter(t=>t.pinnedFields.length>0||a.has(t.index)).map(t=>({index:t.index,text:a.get(t.index)??t.text})),D=E.reduce((t,p)=>t+p.text.length,0);T.push({id:c.id,originalChars:c.originalText.length,keptChars:D,segmentsKept:E.length,segmentsTotal:c.segments.length}),P+=D,E.length!==0&&y.push({id:c.id,text:E.map(t=>t.text).join(`
6
6
 
7
7
  `)})}return{text:A(y),fields:f,sourceStats:T,totalOriginalChars:l,totalCompressedChars:P,ratio:B(l,P)}}export{z as digest};
@@ -1,3 +1,3 @@
1
- async function $(s,d,x){const{query:o,limit:i=5,contentType:u}=x,g=`usage example of ${o}`,f=await s.embed(g),b=await d.search(f,{limit:i*3,contentType:u}),c=new RegExp(`\\b${I(o)}\\b`,"i"),a=b.filter(e=>c.test(e.record.content)),h=a.map(e=>{const t=e.record.content,m=/export\s+(?:async\s+)?(?:function|class|const|interface|type)\s/.test(t),E=/^\s*import\s/m.test(t),p=/(?:^|[\\/])(test|tests|__tests__|spec)(?:[\\/]|$)/i.test(e.record.sourcePath)||/\.(test|spec)\.[jt]sx?$/i.test(e.record.sourcePath);let n=0;m||(n+=.1),E||(n+=.05),p&&(n+=.05);const r=t.split(`
2
- `),l=r.findIndex(F=>c.test(F)),y=Math.max(0,l-2),L=Math.min(r.length,l+5),v=r.slice(y,L).join(`
3
- `);return{path:e.record.sourcePath,startLine:e.record.startLine,endLine:e.record.endLine,content:v||t.slice(0,300),relevance:Math.min(1,e.score+n),context:p?"test":m?"definition":"usage"}}).sort((e,t)=>t.relevance-e.relevance).slice(0,i);return{query:o,examples:h,totalFound:a.length}}function I(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}export{$ as findExamples};
1
+ async function $(s,l,x){const{query:i,limit:r=5,contentType:u}=x,g=`usage example of ${i}`,f=await s.embed(g),h=await l.search(f,{limit:r*3,contentType:u}),c=new RegExp(`\\b${I(i)}\\b`,"i"),a=h.filter(e=>c.test(e.record.content)),E=a.map(e=>{const t=e.record.content,m=/export\s+(?:async\s+)?(?:function|class|const|interface|type)\s/.test(t),y=/^\s*import\s/m.test(t),p=/(?:^|[\\/])(test|tests|__tests__|spec)(?:[\\/]|$)/i.test(e.record.sourcePath)||/\.(test|spec)\.[jt]sx?$/i.test(e.record.sourcePath);let n=0;m||(n+=.1),y||(n+=.05),p&&(n+=.05);const o=t.split(`
2
+ `),d=o.findIndex(F=>c.test(F)),b=Math.max(0,d-2),L=Math.min(o.length,d+5),v=o.slice(b,L).join(`
3
+ `);return{path:e.record.sourcePath,startLine:e.record.startLine,endLine:e.record.endLine,content:v||t.slice(0,300),relevance:Math.min(1,e.score+n),context:p?"test":m?"definition":"usage"}}).sort((e,t)=>t.relevance-e.relevance).slice(0,r);return{query:i,examples:E,totalFound:a.length}}function I(s){return s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}export{$ as findExamples};
@@ -1,4 +1,4 @@
1
- import{existsSync as W,mkdirSync as V,readdirSync as q,rmSync as U,writeFileSync as I}from"node:fs";import{readdir as J,readFile as Z}from"node:fs/promises";import{basename as L,join as K,relative as H,resolve as Q}from"node:path";import{DependencyAnalyzer as X,DiagramGenerator as Y,EntryPointAnalyzer as ee,extractRegexCallGraph as te,extractTsCallGraph as se,PatternAnalyzer as ne,StructureAnalyzer as oe,SymbolAnalyzer as re}from"@kb/analyzers";const N={structure:"Project Structure",dependencies:"Dependencies","entry-points":"Entry Points",symbols:"Symbols",patterns:"Patterns",diagram:"C4 Container Diagram","code-map":"Code Map (Module Graph)","config-values":"Configuration Values","synthesis-guide":"Synthesis Guide"};function ie(g,u,t,p){const n=[`Analysis baselines for **${t}** have been generated.`];u==="generate"?n.push("Individual results are in the sibling `.md` and `.json` files in this directory.",""):n.push("Results are stored in the KB vector store.","");const a=p.get("symbols"),i=p.get("dependencies"),d=p.get("patterns"),y=p.get("entry-points"),b=a?.totalCount??0,k=a?.exportedCount??0,x=i?.totalImports??0,C=y?.total??0,r=(d?.patterns??[]).map(m=>m.pattern),w=r.some(m=>m.startsWith("Spring")),D=r.includes("AWS CDK")||r.includes("CDK IaC"),P=r.includes("Maven"),T=r.includes("Serverless")||C>3,$=i?.external?Object.keys(i.external):[],f=$.some(m=>["express","fastify","next","react","vitest","jest"].includes(m))||x>0,_=$.some(m=>["turbo","lerna","nx"].includes(m))||r.includes("Monorepo");if(n.push("### Project Profile",""),n.push(`- **${b} symbols** (${k} exported), **${x} imports**, **${C} entry ${C===1?"point":"points"}**`),r.length>0&&n.push(`- **Detected**: ${r.slice(0,8).join(", ")}`),n.push(""),b===0&&x===0&&C===0)return n.push("> **Note:** This project appears to be empty or contains no analyzable source code.","> Run onboard again after adding source files."),n.join(`
1
+ import{existsSync as W,mkdirSync as V,readdirSync as q,rmSync as U,writeFileSync as I}from"node:fs";import{readdir as J,readFile as Z}from"node:fs/promises";import{basename as L,join as K,relative as H,resolve as Q}from"node:path";import{DependencyAnalyzer as X,DiagramGenerator as Y,EntryPointAnalyzer as ee,extractRegexCallGraph as te,extractTsCallGraph as se,PatternAnalyzer as ne,StructureAnalyzer as oe,SymbolAnalyzer as re}from"../../analyzers/dist/index.js";const N={structure:"Project Structure",dependencies:"Dependencies","entry-points":"Entry Points",symbols:"Symbols",patterns:"Patterns",diagram:"C4 Container Diagram","code-map":"Code Map (Module Graph)","config-values":"Configuration Values","synthesis-guide":"Synthesis Guide"};function ie(g,u,t,p){const n=[`Analysis baselines for **${t}** have been generated.`];u==="generate"?n.push("Individual results are in the sibling `.md` and `.json` files in this directory.",""):n.push("Results are stored in the KB vector store.","");const a=p.get("symbols"),i=p.get("dependencies"),d=p.get("patterns"),y=p.get("entry-points"),b=a?.totalCount??0,k=a?.exportedCount??0,x=i?.totalImports??0,C=y?.total??0,r=(d?.patterns??[]).map(m=>m.pattern),w=r.some(m=>m.startsWith("Spring")),D=r.includes("AWS CDK")||r.includes("CDK IaC"),P=r.includes("Maven"),T=r.includes("Serverless")||C>3,$=i?.external?Object.keys(i.external):[],f=$.some(m=>["express","fastify","next","react","vitest","jest"].includes(m))||x>0,_=$.some(m=>["turbo","lerna","nx"].includes(m))||r.includes("Monorepo");if(n.push("### Project Profile",""),n.push(`- **${b} symbols** (${k} exported), **${x} imports**, **${C} entry ${C===1?"point":"points"}**`),r.length>0&&n.push(`- **Detected**: ${r.slice(0,8).join(", ")}`),n.push(""),b===0&&x===0&&C===0)return n.push("> **Note:** This project appears to be empty or contains no analyzable source code.","> Run onboard again after adding source files."),n.join(`
2
2
  `);const v=g.filter(m=>m.status==="success"),M=g.filter(m=>m.status==="failed");n.push("### Completed Analyses","");for(const m of v){const S=N[m.name]??m.name,e=m.output.length>1e3?`${Math.round(m.output.length/1024)}KB`:`${m.output.length}B`;u==="generate"?n.push(`- \u2713 [${S}](./${m.name}.md) (${e})`):n.push(`- \u2713 ${S} (${e})`)}if(M.length>0){n.push("","### Failed Analyses","");for(const m of M)n.push(`- \u2717 ${m.name}: ${m.error}`)}n.push("","### Recommended Reading Order","","1. **Start with** `synthesis-guide.md` (this file) \u2192 `entry-points.md` \u2192 `patterns.md`","2. **Module graph** via `code-map.md` \u2014 cross-package call edges with function names","3. **Architecture** via `diagram.md` (C4 Container) \u2192 `dependencies.md`","4. **Browse structure** via `structure.md` for file layout","5. **API surface** via `symbols.md` \u2014 file paths + exported symbols (capped at 80KB)","6. **Reference**: `config-values.md` (config reference)","","> **Size guidance:** Total output is ~");const j=v.reduce((m,S)=>m+S.output.length,0)/1024;return n[n.length-1]+=`${Math.round(j)}KB. Focus on code-map.md + entry-points.md + diagram.md (~${Math.round((v.find(m=>m.name==="code-map")?.output.length??0)/1024+(v.find(m=>m.name==="entry-points")?.output.length??0)/1024+(v.find(m=>m.name==="diagram")?.output.length??0)/1024)}KB) for maximum signal-to-token ratio.`,n.push("","### Synthesize Knowledge","","Produce the following `kb_remember` entries:",""),n.push("1. **Architecture Summary** (category: `architecture`)"),_?(n.push(" - Package boundaries, dependency graph between packages"),n.push(" - Shared vs service-specific code")):T?(n.push(" - Lambda functions, triggers, event flow"),n.push(" - Infrastructure patterns (queues, tables, APIs)")):w?(n.push(" - Controller \u2192 Service \u2192 Repository layers"),n.push(" - Spring configuration and profiles")):(n.push(" - Layer structure, dependency flow"),n.push(" - Key design decisions")),n.push(""),n.push("2. **Domain Model** (category: `architecture`)"),n.push(" - Key entities/types and their relationships"),n.push(" - Data flow from entry points through processing"),n.push(""),n.push("3. **Conventions** (category: `conventions`)"),n.push(" - Naming patterns, file organization, testing approach"),D&&n.push(" - CDK construct patterns and stack organization"),f&&n.push(" - Build tooling, package manager, module system"),P&&n.push(" - Maven module structure, dependency management"),n.push("","### Using KB Tools","","This project has a KB MCP server with tools for search, analysis, memory, and more.","Add the KB tools to your agent configuration so every session benefits from them.","","**Add to `.github/copilot-instructions.md`** or `AGENTS.md`:","","```markdown","## KB Tools","",`Before starting any task on **${t}**, use these MCP tools:`,"","| Action | Tool | Example |","|--------|------|---------|",'| Search code & decisions | `kb_search` | `kb_search({ query: "..." })` |','| Find symbol definition | `kb_symbol` | `kb_symbol({ name: "ClassName" })` |','| Trace call chains | `kb_trace` | `kb_trace({ symbol: "fn", file: "path" })` |','| Impact of a change | `kb_blast_radius` | `kb_blast_radius({ changed_files: ["..."] })` |','| Persist what you learn | `kb_remember` | `kb_remember({ title: "...", category: "decisions" })` |',"| Typecheck + lint | `kb_check` | `kb_check({})` |","| Run tests | `kb_test_run` | `kb_test_run({})` |","```","","**Add to each `.github/agents/*.agent.md`** (Skills Reference table):","","```markdown","| Context | Skill | Details |","|---------|-------|---------|","| KB search, analysis, memory | `kb` | `path/to/skills/kb/SKILL.md` |","```","","The KB skill teaches agents the full tool set:","","| Category | Tools | Purpose |","|----------|-------|---------|","| Search & Discovery | `kb_search`, `kb_find`, `kb_symbol`, `kb_trace` | Find code, symbols, data flow |","| Code Analysis | `kb_analyze_*`, `kb_blast_radius` | Structure, deps, patterns, impact |","| Knowledge | `kb_remember`, `kb_read`, `kb_update`, `kb_forget` | Persistent cross-session memory |","| Execution | `kb_check`, `kb_test_run`, `kb_eval` | Typecheck, lint, test, run code |","| Refactoring | `kb_rename`, `kb_codemod`, `kb_dead_symbols` | Safe renames, transforms, cleanup |","| Web & API | `kb_web_fetch`, `kb_web_search`, `kb_http` | Research, API testing |","| Context | `kb_workset`, `kb_stash`, `kb_checkpoint` | Manage working sets, save progress |","","**Workflow pattern \u2014 use on every task:**","","```",'kb_search({ query: "your task keywords" }) # Recall prior decisions','kb_scope_map({ task: "what you are doing" }) # Get a reading plan',"# ... do the work ...",'kb_remember({ title: "What I learned", category: "decisions" }) # Persist',"```"),n.join(`
3
3
  `)}const ae=new Set(["test","tests","__tests__","spec","specs","__mocks__","__fixtures__","fixtures","test-utils"]);function R(g){return g.replace(/\\/g,"/").split("/").some(t=>ae.has(t))||/\.(test|spec)\.[jt]sx?$/.test(g)||/Test\.java$/.test(g)}function ce(g,u,t){const p=g.get("dependencies"),n=g.get("symbols"),a=g.get("entry-points"),i=[`## Code Map: ${u}
4
4
  `];if(!p&&!n)return i.push("No dependency or symbol data available."),i.join(`
@@ -1 +1 @@
1
- function M(c){return Math.ceil(c.length/4)}async function T(c,h,u){const{task:d,maxFiles:m=15,contentType:l,origin:g}=u,f=await c.embed(d),S={limit:m*3,contentType:l,origin:g},k=await h.search(f,S),o=new Map;for(const e of k){const t=e.record.sourcePath,r=o.get(t);r?(r.chunks.push(e),r.totalChars+=e.record.content.length,r.maxScore=Math.max(r.maxScore,e.score)):o.set(t,{chunks:[e],totalChars:e.record.content.length,maxScore:e.score})}const s=[...o.entries()].sort(([,e],[,t])=>t.maxScore-e.maxScore).slice(0,m).map(([e,{chunks:t,maxScore:r}])=>{const a=t.sort((n,p)=>n.record.startLine-p.record.startLine).map(n=>({start:n.record.startLine,end:n.record.endLine,heading:n.record.headingPath})),i=t.sort((n,p)=>p.score-n.score)[0],x=i.record.headingPath?`Matches: ${i.record.headingPath}`:`Contains relevant ${i.record.contentType} content`;return{path:e,reason:x,estimatedTokens:0,relevance:r,focusRanges:a}});for(const e of s){const t=o.get(e.path);t&&(e.estimatedTokens=M(t.chunks.map(r=>r.record.content).join("")))}const y=s.reduce((e,t)=>e+t.estimatedTokens,0),b=[...s].sort((e,t)=>{const r=e.path.includes("config")||e.path.includes("types")?-1:0,a=t.path.includes("config")||t.path.includes("types")?-1:0;return r!==a?r-a:t.relevance-e.relevance}).map(e=>e.path);return{task:d,files:s,totalEstimatedTokens:y,readingOrder:b}}export{T as scopeMap};
1
+ function M(c){return Math.ceil(c.length/4)}async function T(c,h,u){const{task:d,maxFiles:m=15,contentType:l,origin:g}=u,f=await c.embed(d),S={limit:m*3,contentType:l,origin:g},x=await h.search(f,S),s=new Map;for(const e of x){const t=e.record.sourcePath,r=s.get(t);r?(r.chunks.push(e),r.totalChars+=e.record.content.length,r.maxScore=Math.max(r.maxScore,e.score)):s.set(t,{chunks:[e],totalChars:e.record.content.length,maxScore:e.score})}const o=[...s.entries()].sort(([,e],[,t])=>t.maxScore-e.maxScore).slice(0,m).map(([e,{chunks:t,maxScore:r}])=>{const a=t.sort((n,p)=>n.record.startLine-p.record.startLine).map(n=>({start:n.record.startLine,end:n.record.endLine,heading:n.record.headingPath})),i=t.sort((n,p)=>p.score-n.score)[0],b=i.record.headingPath?`Matches: ${i.record.headingPath}`:`Contains relevant ${i.record.contentType} content`;return{path:e,reason:b,estimatedTokens:0,relevance:r,focusRanges:a}});for(const e of o){const t=s.get(e.path);t&&(e.estimatedTokens=M(t.chunks.map(r=>r.record.content).join("")))}const y=o.reduce((e,t)=>e+t.estimatedTokens,0),k=[...o].sort((e,t)=>{const r=e.path.includes("config")||e.path.includes("types")?-1:0,a=t.path.includes("config")||t.path.includes("types")?-1:0;return r!==a?r-a:t.relevance-e.relevance}).map(e=>e.path);return{task:d,files:o,totalEstimatedTokens:y,readingOrder:k}}export{T as scopeMap};