kirograph 0.15.0 → 0.16.1
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/LICENSE +21 -0
- package/README.md +114 -1
- package/dist/bin/commands/docs.js +357 -0
- package/dist/bin/commands/docs.js.map +7 -0
- package/dist/bin/installer/config-prompt.js +17 -1
- package/dist/bin/installer/config-prompt.js.map +2 -2
- package/dist/bin/installer/index.js +6 -1
- package/dist/bin/installer/index.js.map +2 -2
- package/dist/bin/installer/steering.js +21 -0
- package/dist/bin/installer/steering.js.map +2 -2
- package/dist/bin/installer/targets/index.js.map +1 -1
- package/dist/bin/installer/targets/kiro.js +2 -2
- package/dist/bin/installer/targets/kiro.js.map +2 -2
- package/dist/bin/kirograph.js +3 -1
- package/dist/bin/kirograph.js.map +3 -3
- package/dist/compression/naive-cost.js +19 -0
- package/dist/compression/naive-cost.js.map +2 -2
- package/dist/compression/tracker.js +11 -2
- package/dist/compression/tracker.js.map +2 -2
- package/dist/compression/types.js.map +1 -1
- package/dist/config.js +34 -1
- package/dist/config.js.map +2 -2
- package/dist/core/pipeline.js +23 -0
- package/dist/core/pipeline.js.map +2 -2
- package/dist/db/database.js +11 -0
- package/dist/db/database.js.map +2 -2
- package/dist/db/docs-schema.sql +50 -0
- package/dist/docs/formats/asciidoc.js +108 -0
- package/dist/docs/formats/asciidoc.js.map +7 -0
- package/dist/docs/formats/html.js +100 -0
- package/dist/docs/formats/html.js.map +7 -0
- package/dist/docs/formats/index.js +81 -0
- package/dist/docs/formats/index.js.map +7 -0
- package/dist/docs/formats/markdown.js +146 -0
- package/dist/docs/formats/markdown.js.map +7 -0
- package/dist/docs/formats/openapi.js +228 -0
- package/dist/docs/formats/openapi.js.map +7 -0
- package/dist/docs/formats/org.js +117 -0
- package/dist/docs/formats/org.js.map +7 -0
- package/dist/docs/formats/plaintext.js +119 -0
- package/dist/docs/formats/plaintext.js.map +7 -0
- package/dist/docs/formats/rdoc.js +105 -0
- package/dist/docs/formats/rdoc.js.map +7 -0
- package/dist/docs/formats/rst.js +121 -0
- package/dist/docs/formats/rst.js.map +7 -0
- package/dist/docs/indexer.js +340 -0
- package/dist/docs/indexer.js.map +7 -0
- package/dist/docs/linker.js +151 -0
- package/dist/docs/linker.js.map +7 -0
- package/dist/docs/lint.js +92 -0
- package/dist/docs/lint.js.map +7 -0
- package/dist/docs/queries.js +295 -0
- package/dist/docs/queries.js.map +7 -0
- package/dist/docs/section-id.js +57 -0
- package/dist/docs/section-id.js.map +7 -0
- package/dist/docs/summarizer.js +55 -0
- package/dist/docs/summarizer.js.map +7 -0
- package/dist/docs/types.js +17 -0
- package/dist/docs/types.js.map +7 -0
- package/dist/docs/vectors.js +217 -0
- package/dist/docs/vectors.js.map +7 -0
- package/dist/mcp/tool-names.js +6 -1
- package/dist/mcp/tool-names.js.map +2 -2
- package/dist/mcp/tools.js +245 -1
- package/dist/mcp/tools.js.map +2 -2
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/bin/installer/config-prompt.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * KiroGraph Installer \u2014 configuration prompting\n */\n\nimport * as readline from 'readline';\nimport { KiroGraphConfig } from '../../config';\ntype CavemanMode = 'lite' | 'full' | 'ultra';\nimport { ask, askToggle, arrowSelect, printSection, printSeparator, dim, reset, violet } from './prompts';\nexport type ConfigPatch = Pick<KiroGraphConfig, 'enableEmbeddings' | 'useVecIndex' | 'semanticEngine' | 'typesenseDashboard' | 'qdrantDashboard' | 'extractDocstrings' | 'trackCallSites' | 'enableArchitecture' | 'cavemanMode' | 'shellCompressionLevel' | 'enableMemory'> & { embeddingModel?: string; embeddingDim?: number };\nexport type SemanticEngine = KiroGraphConfig['semanticEngine'];\n\nexport const DEFAULT_EMBEDDING_MODEL = 'nomic-ai/nomic-embed-text-v1.5';\n\n/** Well-known embedding models with their output dimensions. */\nconst PRESET_MODELS = [\n {\n value: 'nomic-ai/nomic-embed-text-v1.5',\n label: 'nomic-embed-text-v1.5',\n dim: 768,\n description: '768-dim \u00B7 ~130MB \u00B7 Best quality for code search (recommended)',\n },\n {\n value: 'onnx-community/embeddinggemma-300m-ONNX',\n label: 'embeddinggemma-300m',\n dim: 768,\n description: '768-dim \u00B7 ~300MB \u00B7 Google Gemma-based, multilingual, 2048-token context',\n },\n {\n value: 'Xenova/all-MiniLM-L6-v2',\n label: 'all-MiniLM-L6-v2',\n dim: 384,\n description: '384-dim \u00B7 ~23MB \u00B7 Fast and lightweight, lower accuracy',\n },\n {\n value: 'BAAI/bge-base-en-v1.5',\n label: 'bge-base-en-v1.5',\n dim: 768,\n description: '768-dim \u00B7 ~110MB \u00B7 Strong general-purpose alternative to nomic',\n },\n {\n value: '__other__',\n label: 'Other',\n dim: 768,\n description: 'Enter a custom HuggingFace model ID and embedding dimension',\n },\n] as const;\n\nexport async function promptConfigOptions(rl: readline.Interface): Promise<ConfigPatch> {\n // \u2500\u2500 Semantic 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\n printSection('\uD83D\uDD0D', 'Semantic Search');\n\n const enableEmbeddings = await askToggle(\n rl,\n 'Semantic embeddings (similarity search):',\n 'Enables natural-language code search via vector embeddings. A local model (~130MB) is downloaded on first use.',\n );\n\n const patch: ConfigPatch = { enableEmbeddings, useVecIndex: false, semanticEngine: 'cosine', typesenseDashboard: false, qdrantDashboard: false, extractDocstrings: true, trackCallSites: true, enableArchitecture: false, cavemanMode: 'off', shellCompressionLevel: 'normal', enableMemory: false };\n\n if (enableEmbeddings) {\n // \u2500\u2500 Model selection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const modelChoice = await arrowSelect<string>(\n rl,\n 'Embedding model:',\n PRESET_MODELS.map(m => ({ value: m.value, label: m.label, description: m.description })),\n );\n\n let embeddingModel: string;\n let embeddingDim: number;\n\n if (modelChoice === '__other__') {\n console.log(`\\n ${dim}Enter a HuggingFace model ID in the format org/model-name.${reset}`);\n while (true) {\n const raw = (await ask(rl, ` ${violet}Model identifier:${reset} `)).trim();\n if (raw.includes('/')) { embeddingModel = raw; break; }\n console.log(` Expected a HuggingFace model ID in the format org/model-name (e.g. nomic-ai/nomic-embed-text-v1.5).`);\n }\n console.log(`\\n ${dim}Enter the embedding output dimension for this model (check the model card on HuggingFace).${reset}`);\n while (true) {\n const raw = (await ask(rl, ` ${violet}Embedding dimension (e.g. 768, 384):${reset} `)).trim();\n const n = parseInt(raw, 10);\n if (!isNaN(n) && n > 0) { embeddingDim = n; break; }\n console.log(` Expected a positive integer (e.g. 768, 384, 1536).`);\n }\n } else {\n const preset = PRESET_MODELS.find(m => m.value === modelChoice)!;\n embeddingModel = preset.value;\n embeddingDim = preset.dim;\n }\n\n patch.embeddingModel = embeddingModel;\n patch.embeddingDim = embeddingDim;\n\n // \u2500\u2500 Engine selection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const semanticEngine = await arrowSelect<SemanticEngine>(rl, 'Vector search engine:', [\n { value: 'cosine', label: 'cosine', description: 'In-process cosine similarity. No extra deps. Best for small/medium projects.' },\n { value: 'sqlite-vec', label: 'sqlite-vec', description: 'ANN index. Sub-linear search. Best for large codebases. Needs: better-sqlite3, sqlite-vec (native).' },\n { value: 'orama', label: 'orama', description: 'Hybrid search (full-text + vector). Pure JS. Needs: @orama/orama, @orama/plugin-data-persistence.' },\n { value: 'pglite', label: 'pglite', description: 'Hybrid search via PostgreSQL + pgvector. Exact results. Pure WASM. Needs: @electric-sql/pglite.' },\n { value: 'lancedb', label: 'lancedb', description: 'ANN search via LanceDB (Apache Lance columnar format). Pure JS. Needs: @lancedb/lancedb.' },\n { value: 'qdrant', label: 'qdrant', description: 'ANN search via Qdrant embedded binary (HNSW index, Cosine). Needs: qdrant-local.' },\n { value: 'typesense', label: 'typesense', description: 'ANN search via Typesense (auto-downloaded binary, HNSW, Cosine). Needs: typesense.' },\n ]);\n patch.semanticEngine = semanticEngine;\n patch.useVecIndex = semanticEngine === 'sqlite-vec';\n\n if (semanticEngine === 'typesense') {\n patch.typesenseDashboard = await askToggle(rl,\n 'Typesense dashboard:',\n 'Serves the Typesense Dashboard locally and opens it in your browser after indexing completes.',\n false,\n );\n }\n\n if (semanticEngine === 'qdrant') {\n patch.qdrantDashboard = await askToggle(rl,\n 'Qdrant dashboard:',\n 'Downloads the Qdrant Web UI (first time only) and opens it in your browser after indexing completes.',\n false,\n );\n }\n }\n\n // \u2500\u2500 Graph Features \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 printSection('\uD83D\uDCCA', 'Graph Features');\n\n patch.extractDocstrings = await askToggle(rl,\n 'Docstring extraction:',\n 'Enriches symbol metadata and improves context quality. Slightly increases indexing time.',\n );\n\n patch.trackCallSites = await askToggle(rl,\n 'Call site tracking (caller/callee graph):',\n 'Enables kirograph_callers and kirograph_callees MCP tools. Increases index size.',\n );\n\n patch.enableArchitecture = await askToggle(rl,\n 'Architecture analysis (packages + layers):',\n 'Detects packages from manifests and architectural layers. Enables kirograph_architecture, kirograph_coupling, kirograph_package.',\n false,\n );\n\n // \u2500\u2500 Agent Behavior \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 printSection('\uD83E\uDD16', 'Agent Behavior');\n\n const cavemanChoice = await arrowSelect(rl, 'Communication style (caveman mode):', [\n { value: 'off', label: 'off', description: 'Normal responses \u2014 no compression' },\n { value: 'lite', label: 'lite', description: 'Compact, no filler, full sentences' },\n { value: 'full', label: 'full', description: 'Fragments, no articles, short synonyms' },\n { value: 'ultra', label: 'ultra', description: 'Max compression, abbreviations, \u2192 for causality' },\n ]);\n patch.cavemanMode = cavemanChoice as CavemanMode | 'off';\n\n const compressionChoice = await arrowSelect(rl, 'Shell compression (kirograph_exec default level):', [\n { value: 'off', label: 'off', description: 'No compression hook or steering (tool still available)' },\n { value: 'normal', label: 'normal', description: 'Balanced: removes noise, keeps structure (recommended)' },\n { value: 'aggressive', label: 'aggressive', description: 'More compact: groups by category, limits output' },\n { value: 'ultra', label: 'ultra', description: 'Maximum compression: counts and summaries only' },\n ]);\n patch.shellCompressionLevel = compressionChoice as KiroGraphConfig['shellCompressionLevel'];\n\n // \u2500\u2500 Memory \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 printSection('\uD83E\uDDE0', 'Memory');\n\n (patch as any).enableMemory = await askToggle(rl,\n 'Persistent memory (cross-session observations):',\n 'Stores decisions, errors, and patterns across sessions. Compressed (if caveman is on), linked to code symbols, searchable via kirograph_mem_* tools. Zero LLM tokens on write.',\n false, // Requires explicit enable\n );\n\n return patch;\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,qBAA8F;AAIvF,MAAM,0BAA0B;AAGvC,MAAM,gBAAgB;AAAA,EACpB;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,KAAK;AAAA,IACL,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,KAAK;AAAA,IACL,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,KAAK;AAAA,IACL,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,KAAK;AAAA,IACL,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,KAAK;AAAA,IACL,aAAa;AAAA,EACf;AACF;AAEA,eAAsB,oBAAoB,IAA8C;AAEtF,mCAAa,aAAM,iBAAiB;AAEpC,QAAM,mBAAmB,UAAM;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,QAAqB,EAAE,kBAAkB,aAAa,OAAO,gBAAgB,UAAU,oBAAoB,OAAO,iBAAiB,OAAO,mBAAmB,MAAM,gBAAgB,MAAM,oBAAoB,OAAO,aAAa,OAAO,uBAAuB,UAAU,cAAc,
|
|
4
|
+
"sourcesContent": ["/**\n * KiroGraph Installer \u2014 configuration prompting\n */\n\nimport * as readline from 'readline';\nimport { KiroGraphConfig } from '../../config';\ntype CavemanMode = 'lite' | 'full' | 'ultra';\nimport { ask, askToggle, arrowSelect, printSection, printSeparator, dim, reset, violet } from './prompts';\nexport type ConfigPatch = Pick<KiroGraphConfig, 'enableEmbeddings' | 'useVecIndex' | 'semanticEngine' | 'typesenseDashboard' | 'qdrantDashboard' | 'extractDocstrings' | 'trackCallSites' | 'enableArchitecture' | 'cavemanMode' | 'shellCompressionLevel' | 'enableMemory' | 'enableDocs' | 'docsContextLimit'> & { embeddingModel?: string; embeddingDim?: number };\nexport type SemanticEngine = KiroGraphConfig['semanticEngine'];\n\nexport const DEFAULT_EMBEDDING_MODEL = 'nomic-ai/nomic-embed-text-v1.5';\n\n/** Well-known embedding models with their output dimensions. */\nconst PRESET_MODELS = [\n {\n value: 'nomic-ai/nomic-embed-text-v1.5',\n label: 'nomic-embed-text-v1.5',\n dim: 768,\n description: '768-dim \u00B7 ~130MB \u00B7 Best quality for code search (recommended)',\n },\n {\n value: 'onnx-community/embeddinggemma-300m-ONNX',\n label: 'embeddinggemma-300m',\n dim: 768,\n description: '768-dim \u00B7 ~300MB \u00B7 Google Gemma-based, multilingual, 2048-token context',\n },\n {\n value: 'Xenova/all-MiniLM-L6-v2',\n label: 'all-MiniLM-L6-v2',\n dim: 384,\n description: '384-dim \u00B7 ~23MB \u00B7 Fast and lightweight, lower accuracy',\n },\n {\n value: 'BAAI/bge-base-en-v1.5',\n label: 'bge-base-en-v1.5',\n dim: 768,\n description: '768-dim \u00B7 ~110MB \u00B7 Strong general-purpose alternative to nomic',\n },\n {\n value: '__other__',\n label: 'Other',\n dim: 768,\n description: 'Enter a custom HuggingFace model ID and embedding dimension',\n },\n] as const;\n\nexport async function promptConfigOptions(rl: readline.Interface): Promise<ConfigPatch> {\n // \u2500\u2500 Semantic 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\n printSection('\uD83D\uDD0D', 'Semantic Search');\n\n const enableEmbeddings = await askToggle(\n rl,\n 'Semantic embeddings (similarity search):',\n 'Enables natural-language code search via vector embeddings. A local model (~130MB) is downloaded on first use.',\n );\n\n const patch: ConfigPatch = { enableEmbeddings, useVecIndex: false, semanticEngine: 'cosine', typesenseDashboard: false, qdrantDashboard: false, extractDocstrings: true, trackCallSites: true, enableArchitecture: false, cavemanMode: 'off', shellCompressionLevel: 'normal', enableMemory: false, enableDocs: false, docsContextLimit: 0 };\n\n if (enableEmbeddings) {\n // \u2500\u2500 Model selection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const modelChoice = await arrowSelect<string>(\n rl,\n 'Embedding model:',\n PRESET_MODELS.map(m => ({ value: m.value, label: m.label, description: m.description })),\n );\n\n let embeddingModel: string;\n let embeddingDim: number;\n\n if (modelChoice === '__other__') {\n console.log(`\\n ${dim}Enter a HuggingFace model ID in the format org/model-name.${reset}`);\n while (true) {\n const raw = (await ask(rl, ` ${violet}Model identifier:${reset} `)).trim();\n if (raw.includes('/')) { embeddingModel = raw; break; }\n console.log(` Expected a HuggingFace model ID in the format org/model-name (e.g. nomic-ai/nomic-embed-text-v1.5).`);\n }\n console.log(`\\n ${dim}Enter the embedding output dimension for this model (check the model card on HuggingFace).${reset}`);\n while (true) {\n const raw = (await ask(rl, ` ${violet}Embedding dimension (e.g. 768, 384):${reset} `)).trim();\n const n = parseInt(raw, 10);\n if (!isNaN(n) && n > 0) { embeddingDim = n; break; }\n console.log(` Expected a positive integer (e.g. 768, 384, 1536).`);\n }\n } else {\n const preset = PRESET_MODELS.find(m => m.value === modelChoice)!;\n embeddingModel = preset.value;\n embeddingDim = preset.dim;\n }\n\n patch.embeddingModel = embeddingModel;\n patch.embeddingDim = embeddingDim;\n\n // \u2500\u2500 Engine selection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const semanticEngine = await arrowSelect<SemanticEngine>(rl, 'Vector search engine:', [\n { value: 'cosine', label: 'cosine', description: 'In-process cosine similarity. No extra deps. Best for small/medium projects.' },\n { value: 'sqlite-vec', label: 'sqlite-vec', description: 'ANN index. Sub-linear search. Best for large codebases. Needs: better-sqlite3, sqlite-vec (native).' },\n { value: 'orama', label: 'orama', description: 'Hybrid search (full-text + vector). Pure JS. Needs: @orama/orama, @orama/plugin-data-persistence.' },\n { value: 'pglite', label: 'pglite', description: 'Hybrid search via PostgreSQL + pgvector. Exact results. Pure WASM. Needs: @electric-sql/pglite.' },\n { value: 'lancedb', label: 'lancedb', description: 'ANN search via LanceDB (Apache Lance columnar format). Pure JS. Needs: @lancedb/lancedb.' },\n { value: 'qdrant', label: 'qdrant', description: 'ANN search via Qdrant embedded binary (HNSW index, Cosine). Needs: qdrant-local.' },\n { value: 'typesense', label: 'typesense', description: 'ANN search via Typesense (auto-downloaded binary, HNSW, Cosine). Needs: typesense.' },\n ]);\n patch.semanticEngine = semanticEngine;\n patch.useVecIndex = semanticEngine === 'sqlite-vec';\n\n if (semanticEngine === 'typesense') {\n patch.typesenseDashboard = await askToggle(rl,\n 'Typesense dashboard:',\n 'Serves the Typesense Dashboard locally and opens it in your browser after indexing completes.',\n false,\n );\n }\n\n if (semanticEngine === 'qdrant') {\n patch.qdrantDashboard = await askToggle(rl,\n 'Qdrant dashboard:',\n 'Downloads the Qdrant Web UI (first time only) and opens it in your browser after indexing completes.',\n false,\n );\n }\n }\n\n // \u2500\u2500 Graph Features \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 printSection('\uD83D\uDCCA', 'Graph Features');\n\n patch.extractDocstrings = await askToggle(rl,\n 'Docstring extraction:',\n 'Enriches symbol metadata and improves context quality. Slightly increases indexing time.',\n );\n\n patch.trackCallSites = await askToggle(rl,\n 'Call site tracking (caller/callee graph):',\n 'Enables kirograph_callers and kirograph_callees MCP tools. Increases index size.',\n );\n\n patch.enableArchitecture = await askToggle(rl,\n 'Architecture analysis (packages + layers):',\n 'Detects packages from manifests and architectural layers. Enables kirograph_architecture, kirograph_coupling, kirograph_package.',\n false,\n );\n\n // \u2500\u2500 Documentation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 printSection('\uD83D\uDCD6', 'Documentation');\n\n (patch as any).enableDocs = await askToggle(rl,\n 'Documentation indexing (section-level retrieval):',\n 'Indexes docs by heading structure. Enables kirograph_docs_toc, kirograph_docs_search, kirograph_docs_section, kirograph_docs_outline, kirograph_docs_refs.',\n false,\n );\n\n if ((patch as any).enableDocs) {\n const contextChoice = await arrowSelect<number>(rl, 'Include doc sections in kirograph_context results?', [\n { value: 0, label: '0 (disabled)', description: 'Docs stay separate \u2014 use kirograph_docs_* tools explicitly (recommended)' },\n { value: 3, label: '3 sections', description: 'Include up to 3 relevant doc sections in context results' },\n { value: 5, label: '5 sections', description: 'Include up to 5 relevant doc sections in context results' },\n { value: 10, label: '10 sections', description: 'Include up to 10 relevant doc sections in context results' },\n ]);\n (patch as any).docsContextLimit = contextChoice;\n }\n\n // \u2500\u2500 Agent Behavior \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 printSection('\uD83E\uDD16', 'Agent Behavior');\n\n const cavemanChoice = await arrowSelect(rl, 'Communication style (caveman mode):', [\n { value: 'off', label: 'off', description: 'Normal responses \u2014 no compression' },\n { value: 'lite', label: 'lite', description: 'Compact, no filler, full sentences' },\n { value: 'full', label: 'full', description: 'Fragments, no articles, short synonyms' },\n { value: 'ultra', label: 'ultra', description: 'Max compression, abbreviations, \u2192 for causality' },\n ]);\n patch.cavemanMode = cavemanChoice as CavemanMode | 'off';\n\n const compressionChoice = await arrowSelect(rl, 'Shell compression (kirograph_exec default level):', [\n { value: 'off', label: 'off', description: 'No compression hook or steering (tool still available)' },\n { value: 'normal', label: 'normal', description: 'Balanced: removes noise, keeps structure (recommended)' },\n { value: 'aggressive', label: 'aggressive', description: 'More compact: groups by category, limits output' },\n { value: 'ultra', label: 'ultra', description: 'Maximum compression: counts and summaries only' },\n ]);\n patch.shellCompressionLevel = compressionChoice as KiroGraphConfig['shellCompressionLevel'];\n\n // \u2500\u2500 Memory \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 printSection('\uD83E\uDDE0', 'Memory');\n\n (patch as any).enableMemory = await askToggle(rl,\n 'Persistent memory (cross-session observations):',\n 'Stores decisions, errors, and patterns across sessions. Compressed (if caveman is on), linked to code symbols, searchable via kirograph_mem_* tools. Zero LLM tokens on write.',\n false, // Requires explicit enable\n );\n\n return patch;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -64,6 +64,7 @@ async function runInstaller(target = "kiro") {
|
|
|
64
64
|
let cavemanMode = "off";
|
|
65
65
|
let shellCompressionLevel = "normal";
|
|
66
66
|
let enableMemory = false;
|
|
67
|
+
let enableDocs = false;
|
|
67
68
|
let shouldOfferIndex = false;
|
|
68
69
|
let typesenseDashboard = false;
|
|
69
70
|
let qdrantDashboard = false;
|
|
@@ -73,6 +74,7 @@ async function runInstaller(target = "kiro") {
|
|
|
73
74
|
cavemanMode = config.cavemanMode ?? "off";
|
|
74
75
|
shellCompressionLevel = config.shellCompressionLevel ?? "normal";
|
|
75
76
|
enableMemory = config.enableMemory ?? false;
|
|
77
|
+
enableDocs = config.enableDocs ?? false;
|
|
76
78
|
console.log(` \u2713 Reusing existing KiroGraph data in ${cwd}/.kirograph/`);
|
|
77
79
|
console.log(` \u2022 semanticEngine: ${config.semanticEngine}`);
|
|
78
80
|
console.log(` \u2022 enableEmbeddings: ${config.enableEmbeddings}`);
|
|
@@ -80,6 +82,7 @@ async function runInstaller(target = "kiro") {
|
|
|
80
82
|
console.log(` \u2022 cavemanMode: ${cavemanMode}`);
|
|
81
83
|
console.log(` \u2022 shellCompressionLevel: ${shellCompressionLevel}`);
|
|
82
84
|
console.log(` \u2022 enableMemory: ${enableMemory}`);
|
|
85
|
+
console.log(` \u2022 enableDocs: ${enableDocs}`);
|
|
83
86
|
} else {
|
|
84
87
|
shouldOfferIndex = true;
|
|
85
88
|
const patch = await (0, import_config_prompt.promptConfigOptions)(rl);
|
|
@@ -87,6 +90,7 @@ async function runInstaller(target = "kiro") {
|
|
|
87
90
|
cavemanMode = patch.cavemanMode ?? "off";
|
|
88
91
|
shellCompressionLevel = patch.shellCompressionLevel ?? "normal";
|
|
89
92
|
enableMemory = patch.enableMemory ?? false;
|
|
93
|
+
enableDocs = patch.enableDocs ?? false;
|
|
90
94
|
typesenseDashboard = patch.typesenseDashboard;
|
|
91
95
|
qdrantDashboard = patch.qdrantDashboard;
|
|
92
96
|
console.log(`
|
|
@@ -166,8 +170,9 @@ async function runInstaller(target = "kiro") {
|
|
|
166
170
|
console.log(` \u2022 cavemanMode: ${cavemanMode}`);
|
|
167
171
|
console.log(` \u2022 shellCompressionLevel: ${shellCompressionLevel}`);
|
|
168
172
|
console.log(` \u2022 enableMemory: ${enableMemory}`);
|
|
173
|
+
console.log(` \u2022 enableDocs: ${enableDocs}`);
|
|
169
174
|
}
|
|
170
|
-
installer.installLate(cwd, cavemanMode, shellCompressionLevel, enableMemory);
|
|
175
|
+
installer.installLate(cwd, cavemanMode, shellCompressionLevel, enableMemory, enableDocs);
|
|
171
176
|
} catch (err) {
|
|
172
177
|
const reason = err instanceof Error ? err.message : String(err);
|
|
173
178
|
console.error(`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/bin/installer/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * KiroGraph Installer\n *\n * The default target wires up Kiro:\n * 1. .kiro/settings/mcp.json \u2014 registers the MCP server (IDE + CLI)\n * 2. .kiro/hooks/*.kiro.hook \u2014 auto-sync hooks for Kiro IDE\n * 3. .kiro/steering/kirograph.md \u2014 teaches Kiro to use the graph tools (IDE + CLI)\n * 4. .kiro/agents/kirograph.json \u2014 custom agent config for Kiro CLI\n */\n\nimport * as readline from 'readline';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { spawnSync } from 'child_process';\nimport { loadConfig, updateConfig } from '../../config';\nimport { printBanner } from '../banner';\nimport { renderIndexProgress } from '../progress';\nimport { dim, reset } from '../ui';\nimport { ask, askToggle } from './prompts';\nimport { promptConfigOptions } from './config-prompt';\nimport { openTypesenseDashboard } from './dashboard';\nimport { ensureQdrantUI, openQdrantDashboard } from './qdrant-dashboard';\nimport type { InstallTarget } from './common';\nimport { getTargetInstaller } from './targets';\nimport type { CavemanMode } from './caveman';\n\nexport async function runInstaller(target: InstallTarget = 'kiro'): Promise<void> {\n printBanner();\n\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n\n try {\n const cwd = process.cwd();\n const installer = getTargetInstaller(target);\n\n console.log(` Workspace: ${cwd}\\n`);\n\n const proceed = await askToggle(rl, `Install KiroGraph for ${installer.label}?`, 'Registers the MCP server and writes integration files for this workspace.');\n if (!proceed) { console.log(' Cancelled.'); rl.close(); return; }\n console.log();\n\n installer.installEarly(cwd);\n\n const alreadyInitialized = fs.existsSync(path.join(cwd, '.kirograph'));\n let cavemanMode: CavemanMode | 'off' = 'off';\n let shellCompressionLevel: 'off' | 'normal' | 'aggressive' | 'ultra' = 'normal';\n let enableMemory = false;\n let shouldOfferIndex = false;\n let typesenseDashboard = false;\n let qdrantDashboard = false;\n\n try {\n if (alreadyInitialized) {\n const config = await loadConfig(cwd);\n cavemanMode = config.cavemanMode ?? 'off';\n shellCompressionLevel = config.shellCompressionLevel ?? 'normal';\n enableMemory = config.enableMemory ?? false;\n console.log(` \u2713 Reusing existing KiroGraph data in ${cwd}/.kirograph/`);\n console.log(` \u2022 semanticEngine: ${config.semanticEngine}`);\n console.log(` \u2022 enableEmbeddings: ${config.enableEmbeddings}`);\n console.log(` \u2022 enableArchitecture: ${config.enableArchitecture}`);\n console.log(` \u2022 cavemanMode: ${cavemanMode}`);\n console.log(` \u2022 shellCompressionLevel: ${shellCompressionLevel}`);\n console.log(` \u2022 enableMemory: ${enableMemory}`);\n } else {\n shouldOfferIndex = true;\n const patch = await promptConfigOptions(rl);\n await updateConfig(cwd, patch);\n cavemanMode = patch.cavemanMode ?? 'off';\n shellCompressionLevel = patch.shellCompressionLevel ?? 'normal';\n enableMemory = patch.enableMemory ?? false;\n typesenseDashboard = patch.typesenseDashboard;\n qdrantDashboard = patch.qdrantDashboard;\n\n console.log(`\\n Configuration saved to ${cwd}/.kirograph/config.json`);\n console.log(` \u2022 enableEmbeddings: ${patch.enableEmbeddings}`);\n if ('embeddingModel' in patch) {\n console.log(` \u2022 embeddingModel: ${patch.embeddingModel} ${dim}(${patch.embeddingDim}-dim)${reset}`);\n }\n if (patch.enableEmbeddings) {\n console.log(` \u2022 semanticEngine: ${patch.semanticEngine}`);\n if (patch.semanticEngine === 'sqlite-vec') {\n console.log(`\\n Installing sqlite-vec dependencies...`);\n const result = spawnSync('npm', ['install', 'better-sqlite3', 'sqlite-vec'], { stdio: 'inherit', shell: true });\n if (result.status === 0) {\n console.log(` \u2713 better-sqlite3 and sqlite-vec installed`);\n } else {\n console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);\n console.warn(` npm install better-sqlite3 sqlite-vec`);\n }\n } else if (patch.semanticEngine === 'orama') {\n console.log(`\\n Installing Orama dependencies...`);\n const result = spawnSync('npm', ['install', '@orama/orama', '@orama/plugin-data-persistence'], { stdio: 'inherit', shell: true });\n if (result.status === 0) {\n console.log(` \u2713 @orama/orama and @orama/plugin-data-persistence installed`);\n } else {\n console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);\n console.warn(` npm install @orama/orama @orama/plugin-data-persistence`);\n }\n } else if (patch.semanticEngine === 'pglite') {\n console.log(`\\n Installing PGlite dependencies...`);\n const result = spawnSync('npm', ['install', '@electric-sql/pglite'], { stdio: 'inherit', shell: true });\n if (result.status === 0) {\n console.log(` \u2713 @electric-sql/pglite installed`);\n } else {\n console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);\n console.warn(` npm install @electric-sql/pglite`);\n }\n } else if (patch.semanticEngine === 'lancedb') {\n console.log(`\\n Installing LanceDB dependencies...`);\n const result = spawnSync('npm', ['install', '@lancedb/lancedb'], { stdio: 'inherit', shell: true });\n if (result.status === 0) {\n console.log(` \u2713 @lancedb/lancedb installed`);\n } else {\n console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);\n console.warn(` npm install @lancedb/lancedb`);\n }\n } else if (patch.semanticEngine === 'qdrant') {\n console.log(`\\n Installing Qdrant dependencies...`);\n const result = spawnSync('npm', ['install', 'qdrant-local'], { stdio: 'inherit', shell: true });\n if (result.status === 0) {\n console.log(` \u2713 qdrant-local installed`);\n } else {\n console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);\n console.warn(` npm install qdrant-local`);\n }\n } else if (patch.semanticEngine === 'typesense') {\n console.log(`\\n Installing Typesense dependencies...`);\n const result = spawnSync('npm', ['install', 'typesense'], { stdio: 'inherit', shell: true });\n if (result.status === 0) {\n console.log(` \u2713 typesense installed`);\n console.log(` \u2139 The Typesense binary (~37MB) will be auto-downloaded on first index run.`);\n } else {\n console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);\n console.warn(` npm install typesense`);\n }\n }\n }\n console.log(` \u2022 extractDocstrings: ${patch.extractDocstrings}`);\n console.log(` \u2022 trackCallSites: ${patch.trackCallSites}`);\n console.log(` \u2022 enableArchitecture: ${patch.enableArchitecture}`);\n console.log(` \u2022 cavemanMode: ${cavemanMode}`);\n console.log(` \u2022 shellCompressionLevel: ${shellCompressionLevel}`);\n console.log(` \u2022 enableMemory: ${enableMemory}`);\n }\n\n installer.installLate(cwd, cavemanMode, shellCompressionLevel, enableMemory);\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n console.error(`\\n \u2717 Failed to write configuration: ${reason}`);\n process.exit(1);\n }\n\n // 5. Pre-download Qdrant UI before indexing so Qdrant starts with static content dir\n if (qdrantDashboard) {\n await ensureQdrantUI(cwd);\n }\n\n // 6. Optionally init + index\n if (shouldOfferIndex && await askToggle(rl, 'Initialize and index this project now?', 'Creates .kirograph/ and indexes all source files. Takes a few seconds for small projects, longer for large ones.')) {\n const KiroGraph = (await Promise.resolve().then(() => require('../../index.js'))).default;\n\n const fileBytes = new Map<string, { loaded: number; total: number }>();\n const modelProgress = (file: string, loaded: number, total: number, done: boolean): void => {\n const entry = fileBytes.get(file) ?? { loaded: 0, total: 0 };\n if (total > 0) entry.total = total;\n entry.loaded = done ? entry.total : loaded;\n fileBytes.set(file, entry);\n\n // Only count files where we know the size (content-length was present)\n const knownFiles = Array.from(fileBytes.values()).filter(f => f.total > 0);\n const totalLoaded = knownFiles.reduce((s, f) => s + f.loaded, 0);\n const totalBytes = knownFiles.reduce((s, f) => s + f.total, 0);\n const pct = totalBytes > 0 ? Math.min((totalLoaded / totalBytes) * 100, 100) : 0;\n\n const filled = Math.round(pct / 5);\n const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(20 - filled);\n const mb = (totalLoaded / 1024 / 1024).toFixed(1);\n const totalMb = (totalBytes / 1024 / 1024).toFixed(1);\n process.stdout.write(`\\r [${bar}] ${pct.toFixed(0).padStart(3)}% ${mb} / ${totalMb} MB `);\n };\n\n // Suppress noisy internal warnings from @huggingface/transformers during download\n const originalStderrWrite = process.stderr.write.bind(process.stderr);\n const stderrFilter = (chunk: unknown, ...args: unknown[]): boolean => {\n const str = typeof chunk === 'string' ? chunk : String(chunk);\n if (str.includes('content-length') || str.includes('dtype not specified')) return true;\n return (originalStderrWrite as (...a: unknown[]) => boolean)(chunk, ...args);\n };\n process.stderr.write = stderrFilter as typeof process.stderr.write;\n\n let cg;\n try {\n if (!KiroGraph.isInitialized(cwd)) {\n process.stdout.write(' Downloading embedding model\u2026\\n');\n cg = await KiroGraph.init(cwd, undefined, modelProgress);\n process.stdout.write('\\n');\n console.log(' \u2713 Created .kirograph/');\n } else {\n cg = await KiroGraph.open(cwd, modelProgress);\n if (fileBytes.size > 0) process.stdout.write('\\n');\n }\n } finally {\n process.stderr.write = originalStderrWrite;\n }\n console.log(' Indexing...');\n const result = await cg.indexAll({ onProgress: renderIndexProgress });\n process.stdout.write('\\n');\n console.log(` \u2713 Indexed ${result.filesIndexed} files, ${result.nodesCreated} symbols, ${result.edgesCreated} edges`);\n cg.close();\n\n if (typesenseDashboard) {\n const dashboardServer = await openTypesenseDashboard(cwd);\n console.log(` ${dim}Press Ctrl+C to stop the dashboard server when done.${reset}`);\n await new Promise<void>(resolve => {\n process.on('SIGINT', () => {\n if (dashboardServer) {\n dashboardServer.close(() => resolve());\n } else {\n resolve();\n }\n });\n });\n return; // rl.close() handled in finally\n }\n\n if (qdrantDashboard) {\n await openQdrantDashboard(cwd);\n }\n }\n\n installer.printNextSteps(cwd);\n } finally {\n rl.close();\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,eAA0B;AAC1B,SAAoB;AACpB,WAAsB;AACtB,2BAA0B;AAC1B,oBAAyC;AACzC,oBAA4B;AAC5B,sBAAoC;AACpC,gBAA2B;AAC3B,qBAA+B;AAC/B,2BAAoC;AACpC,uBAAuC;AACvC,8BAAoD;AAEpD,qBAAmC;AAGnC,eAAsB,aAAa,SAAwB,QAAuB;AAChF,iCAAY;AAEZ,QAAM,KAAK,SAAS,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAEpF,MAAI;AACF,UAAM,MAAM,QAAQ,IAAI;AACxB,UAAM,gBAAY,mCAAmB,MAAM;AAE3C,YAAQ,IAAI,gBAAgB,GAAG;AAAA,CAAI;AAEnC,UAAM,UAAU,UAAM,0BAAU,IAAI,yBAAyB,UAAU,KAAK,KAAK,2EAA2E;AAC5J,QAAI,CAAC,SAAS;AAAE,cAAQ,IAAI,cAAc;AAAG,SAAG,MAAM;AAAG;AAAA,IAAQ;AACjE,YAAQ,IAAI;AAEZ,cAAU,aAAa,GAAG;AAE1B,UAAM,qBAAqB,GAAG,WAAW,KAAK,KAAK,KAAK,YAAY,CAAC;AACrE,QAAI,cAAmC;AACvC,QAAI,wBAAmE;AACvE,QAAI,eAAe;AACnB,QAAI,mBAAmB;AACvB,QAAI,qBAAqB;AACzB,QAAI,kBAAkB;AAEtB,QAAI;AACF,UAAI,oBAAoB;AACtB,cAAM,SAAS,UAAM,0BAAW,GAAG;AACnC,sBAAc,OAAO,eAAe;AACpC,gCAAwB,OAAO,yBAAyB;AACxD,uBAAe,OAAO,gBAAgB;AACtC,gBAAQ,IAAI,+CAA0C,GAAG,cAAc;AACvE,gBAAQ,IAAI,4BAAuB,OAAO,cAAc,EAAE;AAC1D,gBAAQ,IAAI,8BAAyB,OAAO,gBAAgB,EAAE;AAC9D,gBAAQ,IAAI,gCAA2B,OAAO,kBAAkB,EAAE;AAClE,gBAAQ,IAAI,yBAAoB,WAAW,EAAE;AAC7C,gBAAQ,IAAI,mCAA8B,qBAAqB,EAAE;AACjE,gBAAQ,IAAI,0BAAqB,YAAY,EAAE;AAAA,
|
|
4
|
+
"sourcesContent": ["/**\n * KiroGraph Installer\n *\n * The default target wires up Kiro:\n * 1. .kiro/settings/mcp.json \u2014 registers the MCP server (IDE + CLI)\n * 2. .kiro/hooks/*.kiro.hook \u2014 auto-sync hooks for Kiro IDE\n * 3. .kiro/steering/kirograph.md \u2014 teaches Kiro to use the graph tools (IDE + CLI)\n * 4. .kiro/agents/kirograph.json \u2014 custom agent config for Kiro CLI\n */\n\nimport * as readline from 'readline';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { spawnSync } from 'child_process';\nimport { loadConfig, updateConfig } from '../../config';\nimport { printBanner } from '../banner';\nimport { renderIndexProgress } from '../progress';\nimport { dim, reset } from '../ui';\nimport { ask, askToggle } from './prompts';\nimport { promptConfigOptions } from './config-prompt';\nimport { openTypesenseDashboard } from './dashboard';\nimport { ensureQdrantUI, openQdrantDashboard } from './qdrant-dashboard';\nimport type { InstallTarget } from './common';\nimport { getTargetInstaller } from './targets';\nimport type { CavemanMode } from './caveman';\n\nexport async function runInstaller(target: InstallTarget = 'kiro'): Promise<void> {\n printBanner();\n\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n\n try {\n const cwd = process.cwd();\n const installer = getTargetInstaller(target);\n\n console.log(` Workspace: ${cwd}\\n`);\n\n const proceed = await askToggle(rl, `Install KiroGraph for ${installer.label}?`, 'Registers the MCP server and writes integration files for this workspace.');\n if (!proceed) { console.log(' Cancelled.'); rl.close(); return; }\n console.log();\n\n installer.installEarly(cwd);\n\n const alreadyInitialized = fs.existsSync(path.join(cwd, '.kirograph'));\n let cavemanMode: CavemanMode | 'off' = 'off';\n let shellCompressionLevel: 'off' | 'normal' | 'aggressive' | 'ultra' = 'normal';\n let enableMemory = false;\n let enableDocs = false;\n let shouldOfferIndex = false;\n let typesenseDashboard = false;\n let qdrantDashboard = false;\n\n try {\n if (alreadyInitialized) {\n const config = await loadConfig(cwd);\n cavemanMode = config.cavemanMode ?? 'off';\n shellCompressionLevel = config.shellCompressionLevel ?? 'normal';\n enableMemory = config.enableMemory ?? false;\n enableDocs = config.enableDocs ?? false;\n console.log(` \u2713 Reusing existing KiroGraph data in ${cwd}/.kirograph/`);\n console.log(` \u2022 semanticEngine: ${config.semanticEngine}`);\n console.log(` \u2022 enableEmbeddings: ${config.enableEmbeddings}`);\n console.log(` \u2022 enableArchitecture: ${config.enableArchitecture}`);\n console.log(` \u2022 cavemanMode: ${cavemanMode}`);\n console.log(` \u2022 shellCompressionLevel: ${shellCompressionLevel}`);\n console.log(` \u2022 enableMemory: ${enableMemory}`);\n console.log(` \u2022 enableDocs: ${enableDocs}`);\n } else {\n shouldOfferIndex = true;\n const patch = await promptConfigOptions(rl);\n await updateConfig(cwd, patch);\n cavemanMode = patch.cavemanMode ?? 'off';\n shellCompressionLevel = patch.shellCompressionLevel ?? 'normal';\n enableMemory = patch.enableMemory ?? false;\n enableDocs = patch.enableDocs ?? false;\n typesenseDashboard = patch.typesenseDashboard;\n qdrantDashboard = patch.qdrantDashboard;\n\n console.log(`\\n Configuration saved to ${cwd}/.kirograph/config.json`);\n console.log(` \u2022 enableEmbeddings: ${patch.enableEmbeddings}`);\n if ('embeddingModel' in patch) {\n console.log(` \u2022 embeddingModel: ${patch.embeddingModel} ${dim}(${patch.embeddingDim}-dim)${reset}`);\n }\n if (patch.enableEmbeddings) {\n console.log(` \u2022 semanticEngine: ${patch.semanticEngine}`);\n if (patch.semanticEngine === 'sqlite-vec') {\n console.log(`\\n Installing sqlite-vec dependencies...`);\n const result = spawnSync('npm', ['install', 'better-sqlite3', 'sqlite-vec'], { stdio: 'inherit', shell: true });\n if (result.status === 0) {\n console.log(` \u2713 better-sqlite3 and sqlite-vec installed`);\n } else {\n console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);\n console.warn(` npm install better-sqlite3 sqlite-vec`);\n }\n } else if (patch.semanticEngine === 'orama') {\n console.log(`\\n Installing Orama dependencies...`);\n const result = spawnSync('npm', ['install', '@orama/orama', '@orama/plugin-data-persistence'], { stdio: 'inherit', shell: true });\n if (result.status === 0) {\n console.log(` \u2713 @orama/orama and @orama/plugin-data-persistence installed`);\n } else {\n console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);\n console.warn(` npm install @orama/orama @orama/plugin-data-persistence`);\n }\n } else if (patch.semanticEngine === 'pglite') {\n console.log(`\\n Installing PGlite dependencies...`);\n const result = spawnSync('npm', ['install', '@electric-sql/pglite'], { stdio: 'inherit', shell: true });\n if (result.status === 0) {\n console.log(` \u2713 @electric-sql/pglite installed`);\n } else {\n console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);\n console.warn(` npm install @electric-sql/pglite`);\n }\n } else if (patch.semanticEngine === 'lancedb') {\n console.log(`\\n Installing LanceDB dependencies...`);\n const result = spawnSync('npm', ['install', '@lancedb/lancedb'], { stdio: 'inherit', shell: true });\n if (result.status === 0) {\n console.log(` \u2713 @lancedb/lancedb installed`);\n } else {\n console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);\n console.warn(` npm install @lancedb/lancedb`);\n }\n } else if (patch.semanticEngine === 'qdrant') {\n console.log(`\\n Installing Qdrant dependencies...`);\n const result = spawnSync('npm', ['install', 'qdrant-local'], { stdio: 'inherit', shell: true });\n if (result.status === 0) {\n console.log(` \u2713 qdrant-local installed`);\n } else {\n console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);\n console.warn(` npm install qdrant-local`);\n }\n } else if (patch.semanticEngine === 'typesense') {\n console.log(`\\n Installing Typesense dependencies...`);\n const result = spawnSync('npm', ['install', 'typesense'], { stdio: 'inherit', shell: true });\n if (result.status === 0) {\n console.log(` \u2713 typesense installed`);\n console.log(` \u2139 The Typesense binary (~37MB) will be auto-downloaded on first index run.`);\n } else {\n console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);\n console.warn(` npm install typesense`);\n }\n }\n }\n console.log(` \u2022 extractDocstrings: ${patch.extractDocstrings}`);\n console.log(` \u2022 trackCallSites: ${patch.trackCallSites}`);\n console.log(` \u2022 enableArchitecture: ${patch.enableArchitecture}`);\n console.log(` \u2022 cavemanMode: ${cavemanMode}`);\n console.log(` \u2022 shellCompressionLevel: ${shellCompressionLevel}`);\n console.log(` \u2022 enableMemory: ${enableMemory}`);\n console.log(` \u2022 enableDocs: ${enableDocs}`);\n }\n\n installer.installLate(cwd, cavemanMode, shellCompressionLevel, enableMemory, enableDocs);\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n console.error(`\\n \u2717 Failed to write configuration: ${reason}`);\n process.exit(1);\n }\n\n // 5. Pre-download Qdrant UI before indexing so Qdrant starts with static content dir\n if (qdrantDashboard) {\n await ensureQdrantUI(cwd);\n }\n\n // 6. Optionally init + index\n if (shouldOfferIndex && await askToggle(rl, 'Initialize and index this project now?', 'Creates .kirograph/ and indexes all source files. Takes a few seconds for small projects, longer for large ones.')) {\n const KiroGraph = (await Promise.resolve().then(() => require('../../index.js'))).default;\n\n const fileBytes = new Map<string, { loaded: number; total: number }>();\n const modelProgress = (file: string, loaded: number, total: number, done: boolean): void => {\n const entry = fileBytes.get(file) ?? { loaded: 0, total: 0 };\n if (total > 0) entry.total = total;\n entry.loaded = done ? entry.total : loaded;\n fileBytes.set(file, entry);\n\n // Only count files where we know the size (content-length was present)\n const knownFiles = Array.from(fileBytes.values()).filter(f => f.total > 0);\n const totalLoaded = knownFiles.reduce((s, f) => s + f.loaded, 0);\n const totalBytes = knownFiles.reduce((s, f) => s + f.total, 0);\n const pct = totalBytes > 0 ? Math.min((totalLoaded / totalBytes) * 100, 100) : 0;\n\n const filled = Math.round(pct / 5);\n const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(20 - filled);\n const mb = (totalLoaded / 1024 / 1024).toFixed(1);\n const totalMb = (totalBytes / 1024 / 1024).toFixed(1);\n process.stdout.write(`\\r [${bar}] ${pct.toFixed(0).padStart(3)}% ${mb} / ${totalMb} MB `);\n };\n\n // Suppress noisy internal warnings from @huggingface/transformers during download\n const originalStderrWrite = process.stderr.write.bind(process.stderr);\n const stderrFilter = (chunk: unknown, ...args: unknown[]): boolean => {\n const str = typeof chunk === 'string' ? chunk : String(chunk);\n if (str.includes('content-length') || str.includes('dtype not specified')) return true;\n return (originalStderrWrite as (...a: unknown[]) => boolean)(chunk, ...args);\n };\n process.stderr.write = stderrFilter as typeof process.stderr.write;\n\n let cg;\n try {\n if (!KiroGraph.isInitialized(cwd)) {\n process.stdout.write(' Downloading embedding model\u2026\\n');\n cg = await KiroGraph.init(cwd, undefined, modelProgress);\n process.stdout.write('\\n');\n console.log(' \u2713 Created .kirograph/');\n } else {\n cg = await KiroGraph.open(cwd, modelProgress);\n if (fileBytes.size > 0) process.stdout.write('\\n');\n }\n } finally {\n process.stderr.write = originalStderrWrite;\n }\n console.log(' Indexing...');\n const result = await cg.indexAll({ onProgress: renderIndexProgress });\n process.stdout.write('\\n');\n console.log(` \u2713 Indexed ${result.filesIndexed} files, ${result.nodesCreated} symbols, ${result.edgesCreated} edges`);\n cg.close();\n\n if (typesenseDashboard) {\n const dashboardServer = await openTypesenseDashboard(cwd);\n console.log(` ${dim}Press Ctrl+C to stop the dashboard server when done.${reset}`);\n await new Promise<void>(resolve => {\n process.on('SIGINT', () => {\n if (dashboardServer) {\n dashboardServer.close(() => resolve());\n } else {\n resolve();\n }\n });\n });\n return; // rl.close() handled in finally\n }\n\n if (qdrantDashboard) {\n await openQdrantDashboard(cwd);\n }\n }\n\n installer.printNextSteps(cwd);\n } finally {\n rl.close();\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,eAA0B;AAC1B,SAAoB;AACpB,WAAsB;AACtB,2BAA0B;AAC1B,oBAAyC;AACzC,oBAA4B;AAC5B,sBAAoC;AACpC,gBAA2B;AAC3B,qBAA+B;AAC/B,2BAAoC;AACpC,uBAAuC;AACvC,8BAAoD;AAEpD,qBAAmC;AAGnC,eAAsB,aAAa,SAAwB,QAAuB;AAChF,iCAAY;AAEZ,QAAM,KAAK,SAAS,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAEpF,MAAI;AACF,UAAM,MAAM,QAAQ,IAAI;AACxB,UAAM,gBAAY,mCAAmB,MAAM;AAE3C,YAAQ,IAAI,gBAAgB,GAAG;AAAA,CAAI;AAEnC,UAAM,UAAU,UAAM,0BAAU,IAAI,yBAAyB,UAAU,KAAK,KAAK,2EAA2E;AAC5J,QAAI,CAAC,SAAS;AAAE,cAAQ,IAAI,cAAc;AAAG,SAAG,MAAM;AAAG;AAAA,IAAQ;AACjE,YAAQ,IAAI;AAEZ,cAAU,aAAa,GAAG;AAE1B,UAAM,qBAAqB,GAAG,WAAW,KAAK,KAAK,KAAK,YAAY,CAAC;AACrE,QAAI,cAAmC;AACvC,QAAI,wBAAmE;AACvE,QAAI,eAAe;AACnB,QAAI,aAAa;AACjB,QAAI,mBAAmB;AACvB,QAAI,qBAAqB;AACzB,QAAI,kBAAkB;AAEtB,QAAI;AACF,UAAI,oBAAoB;AACtB,cAAM,SAAS,UAAM,0BAAW,GAAG;AACnC,sBAAc,OAAO,eAAe;AACpC,gCAAwB,OAAO,yBAAyB;AACxD,uBAAe,OAAO,gBAAgB;AACtC,qBAAa,OAAO,cAAc;AAClC,gBAAQ,IAAI,+CAA0C,GAAG,cAAc;AACvE,gBAAQ,IAAI,4BAAuB,OAAO,cAAc,EAAE;AAC1D,gBAAQ,IAAI,8BAAyB,OAAO,gBAAgB,EAAE;AAC9D,gBAAQ,IAAI,gCAA2B,OAAO,kBAAkB,EAAE;AAClE,gBAAQ,IAAI,yBAAoB,WAAW,EAAE;AAC7C,gBAAQ,IAAI,mCAA8B,qBAAqB,EAAE;AACjE,gBAAQ,IAAI,0BAAqB,YAAY,EAAE;AAC/C,gBAAQ,IAAI,wBAAmB,UAAU,EAAE;AAAA,MAC7C,OAAO;AACL,2BAAmB;AACnB,cAAM,QAAQ,UAAM,0CAAoB,EAAE;AAC1C,kBAAM,4BAAa,KAAK,KAAK;AAC7B,sBAAc,MAAM,eAAe;AACnC,gCAAwB,MAAM,yBAAyB;AACvD,uBAAe,MAAM,gBAAgB;AACrC,qBAAa,MAAM,cAAc;AACjC,6BAAqB,MAAM;AAC3B,0BAAkB,MAAM;AAExB,gBAAQ,IAAI;AAAA,2BAA8B,GAAG,yBAAyB;AACtE,gBAAQ,IAAI,8BAAyB,MAAM,gBAAgB,EAAE;AAC7D,YAAI,oBAAoB,OAAO;AAC7B,kBAAQ,IAAI,4BAAuB,MAAM,cAAc,KAAK,aAAG,IAAI,MAAM,YAAY,QAAQ,eAAK,EAAE;AAAA,QACtG;AACA,YAAI,MAAM,kBAAkB;AAC1B,kBAAQ,IAAI,4BAAuB,MAAM,cAAc,EAAE;AACzD,cAAI,MAAM,mBAAmB,cAAc;AACzC,oBAAQ,IAAI;AAAA,wCAA2C;AACvD,kBAAM,aAAS,gCAAU,OAAO,CAAC,WAAW,kBAAkB,YAAY,GAAG,EAAE,OAAO,WAAW,OAAO,KAAK,CAAC;AAC9G,gBAAI,OAAO,WAAW,GAAG;AACvB,sBAAQ,IAAI,kDAA6C;AAAA,YAC3D,OAAO;AACL,sBAAQ,KAAK,qCAAgC,OAAO,MAAM,kBAAkB;AAC5E,sBAAQ,KAAK,2CAA2C;AAAA,YAC1D;AAAA,UACF,WAAW,MAAM,mBAAmB,SAAS;AAC3C,oBAAQ,IAAI;AAAA,mCAAsC;AAClD,kBAAM,aAAS,gCAAU,OAAO,CAAC,WAAW,gBAAgB,gCAAgC,GAAG,EAAE,OAAO,WAAW,OAAO,KAAK,CAAC;AAChI,gBAAI,OAAO,WAAW,GAAG;AACvB,sBAAQ,IAAI,oEAA+D;AAAA,YAC7E,OAAO;AACL,sBAAQ,KAAK,qCAAgC,OAAO,MAAM,kBAAkB;AAC5E,sBAAQ,KAAK,6DAA6D;AAAA,YAC5E;AAAA,UACF,WAAW,MAAM,mBAAmB,UAAU;AAC5C,oBAAQ,IAAI;AAAA,oCAAuC;AACnD,kBAAM,aAAS,gCAAU,OAAO,CAAC,WAAW,sBAAsB,GAAG,EAAE,OAAO,WAAW,OAAO,KAAK,CAAC;AACtG,gBAAI,OAAO,WAAW,GAAG;AACvB,sBAAQ,IAAI,yCAAoC;AAAA,YAClD,OAAO;AACL,sBAAQ,KAAK,qCAAgC,OAAO,MAAM,kBAAkB;AAC5E,sBAAQ,KAAK,sCAAsC;AAAA,YACrD;AAAA,UACF,WAAW,MAAM,mBAAmB,WAAW;AAC7C,oBAAQ,IAAI;AAAA,qCAAwC;AACpD,kBAAM,aAAS,gCAAU,OAAO,CAAC,WAAW,kBAAkB,GAAG,EAAE,OAAO,WAAW,OAAO,KAAK,CAAC;AAClG,gBAAI,OAAO,WAAW,GAAG;AACvB,sBAAQ,IAAI,qCAAgC;AAAA,YAC9C,OAAO;AACL,sBAAQ,KAAK,qCAAgC,OAAO,MAAM,kBAAkB;AAC5E,sBAAQ,KAAK,kCAAkC;AAAA,YACjD;AAAA,UACF,WAAW,MAAM,mBAAmB,UAAU;AAC5C,oBAAQ,IAAI;AAAA,oCAAuC;AACnD,kBAAM,aAAS,gCAAU,OAAO,CAAC,WAAW,cAAc,GAAG,EAAE,OAAO,WAAW,OAAO,KAAK,CAAC;AAC9F,gBAAI,OAAO,WAAW,GAAG;AACvB,sBAAQ,IAAI,iCAA4B;AAAA,YAC1C,OAAO;AACL,sBAAQ,KAAK,qCAAgC,OAAO,MAAM,kBAAkB;AAC5E,sBAAQ,KAAK,8BAA8B;AAAA,YAC7C;AAAA,UACF,WAAW,MAAM,mBAAmB,aAAa;AAC/C,oBAAQ,IAAI;AAAA,uCAA0C;AACtD,kBAAM,aAAS,gCAAU,OAAO,CAAC,WAAW,WAAW,GAAG,EAAE,OAAO,WAAW,OAAO,KAAK,CAAC;AAC3F,gBAAI,OAAO,WAAW,GAAG;AACvB,sBAAQ,IAAI,8BAAyB;AACrC,sBAAQ,IAAI,oFAA+E;AAAA,YAC7F,OAAO;AACL,sBAAQ,KAAK,qCAAgC,OAAO,MAAM,kBAAkB;AAC5E,sBAAQ,KAAK,2BAA2B;AAAA,YAC1C;AAAA,UACF;AAAA,QACF;AACA,gBAAQ,IAAI,+BAA0B,MAAM,iBAAiB,EAAE;AAC/D,gBAAQ,IAAI,4BAAuB,MAAM,cAAc,EAAE;AACzD,gBAAQ,IAAI,gCAA2B,MAAM,kBAAkB,EAAE;AACjE,gBAAQ,IAAI,yBAAoB,WAAW,EAAE;AAC7C,gBAAQ,IAAI,mCAA8B,qBAAqB,EAAE;AACjE,gBAAQ,IAAI,0BAAqB,YAAY,EAAE;AAC/C,gBAAQ,IAAI,wBAAmB,UAAU,EAAE;AAAA,MAC7C;AAEA,gBAAU,YAAY,KAAK,aAAa,uBAAuB,cAAc,UAAU;AAAA,IACzF,SAAS,KAAK;AACZ,YAAM,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC9D,cAAQ,MAAM;AAAA,0CAAwC,MAAM,EAAE;AAC9D,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,QAAI,iBAAiB;AACnB,gBAAM,wCAAe,GAAG;AAAA,IAC1B;AAGA,QAAI,oBAAoB,UAAM,0BAAU,IAAI,0CAA0C,kHAAkH,GAAG;AACzM,YAAM,aAAa,MAAM,QAAQ,QAAQ,EAAE,KAAK,MAAM,QAAQ,gBAAgB,CAAC,GAAG;AAElF,YAAM,YAAY,oBAAI,IAA+C;AACrE,YAAM,gBAAgB,CAAC,MAAc,QAAgB,OAAe,SAAwB;AAC1F,cAAM,QAAQ,UAAU,IAAI,IAAI,KAAK,EAAE,QAAQ,GAAG,OAAO,EAAE;AAC3D,YAAI,QAAQ,EAAG,OAAM,QAAQ;AAC7B,cAAM,SAAS,OAAO,MAAM,QAAQ;AACpC,kBAAU,IAAI,MAAM,KAAK;AAGzB,cAAM,aAAa,MAAM,KAAK,UAAU,OAAO,CAAC,EAAE,OAAO,OAAK,EAAE,QAAQ,CAAC;AACzE,cAAM,cAAc,WAAW,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC;AAC/D,cAAM,aAAa,WAAW,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,CAAC;AAC7D,cAAM,MAAM,aAAa,IAAI,KAAK,IAAK,cAAc,aAAc,KAAK,GAAG,IAAI;AAE/E,cAAM,SAAS,KAAK,MAAM,MAAM,CAAC;AACjC,cAAM,MAAM,SAAI,OAAO,MAAM,IAAI,SAAI,OAAO,KAAK,MAAM;AACvD,cAAM,MAAM,cAAc,OAAO,MAAM,QAAQ,CAAC;AAChD,cAAM,WAAW,aAAa,OAAO,MAAM,QAAQ,CAAC;AACpD,gBAAQ,OAAO,MAAM,QAAQ,GAAG,KAAK,IAAI,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC,MAAM,EAAE,MAAM,OAAO,QAAQ;AAAA,MAC9F;AAGA,YAAM,sBAAsB,QAAQ,OAAO,MAAM,KAAK,QAAQ,MAAM;AACpE,YAAM,eAAe,CAAC,UAAmB,SAA6B;AACpE,cAAM,MAAM,OAAO,UAAU,WAAW,QAAQ,OAAO,KAAK;AAC5D,YAAI,IAAI,SAAS,gBAAgB,KAAK,IAAI,SAAS,qBAAqB,EAAG,QAAO;AAClF,eAAQ,oBAAqD,OAAO,GAAG,IAAI;AAAA,MAC7E;AACA,cAAQ,OAAO,QAAQ;AAEvB,UAAI;AACJ,UAAI;AACF,YAAI,CAAC,UAAU,cAAc,GAAG,GAAG;AACjC,kBAAQ,OAAO,MAAM,uCAAkC;AACvD,eAAK,MAAM,UAAU,KAAK,KAAK,QAAW,aAAa;AACvD,kBAAQ,OAAO,MAAM,IAAI;AACzB,kBAAQ,IAAI,8BAAyB;AAAA,QACvC,OAAO;AACL,eAAK,MAAM,UAAU,KAAK,KAAK,aAAa;AAC5C,cAAI,UAAU,OAAO,EAAG,SAAQ,OAAO,MAAM,IAAI;AAAA,QACnD;AAAA,MACF,UAAE;AACA,gBAAQ,OAAO,QAAQ;AAAA,MACzB;AACA,cAAQ,IAAI,eAAe;AAC3B,YAAM,SAAS,MAAM,GAAG,SAAS,EAAE,YAAY,oCAAoB,CAAC;AACpE,cAAQ,OAAO,MAAM,IAAI;AACzB,cAAQ,IAAI,oBAAe,OAAO,YAAY,WAAW,OAAO,YAAY,aAAa,OAAO,YAAY,QAAQ;AACpH,SAAG,MAAM;AAET,UAAI,oBAAoB;AACtB,cAAM,kBAAkB,UAAM,yCAAuB,GAAG;AACxD,gBAAQ,IAAI,KAAK,aAAG,uDAAuD,eAAK,EAAE;AAClF,cAAM,IAAI,QAAc,aAAW;AACjC,kBAAQ,GAAG,UAAU,MAAM;AACzB,gBAAI,iBAAiB;AACnB,8BAAgB,MAAM,MAAM,QAAQ,CAAC;AAAA,YACvC,OAAO;AACL,sBAAQ;AAAA,YACV;AAAA,UACF,CAAC;AAAA,QACH,CAAC;AACD;AAAA,MACF;AAEA,UAAI,iBAAiB;AACnB,kBAAM,6CAAoB,GAAG;AAAA,MAC/B;AAAA,IACF;AAEA,cAAU,eAAe,GAAG;AAAA,EAC9B,UAAE;AACA,OAAG,MAAM;AAAA,EACX;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -361,6 +361,27 @@ at session end.
|
|
|
361
361
|
`;
|
|
362
362
|
content = content.trimEnd() + "\n\n" + memorySection.trim() + "\n";
|
|
363
363
|
}
|
|
364
|
+
if (opts?.enableDocs) {
|
|
365
|
+
const docsSection = `
|
|
366
|
+
## Documentation
|
|
367
|
+
|
|
368
|
+
KiroGraph indexes project documentation by heading structure. Use \`kirograph_docs_search\`
|
|
369
|
+
to find relevant doc sections instead of reading entire files. Use \`kirograph_docs_section\`
|
|
370
|
+
to retrieve the exact section you need by ID.
|
|
371
|
+
|
|
372
|
+
**Available tools:**
|
|
373
|
+
- \`kirograph_docs_toc\` \u2014 table of contents for a file or the whole project
|
|
374
|
+
- \`kirograph_docs_search\` \u2014 search sections by query (independent from code search)
|
|
375
|
+
- \`kirograph_docs_section\` \u2014 retrieve full content of a section by ID
|
|
376
|
+
- \`kirograph_docs_outline\` \u2014 heading hierarchy for a single document
|
|
377
|
+
- \`kirograph_docs_refs\` \u2014 find code symbols referenced by a doc section (or vice versa)
|
|
378
|
+
|
|
379
|
+
**When to use:** Before reading a documentation file directly, check if \`kirograph_docs_search\`
|
|
380
|
+
or \`kirograph_docs_outline\` can give you the specific section you need. This saves tokens
|
|
381
|
+
and gives you structured navigation instead of raw file content.
|
|
382
|
+
`;
|
|
383
|
+
content = content.trimEnd() + "\n\n" + docsSection.trim() + "\n";
|
|
384
|
+
}
|
|
364
385
|
return content;
|
|
365
386
|
}
|
|
366
387
|
function writeSteering(kiroDir, opts) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/bin/installer/steering.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * KiroGraph Installer: Kiro steering file\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { CAVEMAN_RULES, CavemanMode } from './caveman';\n\nconst STEERING_CONTENT = `---\ninclusion: always\n---\n\n# KiroGraph\n\nKiroGraph builds a semantic knowledge graph of your codebase. Use its MCP tools instead of grep/glob/file reads whenever \\`.kirograph/\\` exists in the project.\n\n## Quick decision guide\n\n| Question | Tool |\n|----------|------|\n| Where do I start on this task? | \\`kirograph_context\\` |\n| What is this symbol / show me its code | \\`kirograph_node\\` with \\`includeCode: true\\` |\n| Find a symbol by name | \\`kirograph_search\\` |\n| Who calls function X? | \\`kirograph_callers\\` |\n| What does function X call? | \\`kirograph_callees\\` |\n| What breaks if I change X? | \\`kirograph_impact\\` |\n| How are X and Y connected? | \\`kirograph_path\\` |\n| What extends / implements this type? | \\`kirograph_type_hierarchy\\` |\n| Which code is never called? | \\`kirograph_dead_code\\` |\n| Are there import cycles? | \\`kirograph_circular_deps\\` |\n| What files are indexed? | \\`kirograph_files\\` |\n| Is the index healthy? | \\`kirograph_status\\` |\n| What are the most critical symbols? | \\`kirograph_hotspots\\` |\n| Any unexpected cross-module coupling? | \\`kirograph_surprising\\` |\n| What changed since the last snapshot? | \\`kirograph_diff\\` |\n| What packages/layers exist? | \\`kirograph_architecture\\` |\n| How coupled is package X? | \\`kirograph_coupling\\` |\n| What does package X depend on? | \\`kirograph_package\\` |\n| Run a command with token savings | \\`kirograph_exec\\` |\n| Check token savings stats | \\`kirograph_gain\\` |\n\n---\n\n## Tool reference\n\n### \\`kirograph_context\\`: **start here for any code task**\n\nReturns entry points, related symbols, and code snippets for a natural-language task description. Usually enough to orient without any additional tool calls.\n\n\\`\\`\\`\nkirograph_context(task: \"fix the auth token expiry bug\")\nkirograph_context(task: \"add dark mode\", maxNodes: 30)\nkirograph_context(task: \"refactor payment service\", includeCode: false)\n\\`\\`\\`\n\n### \\`kirograph_search\\`: find symbols by name\n\nExact match \u2192 FTS \u2192 LIKE fallback \u2192 vector (last resort). Use instead of grep.\n\n\\`\\`\\`\nkirograph_search(query: \"signIn\")\nkirograph_search(query: \"UserService\", kind: \"class\")\nkirograph_search(query: \"auth\", limit: 20)\n\\`\\`\\`\n\nSupported kinds: \\`function\\`, \\`method\\`, \\`class\\`, \\`interface\\`, \\`type_alias\\`, \\`variable\\`, \\`route\\`, \\`component\\`\n\n### \\`kirograph_node\\`: inspect a symbol\n\nReturns kind, file, signature, docstring. Add \\`includeCode: true\\` to get the full source.\n\n\\`\\`\\`\nkirograph_node(symbol: \"validateToken\")\nkirograph_node(symbol: \"AuthService\", includeCode: true)\n\\`\\`\\`\n\n### \\`kirograph_callers\\`: who calls this?\n\nBFS over incoming \\`calls\\` edges (depth 1).\n\n\\`\\`\\`\nkirograph_callers(symbol: \"processPayment\", limit: 30)\n\\`\\`\\`\n\n### \\`kirograph_callees\\`: what does this call?\n\nBFS over outgoing \\`calls\\` edges (depth 1).\n\n\\`\\`\\`\nkirograph_callees(symbol: \"handleRequest\")\n\\`\\`\\`\n\n### \\`kirograph_impact\\`: blast radius before a change\n\nTraverses all incoming edges up to \\`depth\\` hops. Call this before editing a symbol.\n\n\\`\\`\\`\nkirograph_impact(symbol: \"UserRepository\", depth: 3)\n\\`\\`\\`\n\n### \\`kirograph_path\\`: how are two symbols connected?\n\nBFS shortest path across all edge types.\n\n\\`\\`\\`\nkirograph_path(from: \"LoginController\", to: \"DatabasePool\")\n\\`\\`\\`\n\n### \\`kirograph_type_hierarchy\\`: class/interface inheritance\n\n\\`\\`\\`\nkirograph_type_hierarchy(symbol: \"BaseRepository\", direction: \"down\") // derived types\nkirograph_type_hierarchy(symbol: \"PaymentService\", direction: \"up\") // base types\nkirograph_type_hierarchy(symbol: \"IUserStore\", direction: \"both\") // all\n\\`\\`\\`\n\n### \\`kirograph_dead_code\\`: unreferenced symbols\n\nReturns unexported symbols with zero incoming edges. Good first step when cleaning up.\n\n\\`\\`\\`\nkirograph_dead_code(limit: 50)\n\\`\\`\\`\n\n### \\`kirograph_circular_deps\\`: import cycles\n\nRuns Tarjan's SCC over import edges. No parameters needed.\n\n\\`\\`\\`\nkirograph_circular_deps()\n\\`\\`\\`\n\n### \\`kirograph_files\\`: indexed file structure\n\n\\`\\`\\`\nkirograph_files(format: \"tree\") // default\nkirograph_files(format: \"flat\") // one path per line\nkirograph_files(format: \"grouped\") // by directory\nkirograph_files(filterPath: \"src/auth\", maxDepth: 2)\nkirograph_files(pattern: \"**/*.test.ts\")\n\\`\\`\\`\n\n### \\`kirograph_status\\`: index health\n\nReturns file count, symbol count, edge count, embedding coverage, DB size. Call when something feels off.\n\n### \\`kirograph_hotspots\\`: most-connected symbols\n\nReturns the top-N symbols by total edge degree (in + out, excluding structural \\`contains\\` edges). Use to find core abstractions, identify high blast-radius symbols before a refactor, or understand what the codebase revolves around.\n\n\\`\\`\\`\nkirograph_hotspots(limit: 20)\n\\`\\`\\`\n\n### \\`kirograph_surprising\\`: unexpected cross-module coupling\n\nFinds direct edges between symbols in structurally distant files, scored by path distance \u00D7 edge-kind weight. Use before a refactor to discover hidden dependencies that will break. High score = more unexpected.\n\n\\`\\`\\`\nkirograph_surprising(limit: 20)\n\\`\\`\\`\n\n### \\`kirograph_diff\\`: what changed since a snapshot?\n\nCompares the current graph against a saved snapshot. Shows added/removed symbols and edges. A snapshot must exist: the user saves one with \\`kirograph snapshot save <label>\\` before making changes.\n\n\\`\\`\\`\nkirograph_diff() // vs latest snapshot\nkirograph_diff(snapshot: \"pre-refactor\") // vs named snapshot\n\\`\\`\\`\n\n---\n\n## Architecture tools *(require \\`enableArchitecture: true\\` in config)*\n\n### \\`kirograph_architecture\\`: **start here for architectural questions**\n\nReturns the full package graph, detected layers (api/service/data/ui/shared), and their dependency edges.\n\n\\`\\`\\`\nkirograph_architecture() // packages + layers\nkirograph_architecture(level: \"packages\")\nkirograph_architecture(level: \"layers\")\nkirograph_architecture(includeFiles: true) // add file\u2192package assignments\n\\`\\`\\`\n\n### \\`kirograph_coupling\\`: stability metrics per package\n\nReturns Ca (afferent: depended on by), Ce (efferent: depends on), and instability (Ce/(Ca+Ce)).\n- High Ca + low instability = load-bearing, safe to depend on, risky to change interface.\n- High Ce + high instability = depends on many things, safe to refactor internals.\n\n\\`\\`\\`\nkirograph_coupling() // all packages, sorted by instability\nkirograph_coupling(sortBy: \"afferent\") // most depended-on first\nkirograph_coupling(sortBy: \"efferent\") // most outgoing deps first\n\\`\\`\\`\n\n### \\`kirograph_package\\`: drill into one package\n\nReturns metadata, coupling metrics, outgoing deps, incoming dependents, and file list.\n\n\\`\\`\\`\nkirograph_package(package: \"auth\")\nkirograph_package(package: \"src/services\", includeFiles: false)\n\\`\\`\\`\n\n---\n\n## Workflows\n\n**Bug fix or feature:**\n1. \\`kirograph_context\\`: orient, find entry points.\n2. \\`kirograph_node\\` with \\`includeCode: true\\`: read the relevant symbol.\n3. \\`kirograph_callers\\` / \\`kirograph_callees\\`: trace the call flow.\n4. \\`kirograph_impact\\`: check blast radius before editing.\n\n**Refactor planning:**\n1. \\`kirograph_hotspots\\`: identify the most-connected symbols; changing these is risky.\n2. \\`kirograph_surprising\\`: surface hidden coupling that will break.\n3. \\`kirograph_impact\\` on specific targets: confirm blast radius.\n4. \\`kirograph_diff\\` after the refactor: verify the structural change matches intent.\n\n**Architectural review:**\n1. \\`kirograph_architecture\\`: get the package and layer map.\n2. \\`kirograph_coupling\\`: find the most stable (high Ca) and most volatile (high instability) packages.\n3. \\`kirograph_package\\`: drill into any package of interest.\n4. \\`kirograph_circular_deps\\`: check for import cycles.\n\n**Code cleanup:**\n1. \\`kirograph_dead_code\\`: find unreferenced unexported symbols.\n2. \\`kirograph_circular_deps\\`: find import cycles to untangle.\n3. \\`kirograph_surprising\\`: find unexpected coupling to decouple.\n\n---\n\n## If \\`.kirograph/\\` does NOT exist\n\nAsk the user: \"This project doesn't have KiroGraph initialized. Run \\`kirograph init -i\\` to build a code knowledge graph for faster exploration?\"\n`;\n\n// \u2500\u2500 Compression section builder (level-aware) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nconst LEVEL_DESCRIPTIONS: Record<string, string> = {\n normal: 'Balanced: removes noise, keeps structure.',\n aggressive: 'Compact: groups by category, limits output.',\n ultra: 'Maximum compression: counts and summaries only.',\n};\n\nconst LEVEL_EXAMPLES: Record<string, string> = {\n normal: `\\\\\\`\\\\\\`\\\\\\`\nkirograph_exec(command: \"git status\")\nkirograph_exec(command: \"npm test\")\nkirograph_exec(command: \"cargo build\")\nkirograph_exec(command: \"ls -la src/\")\n\\\\\\`\\\\\\`\\\\\\``,\n aggressive: `\\\\\\`\\\\\\`\\\\\\`\nkirograph_exec(command: \"git status\", level: \"aggressive\")\nkirograph_exec(command: \"npm test\", level: \"aggressive\")\nkirograph_exec(command: \"eslint .\", level: \"aggressive\")\nkirograph_exec(command: \"find . -name '*.ts'\", level: \"aggressive\")\n\\\\\\`\\\\\\`\\\\\\``,\n ultra: `\\\\\\`\\\\\\`\\\\\\`\nkirograph_exec(command: \"git status\", level: \"ultra\")\nkirograph_exec(command: \"npm test\", level: \"ultra\")\nkirograph_exec(command: \"docker ps\", level: \"ultra\")\nkirograph_exec(command: \"ls -la src/\", level: \"ultra\")\n\\\\\\`\\\\\\`\\\\\\``,\n};\n\nfunction buildCompressionSection(level: 'normal' | 'aggressive' | 'ultra'): string {\n return `\n---\n\n## Shell Compression (\\\\\\`kirograph_exec\\\\\\`)\n\nWhen running shell commands, prefer \\\\\\`kirograph_exec\\\\\\` over raw shell execution for:\n- **git** operations (status, log, diff, push, pull, commit, add, fetch, branch)\n- **GitHub CLI** (gh pr list/view, gh issue list, gh run list)\n- **test runners** (jest, vitest, pytest, cargo test, go test, rspec, minitest, playwright)\n- **linters/build** (eslint, tsc, ruff, clippy, cargo build, prettier, biome, golangci-lint, rubocop, next build)\n- **file listings** (ls, find, tree)\n- **search** (grep, rg/ripgrep: grouped by file)\n- **diff** (diff file1 file2: condensed context)\n- **docker/k8s** (docker ps, images, logs, compose ps, kubectl pods, logs, services)\n- **package managers** (npm/pnpm install/list, pip list/install, bundle install, prisma generate)\n- **AWS CLI** (sts, ec2, lambda, logs, cloudformation, dynamodb, iam, s3, ecs, sqs, sns)\n- **network** (curl, wget: strip progress bars and headers)\n\nThis saves 60-90% of tokens compared to raw output.\n\nCompression level: **${level}**: ${LEVEL_DESCRIPTIONS[level]}\n\n${LEVEL_EXAMPLES[level]}\n\n**Important:** Error details are always preserved. Failed commands show full diagnostic output regardless of level.\n\n**Do NOT re-run commands:** When \\\\\\`kirograph_exec\\\\\\` returns a result, treat it as the final answer. Never re-run the same command with raw shell execution to \"get more details.\" The compressed output preserves all essential information. If you genuinely need something missing from the output, explain what's missing before making a second call.\n\nUse \\\\\\`kirograph_gain\\\\\\` to check token savings statistics.`;\n}\n\nexport interface SteeringOptions {\n cavemanMode?: CavemanMode | 'off';\n enableCompression?: boolean;\n shellCompressionLevel?: 'off' | 'normal' | 'aggressive' | 'ultra';\n enableMemory?: boolean;\n}\n\nfunction buildSteeringContent(opts?: SteeringOptions): string {\n const cavemanMode = opts?.cavemanMode;\n const enableCompression = opts?.enableCompression !== false && opts?.shellCompressionLevel !== 'off';\n const shellCompressionLevel = opts?.shellCompressionLevel ?? 'normal';\n\n let content = STEERING_CONTENT;\n\n // Insert compression section before the \"If .kirograph/ does NOT exist\" section\n if (enableCompression && shellCompressionLevel !== 'off') {\n const section = buildCompressionSection(shellCompressionLevel as 'normal' | 'aggressive' | 'ultra');\n content = content.replace(\n '---\\n\\n## If `.kirograph/` does NOT exist',\n section.trim() + '\\n\\n---\\n\\n## If `.kirograph/` does NOT exist',\n );\n }\n\n // Remove compression tools from decision guide if disabled\n if (!enableCompression) {\n content = content.replace('| Run a command with token savings | `kirograph_exec` |\\n', '');\n content = content.replace('| Check token savings stats | `kirograph_gain` |\\n', '');\n }\n\n const caveman = cavemanMode && cavemanMode !== 'off' ? CAVEMAN_RULES[cavemanMode] : null;\n if (caveman) {\n content = content.trimEnd() + '\\n\\n' + caveman + '\\n';\n }\n\n // Memory section\n if (opts?.enableMemory) {\n const memorySection = `\n## Memory\n\nKiroGraph has persistent memory. Use \\`kirograph_mem_search\\` to recall past decisions,\nerrors, and patterns before making changes. Use \\`kirograph_mem_store\\` to save important\nobservations (architecture decisions, bug root causes, patterns discovered).\n\nMemory is searchable via hybrid FTS + vector search. Observations are automatically\nlinked to code symbols in the graph and surface in \\`kirograph_context\\` and\n\\`kirograph_impact\\` results when relevant.\n\n**When to store:** After fixing a bug, making an architecture decision, discovering a pattern,\nencountering a non-obvious error, or learning something about the codebase that future sessions\nshould know. Keep observations concise \u2014 one fact per store call. A hook will also remind you\nat session end.\n`;\n content = content.trimEnd() + '\\n\\n' + memorySection.trim() + '\\n';\n }\n\n return content;\n}\n\nexport function writeSteering(kiroDir: string, opts?: SteeringOptions | CavemanMode | 'off'): void {\n const steeringDir = path.join(kiroDir, 'steering');\n fs.mkdirSync(steeringDir, { recursive: true });\n const steeringPath = path.join(steeringDir, 'kirograph.md');\n\n // Support both old signature (cavemanMode string) and new signature (options object)\n const resolvedOpts: SteeringOptions = typeof opts === 'string'\n ? { cavemanMode: opts }\n : opts ?? {};\n\n fs.writeFileSync(steeringPath, buildSteeringContent(resolvedOpts));\n console.log(` \u2713 Steering file written to ${steeringPath}`);\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,SAAoB;AACpB,WAAsB;AACtB,qBAA2C;AAE3C,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2OzB,MAAM,qBAA6C;AAAA,EACjD,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,OAAO;AACT;AAEA,MAAM,iBAAyC;AAAA,EAC7C,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMR,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMZ,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAMT;AAEA,SAAS,wBAAwB,OAAkD;AACjF,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAoBc,KAAK,OAAO,mBAAmB,KAAK,CAAC;AAAA;AAAA,EAE1D,eAAe,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOvB;
|
|
4
|
+
"sourcesContent": ["/**\n * KiroGraph Installer: Kiro steering file\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { CAVEMAN_RULES, CavemanMode } from './caveman';\n\nconst STEERING_CONTENT = `---\ninclusion: always\n---\n\n# KiroGraph\n\nKiroGraph builds a semantic knowledge graph of your codebase. Use its MCP tools instead of grep/glob/file reads whenever \\`.kirograph/\\` exists in the project.\n\n## Quick decision guide\n\n| Question | Tool |\n|----------|------|\n| Where do I start on this task? | \\`kirograph_context\\` |\n| What is this symbol / show me its code | \\`kirograph_node\\` with \\`includeCode: true\\` |\n| Find a symbol by name | \\`kirograph_search\\` |\n| Who calls function X? | \\`kirograph_callers\\` |\n| What does function X call? | \\`kirograph_callees\\` |\n| What breaks if I change X? | \\`kirograph_impact\\` |\n| How are X and Y connected? | \\`kirograph_path\\` |\n| What extends / implements this type? | \\`kirograph_type_hierarchy\\` |\n| Which code is never called? | \\`kirograph_dead_code\\` |\n| Are there import cycles? | \\`kirograph_circular_deps\\` |\n| What files are indexed? | \\`kirograph_files\\` |\n| Is the index healthy? | \\`kirograph_status\\` |\n| What are the most critical symbols? | \\`kirograph_hotspots\\` |\n| Any unexpected cross-module coupling? | \\`kirograph_surprising\\` |\n| What changed since the last snapshot? | \\`kirograph_diff\\` |\n| What packages/layers exist? | \\`kirograph_architecture\\` |\n| How coupled is package X? | \\`kirograph_coupling\\` |\n| What does package X depend on? | \\`kirograph_package\\` |\n| Run a command with token savings | \\`kirograph_exec\\` |\n| Check token savings stats | \\`kirograph_gain\\` |\n\n---\n\n## Tool reference\n\n### \\`kirograph_context\\`: **start here for any code task**\n\nReturns entry points, related symbols, and code snippets for a natural-language task description. Usually enough to orient without any additional tool calls.\n\n\\`\\`\\`\nkirograph_context(task: \"fix the auth token expiry bug\")\nkirograph_context(task: \"add dark mode\", maxNodes: 30)\nkirograph_context(task: \"refactor payment service\", includeCode: false)\n\\`\\`\\`\n\n### \\`kirograph_search\\`: find symbols by name\n\nExact match \u2192 FTS \u2192 LIKE fallback \u2192 vector (last resort). Use instead of grep.\n\n\\`\\`\\`\nkirograph_search(query: \"signIn\")\nkirograph_search(query: \"UserService\", kind: \"class\")\nkirograph_search(query: \"auth\", limit: 20)\n\\`\\`\\`\n\nSupported kinds: \\`function\\`, \\`method\\`, \\`class\\`, \\`interface\\`, \\`type_alias\\`, \\`variable\\`, \\`route\\`, \\`component\\`\n\n### \\`kirograph_node\\`: inspect a symbol\n\nReturns kind, file, signature, docstring. Add \\`includeCode: true\\` to get the full source.\n\n\\`\\`\\`\nkirograph_node(symbol: \"validateToken\")\nkirograph_node(symbol: \"AuthService\", includeCode: true)\n\\`\\`\\`\n\n### \\`kirograph_callers\\`: who calls this?\n\nBFS over incoming \\`calls\\` edges (depth 1).\n\n\\`\\`\\`\nkirograph_callers(symbol: \"processPayment\", limit: 30)\n\\`\\`\\`\n\n### \\`kirograph_callees\\`: what does this call?\n\nBFS over outgoing \\`calls\\` edges (depth 1).\n\n\\`\\`\\`\nkirograph_callees(symbol: \"handleRequest\")\n\\`\\`\\`\n\n### \\`kirograph_impact\\`: blast radius before a change\n\nTraverses all incoming edges up to \\`depth\\` hops. Call this before editing a symbol.\n\n\\`\\`\\`\nkirograph_impact(symbol: \"UserRepository\", depth: 3)\n\\`\\`\\`\n\n### \\`kirograph_path\\`: how are two symbols connected?\n\nBFS shortest path across all edge types.\n\n\\`\\`\\`\nkirograph_path(from: \"LoginController\", to: \"DatabasePool\")\n\\`\\`\\`\n\n### \\`kirograph_type_hierarchy\\`: class/interface inheritance\n\n\\`\\`\\`\nkirograph_type_hierarchy(symbol: \"BaseRepository\", direction: \"down\") // derived types\nkirograph_type_hierarchy(symbol: \"PaymentService\", direction: \"up\") // base types\nkirograph_type_hierarchy(symbol: \"IUserStore\", direction: \"both\") // all\n\\`\\`\\`\n\n### \\`kirograph_dead_code\\`: unreferenced symbols\n\nReturns unexported symbols with zero incoming edges. Good first step when cleaning up.\n\n\\`\\`\\`\nkirograph_dead_code(limit: 50)\n\\`\\`\\`\n\n### \\`kirograph_circular_deps\\`: import cycles\n\nRuns Tarjan's SCC over import edges. No parameters needed.\n\n\\`\\`\\`\nkirograph_circular_deps()\n\\`\\`\\`\n\n### \\`kirograph_files\\`: indexed file structure\n\n\\`\\`\\`\nkirograph_files(format: \"tree\") // default\nkirograph_files(format: \"flat\") // one path per line\nkirograph_files(format: \"grouped\") // by directory\nkirograph_files(filterPath: \"src/auth\", maxDepth: 2)\nkirograph_files(pattern: \"**/*.test.ts\")\n\\`\\`\\`\n\n### \\`kirograph_status\\`: index health\n\nReturns file count, symbol count, edge count, embedding coverage, DB size. Call when something feels off.\n\n### \\`kirograph_hotspots\\`: most-connected symbols\n\nReturns the top-N symbols by total edge degree (in + out, excluding structural \\`contains\\` edges). Use to find core abstractions, identify high blast-radius symbols before a refactor, or understand what the codebase revolves around.\n\n\\`\\`\\`\nkirograph_hotspots(limit: 20)\n\\`\\`\\`\n\n### \\`kirograph_surprising\\`: unexpected cross-module coupling\n\nFinds direct edges between symbols in structurally distant files, scored by path distance \u00D7 edge-kind weight. Use before a refactor to discover hidden dependencies that will break. High score = more unexpected.\n\n\\`\\`\\`\nkirograph_surprising(limit: 20)\n\\`\\`\\`\n\n### \\`kirograph_diff\\`: what changed since a snapshot?\n\nCompares the current graph against a saved snapshot. Shows added/removed symbols and edges. A snapshot must exist: the user saves one with \\`kirograph snapshot save <label>\\` before making changes.\n\n\\`\\`\\`\nkirograph_diff() // vs latest snapshot\nkirograph_diff(snapshot: \"pre-refactor\") // vs named snapshot\n\\`\\`\\`\n\n---\n\n## Architecture tools *(require \\`enableArchitecture: true\\` in config)*\n\n### \\`kirograph_architecture\\`: **start here for architectural questions**\n\nReturns the full package graph, detected layers (api/service/data/ui/shared), and their dependency edges.\n\n\\`\\`\\`\nkirograph_architecture() // packages + layers\nkirograph_architecture(level: \"packages\")\nkirograph_architecture(level: \"layers\")\nkirograph_architecture(includeFiles: true) // add file\u2192package assignments\n\\`\\`\\`\n\n### \\`kirograph_coupling\\`: stability metrics per package\n\nReturns Ca (afferent: depended on by), Ce (efferent: depends on), and instability (Ce/(Ca+Ce)).\n- High Ca + low instability = load-bearing, safe to depend on, risky to change interface.\n- High Ce + high instability = depends on many things, safe to refactor internals.\n\n\\`\\`\\`\nkirograph_coupling() // all packages, sorted by instability\nkirograph_coupling(sortBy: \"afferent\") // most depended-on first\nkirograph_coupling(sortBy: \"efferent\") // most outgoing deps first\n\\`\\`\\`\n\n### \\`kirograph_package\\`: drill into one package\n\nReturns metadata, coupling metrics, outgoing deps, incoming dependents, and file list.\n\n\\`\\`\\`\nkirograph_package(package: \"auth\")\nkirograph_package(package: \"src/services\", includeFiles: false)\n\\`\\`\\`\n\n---\n\n## Workflows\n\n**Bug fix or feature:**\n1. \\`kirograph_context\\`: orient, find entry points.\n2. \\`kirograph_node\\` with \\`includeCode: true\\`: read the relevant symbol.\n3. \\`kirograph_callers\\` / \\`kirograph_callees\\`: trace the call flow.\n4. \\`kirograph_impact\\`: check blast radius before editing.\n\n**Refactor planning:**\n1. \\`kirograph_hotspots\\`: identify the most-connected symbols; changing these is risky.\n2. \\`kirograph_surprising\\`: surface hidden coupling that will break.\n3. \\`kirograph_impact\\` on specific targets: confirm blast radius.\n4. \\`kirograph_diff\\` after the refactor: verify the structural change matches intent.\n\n**Architectural review:**\n1. \\`kirograph_architecture\\`: get the package and layer map.\n2. \\`kirograph_coupling\\`: find the most stable (high Ca) and most volatile (high instability) packages.\n3. \\`kirograph_package\\`: drill into any package of interest.\n4. \\`kirograph_circular_deps\\`: check for import cycles.\n\n**Code cleanup:**\n1. \\`kirograph_dead_code\\`: find unreferenced unexported symbols.\n2. \\`kirograph_circular_deps\\`: find import cycles to untangle.\n3. \\`kirograph_surprising\\`: find unexpected coupling to decouple.\n\n---\n\n## If \\`.kirograph/\\` does NOT exist\n\nAsk the user: \"This project doesn't have KiroGraph initialized. Run \\`kirograph init -i\\` to build a code knowledge graph for faster exploration?\"\n`;\n\n// \u2500\u2500 Compression section builder (level-aware) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nconst LEVEL_DESCRIPTIONS: Record<string, string> = {\n normal: 'Balanced: removes noise, keeps structure.',\n aggressive: 'Compact: groups by category, limits output.',\n ultra: 'Maximum compression: counts and summaries only.',\n};\n\nconst LEVEL_EXAMPLES: Record<string, string> = {\n normal: `\\\\\\`\\\\\\`\\\\\\`\nkirograph_exec(command: \"git status\")\nkirograph_exec(command: \"npm test\")\nkirograph_exec(command: \"cargo build\")\nkirograph_exec(command: \"ls -la src/\")\n\\\\\\`\\\\\\`\\\\\\``,\n aggressive: `\\\\\\`\\\\\\`\\\\\\`\nkirograph_exec(command: \"git status\", level: \"aggressive\")\nkirograph_exec(command: \"npm test\", level: \"aggressive\")\nkirograph_exec(command: \"eslint .\", level: \"aggressive\")\nkirograph_exec(command: \"find . -name '*.ts'\", level: \"aggressive\")\n\\\\\\`\\\\\\`\\\\\\``,\n ultra: `\\\\\\`\\\\\\`\\\\\\`\nkirograph_exec(command: \"git status\", level: \"ultra\")\nkirograph_exec(command: \"npm test\", level: \"ultra\")\nkirograph_exec(command: \"docker ps\", level: \"ultra\")\nkirograph_exec(command: \"ls -la src/\", level: \"ultra\")\n\\\\\\`\\\\\\`\\\\\\``,\n};\n\nfunction buildCompressionSection(level: 'normal' | 'aggressive' | 'ultra'): string {\n return `\n---\n\n## Shell Compression (\\\\\\`kirograph_exec\\\\\\`)\n\nWhen running shell commands, prefer \\\\\\`kirograph_exec\\\\\\` over raw shell execution for:\n- **git** operations (status, log, diff, push, pull, commit, add, fetch, branch)\n- **GitHub CLI** (gh pr list/view, gh issue list, gh run list)\n- **test runners** (jest, vitest, pytest, cargo test, go test, rspec, minitest, playwright)\n- **linters/build** (eslint, tsc, ruff, clippy, cargo build, prettier, biome, golangci-lint, rubocop, next build)\n- **file listings** (ls, find, tree)\n- **search** (grep, rg/ripgrep: grouped by file)\n- **diff** (diff file1 file2: condensed context)\n- **docker/k8s** (docker ps, images, logs, compose ps, kubectl pods, logs, services)\n- **package managers** (npm/pnpm install/list, pip list/install, bundle install, prisma generate)\n- **AWS CLI** (sts, ec2, lambda, logs, cloudformation, dynamodb, iam, s3, ecs, sqs, sns)\n- **network** (curl, wget: strip progress bars and headers)\n\nThis saves 60-90% of tokens compared to raw output.\n\nCompression level: **${level}**: ${LEVEL_DESCRIPTIONS[level]}\n\n${LEVEL_EXAMPLES[level]}\n\n**Important:** Error details are always preserved. Failed commands show full diagnostic output regardless of level.\n\n**Do NOT re-run commands:** When \\\\\\`kirograph_exec\\\\\\` returns a result, treat it as the final answer. Never re-run the same command with raw shell execution to \"get more details.\" The compressed output preserves all essential information. If you genuinely need something missing from the output, explain what's missing before making a second call.\n\nUse \\\\\\`kirograph_gain\\\\\\` to check token savings statistics.`;\n}\n\nexport interface SteeringOptions {\n cavemanMode?: CavemanMode | 'off';\n enableCompression?: boolean;\n shellCompressionLevel?: 'off' | 'normal' | 'aggressive' | 'ultra';\n enableMemory?: boolean;\n enableDocs?: boolean;\n}\n\nfunction buildSteeringContent(opts?: SteeringOptions): string {\n const cavemanMode = opts?.cavemanMode;\n const enableCompression = opts?.enableCompression !== false && opts?.shellCompressionLevel !== 'off';\n const shellCompressionLevel = opts?.shellCompressionLevel ?? 'normal';\n\n let content = STEERING_CONTENT;\n\n // Insert compression section before the \"If .kirograph/ does NOT exist\" section\n if (enableCompression && shellCompressionLevel !== 'off') {\n const section = buildCompressionSection(shellCompressionLevel as 'normal' | 'aggressive' | 'ultra');\n content = content.replace(\n '---\\n\\n## If `.kirograph/` does NOT exist',\n section.trim() + '\\n\\n---\\n\\n## If `.kirograph/` does NOT exist',\n );\n }\n\n // Remove compression tools from decision guide if disabled\n if (!enableCompression) {\n content = content.replace('| Run a command with token savings | `kirograph_exec` |\\n', '');\n content = content.replace('| Check token savings stats | `kirograph_gain` |\\n', '');\n }\n\n const caveman = cavemanMode && cavemanMode !== 'off' ? CAVEMAN_RULES[cavemanMode] : null;\n if (caveman) {\n content = content.trimEnd() + '\\n\\n' + caveman + '\\n';\n }\n\n // Memory section\n if (opts?.enableMemory) {\n const memorySection = `\n## Memory\n\nKiroGraph has persistent memory. Use \\`kirograph_mem_search\\` to recall past decisions,\nerrors, and patterns before making changes. Use \\`kirograph_mem_store\\` to save important\nobservations (architecture decisions, bug root causes, patterns discovered).\n\nMemory is searchable via hybrid FTS + vector search. Observations are automatically\nlinked to code symbols in the graph and surface in \\`kirograph_context\\` and\n\\`kirograph_impact\\` results when relevant.\n\n**When to store:** After fixing a bug, making an architecture decision, discovering a pattern,\nencountering a non-obvious error, or learning something about the codebase that future sessions\nshould know. Keep observations concise \u2014 one fact per store call. A hook will also remind you\nat session end.\n`;\n content = content.trimEnd() + '\\n\\n' + memorySection.trim() + '\\n';\n }\n\n // Documentation section\n if (opts?.enableDocs) {\n const docsSection = `\n## Documentation\n\nKiroGraph indexes project documentation by heading structure. Use \\`kirograph_docs_search\\`\nto find relevant doc sections instead of reading entire files. Use \\`kirograph_docs_section\\`\nto retrieve the exact section you need by ID.\n\n**Available tools:**\n- \\`kirograph_docs_toc\\` \u2014 table of contents for a file or the whole project\n- \\`kirograph_docs_search\\` \u2014 search sections by query (independent from code search)\n- \\`kirograph_docs_section\\` \u2014 retrieve full content of a section by ID\n- \\`kirograph_docs_outline\\` \u2014 heading hierarchy for a single document\n- \\`kirograph_docs_refs\\` \u2014 find code symbols referenced by a doc section (or vice versa)\n\n**When to use:** Before reading a documentation file directly, check if \\`kirograph_docs_search\\`\nor \\`kirograph_docs_outline\\` can give you the specific section you need. This saves tokens\nand gives you structured navigation instead of raw file content.\n`;\n content = content.trimEnd() + '\\n\\n' + docsSection.trim() + '\\n';\n }\n\n return content;\n}\n\nexport function writeSteering(kiroDir: string, opts?: SteeringOptions | CavemanMode | 'off'): void {\n const steeringDir = path.join(kiroDir, 'steering');\n fs.mkdirSync(steeringDir, { recursive: true });\n const steeringPath = path.join(steeringDir, 'kirograph.md');\n\n // Support both old signature (cavemanMode string) and new signature (options object)\n const resolvedOpts: SteeringOptions = typeof opts === 'string'\n ? { cavemanMode: opts }\n : opts ?? {};\n\n fs.writeFileSync(steeringPath, buildSteeringContent(resolvedOpts));\n console.log(` \u2713 Steering file written to ${steeringPath}`);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/bin/installer/targets/index.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CavemanMode } from '../caveman';\nimport type { InstallTarget } from '../common';\nimport { installKiroEarly, installKiroLate, printKiroNextSteps } from './kiro';\nimport { installClaudeEarly, installClaudeLate, printClaudeNextSteps, uninitClaude } from './claude';\nimport { installCodexEarly, installCodexLate, printCodexNextSteps, uninitCodex } from './codex';\n\nexport interface TargetInstaller {\n label: string;\n installEarly(projectRoot: string): void;\n installLate(projectRoot: string, cavemanMode?: CavemanMode | 'off', shellCompressionLevel?: string, enableMemory?: boolean): void;\n printNextSteps(projectRoot: string): void;\n uninit?(projectRoot: string): void;\n}\n\nexport function getTargetInstaller(target: InstallTarget): TargetInstaller {\n if (target === 'claude') {\n return {\n label: 'Claude Code',\n installEarly: installClaudeEarly,\n installLate: installClaudeLate,\n printNextSteps: printClaudeNextSteps,\n uninit: uninitClaude,\n };\n }\n\n if (target === 'codex') {\n return {\n label: 'Codex',\n installEarly: installCodexEarly,\n installLate: installCodexLate,\n printNextSteps: printCodexNextSteps,\n uninit: uninitCodex,\n };\n }\n\n return {\n label: 'Kiro',\n installEarly: installKiroEarly,\n installLate: installKiroLate,\n printNextSteps: printKiroNextSteps,\n };\n}\n\n"],
|
|
4
|
+
"sourcesContent": ["import type { CavemanMode } from '../caveman';\nimport type { InstallTarget } from '../common';\nimport { installKiroEarly, installKiroLate, printKiroNextSteps } from './kiro';\nimport { installClaudeEarly, installClaudeLate, printClaudeNextSteps, uninitClaude } from './claude';\nimport { installCodexEarly, installCodexLate, printCodexNextSteps, uninitCodex } from './codex';\n\nexport interface TargetInstaller {\n label: string;\n installEarly(projectRoot: string): void;\n installLate(projectRoot: string, cavemanMode?: CavemanMode | 'off', shellCompressionLevel?: string, enableMemory?: boolean, enableDocs?: boolean): void;\n printNextSteps(projectRoot: string): void;\n uninit?(projectRoot: string): void;\n}\n\nexport function getTargetInstaller(target: InstallTarget): TargetInstaller {\n if (target === 'claude') {\n return {\n label: 'Claude Code',\n installEarly: installClaudeEarly,\n installLate: installClaudeLate,\n printNextSteps: printClaudeNextSteps,\n uninit: uninitClaude,\n };\n }\n\n if (target === 'codex') {\n return {\n label: 'Codex',\n installEarly: installCodexEarly,\n installLate: installCodexLate,\n printNextSteps: printCodexNextSteps,\n uninit: uninitCodex,\n };\n }\n\n return {\n label: 'Kiro',\n installEarly: installKiroEarly,\n installLate: installKiroLate,\n printNextSteps: printKiroNextSteps,\n };\n}\n\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,kBAAsE;AACtE,oBAA0F;AAC1F,mBAAsF;AAU/E,SAAS,mBAAmB,QAAwC;AACzE,MAAI,WAAW,UAAU;AACvB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,cAAc;AAAA,MACd,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,WAAW,SAAS;AACtB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,cAAc;AAAA,MACd,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,cAAc;AAAA,IACd,aAAa;AAAA,IACb,gBAAgB;AAAA,EAClB;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -43,11 +43,11 @@ function installKiroEarly(projectRoot) {
|
|
|
43
43
|
(0, import_mcp.writeMcpConfig)(kiroDir);
|
|
44
44
|
(0, import_hooks.writeHooks)(kiroDir);
|
|
45
45
|
}
|
|
46
|
-
function installKiroLate(projectRoot, cavemanMode, shellCompressionLevel, enableMemory) {
|
|
46
|
+
function installKiroLate(projectRoot, cavemanMode, shellCompressionLevel, enableMemory, enableDocs) {
|
|
47
47
|
const kiroDir = path.join(projectRoot, ".kiro");
|
|
48
48
|
const enableCompression = shellCompressionLevel !== "off";
|
|
49
49
|
(0, import_hooks.writeHooks)(kiroDir, { enableCompression, enableMemory });
|
|
50
|
-
(0, import_steering.writeSteering)(kiroDir, { cavemanMode, enableCompression, shellCompressionLevel, enableMemory });
|
|
50
|
+
(0, import_steering.writeSteering)(kiroDir, { cavemanMode, enableCompression, shellCompressionLevel, enableMemory, enableDocs });
|
|
51
51
|
(0, import_cli_agent.writeCliAgent)(kiroDir);
|
|
52
52
|
}
|
|
53
53
|
function printKiroNextSteps() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/bin/installer/targets/kiro.ts"],
|
|
4
|
-
"sourcesContent": ["import * as path from 'path';\nimport { CavemanMode } from '../caveman';\nimport { writeCliAgent } from '../cli-agent';\nimport { writeHooks } from '../hooks';\nimport { writeMcpConfig } from '../mcp';\nimport { writeSteering } from '../steering';\n\nexport function installKiroEarly(projectRoot: string): void {\n const kiroDir = path.join(projectRoot, '.kiro');\n writeMcpConfig(kiroDir);\n writeHooks(kiroDir);\n}\n\nexport function installKiroLate(projectRoot: string, cavemanMode?: CavemanMode | 'off', shellCompressionLevel?: string, enableMemory?: boolean): void {\n const kiroDir = path.join(projectRoot, '.kiro');\n const enableCompression = shellCompressionLevel !== 'off';\n // Re-write hooks with compression and memory awareness\n writeHooks(kiroDir, { enableCompression, enableMemory });\n writeSteering(kiroDir, { cavemanMode, enableCompression, shellCompressionLevel: shellCompressionLevel as any, enableMemory });\n writeCliAgent(kiroDir);\n}\n\nexport function printKiroNextSteps(): void {\n console.log('\\n Done! Restart Kiro IDE for the MCP server to load.');\n console.log(' For Kiro CLI, use the \"kirograph\" agent: kiro-cli --agent kirograph\\n');\n}\n\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAAsB;AAEtB,uBAA8B;AAC9B,mBAA2B;AAC3B,iBAA+B;AAC/B,sBAA8B;AAEvB,SAAS,iBAAiB,aAA2B;AAC1D,QAAM,UAAU,KAAK,KAAK,aAAa,OAAO;AAC9C,iCAAe,OAAO;AACtB,+BAAW,OAAO;AACpB;AAEO,SAAS,gBAAgB,aAAqB,aAAmC,uBAAgC,
|
|
4
|
+
"sourcesContent": ["import * as path from 'path';\nimport { CavemanMode } from '../caveman';\nimport { writeCliAgent } from '../cli-agent';\nimport { writeHooks } from '../hooks';\nimport { writeMcpConfig } from '../mcp';\nimport { writeSteering } from '../steering';\n\nexport function installKiroEarly(projectRoot: string): void {\n const kiroDir = path.join(projectRoot, '.kiro');\n writeMcpConfig(kiroDir);\n writeHooks(kiroDir);\n}\n\nexport function installKiroLate(projectRoot: string, cavemanMode?: CavemanMode | 'off', shellCompressionLevel?: string, enableMemory?: boolean, enableDocs?: boolean): void {\n const kiroDir = path.join(projectRoot, '.kiro');\n const enableCompression = shellCompressionLevel !== 'off';\n // Re-write hooks with compression and memory awareness\n writeHooks(kiroDir, { enableCompression, enableMemory });\n writeSteering(kiroDir, { cavemanMode, enableCompression, shellCompressionLevel: shellCompressionLevel as any, enableMemory, enableDocs });\n writeCliAgent(kiroDir);\n}\n\nexport function printKiroNextSteps(): void {\n console.log('\\n Done! Restart Kiro IDE for the MCP server to load.');\n console.log(' For Kiro CLI, use the \"kirograph\" agent: kiro-cli --agent kirograph\\n');\n}\n\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAAsB;AAEtB,uBAA8B;AAC9B,mBAA2B;AAC3B,iBAA+B;AAC/B,sBAA8B;AAEvB,SAAS,iBAAiB,aAA2B;AAC1D,QAAM,UAAU,KAAK,KAAK,aAAa,OAAO;AAC9C,iCAAe,OAAO;AACtB,+BAAW,OAAO;AACpB;AAEO,SAAS,gBAAgB,aAAqB,aAAmC,uBAAgC,cAAwB,YAA4B;AAC1K,QAAM,UAAU,KAAK,KAAK,aAAa,OAAO;AAC9C,QAAM,oBAAoB,0BAA0B;AAEpD,+BAAW,SAAS,EAAE,mBAAmB,aAAa,CAAC;AACvD,qCAAc,SAAS,EAAE,aAAa,mBAAmB,uBAAqD,cAAc,WAAW,CAAC;AACxI,sCAAc,OAAO;AACvB;AAEO,SAAS,qBAA2B;AACzC,UAAQ,IAAI,wDAAwD;AACpE,UAAQ,IAAI,yEAAyE;AACvF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/bin/kirograph.js
CHANGED
|
@@ -32,6 +32,7 @@ var import_gain = require("./commands/gain");
|
|
|
32
32
|
var import_compression = require("./commands/compression");
|
|
33
33
|
var import_exec = require("./commands/exec");
|
|
34
34
|
var import_memory = require("./commands/memory");
|
|
35
|
+
var import_docs = require("./commands/docs");
|
|
35
36
|
process.on("uncaughtException", (err) => {
|
|
36
37
|
const msg = err?.message ?? String(err);
|
|
37
38
|
const isWasmAbort = msg.includes("Aborted(") || msg.includes("RuntimeError") || err?.constructor?.name === "RuntimeError";
|
|
@@ -60,7 +61,7 @@ process.on("uncaughtException", (err) => {
|
|
|
60
61
|
process.exit(1);
|
|
61
62
|
});
|
|
62
63
|
const program = new import_commander.Command();
|
|
63
|
-
program.name("kirograph").description("Semantic code knowledge graph for Kiro").version("0.
|
|
64
|
+
program.name("kirograph").description("Semantic code knowledge graph for Kiro").version("0.16.0").addHelpCommand(true).hook("preAction", (thisCommand) => {
|
|
64
65
|
const name = thisCommand.name();
|
|
65
66
|
if (name === "init") (0, import_banner.printBanner)();
|
|
66
67
|
});
|
|
@@ -93,6 +94,7 @@ program.name("kirograph").description("Semantic code knowledge graph for Kiro").
|
|
|
93
94
|
(0, import_compression.register)(program);
|
|
94
95
|
(0, import_exec.register)(program);
|
|
95
96
|
(0, import_memory.register)(program);
|
|
97
|
+
(0, import_docs.register)(program);
|
|
96
98
|
if (process.argv.length === 2) {
|
|
97
99
|
(0, import_banner.printBanner)();
|
|
98
100
|
(0, import_help.printColoredHelp)();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/bin/kirograph.ts"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\n/**\n * KiroGraph CLI\n */\n\nimport { Command } from 'commander';\nimport { printBanner } from './banner';\nimport { printColoredHelp, register as registerHelp } from './commands/help';\nimport { register as registerInit } from './commands/init';\nimport { register as registerUninit } from './commands/uninit';\nimport { register as registerIndex } from './commands/index';\nimport { register as registerSync } from './commands/sync';\nimport { register as registerStatus } from './commands/status';\nimport { register as registerQuery } from './commands/query';\nimport { register as registerFiles } from './commands/files';\nimport { register as registerContext } from './commands/context';\nimport { register as registerAffected } from './commands/affected';\nimport { register as registerMarkDirty } from './commands/mark-dirty';\nimport { register as registerSyncIfDirty } from './commands/sync-if-dirty';\nimport { register as registerUnlock } from './commands/unlock';\nimport { register as registerInstall } from './commands/install';\nimport { register as registerServe } from './commands/serve';\nimport { register as registerDashboard } from './commands/dashboard';\nimport { register as registerArchitecture } from './commands/architecture';\nimport { register as registerCoupling } from './commands/coupling';\nimport { register as registerPackage } from './commands/package';\nimport { register as registerCaveman } from './commands/caveman';\nimport { register as registerDeadCode } from './commands/dead-code';\nimport { register as registerHotspots } from './commands/hotspots';\nimport { register as registerSurprising } from './commands/surprising';\nimport { register as registerSnapshot } from './commands/snapshot';\nimport { register as registerPath } from './commands/path';\nimport { register as registerExport } from './commands/export';\nimport { register as registerGain } from './commands/gain';\nimport { register as registerCompression } from './commands/compression';\nimport { register as registerExec } from './commands/exec';\nimport { register as registerMemory } from './commands/memory';\n\n// \u2500\u2500 Global error handler for WASM runtime crashes \u2500\u2500\u2500\u2500\u2500\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// node-sqlite3-wasm calls process.abort() when it hits a fatal error (e.g.\n// database is locked by another process). This produces a raw \"Aborted()\"\n// message with no context. We intercept it here to print a clear explanation\n// before the process exits.\nprocess.on('uncaughtException', (err: Error) => {\n const msg = err?.message ?? String(err);\n const isWasmAbort = msg.includes('Aborted(') || msg.includes('RuntimeError') || (err as any)?.constructor?.name === 'RuntimeError';\n\n if (isWasmAbort) {\n process.stderr.write([\n '',\n ' \u2716 KiroGraph crashed: SQLite WASM runtime aborted.',\n '',\n ' Most likely cause: another process (e.g. the Kiro MCP server) is',\n ' holding the database open while indexing is running.',\n '',\n ' How to fix:',\n ' 1. Close Kiro IDE (or disable the kirograph MCP server) before indexing',\n ' 2. Run: kirograph unlock',\n ' 3. Then retry: kirograph index',\n '',\n ' If the problem persists, delete the lock manually:',\n ' del .kirograph\\\\kirograph.db.lock (Windows)',\n ' rm -rf .kirograph/kirograph.db.lock (macOS/Linux)',\n '',\n ].join('\\n'));\n process.exit(1);\n }\n\n // Not a WASM crash \u2014 re-throw as normal\n process.stderr.write(`Uncaught error: ${msg}\\n`);\n process.exit(1);\n});\n\ndeclare const __CLI_VERSION__: string;\n\nconst program = new Command();\n\nprogram\n .name('kirograph')\n .description('Semantic code knowledge graph for Kiro')\n .version(__CLI_VERSION__)\n .addHelpCommand(true)\n .hook('preAction', (thisCommand) => {\n const name = thisCommand.name();\n if (name === 'init') printBanner();\n });\n\nregisterInstall(program);\nregisterInit(program);\nregisterUninit(program);\nregisterIndex(program);\nregisterSync(program);\nregisterSyncIfDirty(program);\nregisterMarkDirty(program);\nregisterStatus(program);\nregisterQuery(program);\nregisterContext(program);\nregisterFiles(program);\nregisterAffected(program);\nregisterUnlock(program);\nregisterServe(program);\nregisterDashboard(program);\nregisterArchitecture(program);\nregisterCoupling(program);\nregisterPackage(program);\nregisterCaveman(program);\nregisterDeadCode(program);\nregisterHotspots(program);\nregisterSurprising(program);\nregisterSnapshot(program);\nregisterPath(program);\nregisterExport(program);\nregisterGain(program);\nregisterCompression(program);\nregisterExec(program);\nregisterMemory(program);\n\n// Show banner + help when called with no arguments, otherwise parse normally\nif (process.argv.length === 2) {\n printBanner();\n printColoredHelp();\n process.exit(0);\n}\n\nregisterHelp(program);\n\nprogram.parse(process.argv);\n"],
|
|
5
|
-
"mappings": ";;AAKA,uBAAwB;AACxB,oBAA4B;AAC5B,kBAA2D;AAC3D,kBAAyC;AACzC,oBAA2C;AAC3C,sBAA0C;AAC1C,kBAAyC;AACzC,oBAA2C;AAC3C,mBAA0C;AAC1C,mBAA0C;AAC1C,qBAA4C;AAC5C,sBAA6C;AAC7C,wBAA8C;AAC9C,2BAAgD;AAChD,oBAA2C;AAC3C,qBAA4C;AAC5C,mBAA0C;AAC1C,uBAA8C;AAC9C,0BAAiD;AACjD,sBAA6C;AAC7C,qBAA4C;AAC5C,qBAA4C;AAC5C,uBAA6C;AAC7C,sBAA6C;AAC7C,wBAA+C;AAC/C,sBAA6C;AAC7C,kBAAyC;AACzC,oBAA2C;AAC3C,kBAAyC;AACzC,yBAAgD;AAChD,kBAAyC;AACzC,oBAA2C;
|
|
6
|
-
"names": ["registerInstall", "registerInit", "registerUninit", "registerIndex", "registerSync", "registerSyncIfDirty", "registerMarkDirty", "registerStatus", "registerQuery", "registerContext", "registerFiles", "registerAffected", "registerUnlock", "registerServe", "registerDashboard", "registerArchitecture", "registerCoupling", "registerPackage", "registerCaveman", "registerDeadCode", "registerHotspots", "registerSurprising", "registerSnapshot", "registerPath", "registerExport", "registerGain", "registerCompression", "registerExec", "registerMemory", "registerHelp"]
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n/**\n * KiroGraph CLI\n */\n\nimport { Command } from 'commander';\nimport { printBanner } from './banner';\nimport { printColoredHelp, register as registerHelp } from './commands/help';\nimport { register as registerInit } from './commands/init';\nimport { register as registerUninit } from './commands/uninit';\nimport { register as registerIndex } from './commands/index';\nimport { register as registerSync } from './commands/sync';\nimport { register as registerStatus } from './commands/status';\nimport { register as registerQuery } from './commands/query';\nimport { register as registerFiles } from './commands/files';\nimport { register as registerContext } from './commands/context';\nimport { register as registerAffected } from './commands/affected';\nimport { register as registerMarkDirty } from './commands/mark-dirty';\nimport { register as registerSyncIfDirty } from './commands/sync-if-dirty';\nimport { register as registerUnlock } from './commands/unlock';\nimport { register as registerInstall } from './commands/install';\nimport { register as registerServe } from './commands/serve';\nimport { register as registerDashboard } from './commands/dashboard';\nimport { register as registerArchitecture } from './commands/architecture';\nimport { register as registerCoupling } from './commands/coupling';\nimport { register as registerPackage } from './commands/package';\nimport { register as registerCaveman } from './commands/caveman';\nimport { register as registerDeadCode } from './commands/dead-code';\nimport { register as registerHotspots } from './commands/hotspots';\nimport { register as registerSurprising } from './commands/surprising';\nimport { register as registerSnapshot } from './commands/snapshot';\nimport { register as registerPath } from './commands/path';\nimport { register as registerExport } from './commands/export';\nimport { register as registerGain } from './commands/gain';\nimport { register as registerCompression } from './commands/compression';\nimport { register as registerExec } from './commands/exec';\nimport { register as registerMemory } from './commands/memory';\nimport { register as registerDocs } from './commands/docs';\n\n// \u2500\u2500 Global error handler for WASM runtime crashes \u2500\u2500\u2500\u2500\u2500\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// node-sqlite3-wasm calls process.abort() when it hits a fatal error (e.g.\n// database is locked by another process). This produces a raw \"Aborted()\"\n// message with no context. We intercept it here to print a clear explanation\n// before the process exits.\nprocess.on('uncaughtException', (err: Error) => {\n const msg = err?.message ?? String(err);\n const isWasmAbort = msg.includes('Aborted(') || msg.includes('RuntimeError') || (err as any)?.constructor?.name === 'RuntimeError';\n\n if (isWasmAbort) {\n process.stderr.write([\n '',\n ' \u2716 KiroGraph crashed: SQLite WASM runtime aborted.',\n '',\n ' Most likely cause: another process (e.g. the Kiro MCP server) is',\n ' holding the database open while indexing is running.',\n '',\n ' How to fix:',\n ' 1. Close Kiro IDE (or disable the kirograph MCP server) before indexing',\n ' 2. Run: kirograph unlock',\n ' 3. Then retry: kirograph index',\n '',\n ' If the problem persists, delete the lock manually:',\n ' del .kirograph\\\\kirograph.db.lock (Windows)',\n ' rm -rf .kirograph/kirograph.db.lock (macOS/Linux)',\n '',\n ].join('\\n'));\n process.exit(1);\n }\n\n // Not a WASM crash \u2014 re-throw as normal\n process.stderr.write(`Uncaught error: ${msg}\\n`);\n process.exit(1);\n});\n\ndeclare const __CLI_VERSION__: string;\n\nconst program = new Command();\n\nprogram\n .name('kirograph')\n .description('Semantic code knowledge graph for Kiro')\n .version(__CLI_VERSION__)\n .addHelpCommand(true)\n .hook('preAction', (thisCommand) => {\n const name = thisCommand.name();\n if (name === 'init') printBanner();\n });\n\nregisterInstall(program);\nregisterInit(program);\nregisterUninit(program);\nregisterIndex(program);\nregisterSync(program);\nregisterSyncIfDirty(program);\nregisterMarkDirty(program);\nregisterStatus(program);\nregisterQuery(program);\nregisterContext(program);\nregisterFiles(program);\nregisterAffected(program);\nregisterUnlock(program);\nregisterServe(program);\nregisterDashboard(program);\nregisterArchitecture(program);\nregisterCoupling(program);\nregisterPackage(program);\nregisterCaveman(program);\nregisterDeadCode(program);\nregisterHotspots(program);\nregisterSurprising(program);\nregisterSnapshot(program);\nregisterPath(program);\nregisterExport(program);\nregisterGain(program);\nregisterCompression(program);\nregisterExec(program);\nregisterMemory(program);\nregisterDocs(program);\n\n// Show banner + help when called with no arguments, otherwise parse normally\nif (process.argv.length === 2) {\n printBanner();\n printColoredHelp();\n process.exit(0);\n}\n\nregisterHelp(program);\n\nprogram.parse(process.argv);\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["registerInstall", "registerInit", "registerUninit", "registerIndex", "registerSync", "registerSyncIfDirty", "registerMarkDirty", "registerStatus", "registerQuery", "registerContext", "registerFiles", "registerAffected", "registerUnlock", "registerServe", "registerDashboard", "registerArchitecture", "registerCoupling", "registerPackage", "registerCaveman", "registerDeadCode", "registerHotspots", "registerSurprising", "registerSnapshot", "registerPath", "registerExport", "registerGain", "registerCompression", "registerExec", "registerMemory", "registerDocs", "registerHelp"]
|
|
7
7
|
}
|
|
@@ -96,6 +96,25 @@ function estimateNaiveCost(toolName, outputTokens, args) {
|
|
|
96
96
|
case "kirograph_mem_status": {
|
|
97
97
|
return 500;
|
|
98
98
|
}
|
|
99
|
+
// ── Docs tools ────────────────────────────────────────────────────────────
|
|
100
|
+
case "kirograph_docs_toc": {
|
|
101
|
+
return AVG_FILE_TOKENS * 4 + AVG_FILE_TOKENS;
|
|
102
|
+
}
|
|
103
|
+
case "kirograph_docs_search": {
|
|
104
|
+
const limit = args?.limit || 10;
|
|
105
|
+
const filesEstimate = Math.min(Math.ceil(limit / 2), 5);
|
|
106
|
+
return AVG_GREP_TOKENS + filesEstimate * AVG_FILE_TOKENS;
|
|
107
|
+
}
|
|
108
|
+
case "kirograph_docs_section": {
|
|
109
|
+
const withContext = args?.context;
|
|
110
|
+
return withContext ? AVG_FILE_TOKENS * 3 : AVG_FILE_TOKENS * 2;
|
|
111
|
+
}
|
|
112
|
+
case "kirograph_docs_outline": {
|
|
113
|
+
return AVG_FILE_TOKENS * 2;
|
|
114
|
+
}
|
|
115
|
+
case "kirograph_docs_refs": {
|
|
116
|
+
return AVG_GREP_TOKENS * 3 + AVG_FILE_TOKENS * 2;
|
|
117
|
+
}
|
|
99
118
|
// kirograph_exec and kirograph_gain are tracked separately
|
|
100
119
|
default:
|
|
101
120
|
return null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/compression/naive-cost.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Naive cost estimator for KiroGraph MCP tools.\n *\n * Estimates how many tokens the agent would have consumed doing the same\n * work without KiroGraph (reading files, running grep, etc.).\n *\n * These are conservative estimates based on typical agent behavior:\n * - kirograph_context: agent would read 5-10 files fully to orient\n * - kirograph_search: agent would run grep/ripgrep across the project\n * - kirograph_callers/callees: agent would grep for the symbol name + read each file\n * - kirograph_impact: agent would trace callers recursively (multiple grep + read cycles)\n * - kirograph_node: agent would read the full file containing the symbol\n * - kirograph_files: agent would run find/ls -R\n * - kirograph_status: agent would check file counts, run wc, etc.\n * - kirograph_hotspots/surprising/dead_code: not feasible manually (infinite cost \u2192 cap at 5x)\n */\n\nimport { estimateTokens } from './index';\n\n/** Average tokens per file read (medium-sized source file ~200 lines) */\nconst AVG_FILE_TOKENS = 1500;\n\n/** Average tokens for a grep result across a medium project */\nconst AVG_GREP_TOKENS = 800;\n\n/** Average tokens for ls -R or find output on a medium project */\nconst AVG_FIND_TOKENS = 2000;\n\n/**\n * Estimate the naive token cost (what the agent would have spent without KiroGraph).\n *\n * @param toolName - The MCP tool that was called\n * @param outputTokens - Actual tokens in the tool's response\n * @param args - The tool arguments (for context-aware estimation)\n * @returns Estimated naive cost in tokens, or null if not estimable\n */\nexport function estimateNaiveCost(toolName: string, outputTokens: number, args?: Record<string, unknown>): number | null {\n switch (toolName) {\n case 'kirograph_context': {\n // Agent would read ~5-10 files to understand a task area\n const maxNodes = (args?.maxNodes as number) || 20;\n const filesEstimate = Math.min(Math.ceil(maxNodes / 2), 10);\n return filesEstimate * AVG_FILE_TOKENS;\n }\n\n case 'kirograph_search': {\n // Agent would run grep/ripgrep and read through results\n const limit = (args?.limit as number) || 10;\n // grep output + reading top matches\n return AVG_GREP_TOKENS + Math.min(limit, 5) * (AVG_FILE_TOKENS / 3);\n }\n\n case 'kirograph_callers': {\n // Agent would grep for the symbol, then read each calling file\n const limit = (args?.limit as number) || 20;\n const callersEstimate = Math.min(limit, 10);\n return AVG_GREP_TOKENS + callersEstimate * (AVG_FILE_TOKENS / 2);\n }\n\n case 'kirograph_callees': {\n // Agent would read the function body + grep for each called symbol\n return AVG_FILE_TOKENS + AVG_GREP_TOKENS * 3;\n }\n\n case 'kirograph_impact': {\n // Agent would need multiple rounds of grep + read (recursive)\n const depth = (args?.depth as number) || 2;\n return (AVG_GREP_TOKENS + AVG_FILE_TOKENS * 3) * depth;\n }\n\n case 'kirograph_node': {\n // Agent would read the full file to find the symbol\n return AVG_FILE_TOKENS;\n }\n\n case 'kirograph_files': {\n // Agent would run find or ls -R\n return AVG_FIND_TOKENS;\n }\n\n case 'kirograph_status': {\n // Agent would run multiple commands (wc -l, find, du, etc.)\n return 500;\n }\n\n case 'kirograph_path': {\n // Agent would need to manually trace connections \u2014 multiple grep + read cycles\n return AVG_GREP_TOKENS * 4 + AVG_FILE_TOKENS * 3;\n }\n\n case 'kirograph_type_hierarchy': {\n // Agent would grep for extends/implements, read each file\n return AVG_GREP_TOKENS * 3 + AVG_FILE_TOKENS * 2;\n }\n\n case 'kirograph_dead_code': {\n // Not feasible manually \u2014 would require reading every file and cross-referencing\n // Cap at 5x the output (conservative)\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 10);\n }\n\n case 'kirograph_circular_deps': {\n // Not feasible manually \u2014 would require building a full import graph\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 8);\n }\n\n case 'kirograph_hotspots': {\n // Not feasible manually \u2014 would require counting edges for every symbol\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 10);\n }\n\n case 'kirograph_surprising': {\n // Not feasible manually\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 10);\n }\n\n case 'kirograph_architecture':\n case 'kirograph_coupling':\n case 'kirograph_package': {\n // Architecture analysis is not feasible manually\n return Math.max(outputTokens * 4, AVG_FILE_TOKENS * 5);\n }\n\n case 'kirograph_diff': {\n // Agent would need to compare file lists and grep for symbols\n return Math.max(outputTokens * 3, AVG_FILE_TOKENS * 5);\n }\n\n case 'kirograph_mem_search': {\n // Without memory, agent would re-read files to rediscover past decisions.\n // Typically 3-5 files + grep for related context.\n const limit = (args?.limit as number) || 10;\n const filesEstimate = Math.min(Math.ceil(limit / 2), 5);\n return filesEstimate * AVG_FILE_TOKENS + AVG_GREP_TOKENS;\n }\n\n case 'kirograph_mem_store': {\n // Storing has no direct naive equivalent \u2014 the knowledge would simply be lost.\n // We don't count savings on store; savings are realized on future searches.\n return null;\n }\n\n case 'kirograph_mem_timeline': {\n // Agent would ask user or re-read previous session context.\n return AVG_FILE_TOKENS + AVG_GREP_TOKENS;\n }\n\n case 'kirograph_mem_status': {\n // Lightweight status check, minimal naive cost.\n return 500;\n }\n\n // kirograph_exec and kirograph_gain are tracked separately\n default:\n return null;\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBA,MAAM,kBAAkB;AAGxB,MAAM,kBAAkB;AAGxB,MAAM,kBAAkB;AAUjB,SAAS,kBAAkB,UAAkB,cAAsB,MAA+C;AACvH,UAAQ,UAAU;AAAA,IAChB,KAAK,qBAAqB;AAExB,YAAM,WAAY,MAAM,YAAuB;AAC/C,YAAM,gBAAgB,KAAK,IAAI,KAAK,KAAK,WAAW,CAAC,GAAG,EAAE;AAC1D,aAAO,gBAAgB;AAAA,IACzB;AAAA,IAEA,KAAK,oBAAoB;AAEvB,YAAM,QAAS,MAAM,SAAoB;AAEzC,aAAO,kBAAkB,KAAK,IAAI,OAAO,CAAC,KAAK,kBAAkB;AAAA,IACnE;AAAA,IAEA,KAAK,qBAAqB;AAExB,YAAM,QAAS,MAAM,SAAoB;AACzC,YAAM,kBAAkB,KAAK,IAAI,OAAO,EAAE;AAC1C,aAAO,kBAAkB,mBAAmB,kBAAkB;AAAA,IAChE;AAAA,IAEA,KAAK,qBAAqB;AAExB,aAAO,kBAAkB,kBAAkB;AAAA,IAC7C;AAAA,IAEA,KAAK,oBAAoB;AAEvB,YAAM,QAAS,MAAM,SAAoB;AACzC,cAAQ,kBAAkB,kBAAkB,KAAK;AAAA,IACnD;AAAA,IAEA,KAAK,kBAAkB;AAErB,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,mBAAmB;AAEtB,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,oBAAoB;AAEvB,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,kBAAkB;AAErB,aAAO,kBAAkB,IAAI,kBAAkB;AAAA,IACjD;AAAA,IAEA,KAAK,4BAA4B;AAE/B,aAAO,kBAAkB,IAAI,kBAAkB;AAAA,IACjD;AAAA,IAEA,KAAK,uBAAuB;AAG1B,aAAO,KAAK,IAAI,eAAe,GAAG,kBAAkB,EAAE;AAAA,IACxD;AAAA,IAEA,KAAK,2BAA2B;AAE9B,aAAO,KAAK,IAAI,eAAe,GAAG,kBAAkB,CAAC;AAAA,IACvD;AAAA,IAEA,KAAK,sBAAsB;AAEzB,aAAO,KAAK,IAAI,eAAe,GAAG,kBAAkB,EAAE;AAAA,IACxD;AAAA,IAEA,KAAK,wBAAwB;AAE3B,aAAO,KAAK,IAAI,eAAe,GAAG,kBAAkB,EAAE;AAAA,IACxD;AAAA,IAEA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK,qBAAqB;AAExB,aAAO,KAAK,IAAI,eAAe,GAAG,kBAAkB,CAAC;AAAA,IACvD;AAAA,IAEA,KAAK,kBAAkB;AAErB,aAAO,KAAK,IAAI,eAAe,GAAG,kBAAkB,CAAC;AAAA,IACvD;AAAA,IAEA,KAAK,wBAAwB;AAG3B,YAAM,QAAS,MAAM,SAAoB;AACzC,YAAM,gBAAgB,KAAK,IAAI,KAAK,KAAK,QAAQ,CAAC,GAAG,CAAC;AACtD,aAAO,gBAAgB,kBAAkB;AAAA,IAC3C;AAAA,IAEA,KAAK,uBAAuB;AAG1B,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,0BAA0B;AAE7B,aAAO,kBAAkB;AAAA,IAC3B;AAAA,IAEA,KAAK,wBAAwB;AAE3B,aAAO;AAAA,IACT;AAAA;AAAA,IAGA;AACE,aAAO;AAAA,EACX;AACF;",
|
|
4
|
+
"sourcesContent": ["/**\n * Naive cost estimator for KiroGraph MCP tools.\n *\n * Estimates how many tokens the agent would have consumed doing the same\n * work without KiroGraph (reading files, running grep, etc.).\n *\n * These are conservative estimates based on typical agent behavior:\n * - kirograph_context: agent would read 5-10 files fully to orient\n * - kirograph_search: agent would run grep/ripgrep across the project\n * - kirograph_callers/callees: agent would grep for the symbol name + read each file\n * - kirograph_impact: agent would trace callers recursively (multiple grep + read cycles)\n * - kirograph_node: agent would read the full file containing the symbol\n * - kirograph_files: agent would run find/ls -R\n * - kirograph_status: agent would check file counts, run wc, etc.\n * - kirograph_hotspots/surprising/dead_code: not feasible manually (infinite cost \u2192 cap at 5x)\n */\n\nimport { estimateTokens } from './index';\n\n/** Average tokens per file read (medium-sized source file ~200 lines) */\nconst AVG_FILE_TOKENS = 1500;\n\n/** Average tokens for a grep result across a medium project */\nconst AVG_GREP_TOKENS = 800;\n\n/** Average tokens for ls -R or find output on a medium project */\nconst AVG_FIND_TOKENS = 2000;\n\n/**\n * Estimate the naive token cost (what the agent would have spent without KiroGraph).\n *\n * @param toolName - The MCP tool that was called\n * @param outputTokens - Actual tokens in the tool's response\n * @param args - The tool arguments (for context-aware estimation)\n * @returns Estimated naive cost in tokens, or null if not estimable\n */\nexport function estimateNaiveCost(toolName: string, outputTokens: number, args?: Record<string, unknown>): number | null {\n switch (toolName) {\n case 'kirograph_context': {\n // Agent would read ~5-10 files to understand a task area\n const maxNodes = (args?.maxNodes as number) || 20;\n const filesEstimate = Math.min(Math.ceil(maxNodes / 2), 10);\n return filesEstimate * AVG_FILE_TOKENS;\n }\n\n case 'kirograph_search': {\n // Agent would run grep/ripgrep and read through results\n const limit = (args?.limit as number) || 10;\n // grep output + reading top matches\n return AVG_GREP_TOKENS + Math.min(limit, 5) * (AVG_FILE_TOKENS / 3);\n }\n\n case 'kirograph_callers': {\n // Agent would grep for the symbol, then read each calling file\n const limit = (args?.limit as number) || 20;\n const callersEstimate = Math.min(limit, 10);\n return AVG_GREP_TOKENS + callersEstimate * (AVG_FILE_TOKENS / 2);\n }\n\n case 'kirograph_callees': {\n // Agent would read the function body + grep for each called symbol\n return AVG_FILE_TOKENS + AVG_GREP_TOKENS * 3;\n }\n\n case 'kirograph_impact': {\n // Agent would need multiple rounds of grep + read (recursive)\n const depth = (args?.depth as number) || 2;\n return (AVG_GREP_TOKENS + AVG_FILE_TOKENS * 3) * depth;\n }\n\n case 'kirograph_node': {\n // Agent would read the full file to find the symbol\n return AVG_FILE_TOKENS;\n }\n\n case 'kirograph_files': {\n // Agent would run find or ls -R\n return AVG_FIND_TOKENS;\n }\n\n case 'kirograph_status': {\n // Agent would run multiple commands (wc -l, find, du, etc.)\n return 500;\n }\n\n case 'kirograph_path': {\n // Agent would need to manually trace connections \u2014 multiple grep + read cycles\n return AVG_GREP_TOKENS * 4 + AVG_FILE_TOKENS * 3;\n }\n\n case 'kirograph_type_hierarchy': {\n // Agent would grep for extends/implements, read each file\n return AVG_GREP_TOKENS * 3 + AVG_FILE_TOKENS * 2;\n }\n\n case 'kirograph_dead_code': {\n // Not feasible manually \u2014 would require reading every file and cross-referencing\n // Cap at 5x the output (conservative)\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 10);\n }\n\n case 'kirograph_circular_deps': {\n // Not feasible manually \u2014 would require building a full import graph\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 8);\n }\n\n case 'kirograph_hotspots': {\n // Not feasible manually \u2014 would require counting edges for every symbol\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 10);\n }\n\n case 'kirograph_surprising': {\n // Not feasible manually\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 10);\n }\n\n case 'kirograph_architecture':\n case 'kirograph_coupling':\n case 'kirograph_package': {\n // Architecture analysis is not feasible manually\n return Math.max(outputTokens * 4, AVG_FILE_TOKENS * 5);\n }\n\n case 'kirograph_diff': {\n // Agent would need to compare file lists and grep for symbols\n return Math.max(outputTokens * 3, AVG_FILE_TOKENS * 5);\n }\n\n case 'kirograph_mem_search': {\n // Without memory, agent would re-read files to rediscover past decisions.\n // Typically 3-5 files + grep for related context.\n const limit = (args?.limit as number) || 10;\n const filesEstimate = Math.min(Math.ceil(limit / 2), 5);\n return filesEstimate * AVG_FILE_TOKENS + AVG_GREP_TOKENS;\n }\n\n case 'kirograph_mem_store': {\n // Storing has no direct naive equivalent \u2014 the knowledge would simply be lost.\n // We don't count savings on store; savings are realized on future searches.\n return null;\n }\n\n case 'kirograph_mem_timeline': {\n // Agent would ask user or re-read previous session context.\n return AVG_FILE_TOKENS + AVG_GREP_TOKENS;\n }\n\n case 'kirograph_mem_status': {\n // Lightweight status check, minimal naive cost.\n return 500;\n }\n\n // \u2500\u2500 Docs tools \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 case 'kirograph_docs_toc': {\n // Agent would read all doc files to understand structure.\n // Conservative: 3-5 doc files fully read.\n return AVG_FILE_TOKENS * 4 + AVG_FILE_TOKENS; // docs are ~2500 tokens avg\n }\n\n case 'kirograph_docs_search': {\n // Agent would grep across all doc files + read top matches.\n const limit = (args?.limit as number) || 10;\n const filesEstimate = Math.min(Math.ceil(limit / 2), 5);\n return AVG_GREP_TOKENS + filesEstimate * AVG_FILE_TOKENS;\n }\n\n case 'kirograph_docs_section': {\n // Agent would read the full file to find the relevant section.\n // With context=true, agent would also read parent/child files.\n const withContext = args?.context as boolean;\n return withContext ? AVG_FILE_TOKENS * 3 : AVG_FILE_TOKENS * 2;\n }\n\n case 'kirograph_docs_outline': {\n // Agent would read the full file to understand its structure.\n return AVG_FILE_TOKENS * 2;\n }\n\n case 'kirograph_docs_refs': {\n // Agent would grep for symbol names across docs + read code files.\n return AVG_GREP_TOKENS * 3 + AVG_FILE_TOKENS * 2;\n }\n\n // kirograph_exec and kirograph_gain are tracked separately\n default:\n return null;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -96,6 +96,15 @@ class TokenTracker {
|
|
|
96
96
|
recordMemorySaving(toolName, outputTokens, naiveCost) {
|
|
97
97
|
this.record(toolName, naiveCost, outputTokens, `memory:${toolName}`, "memory");
|
|
98
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Record a docs tool saving.
|
|
101
|
+
* @param toolName - The MCP tool that was called
|
|
102
|
+
* @param outputTokens - Actual tokens returned by the tool
|
|
103
|
+
* @param naiveCost - Estimated tokens the agent would have used without docs indexing
|
|
104
|
+
*/
|
|
105
|
+
recordDocsSaving(toolName, outputTokens, naiveCost) {
|
|
106
|
+
this.record(toolName, naiveCost, outputTokens, `docs:${toolName}`, "docs");
|
|
107
|
+
}
|
|
99
108
|
/**
|
|
100
109
|
* Get aggregated statistics for a time period.
|
|
101
110
|
*/
|
|
@@ -110,13 +119,13 @@ class TokenTracker {
|
|
|
110
119
|
savingsPercent: 0,
|
|
111
120
|
byFamily: {},
|
|
112
121
|
recentCommands: [],
|
|
113
|
-
bySource: { exec: { count: 0, saved: 0 }, graph: { count: 0, saved: 0 }, memory: { count: 0, saved: 0 } }
|
|
122
|
+
bySource: { exec: { count: 0, saved: 0 }, graph: { count: 0, saved: 0 }, memory: { count: 0, saved: 0 }, docs: { count: 0, saved: 0 } }
|
|
114
123
|
};
|
|
115
124
|
}
|
|
116
125
|
let totalOriginal = 0;
|
|
117
126
|
let totalCompressed = 0;
|
|
118
127
|
const byFamily = /* @__PURE__ */ new Map();
|
|
119
|
-
const bySource = { exec: { count: 0, saved: 0 }, graph: { count: 0, saved: 0 }, memory: { count: 0, saved: 0 } };
|
|
128
|
+
const bySource = { exec: { count: 0, saved: 0 }, graph: { count: 0, saved: 0 }, memory: { count: 0, saved: 0 }, docs: { count: 0, saved: 0 } };
|
|
120
129
|
for (const r of records) {
|
|
121
130
|
totalOriginal += r.originalTokens;
|
|
122
131
|
totalCompressed += r.compressedTokens;
|