kirograph 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -20
- package/dist/assets/logo.png +0 -0
- package/dist/bin/commands/help.js +3 -0
- package/dist/bin/commands/help.js.map +2 -2
- package/dist/bin/commands/memory.js +483 -0
- package/dist/bin/commands/memory.js.map +7 -0
- package/dist/bin/commands/uninit.js +22 -13
- package/dist/bin/commands/uninit.js.map +2 -2
- package/dist/bin/installer/config-prompt.js +37 -23
- package/dist/bin/installer/config-prompt.js.map +2 -2
- package/dist/bin/installer/hooks.js +53 -75
- package/dist/bin/installer/hooks.js.map +2 -2
- package/dist/bin/installer/index.js +9 -4
- package/dist/bin/installer/index.js.map +2 -2
- package/dist/bin/installer/prompts.js +37 -6
- package/dist/bin/installer/prompts.js.map +2 -2
- package/dist/bin/installer/steering.js +19 -0
- package/dist/bin/installer/steering.js.map +2 -2
- package/dist/bin/installer/targets/aider.js +72 -0
- package/dist/bin/installer/targets/aider.js.map +7 -0
- package/dist/bin/installer/targets/amp.js +91 -0
- package/dist/bin/installer/targets/amp.js.map +7 -0
- package/dist/bin/installer/targets/antigravity.js +109 -0
- package/dist/bin/installer/targets/antigravity.js.map +7 -0
- package/dist/bin/installer/targets/augment.js +81 -0
- package/dist/bin/installer/targets/augment.js.map +7 -0
- package/dist/bin/installer/targets/claude.js +1 -1
- package/dist/bin/installer/targets/claude.js.map +2 -2
- package/dist/bin/installer/targets/cline.js +91 -0
- package/dist/bin/installer/targets/cline.js.map +7 -0
- package/dist/bin/installer/targets/codex.js +1 -1
- package/dist/bin/installer/targets/codex.js.map +2 -2
- package/dist/bin/installer/targets/continue.js +107 -0
- package/dist/bin/installer/targets/continue.js.map +7 -0
- package/dist/bin/installer/targets/copilot.js +123 -0
- package/dist/bin/installer/targets/copilot.js.map +7 -0
- package/dist/bin/installer/targets/cursor.js +143 -0
- package/dist/bin/installer/targets/cursor.js.map +7 -0
- package/dist/bin/installer/targets/devin.js +148 -0
- package/dist/bin/installer/targets/devin.js.map +7 -0
- package/dist/bin/installer/targets/gemini-cli.js +126 -0
- package/dist/bin/installer/targets/gemini-cli.js.map +7 -0
- package/dist/bin/installer/targets/generic.js +120 -0
- package/dist/bin/installer/targets/generic.js.map +7 -0
- package/dist/bin/installer/targets/goose.js +72 -0
- package/dist/bin/installer/targets/goose.js.map +7 -0
- package/dist/bin/installer/targets/index.js.map +1 -1
- package/dist/bin/installer/targets/junie.js +105 -0
- package/dist/bin/installer/targets/junie.js.map +7 -0
- package/dist/bin/installer/targets/kilo.js +122 -0
- package/dist/bin/installer/targets/kilo.js.map +7 -0
- package/dist/bin/installer/targets/kiro.js +3 -3
- package/dist/bin/installer/targets/kiro.js.map +2 -2
- package/dist/bin/installer/targets/opencode.js +135 -0
- package/dist/bin/installer/targets/opencode.js.map +7 -0
- package/dist/bin/installer/targets/openhands.js +90 -0
- package/dist/bin/installer/targets/openhands.js.map +7 -0
- package/dist/bin/installer/targets/replit.js +72 -0
- package/dist/bin/installer/targets/replit.js.map +7 -0
- package/dist/bin/installer/targets/roo.js +96 -0
- package/dist/bin/installer/targets/roo.js.map +7 -0
- package/dist/bin/installer/targets/tabnine.js +82 -0
- package/dist/bin/installer/targets/tabnine.js.map +7 -0
- package/dist/bin/installer/targets/trae.js +84 -0
- package/dist/bin/installer/targets/trae.js.map +7 -0
- package/dist/bin/installer/targets/warp.js +97 -0
- package/dist/bin/installer/targets/warp.js.map +7 -0
- package/dist/bin/installer/targets/windsurf.js +141 -0
- package/dist/bin/installer/targets/windsurf.js.map +7 -0
- package/dist/bin/kirograph.js +3 -1
- package/dist/bin/kirograph.js.map +3 -3
- package/dist/compression/naive-cost.js +14 -0
- package/dist/compression/naive-cost.js.map +2 -2
- package/dist/compression/tracker.js +18 -4
- package/dist/compression/tracker.js.map +2 -2
- package/dist/compression/types.js.map +1 -1
- package/dist/config.js +33 -1
- package/dist/config.js.map +2 -2
- package/dist/db/database.js +17 -0
- package/dist/db/database.js.map +2 -2
- package/dist/db/memory-schema.sql +51 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +2 -2
- package/dist/mcp/tool-names.js +5 -1
- package/dist/mcp/tool-names.js.map +2 -2
- package/dist/mcp/tools.js +232 -3
- package/dist/mcp/tools.js.map +2 -2
- package/dist/memory/compress.js +142 -0
- package/dist/memory/compress.js.map +7 -0
- package/dist/memory/database.js +375 -0
- package/dist/memory/database.js.map +7 -0
- package/dist/memory/index.js +239 -0
- package/dist/memory/index.js.map +7 -0
- package/dist/memory/symbols.js +54 -0
- package/dist/memory/symbols.js.map +7 -0
- package/dist/memory/types.js +17 -0
- package/dist/memory/types.js.map +7 -0
- package/dist/memory/vectors.js +199 -0
- package/dist/memory/vectors.js.map +7 -0
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * KiroGraph \u2014 Semantic code knowledge graph for Kiro\n *\n * Pure facade. Every method delegates to a focused sub-system.\n * No business logic lives here.\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { GraphDatabase } from './db/database';\nimport { validatePathWithinRoot, validateProjectPath } from './utils';\nimport { loadConfig, createDefaultConfig, saveConfig } from './config';\nimport type { KiroGraphConfig } from './config';\nimport { GraphQueryManager } from './graph/queries';\nimport { ReferenceResolver } from './resolution/index';\nimport { VectorManager } from './vectors/index';\nimport { ContextBuilder } from './context/index';\nimport { ArchitectureAnalyzer } from './architecture/index';\nimport { LockManager } from './core/lock-manager';\nimport { IndexPipeline } from './core/pipeline';\nimport { buildFileTree } from './core/file-tree';\nimport { SnapshotManager } from './core/snapshot';\nimport { Searcher } from './search/searcher';\nimport type { FileTreeNode, FileTree } from './core/file-tree';\nimport type { GraphSnapshot, GraphDiff } from './core/snapshot';\n\nexport type { GraphSnapshot, GraphDiff };\nimport type {\n Node, Edge, NodeKind, IndexResult, IndexProgress, SyncResult, TaskContext,\n SearchResult, SearchOptions, NodeContext, NodeMetrics,\n} from './types';\nimport type { ArchitectureResult } from './architecture/types';\n\nexport type { FileTreeNode, FileTree };\n\nconst KIROGRAPH_DIR = '.kirograph';\n\nexport default class KiroGraph {\n private readonly db: GraphDatabase;\n private readonly config: KiroGraphConfig;\n private readonly projectRoot: string;\n private readonly queryManager: GraphQueryManager;\n private readonly resolver: ReferenceResolver;\n private readonly vectors: VectorManager;\n private readonly contextBuilder: ContextBuilder;\n private readonly arch: ArchitectureAnalyzer;\n private readonly lock: LockManager;\n private readonly pipeline: IndexPipeline;\n private readonly searcher: Searcher;\n\n private constructor(projectRoot: string, db: GraphDatabase, config: KiroGraphConfig) {\n this.projectRoot = projectRoot;\n this.db = db;\n this.config = config;\n this.queryManager = new GraphQueryManager(db);\n this.resolver = new ReferenceResolver(db, config);\n this.vectors = new VectorManager(db, config, projectRoot);\n this.contextBuilder = new ContextBuilder(db, this.resolver, this.vectors, projectRoot);\n this.arch = new ArchitectureAnalyzer(db, config, projectRoot);\n this.lock = new LockManager(projectRoot);\n this.pipeline = new IndexPipeline(db, this.vectors, this.resolver, this.arch, this.lock, config, projectRoot);\n this.searcher = new Searcher(db);\n }\n\n // \u2500\u2500 Factory \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n static async init(\n projectRoot: string,\n config?: Partial<KiroGraphConfig>,\n onModelProgress?: (file: string, loaded: number, total: number, done: boolean) => void,\n ): Promise<KiroGraph> {\n const resolved = path.resolve(projectRoot);\n validateProjectPath(resolved);\n fs.mkdirSync(path.join(resolved, KIROGRAPH_DIR), { recursive: true });\n const cfg = { ...createDefaultConfig(resolved), ...config };\n await saveConfig(resolved, cfg);\n const db = new GraphDatabase(resolved);\n const kg = new KiroGraph(resolved, db, cfg);\n await kg.vectors.initialize(onModelProgress);\n return kg;\n }\n\n static async open(\n projectRoot: string,\n onModelProgress?: (file: string, loaded: number, total: number, done: boolean) => void,\n ): Promise<KiroGraph> {\n const resolved = path.resolve(projectRoot);\n validateProjectPath(resolved);\n if (!fs.existsSync(path.join(resolved, KIROGRAPH_DIR))) {\n throw new Error(`KiroGraph not initialized at ${resolved}. Run: kirograph init`);\n }\n const cfg = await loadConfig(resolved);\n const db = new GraphDatabase(resolved);\n const kg = new KiroGraph(resolved, db, cfg);\n await kg.vectors.initialize(onModelProgress);\n return kg;\n }\n\n static isInitialized(projectRoot: string): boolean {\n return fs.existsSync(path.join(path.resolve(projectRoot), KIROGRAPH_DIR));\n }\n\n // \u2500\u2500 Lock / dirty marker \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n unlockForce(): void { this.lock.forceRelease(); }\n markDirty(): void { this.lock.markDirty(); }\n clearDirty(): void { this.lock.clearDirty(); }\n isDirty(): boolean { return this.lock.isDirty(); }\n isIndexLocked(): boolean { return this.lock.isLocked(); }\n\n async syncIfDirty(): Promise<SyncResult | null> {\n if (!this.isDirty()) return null;\n return this.sync();\n }\n\n /**\n * Returns the number of files that have changed on disk but are not yet\n * reflected in the index. Used by the MCP status tool to warn the agent\n * when the index may be stale.\n */\n async getPendingSyncCount(): Promise<number> {\n try {\n const { getChangedFiles, scanDirectory } = await Promise.resolve().then(() => require('./sync/index.js'));\n const gitChanged = await getChangedFiles(this.projectRoot, this.config);\n const hasGitChanges =\n gitChanged.added.length > 0 ||\n gitChanged.modified.length > 0 ||\n gitChanged.removed.length > 0;\n\n if (hasGitChanges) {\n return gitChanged.added.length + gitChanged.modified.length + gitChanged.removed.length;\n }\n\n // Fallback: compare indexed set vs current filesystem set\n const indexed = new Set(this.db.getAllFiles().map((f: { path: string }) => f.path));\n const current = new Set(\n (await scanDirectory(this.projectRoot, this.config))\n .map(f => require('path').relative(this.projectRoot, f).replace(/\\\\/g, '/'))\n );\n let pending = 0;\n for (const p of indexed) { if (!current.has(p)) pending++; }\n for (const p of current) { if (!indexed.has(p)) pending++; }\n return pending;\n } catch {\n return 0;\n }\n }\n\n // \u2500\u2500 Indexing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async indexAll(opts?: { onProgress?: (p: IndexProgress) => void; force?: boolean; signal?: AbortSignal }): Promise<IndexResult> {\n return this.pipeline.indexAll(opts);\n }\n\n async sync(changedFilesOrOpts?: string[] | { files?: string[]; onProgress?: (p: IndexProgress) => void }): Promise<SyncResult> {\n if (Array.isArray(changedFilesOrOpts)) {\n return this.pipeline.sync({ changedFiles: changedFilesOrOpts });\n }\n return this.pipeline.sync({\n changedFiles: changedFilesOrOpts?.files,\n onProgress: changedFilesOrOpts?.onProgress,\n });\n }\n\n // \u2500\u2500 Symbol search \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n searchNodes(query: string, kindOrOpts?: NodeKind | SearchOptions, limit = 20): SearchResult[] {\n return this.searcher.search(query, kindOrOpts, limit);\n }\n\n // \u2500\u2500 Graph queries \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async getCallers(nodeId: string, limit = 30): Promise<Node[]> { return this.queryManager.getCallers(nodeId, limit); }\n async getCallees(nodeId: string, limit = 30): Promise<Node[]> { return this.queryManager.getCallees(nodeId, limit); }\n async getImpactRadius(nodeId: string, depth = 2): Promise<Node[]> { return this.queryManager.getImpactRadius(nodeId, depth); }\n getAllNodes(): Node[] { return this.db.getAllNodes(); }\n getAllEdges(): Edge[] { return this.db.getAllEdges(); }\n findDeadCode(limit = 50): Node[] { return this.db.findDeadCode(limit); }\n findCircularDependencies(): string[][] { return this.db.findCircularDependencies(); }\n async findPath(fromId: string, toId: string, maxDepth = 10): Promise<Node[]> { return this.queryManager.findPath(fromId, toId, maxDepth); }\n getTypeHierarchy(nodeId: string, direction: 'up' | 'down' | 'both' = 'both'): Node[] { return this.db.getTypeHierarchy(nodeId, direction); }\n getNode(id: string): Node | null { return this.db.getNode(id); }\n getNodeContext(nodeId: string): NodeContext | null { return this.db.getNodeContext(nodeId); }\n getNodeMetrics(nodeId: string): NodeMetrics { return this.db.getNodeMetrics(nodeId); }\n\n getNodeSource(node: Node): string | null {\n const absPath = validatePathWithinRoot(path.join(this.projectRoot, node.filePath), this.projectRoot);\n if (!absPath) return null;\n try {\n return fs.readFileSync(absPath, 'utf8').split('\\n').slice(node.startLine - 1, node.endLine).join('\\n');\n } catch { return null; }\n }\n\n // \u2500\u2500 Context building \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async buildContext(task: string, opts?: { maxNodes?: number; includeCode?: boolean }): Promise<TaskContext> {\n return this.contextBuilder.buildTaskContext(task, opts);\n }\n\n // \u2500\u2500 File browsing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n getFiles(opts?: { filterPath?: string; pattern?: string; maxDepth?: number }): FileTree {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const picomatch = opts?.pattern ? require('picomatch')(opts.pattern) : null;\n const filtered = this.db.getAllFiles().filter(f => {\n if (opts?.filterPath && !f.path.startsWith(opts.filterPath)) return false;\n if (picomatch && !picomatch(f.path)) return false;\n return true;\n });\n return buildFileTree(filtered, opts?.maxDepth);\n }\n\n getAffectedTests(changedFiles: string[], opts?: { depth?: number; testPattern?: string }): string[] {\n return this.queryManager.getAffectedTests(changedFiles, opts);\n }\n\n // \u2500\u2500 Graph insights \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n findHotspots(limit = 20): Array<Node & { degree: number; inDegree: number; outDegree: number }> {\n return this.db.findHotspots(limit);\n }\n\n findSurprisingConnections(limit = 20): Array<{ source: Node; target: Node; kind: string; score: number }> {\n return this.db.findSurprisingConnections(limit);\n }\n\n // \u2500\u2500 Snapshots \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n createSnapshotManager(): SnapshotManager {\n return new SnapshotManager(this.db, this.projectRoot);\n }\n\n // \u2500\u2500 Stats \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async getStats() {\n const stats = this.db.getStats();\n const vecIndexCount = await this.vectors.vecIndexCount();\n const embeddingCount = vecIndexCount > 0 ? vecIndexCount : stats.embeddingCount;\n const EMBEDDABLE = ['function', 'method', 'class', 'interface', 'type_alias', 'component', 'module'];\n const embeddableNodeCount = EMBEDDABLE.reduce((sum, k) => sum + (stats.nodesByKind[k] ?? 0), 0);\n const pendingFiles = await this.getPendingSyncCount();\n const syncRunning = this.isIndexLocked();\n return {\n ...stats,\n embeddingCount,\n embeddableNodeCount,\n embeddingsEnabled: this.config.enableEmbeddings ?? false,\n embeddingModel: this.config.embeddingModel,\n useVecIndex: this.config.useVecIndex ?? false,\n semanticEngine: this.config.semanticEngine ?? 'cosine',\n vecIndexCount,\n engineFallback: this.vectors.getEngineFallback(),\n frameworks: this.config.frameworkHints ?? [],\n architectureEnabled: this.config.enableArchitecture ?? false,\n ...(this.config.enableArchitecture ? { architectureStats: this.db.getArchStats() } : {}),\n pendingFiles,\n syncRunning,\n syncWarningThreshold: this.config.syncWarningThreshold ?? 10,\n };\n }\n\n getEngineFallback(): string | null { return this.vectors.getEngineFallback(); }\n\n // \u2500\u2500 Architecture API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n getArchitecture(): ArchitectureResult & {\n filePackages: Record<string, string[]>;\n fileLayers: Record<string, Array<{ layerId: string; confidence: number; matchedPattern: string }>>;\n } {\n const base = this.db.getArchitectureResult();\n\n const filePackages: Record<string, string[]> = {};\n for (const { filePath, packageId } of this.db.getArchFilePackages()) {\n if (!filePackages[filePath]) filePackages[filePath] = [];\n filePackages[filePath].push(packageId);\n }\n\n const fileLayers: Record<string, Array<{ layerId: string; confidence: number; matchedPattern: string }>> = {};\n for (const row of this.db.getArchFileLayers()) {\n if (!fileLayers[row.filePath]) fileLayers[row.filePath] = [];\n fileLayers[row.filePath].push({ layerId: row.layerId, confidence: row.confidence, matchedPattern: row.matchedPattern });\n }\n\n return { ...base, filePackages, fileLayers };\n }\n\n isArchitectureEnabled(): boolean { return this.config.enableArchitecture ?? false; }\n\n // \u2500\u2500 Misc \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n getProjectRoot(): string { return this.projectRoot; }\n\n close(): void {\n this.vectors.close();\n this.lock.release();\n this.db.close();\n }\n}\n\n// \u2500\u2500 Module-level helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Walk up directories to find the nearest .kirograph/ folder. */\nexport function findNearestKiroGraphRoot(startPath: string): string | null {\n let current = path.resolve(startPath);\n while (true) {\n if (fs.existsSync(path.join(current, KIROGRAPH_DIR))) return current;\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * KiroGraph \u2014 Semantic code knowledge graph for Kiro\n *\n * Pure facade. Every method delegates to a focused sub-system.\n * No business logic lives here.\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { GraphDatabase } from './db/database';\nimport { validatePathWithinRoot, validateProjectPath } from './utils';\nimport { loadConfig, createDefaultConfig, saveConfig } from './config';\nimport type { KiroGraphConfig } from './config';\nimport { GraphQueryManager } from './graph/queries';\nimport { ReferenceResolver } from './resolution/index';\nimport { VectorManager } from './vectors/index';\nimport { ContextBuilder } from './context/index';\nimport { ArchitectureAnalyzer } from './architecture/index';\nimport { LockManager } from './core/lock-manager';\nimport { IndexPipeline } from './core/pipeline';\nimport { buildFileTree } from './core/file-tree';\nimport { SnapshotManager } from './core/snapshot';\nimport { Searcher } from './search/searcher';\nimport type { FileTreeNode, FileTree } from './core/file-tree';\nimport type { GraphSnapshot, GraphDiff } from './core/snapshot';\n\nexport type { GraphSnapshot, GraphDiff };\nimport type {\n Node, Edge, NodeKind, IndexResult, IndexProgress, SyncResult, TaskContext,\n SearchResult, SearchOptions, NodeContext, NodeMetrics,\n} from './types';\nimport type { ArchitectureResult } from './architecture/types';\n\nexport type { FileTreeNode, FileTree };\n\nconst KIROGRAPH_DIR = '.kirograph';\n\nexport default class KiroGraph {\n private readonly db: GraphDatabase;\n private readonly config: KiroGraphConfig;\n private readonly projectRoot: string;\n private readonly queryManager: GraphQueryManager;\n private readonly resolver: ReferenceResolver;\n private readonly vectors: VectorManager;\n private readonly contextBuilder: ContextBuilder;\n private readonly arch: ArchitectureAnalyzer;\n private readonly lock: LockManager;\n private readonly pipeline: IndexPipeline;\n private readonly searcher: Searcher;\n\n private constructor(projectRoot: string, db: GraphDatabase, config: KiroGraphConfig) {\n this.projectRoot = projectRoot;\n this.db = db;\n this.config = config;\n this.queryManager = new GraphQueryManager(db);\n this.resolver = new ReferenceResolver(db, config);\n this.vectors = new VectorManager(db, config, projectRoot);\n this.contextBuilder = new ContextBuilder(db, this.resolver, this.vectors, projectRoot);\n this.arch = new ArchitectureAnalyzer(db, config, projectRoot);\n this.lock = new LockManager(projectRoot);\n this.pipeline = new IndexPipeline(db, this.vectors, this.resolver, this.arch, this.lock, config, projectRoot);\n this.searcher = new Searcher(db);\n }\n\n // \u2500\u2500 Factory \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n static async init(\n projectRoot: string,\n config?: Partial<KiroGraphConfig>,\n onModelProgress?: (file: string, loaded: number, total: number, done: boolean) => void,\n ): Promise<KiroGraph> {\n const resolved = path.resolve(projectRoot);\n validateProjectPath(resolved);\n fs.mkdirSync(path.join(resolved, KIROGRAPH_DIR), { recursive: true });\n const cfg = { ...createDefaultConfig(resolved), ...config };\n await saveConfig(resolved, cfg);\n const db = new GraphDatabase(resolved);\n const kg = new KiroGraph(resolved, db, cfg);\n await kg.vectors.initialize(onModelProgress);\n return kg;\n }\n\n static async open(\n projectRoot: string,\n onModelProgress?: (file: string, loaded: number, total: number, done: boolean) => void,\n ): Promise<KiroGraph> {\n const resolved = path.resolve(projectRoot);\n validateProjectPath(resolved);\n if (!fs.existsSync(path.join(resolved, KIROGRAPH_DIR))) {\n throw new Error(`KiroGraph not initialized at ${resolved}. Run: kirograph init`);\n }\n const cfg = await loadConfig(resolved);\n const db = new GraphDatabase(resolved);\n const kg = new KiroGraph(resolved, db, cfg);\n await kg.vectors.initialize(onModelProgress);\n return kg;\n }\n\n static isInitialized(projectRoot: string): boolean {\n return fs.existsSync(path.join(path.resolve(projectRoot), KIROGRAPH_DIR));\n }\n\n // \u2500\u2500 Lock / dirty marker \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n unlockForce(): void { this.lock.forceRelease(); }\n markDirty(): void { this.lock.markDirty(); }\n clearDirty(): void { this.lock.clearDirty(); }\n isDirty(): boolean { return this.lock.isDirty(); }\n isIndexLocked(): boolean { return this.lock.isLocked(); }\n\n async syncIfDirty(): Promise<SyncResult | null> {\n if (!this.isDirty()) return null;\n return this.sync();\n }\n\n /**\n * Returns the number of files that have changed on disk but are not yet\n * reflected in the index. Used by the MCP status tool to warn the agent\n * when the index may be stale.\n */\n async getPendingSyncCount(): Promise<number> {\n try {\n const { getChangedFiles, scanDirectory } = await Promise.resolve().then(() => require('./sync/index.js'));\n const gitChanged = await getChangedFiles(this.projectRoot, this.config);\n const hasGitChanges =\n gitChanged.added.length > 0 ||\n gitChanged.modified.length > 0 ||\n gitChanged.removed.length > 0;\n\n if (hasGitChanges) {\n return gitChanged.added.length + gitChanged.modified.length + gitChanged.removed.length;\n }\n\n // Fallback: compare indexed set vs current filesystem set\n const indexed = new Set(this.db.getAllFiles().map((f: { path: string }) => f.path));\n const current = new Set(\n (await scanDirectory(this.projectRoot, this.config))\n .map(f => require('path').relative(this.projectRoot, f).replace(/\\\\/g, '/'))\n );\n let pending = 0;\n for (const p of indexed) { if (!current.has(p)) pending++; }\n for (const p of current) { if (!indexed.has(p)) pending++; }\n return pending;\n } catch {\n return 0;\n }\n }\n\n // \u2500\u2500 Indexing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async indexAll(opts?: { onProgress?: (p: IndexProgress) => void; force?: boolean; signal?: AbortSignal }): Promise<IndexResult> {\n return this.pipeline.indexAll(opts);\n }\n\n async sync(changedFilesOrOpts?: string[] | { files?: string[]; onProgress?: (p: IndexProgress) => void }): Promise<SyncResult> {\n if (Array.isArray(changedFilesOrOpts)) {\n return this.pipeline.sync({ changedFiles: changedFilesOrOpts });\n }\n return this.pipeline.sync({\n changedFiles: changedFilesOrOpts?.files,\n onProgress: changedFilesOrOpts?.onProgress,\n });\n }\n\n // \u2500\u2500 Symbol search \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n searchNodes(query: string, kindOrOpts?: NodeKind | SearchOptions, limit = 20): SearchResult[] {\n return this.searcher.search(query, kindOrOpts, limit);\n }\n\n // \u2500\u2500 Graph queries \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async getCallers(nodeId: string, limit = 30): Promise<Node[]> { return this.queryManager.getCallers(nodeId, limit); }\n async getCallees(nodeId: string, limit = 30): Promise<Node[]> { return this.queryManager.getCallees(nodeId, limit); }\n async getImpactRadius(nodeId: string, depth = 2): Promise<Node[]> { return this.queryManager.getImpactRadius(nodeId, depth); }\n getAllNodes(): Node[] { return this.db.getAllNodes(); }\n getAllEdges(): Edge[] { return this.db.getAllEdges(); }\n findDeadCode(limit = 50): Node[] { return this.db.findDeadCode(limit); }\n findCircularDependencies(): string[][] { return this.db.findCircularDependencies(); }\n async findPath(fromId: string, toId: string, maxDepth = 10): Promise<Node[]> { return this.queryManager.findPath(fromId, toId, maxDepth); }\n getTypeHierarchy(nodeId: string, direction: 'up' | 'down' | 'both' = 'both'): Node[] { return this.db.getTypeHierarchy(nodeId, direction); }\n getNode(id: string): Node | null { return this.db.getNode(id); }\n getNodeContext(nodeId: string): NodeContext | null { return this.db.getNodeContext(nodeId); }\n getNodeMetrics(nodeId: string): NodeMetrics { return this.db.getNodeMetrics(nodeId); }\n\n getNodeSource(node: Node): string | null {\n const absPath = validatePathWithinRoot(path.join(this.projectRoot, node.filePath), this.projectRoot);\n if (!absPath) return null;\n try {\n return fs.readFileSync(absPath, 'utf8').split('\\n').slice(node.startLine - 1, node.endLine).join('\\n');\n } catch { return null; }\n }\n\n // \u2500\u2500 Context building \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async buildContext(task: string, opts?: { maxNodes?: number; includeCode?: boolean }): Promise<TaskContext> {\n return this.contextBuilder.buildTaskContext(task, opts);\n }\n\n // \u2500\u2500 File browsing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n getFiles(opts?: { filterPath?: string; pattern?: string; maxDepth?: number }): FileTree {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const picomatch = opts?.pattern ? require('picomatch')(opts.pattern) : null;\n const filtered = this.db.getAllFiles().filter(f => {\n if (opts?.filterPath && !f.path.startsWith(opts.filterPath)) return false;\n if (picomatch && !picomatch(f.path)) return false;\n return true;\n });\n return buildFileTree(filtered, opts?.maxDepth);\n }\n\n getAffectedTests(changedFiles: string[], opts?: { depth?: number; testPattern?: string }): string[] {\n return this.queryManager.getAffectedTests(changedFiles, opts);\n }\n\n // \u2500\u2500 Graph insights \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n findHotspots(limit = 20): Array<Node & { degree: number; inDegree: number; outDegree: number }> {\n return this.db.findHotspots(limit);\n }\n\n findSurprisingConnections(limit = 20): Array<{ source: Node; target: Node; kind: string; score: number }> {\n return this.db.findSurprisingConnections(limit);\n }\n\n // \u2500\u2500 Snapshots \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n createSnapshotManager(): SnapshotManager {\n return new SnapshotManager(this.db, this.projectRoot);\n }\n\n // \u2500\u2500 Stats \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async getStats() {\n const stats = this.db.getStats();\n const vecIndexCount = await this.vectors.vecIndexCount();\n const embeddingCount = vecIndexCount > 0 ? vecIndexCount : stats.embeddingCount;\n const EMBEDDABLE = ['function', 'method', 'class', 'interface', 'type_alias', 'component', 'module'];\n const embeddableNodeCount = EMBEDDABLE.reduce((sum, k) => sum + (stats.nodesByKind[k] ?? 0), 0);\n const pendingFiles = await this.getPendingSyncCount();\n const syncRunning = this.isIndexLocked();\n return {\n ...stats,\n embeddingCount,\n embeddableNodeCount,\n embeddingsEnabled: this.config.enableEmbeddings ?? false,\n embeddingModel: this.config.embeddingModel,\n useVecIndex: this.config.useVecIndex ?? false,\n semanticEngine: this.config.semanticEngine ?? 'cosine',\n vecIndexCount,\n engineFallback: this.vectors.getEngineFallback(),\n frameworks: this.config.frameworkHints ?? [],\n architectureEnabled: this.config.enableArchitecture ?? false,\n ...(this.config.enableArchitecture ? { architectureStats: this.db.getArchStats() } : {}),\n pendingFiles,\n syncRunning,\n syncWarningThreshold: this.config.syncWarningThreshold ?? 10,\n };\n }\n\n getEngineFallback(): string | null { return this.vectors.getEngineFallback(); }\n\n // \u2500\u2500 Architecture API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n getArchitecture(): ArchitectureResult & {\n filePackages: Record<string, string[]>;\n fileLayers: Record<string, Array<{ layerId: string; confidence: number; matchedPattern: string }>>;\n } {\n const base = this.db.getArchitectureResult();\n\n const filePackages: Record<string, string[]> = {};\n for (const { filePath, packageId } of this.db.getArchFilePackages()) {\n if (!filePackages[filePath]) filePackages[filePath] = [];\n filePackages[filePath].push(packageId);\n }\n\n const fileLayers: Record<string, Array<{ layerId: string; confidence: number; matchedPattern: string }>> = {};\n for (const row of this.db.getArchFileLayers()) {\n if (!fileLayers[row.filePath]) fileLayers[row.filePath] = [];\n fileLayers[row.filePath].push({ layerId: row.layerId, confidence: row.confidence, matchedPattern: row.matchedPattern });\n }\n\n return { ...base, filePackages, fileLayers };\n }\n\n isArchitectureEnabled(): boolean { return this.config.enableArchitecture ?? false; }\n\n // \u2500\u2500 Misc \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n getProjectRoot(): string { return this.projectRoot; }\n\n getDatabase(): GraphDatabase { return this.db; }\n\n close(): void {\n this.vectors.close();\n this.lock.release();\n this.db.close();\n }\n}\n\n// \u2500\u2500 Module-level helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Walk up directories to find the nearest .kirograph/ folder. */\nexport function findNearestKiroGraphRoot(startPath: string): string | null {\n let current = path.resolve(startPath);\n while (true) {\n if (fs.existsSync(path.join(current, KIROGRAPH_DIR))) return current;\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/mcp/tool-names.js
CHANGED
|
@@ -41,7 +41,11 @@ const KIROGRAPH_TOOL_NAMES = [
|
|
|
41
41
|
"kirograph_diff",
|
|
42
42
|
"kirograph_type_hierarchy",
|
|
43
43
|
"kirograph_exec",
|
|
44
|
-
"kirograph_gain"
|
|
44
|
+
"kirograph_gain",
|
|
45
|
+
"kirograph_mem_search",
|
|
46
|
+
"kirograph_mem_store",
|
|
47
|
+
"kirograph_mem_timeline",
|
|
48
|
+
"kirograph_mem_status"
|
|
45
49
|
];
|
|
46
50
|
// Annotate the CommonJS export names for ESM import in node:
|
|
47
51
|
0 && (module.exports = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/mcp/tool-names.ts"],
|
|
4
|
-
"sourcesContent": ["export const KIROGRAPH_TOOL_NAMES = [\n 'kirograph_search',\n 'kirograph_context',\n 'kirograph_callers',\n 'kirograph_callees',\n 'kirograph_impact',\n 'kirograph_node',\n 'kirograph_status',\n 'kirograph_files',\n 'kirograph_dead_code',\n 'kirograph_circular_deps',\n 'kirograph_path',\n 'kirograph_architecture',\n 'kirograph_coupling',\n 'kirograph_package',\n 'kirograph_hotspots',\n 'kirograph_surprising',\n 'kirograph_diff',\n 'kirograph_type_hierarchy',\n 'kirograph_exec',\n 'kirograph_gain',\n];\n\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,MAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;",
|
|
4
|
+
"sourcesContent": ["export const KIROGRAPH_TOOL_NAMES = [\n 'kirograph_search',\n 'kirograph_context',\n 'kirograph_callers',\n 'kirograph_callees',\n 'kirograph_impact',\n 'kirograph_node',\n 'kirograph_status',\n 'kirograph_files',\n 'kirograph_dead_code',\n 'kirograph_circular_deps',\n 'kirograph_path',\n 'kirograph_architecture',\n 'kirograph_coupling',\n 'kirograph_package',\n 'kirograph_hotspots',\n 'kirograph_surprising',\n 'kirograph_diff',\n 'kirograph_type_hierarchy',\n 'kirograph_exec',\n 'kirograph_gain',\n 'kirograph_mem_search',\n 'kirograph_mem_store',\n 'kirograph_mem_timeline',\n 'kirograph_mem_status',\n];\n\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,MAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/mcp/tools.js
CHANGED
|
@@ -61,6 +61,19 @@ function writeSessionMarker(projectRoot) {
|
|
|
61
61
|
} catch {
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
+
function formatAge(timestamp) {
|
|
65
|
+
const diff = Date.now() - timestamp;
|
|
66
|
+
const minutes = Math.floor(diff / 6e4);
|
|
67
|
+
if (minutes < 60) return `${minutes}m ago`;
|
|
68
|
+
const hours = Math.floor(minutes / 60);
|
|
69
|
+
if (hours < 24) return `${hours}h ago`;
|
|
70
|
+
const days = Math.floor(hours / 24);
|
|
71
|
+
if (days < 7) return `${days}d ago`;
|
|
72
|
+
const weeks = Math.floor(days / 7);
|
|
73
|
+
if (weeks < 5) return `${weeks}w ago`;
|
|
74
|
+
const months = Math.floor(days / 30);
|
|
75
|
+
return `${months}mo ago`;
|
|
76
|
+
}
|
|
64
77
|
const tools = [
|
|
65
78
|
{
|
|
66
79
|
name: "kirograph_search",
|
|
@@ -343,6 +356,66 @@ const tools = [
|
|
|
343
356
|
projectPath: { type: "string", description: "Project root path (optional)" }
|
|
344
357
|
}
|
|
345
358
|
}
|
|
359
|
+
},
|
|
360
|
+
// ── Memory tools (require enableMemory=true) ────────────────────────────────
|
|
361
|
+
{
|
|
362
|
+
name: "kirograph_mem_search",
|
|
363
|
+
description: "Search project memory for past decisions, errors, patterns, and context. Returns observations ranked by relevance.",
|
|
364
|
+
inputSchema: {
|
|
365
|
+
type: "object",
|
|
366
|
+
properties: {
|
|
367
|
+
query: { type: "string", description: "Natural language search query" },
|
|
368
|
+
kind: {
|
|
369
|
+
type: "string",
|
|
370
|
+
description: "Filter by observation kind",
|
|
371
|
+
enum: ["decision", "error", "pattern", "architecture", "summary", "note"]
|
|
372
|
+
},
|
|
373
|
+
limit: { type: "number", description: "Max results (default: 10)", default: 10 },
|
|
374
|
+
sessionId: { type: "string", description: "Filter to specific session" },
|
|
375
|
+
projectPath: { type: "string", description: "Project root path (optional)" }
|
|
376
|
+
},
|
|
377
|
+
required: ["query"]
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
name: "kirograph_mem_store",
|
|
382
|
+
description: "Store an observation in project memory. Content is automatically compressed (if caveman mode is on) and linked to relevant code symbols.",
|
|
383
|
+
inputSchema: {
|
|
384
|
+
type: "object",
|
|
385
|
+
properties: {
|
|
386
|
+
content: { type: "string", description: "Observation text" },
|
|
387
|
+
kind: {
|
|
388
|
+
type: "string",
|
|
389
|
+
description: "Observation kind",
|
|
390
|
+
enum: ["decision", "error", "pattern", "architecture", "summary", "note"],
|
|
391
|
+
default: "note"
|
|
392
|
+
},
|
|
393
|
+
projectPath: { type: "string", description: "Project root path (optional)" }
|
|
394
|
+
},
|
|
395
|
+
required: ["content"]
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
name: "kirograph_mem_timeline",
|
|
400
|
+
description: "List recent sessions and their observations chronologically.",
|
|
401
|
+
inputSchema: {
|
|
402
|
+
type: "object",
|
|
403
|
+
properties: {
|
|
404
|
+
limit: { type: "number", description: "Number of sessions to show (default: 5)", default: 5 },
|
|
405
|
+
sessionId: { type: "string", description: "Show observations for a specific session" },
|
|
406
|
+
projectPath: { type: "string", description: "Project root path (optional)" }
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
name: "kirograph_mem_status",
|
|
412
|
+
description: "Memory subsystem health: session count, observations, embedding coverage, storage size.",
|
|
413
|
+
inputSchema: {
|
|
414
|
+
type: "object",
|
|
415
|
+
properties: {
|
|
416
|
+
projectPath: { type: "string", description: "Project root path (optional)" }
|
|
417
|
+
}
|
|
418
|
+
}
|
|
346
419
|
}
|
|
347
420
|
];
|
|
348
421
|
class ToolHandler {
|
|
@@ -388,7 +461,11 @@ class ToolHandler {
|
|
|
388
461
|
const naiveCost = estimateNaiveCost(toolName, outputTokens, args);
|
|
389
462
|
if (naiveCost !== null && naiveCost > outputTokens) {
|
|
390
463
|
const tracker = new import_tracker.TokenTracker(projectRoot);
|
|
391
|
-
|
|
464
|
+
if (toolName.startsWith("kirograph_mem_")) {
|
|
465
|
+
tracker.recordMemorySaving(toolName, outputTokens, naiveCost);
|
|
466
|
+
} else {
|
|
467
|
+
tracker.recordGraphSaving(toolName, outputTokens, naiveCost);
|
|
468
|
+
}
|
|
392
469
|
}
|
|
393
470
|
} catch {
|
|
394
471
|
}
|
|
@@ -455,7 +532,7 @@ class ToolHandler {
|
|
|
455
532
|
` Tokens with KiroGraph: ~${stats.totalCompressed.toLocaleString()}`,
|
|
456
533
|
` Saved: ${stats.totalSaved.toLocaleString()} tokens (${stats.savingsPercent}%)`
|
|
457
534
|
];
|
|
458
|
-
if (stats.bySource.exec.count > 0 || stats.bySource.graph.count > 0) {
|
|
535
|
+
if (stats.bySource.exec.count > 0 || stats.bySource.graph.count > 0 || stats.bySource.memory.count > 0) {
|
|
459
536
|
lines.push("", "By source:");
|
|
460
537
|
if (stats.bySource.graph.count > 0) {
|
|
461
538
|
lines.push(` Graph tools: ${stats.bySource.graph.count} calls, ~${stats.bySource.graph.saved.toLocaleString()} tokens saved (vs file reads/grep)`);
|
|
@@ -463,6 +540,9 @@ class ToolHandler {
|
|
|
463
540
|
if (stats.bySource.exec.count > 0) {
|
|
464
541
|
lines.push(` Compression: ${stats.bySource.exec.count} calls, ~${stats.bySource.exec.saved.toLocaleString()} tokens saved (vs raw output)`);
|
|
465
542
|
}
|
|
543
|
+
if (stats.bySource.memory.count > 0) {
|
|
544
|
+
lines.push(` Memory: ${stats.bySource.memory.count} calls, ~${stats.bySource.memory.saved.toLocaleString()} tokens saved (vs re-discovering context)`);
|
|
545
|
+
}
|
|
466
546
|
}
|
|
467
547
|
if (Object.keys(stats.byFamily).length > 0) {
|
|
468
548
|
lines.push("", "Top families:");
|
|
@@ -520,6 +600,36 @@ class ToolHandler {
|
|
|
520
600
|
}
|
|
521
601
|
}
|
|
522
602
|
}
|
|
603
|
+
try {
|
|
604
|
+
const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
|
|
605
|
+
const projectRoot = cg.getProjectRoot();
|
|
606
|
+
const config = await loadConfig(projectRoot);
|
|
607
|
+
if (config.enableMemory) {
|
|
608
|
+
const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
|
|
609
|
+
const db = cg.getDatabase();
|
|
610
|
+
db.applyMemorySchema();
|
|
611
|
+
const mem = new MemoryManager(config, db.getRawDb());
|
|
612
|
+
mem.initialize();
|
|
613
|
+
const qualifiedNames = [
|
|
614
|
+
...ctx.entryPoints.map((n) => n.qualifiedName),
|
|
615
|
+
...ctx.relatedNodes.slice(0, 5).map((n) => n.qualifiedName)
|
|
616
|
+
].filter(Boolean);
|
|
617
|
+
const contextLimit = config.memoryContextLimit ?? 3;
|
|
618
|
+
const contextThreshold = config.memoryContextThreshold ?? 0.3;
|
|
619
|
+
let memResults = mem.getLinkedObservations(qualifiedNames, contextLimit, contextThreshold);
|
|
620
|
+
if (memResults.length === 0) {
|
|
621
|
+
memResults = (await mem.search(args.task, { limit: contextLimit })).filter((r) => r.score >= contextThreshold);
|
|
622
|
+
}
|
|
623
|
+
if (memResults.length > 0) {
|
|
624
|
+
lines.push("", "## Related Memory");
|
|
625
|
+
for (const r of memResults.slice(0, contextLimit)) {
|
|
626
|
+
const age = formatAge(r.observation.createdAt);
|
|
627
|
+
lines.push(`- [${r.observation.kind}] ${r.observation.content} (${age})`);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
} catch {
|
|
632
|
+
}
|
|
523
633
|
return lines.join("\n");
|
|
524
634
|
}
|
|
525
635
|
case "kirograph_callers": {
|
|
@@ -552,8 +662,37 @@ class ToolHandler {
|
|
|
552
662
|
const node = results[0].node;
|
|
553
663
|
const affected = await cg.getImpactRadius(node.id, args.depth ?? 2);
|
|
554
664
|
if (affected.length === 0) return `No dependents found for \`${node.name}\`.`;
|
|
555
|
-
|
|
665
|
+
let output = `Changing \`${node.name}\` may affect ${affected.length} symbol(s):
|
|
556
666
|
` + affected.map((n) => `- ${mapKind(n.kind)} \`${n.name}\` \u2014 ${n.filePath}:${n.startLine}`).join("\n");
|
|
667
|
+
try {
|
|
668
|
+
const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
|
|
669
|
+
const projectRoot = cg.getProjectRoot();
|
|
670
|
+
const config = await loadConfig(projectRoot);
|
|
671
|
+
if (config.enableMemory) {
|
|
672
|
+
const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
|
|
673
|
+
const db = cg.getDatabase();
|
|
674
|
+
db.applyMemorySchema();
|
|
675
|
+
const mem = new MemoryManager(config, db.getRawDb());
|
|
676
|
+
mem.initialize();
|
|
677
|
+
const contextLimit = config.memoryContextLimit ?? 3;
|
|
678
|
+
const contextThreshold = config.memoryContextThreshold ?? 0.3;
|
|
679
|
+
const memResults = mem.getLinkedObservations(
|
|
680
|
+
[node.qualifiedName],
|
|
681
|
+
contextLimit,
|
|
682
|
+
contextThreshold
|
|
683
|
+
);
|
|
684
|
+
if (memResults.length > 0) {
|
|
685
|
+
output += "\n\nRelated Memory:";
|
|
686
|
+
for (const r of memResults) {
|
|
687
|
+
const age = formatAge(r.observation.createdAt);
|
|
688
|
+
output += `
|
|
689
|
+
- [${r.observation.kind}] ${r.observation.content} (${age})`;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
} catch {
|
|
694
|
+
}
|
|
695
|
+
return output;
|
|
557
696
|
}
|
|
558
697
|
case "kirograph_node": {
|
|
559
698
|
const results = cg.searchNodes(args.symbol, void 0, 5);
|
|
@@ -934,6 +1073,96 @@ class ToolHandler {
|
|
|
934
1073
|
}
|
|
935
1074
|
return lines.join("\n");
|
|
936
1075
|
}
|
|
1076
|
+
// ── Memory tools ────────────────────────────────────────────────────────
|
|
1077
|
+
case "kirograph_mem_search": {
|
|
1078
|
+
const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
|
|
1079
|
+
const projectRoot = cg.getProjectRoot();
|
|
1080
|
+
const config = await loadConfig(projectRoot);
|
|
1081
|
+
if (!config.enableMemory) return "Memory is not enabled. Set enableMemory: true in .kirograph/config.json";
|
|
1082
|
+
const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
|
|
1083
|
+
const db = cg.getDatabase();
|
|
1084
|
+
db.applyMemorySchema();
|
|
1085
|
+
const mem = new MemoryManager(config, db.getRawDb());
|
|
1086
|
+
mem.initialize();
|
|
1087
|
+
const results = await mem.search(args.query, {
|
|
1088
|
+
limit: args.limit ?? 10,
|
|
1089
|
+
kind: args.kind,
|
|
1090
|
+
sessionId: args.sessionId
|
|
1091
|
+
});
|
|
1092
|
+
if (results.length === 0) return `No memory observations found for "${args.query}".`;
|
|
1093
|
+
return results.map((r, i) => {
|
|
1094
|
+
const age = formatAge(r.observation.createdAt);
|
|
1095
|
+
return `${i + 1}. [${r.observation.kind}] ${r.observation.content} (${age})`;
|
|
1096
|
+
}).join("\n");
|
|
1097
|
+
}
|
|
1098
|
+
case "kirograph_mem_store": {
|
|
1099
|
+
const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
|
|
1100
|
+
const projectRoot = cg.getProjectRoot();
|
|
1101
|
+
const config = await loadConfig(projectRoot);
|
|
1102
|
+
if (!config.enableMemory) return "Memory is not enabled. Set enableMemory: true in .kirograph/config.json";
|
|
1103
|
+
const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
|
|
1104
|
+
const db = cg.getDatabase();
|
|
1105
|
+
db.applyMemorySchema();
|
|
1106
|
+
const mem = new MemoryManager(config, db.getRawDb());
|
|
1107
|
+
mem.initialize();
|
|
1108
|
+
const id = await mem.store({
|
|
1109
|
+
content: args.content,
|
|
1110
|
+
kind: args.kind ?? "note",
|
|
1111
|
+
source: "agent"
|
|
1112
|
+
});
|
|
1113
|
+
if (!id) return "Observation already exists (duplicate content).";
|
|
1114
|
+
return `Stored observation ${id} [${args.kind ?? "note"}]`;
|
|
1115
|
+
}
|
|
1116
|
+
case "kirograph_mem_timeline": {
|
|
1117
|
+
const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
|
|
1118
|
+
const projectRoot = cg.getProjectRoot();
|
|
1119
|
+
const config = await loadConfig(projectRoot);
|
|
1120
|
+
if (!config.enableMemory) return "Memory is not enabled. Set enableMemory: true in .kirograph/config.json";
|
|
1121
|
+
const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
|
|
1122
|
+
const db = cg.getDatabase();
|
|
1123
|
+
db.applyMemorySchema();
|
|
1124
|
+
const mem = new MemoryManager(config, db.getRawDb());
|
|
1125
|
+
mem.initialize();
|
|
1126
|
+
const { sessions, observations } = mem.timeline({
|
|
1127
|
+
limit: args.limit ?? 5,
|
|
1128
|
+
sessionId: args.sessionId
|
|
1129
|
+
});
|
|
1130
|
+
if (sessions.length === 0) return "No memory sessions found.";
|
|
1131
|
+
const lines = [];
|
|
1132
|
+
for (const session of sessions) {
|
|
1133
|
+
const start = new Date(session.startedAt).toISOString().slice(0, 16).replace("T", " ");
|
|
1134
|
+
const status = session.endedAt ? "ended" : "active";
|
|
1135
|
+
const obs = observations.get(session.id) ?? [];
|
|
1136
|
+
lines.push(`## ${start} [${session.ide ?? "unknown"}] (${status}, ${obs.length} observations)`);
|
|
1137
|
+
for (const o of obs.slice(0, 5)) {
|
|
1138
|
+
lines.push(` - [${o.kind}] ${o.content.slice(0, 120)}`);
|
|
1139
|
+
}
|
|
1140
|
+
if (obs.length > 5) lines.push(` \u2026and ${obs.length - 5} more`);
|
|
1141
|
+
}
|
|
1142
|
+
return lines.join("\n");
|
|
1143
|
+
}
|
|
1144
|
+
case "kirograph_mem_status": {
|
|
1145
|
+
const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
|
|
1146
|
+
const projectRoot = cg.getProjectRoot();
|
|
1147
|
+
const config = await loadConfig(projectRoot);
|
|
1148
|
+
if (!config.enableMemory) return "Memory is not enabled. Set enableMemory: true in .kirograph/config.json";
|
|
1149
|
+
const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
|
|
1150
|
+
const db = cg.getDatabase();
|
|
1151
|
+
db.applyMemorySchema();
|
|
1152
|
+
const mem = new MemoryManager(config, db.getRawDb());
|
|
1153
|
+
mem.initialize();
|
|
1154
|
+
const stats = mem.getStats();
|
|
1155
|
+
const lines = [
|
|
1156
|
+
"KiroGraph Memory Status",
|
|
1157
|
+
` Sessions: ${stats.sessions} (${stats.activeSessions} active)`,
|
|
1158
|
+
` Observations: ${stats.observations}`,
|
|
1159
|
+
` Symbol links: ${stats.links}`,
|
|
1160
|
+
` Embeddings: ${stats.vectors} / ${stats.embeddableCount}`,
|
|
1161
|
+
` Model mismatch: ${stats.modelMismatch ? "\u26A0 yes \u2014 run kirograph mem reembed" : "no"}`,
|
|
1162
|
+
` Caveman compression: ${config.cavemanMode !== "off" ? config.cavemanMode : "off (storing raw)"}`
|
|
1163
|
+
];
|
|
1164
|
+
return lines.join("\n");
|
|
1165
|
+
}
|
|
937
1166
|
default:
|
|
938
1167
|
return `Unknown tool: ${toolName}`;
|
|
939
1168
|
}
|