kirograph 0.13.1 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +191 -8
- package/dist/bin/commands/caveman.js +7 -2
- package/dist/bin/commands/caveman.js.map +2 -2
- package/dist/bin/commands/compression.js +109 -0
- package/dist/bin/commands/compression.js.map +7 -0
- package/dist/bin/commands/context.js +31 -24
- package/dist/bin/commands/context.js.map +2 -2
- package/dist/bin/commands/exec.js +107 -0
- package/dist/bin/commands/exec.js.map +7 -0
- package/dist/bin/commands/gain.js +119 -0
- package/dist/bin/commands/gain.js.map +7 -0
- package/dist/bin/commands/help.js +10 -1
- package/dist/bin/commands/help.js.map +2 -2
- package/dist/bin/commands/query.js +5 -1
- package/dist/bin/commands/query.js.map +2 -2
- package/dist/bin/commands/uninit.js +1 -1
- package/dist/bin/commands/uninit.js.map +2 -2
- package/dist/bin/commands/utils.js +16 -0
- package/dist/bin/commands/utils.js.map +2 -2
- package/dist/bin/installer/config-prompt.js +9 -2
- package/dist/bin/installer/config-prompt.js.map +2 -2
- package/dist/bin/installer/hooks.js +19 -1
- package/dist/bin/installer/hooks.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 +116 -40
- 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 +4 -2
- package/dist/bin/installer/targets/kiro.js.map +2 -2
- package/dist/bin/kirograph.js +7 -1
- package/dist/bin/kirograph.js.map +3 -3
- package/dist/compression/filters/aws.js +418 -0
- package/dist/compression/filters/aws.js.map +7 -0
- package/dist/compression/filters/docker.js +153 -0
- package/dist/compression/filters/docker.js.map +7 -0
- package/dist/compression/filters/files.js +150 -0
- package/dist/compression/filters/files.js.map +7 -0
- package/dist/compression/filters/generic.js +86 -0
- package/dist/compression/filters/generic.js.map +7 -0
- package/dist/compression/filters/git.js +272 -0
- package/dist/compression/filters/git.js.map +7 -0
- package/dist/compression/filters/github.js +137 -0
- package/dist/compression/filters/github.js.map +7 -0
- package/dist/compression/filters/lint.js +280 -0
- package/dist/compression/filters/lint.js.map +7 -0
- package/dist/compression/filters/misc.js +212 -0
- package/dist/compression/filters/misc.js.map +7 -0
- package/dist/compression/filters/package.js +151 -0
- package/dist/compression/filters/package.js.map +7 -0
- package/dist/compression/filters/test.js +266 -0
- package/dist/compression/filters/test.js.map +7 -0
- package/dist/compression/index.js +144 -0
- package/dist/compression/index.js.map +7 -0
- package/dist/compression/naive-cost.js +94 -0
- package/dist/compression/naive-cost.js.map +7 -0
- package/dist/compression/tracker.js +228 -0
- package/dist/compression/tracker.js.map +7 -0
- package/dist/compression/types.js +17 -0
- package/dist/compression/types.js.map +7 -0
- package/dist/config.js +18 -1
- package/dist/config.js.map +2 -2
- package/dist/mcp/tool-names.js +3 -1
- package/dist/mcp/tool-names.js.map +2 -2
- package/dist/mcp/tools.js +170 -4
- package/dist/mcp/tools.js.map +3 -3
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/bin/installer/steering.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * KiroGraph Installer \u2014 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\n---\n\n## Tool reference\n\n### \\`kirograph_context\\` \u2014 **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\\` \u2014 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\\` \u2014 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\\` \u2014 who calls this?\n\nBFS over incoming \\`calls\\` edges (depth 1).\n\n\\`\\`\\`\nkirograph_callers(symbol: \"processPayment\", limit: 30)\n\\`\\`\\`\n\n### \\`kirograph_callees\\` \u2014 what does this call?\n\nBFS over outgoing \\`calls\\` edges (depth 1).\n\n\\`\\`\\`\nkirograph_callees(symbol: \"handleRequest\")\n\\`\\`\\`\n\n### \\`kirograph_impact\\` \u2014 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\\` \u2014 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\\` \u2014 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\\` \u2014 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\\` \u2014 import cycles\n\nRuns Tarjan's SCC over import edges. No parameters needed.\n\n\\`\\`\\`\nkirograph_circular_deps()\n\\`\\`\\`\n\n### \\`kirograph_files\\` \u2014 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\\` \u2014 index health\n\nReturns file count, symbol count, edge count, embedding coverage, DB size. Call when something feels off.\n\n### \\`kirograph_hotspots\\` \u2014 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\\` \u2014 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\\` \u2014 what changed since a snapshot?\n\nCompares the current graph against a saved snapshot. Shows added/removed symbols and edges. A snapshot must exist \u2014 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\\` \u2014 **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\\` \u2014 stability metrics per package\n\nReturns Ca (afferent \u2014 depended on by), Ce (efferent \u2014 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\\` \u2014 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\\` \u2014 orient, find entry points.\n2. \\`kirograph_node\\` with \\`includeCode: true\\` \u2014 read the relevant symbol.\n3. \\`kirograph_callers\\` / \\`kirograph_callees\\` \u2014 trace the call flow.\n4. \\`kirograph_impact\\` \u2014 check blast radius before editing.\n\n**Refactor planning:**\n1. \\`kirograph_hotspots\\` \u2014 identify the most-connected symbols; changing these is risky.\n2. \\`kirograph_surprising\\` \u2014 surface hidden coupling that will break.\n3. \\`kirograph_impact\\` on specific targets \u2014 confirm blast radius.\n4. \\`kirograph_diff\\` after the refactor \u2014 verify the structural change matches intent.\n\n**Architectural review:**\n1. \\`kirograph_architecture\\` \u2014 get the package and layer map.\n2. \\`kirograph_coupling\\` \u2014 find the most stable (high Ca) and most volatile (high instability) packages.\n3. \\`kirograph_package\\` \u2014 drill into any package of interest.\n4. \\`kirograph_circular_deps\\` \u2014 check for import cycles.\n\n**Code cleanup:**\n1. \\`kirograph_dead_code\\` \u2014 find unreferenced unexported symbols.\n2. \\`kirograph_circular_deps\\` \u2014 find import cycles to untangle.\n3. \\`kirograph_surprising\\` \u2014 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\nfunction buildSteeringContent(cavemanMode?: CavemanMode | 'off'): string {\n const caveman = cavemanMode && cavemanMode !== 'off' ? CAVEMAN_RULES[cavemanMode] : null;\n if (!caveman) return STEERING_CONTENT;\n return STEERING_CONTENT.trimEnd() + '\\n\\n' + caveman + '\\n';\n}\n\nexport function writeSteering(kiroDir: string, cavemanMode?: 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 fs.writeFileSync(steeringPath, buildSteeringContent(cavemanMode));\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;
|
|
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}\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 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;AAQA,SAAS,qBAAqB,MAAgC;AAC5D,QAAM,cAAc,MAAM;AAC1B,QAAM,oBAAoB,MAAM,sBAAsB,SAAS,MAAM,0BAA0B;AAC/F,QAAM,wBAAwB,MAAM,yBAAyB;AAE7D,MAAI,UAAU;AAGd,MAAI,qBAAqB,0BAA0B,OAAO;AACxD,UAAM,UAAU,wBAAwB,qBAA0D;AAClG,cAAU,QAAQ;AAAA,MAChB;AAAA,MACA,QAAQ,KAAK,IAAI;AAAA,IACnB;AAAA,EACF;AAGA,MAAI,CAAC,mBAAmB;AACtB,cAAU,QAAQ,QAAQ,6DAA6D,EAAE;AACzF,cAAU,QAAQ,QAAQ,sDAAsD,EAAE;AAAA,EACpF;AAEA,QAAM,UAAU,eAAe,gBAAgB,QAAQ,6BAAc,WAAW,IAAI;AACpF,MAAI,SAAS;AACX,cAAU,QAAQ,QAAQ,IAAI,SAAS,UAAU;AAAA,EACnD;AAEA,SAAO;AACT;AAEO,SAAS,cAAc,SAAiB,MAAoD;AACjG,QAAM,cAAc,KAAK,KAAK,SAAS,UAAU;AACjD,KAAG,UAAU,aAAa,EAAE,WAAW,KAAK,CAAC;AAC7C,QAAM,eAAe,KAAK,KAAK,aAAa,cAAc;AAG1D,QAAM,eAAgC,OAAO,SAAS,WAClD,EAAE,aAAa,KAAK,IACpB,QAAQ,CAAC;AAEb,KAAG,cAAc,cAAc,qBAAqB,YAAY,CAAC;AACjE,UAAQ,IAAI,qCAAgC,YAAY,EAAE;AAC5D;",
|
|
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'): 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): 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,9 +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) {
|
|
46
|
+
function installKiroLate(projectRoot, cavemanMode, shellCompressionLevel) {
|
|
47
47
|
const kiroDir = path.join(projectRoot, ".kiro");
|
|
48
|
-
|
|
48
|
+
const enableCompression = shellCompressionLevel !== "off";
|
|
49
|
+
(0, import_hooks.writeHooks)(kiroDir, { enableCompression });
|
|
50
|
+
(0, import_steering.writeSteering)(kiroDir, { cavemanMode, enableCompression, shellCompressionLevel });
|
|
49
51
|
(0, import_cli_agent.writeCliAgent)(kiroDir);
|
|
50
52
|
}
|
|
51
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'): void {\n const kiroDir = path.join(projectRoot, '.kiro');\n writeSteering(kiroDir, cavemanMode);\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,
|
|
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): void {\n const kiroDir = path.join(projectRoot, '.kiro');\n const enableCompression = shellCompressionLevel !== 'off';\n // Re-write hooks with compression awareness\n writeHooks(kiroDir, { enableCompression });\n writeSteering(kiroDir, { cavemanMode, enableCompression, shellCompressionLevel: shellCompressionLevel as any });\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,uBAAsC;AAC5H,QAAM,UAAU,KAAK,KAAK,aAAa,OAAO;AAC9C,QAAM,oBAAoB,0BAA0B;AAEpD,+BAAW,SAAS,EAAE,kBAAkB,CAAC;AACzC,qCAAc,SAAS,EAAE,aAAa,mBAAmB,sBAAoD,CAAC;AAC9G,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
|
@@ -28,6 +28,9 @@ var import_surprising = require("./commands/surprising");
|
|
|
28
28
|
var import_snapshot = require("./commands/snapshot");
|
|
29
29
|
var import_path = require("./commands/path");
|
|
30
30
|
var import_export = require("./commands/export");
|
|
31
|
+
var import_gain = require("./commands/gain");
|
|
32
|
+
var import_compression = require("./commands/compression");
|
|
33
|
+
var import_exec = require("./commands/exec");
|
|
31
34
|
process.on("uncaughtException", (err) => {
|
|
32
35
|
const msg = err?.message ?? String(err);
|
|
33
36
|
const isWasmAbort = msg.includes("Aborted(") || msg.includes("RuntimeError") || err?.constructor?.name === "RuntimeError";
|
|
@@ -56,7 +59,7 @@ process.on("uncaughtException", (err) => {
|
|
|
56
59
|
process.exit(1);
|
|
57
60
|
});
|
|
58
61
|
const program = new import_commander.Command();
|
|
59
|
-
program.name("kirograph").description("Semantic code knowledge graph for Kiro").version("0.
|
|
62
|
+
program.name("kirograph").description("Semantic code knowledge graph for Kiro").version("0.14.0").addHelpCommand(true).hook("preAction", (thisCommand) => {
|
|
60
63
|
const name = thisCommand.name();
|
|
61
64
|
if (name === "init") (0, import_banner.printBanner)();
|
|
62
65
|
});
|
|
@@ -85,6 +88,9 @@ program.name("kirograph").description("Semantic code knowledge graph for Kiro").
|
|
|
85
88
|
(0, import_snapshot.register)(program);
|
|
86
89
|
(0, import_path.register)(program);
|
|
87
90
|
(0, import_export.register)(program);
|
|
91
|
+
(0, import_gain.register)(program);
|
|
92
|
+
(0, import_compression.register)(program);
|
|
93
|
+
(0, import_exec.register)(program);
|
|
88
94
|
if (process.argv.length === 2) {
|
|
89
95
|
(0, import_banner.printBanner)();
|
|
90
96
|
(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';\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);\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;
|
|
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", "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';\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);\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;AAQzC,QAAQ,GAAG,qBAAqB,CAAC,QAAe;AAC9C,QAAM,MAAM,KAAK,WAAW,OAAO,GAAG;AACtC,QAAM,cAAc,IAAI,SAAS,UAAU,KAAK,IAAI,SAAS,cAAc,KAAM,KAAa,aAAa,SAAS;AAEpH,MAAI,aAAa;AACf,YAAQ,OAAO,MAAM;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI,CAAC;AACZ,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,UAAQ,OAAO,MAAM,mBAAmB,GAAG;AAAA,CAAI;AAC/C,UAAQ,KAAK,CAAC;AAChB,CAAC;AAID,MAAM,UAAU,IAAI,yBAAQ;AAE5B,QACG,KAAK,WAAW,EAChB,YAAY,wCAAwC,EACpD,QAAQ,QAAe,EACvB,eAAe,IAAI,EACnB,KAAK,aAAa,CAAC,gBAAgB;AAClC,QAAM,OAAO,YAAY,KAAK;AAC9B,MAAI,SAAS,OAAQ,gCAAY;AACnC,CAAC;AAAA,IAEH,eAAAA,UAAgB,OAAO;AAAA,IACvB,YAAAC,UAAa,OAAO;AAAA,IACpB,cAAAC,UAAe,OAAO;AAAA,IACtB,gBAAAC,UAAc,OAAO;AAAA,IACrB,YAAAC,UAAa,OAAO;AAAA,IACpB,qBAAAC,UAAoB,OAAO;AAAA,IAC3B,kBAAAC,UAAkB,OAAO;AAAA,IACzB,cAAAC,UAAe,OAAO;AAAA,IACtB,aAAAC,UAAc,OAAO;AAAA,IACrB,eAAAC,UAAgB,OAAO;AAAA,IACvB,aAAAC,UAAc,OAAO;AAAA,IACrB,gBAAAC,UAAiB,OAAO;AAAA,IACxB,cAAAC,UAAe,OAAO;AAAA,IACtB,aAAAC,UAAc,OAAO;AAAA,IACrB,iBAAAC,UAAkB,OAAO;AAAA,IACzB,oBAAAC,UAAqB,OAAO;AAAA,IAC5B,gBAAAC,UAAiB,OAAO;AAAA,IACxB,eAAAC,UAAgB,OAAO;AAAA,IACvB,eAAAC,UAAgB,OAAO;AAAA,IACvB,iBAAAC,UAAiB,OAAO;AAAA,IACxB,gBAAAC,UAAiB,OAAO;AAAA,IACxB,kBAAAC,UAAmB,OAAO;AAAA,IAC1B,gBAAAC,UAAiB,OAAO;AAAA,IACxB,YAAAC,UAAa,OAAO;AAAA,IACpB,cAAAC,UAAe,OAAO;AAAA,IACtB,YAAAC,UAAa,OAAO;AAAA,IACpB,mBAAAC,UAAoB,OAAO;AAAA,IAC3B,YAAAC,UAAa,OAAO;AAGpB,IAAI,QAAQ,KAAK,WAAW,GAAG;AAC7B,iCAAY;AACZ,oCAAiB;AACjB,UAAQ,KAAK,CAAC;AAChB;AAAA,IAEA,YAAAC,UAAa,OAAO;AAEpB,QAAQ,MAAM,QAAQ,IAAI;",
|
|
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", "registerHelp"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var aws_exports = {};
|
|
20
|
+
__export(aws_exports, {
|
|
21
|
+
awsFilter: () => awsFilter
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(aws_exports);
|
|
24
|
+
const awsFilter = {
|
|
25
|
+
name: "aws",
|
|
26
|
+
matches(command) {
|
|
27
|
+
return /\baws\s/.test(command);
|
|
28
|
+
},
|
|
29
|
+
filter(command, rawOutput, level) {
|
|
30
|
+
const subcommand = extractAwsSubcommand(command);
|
|
31
|
+
switch (subcommand) {
|
|
32
|
+
case "sts:get-caller-identity":
|
|
33
|
+
return filterStsIdentity(rawOutput, level);
|
|
34
|
+
case "ec2:describe-instances":
|
|
35
|
+
return filterEc2Instances(rawOutput, level);
|
|
36
|
+
case "lambda:list-functions":
|
|
37
|
+
return filterLambdaFunctions(rawOutput, level);
|
|
38
|
+
case "logs:get-log-events":
|
|
39
|
+
return filterLogEvents(rawOutput, level);
|
|
40
|
+
case "cloudformation:describe-stack-events":
|
|
41
|
+
return filterCfnEvents(rawOutput, level);
|
|
42
|
+
case "dynamodb:scan":
|
|
43
|
+
case "dynamodb:query":
|
|
44
|
+
case "dynamodb:get-item":
|
|
45
|
+
return filterDynamoDB(rawOutput, level);
|
|
46
|
+
case "iam:list-roles":
|
|
47
|
+
return filterIamRoles(rawOutput, level);
|
|
48
|
+
case "iam:list-policies":
|
|
49
|
+
return filterIamPolicies(rawOutput, level);
|
|
50
|
+
case "s3:ls":
|
|
51
|
+
return filterS3Ls(rawOutput, level);
|
|
52
|
+
case "s3:cp":
|
|
53
|
+
case "s3:sync":
|
|
54
|
+
return filterS3Transfer(rawOutput, level);
|
|
55
|
+
case "ecs:list-tasks":
|
|
56
|
+
case "ecs:describe-tasks":
|
|
57
|
+
return filterEcsTasks(rawOutput, level);
|
|
58
|
+
case "ecs:describe-services":
|
|
59
|
+
return filterEcsServices(rawOutput, level);
|
|
60
|
+
case "sqs:list-queues":
|
|
61
|
+
return filterSqsQueues(rawOutput, level);
|
|
62
|
+
case "sns:list-topics":
|
|
63
|
+
return filterSnsTopics(rawOutput, level);
|
|
64
|
+
default:
|
|
65
|
+
return filterGenericAws(rawOutput, level);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
function extractAwsSubcommand(command) {
|
|
70
|
+
const match = command.match(/aws\s+(\S+)\s+(\S+)/);
|
|
71
|
+
if (match) return `${match[1]}:${match[2]}`;
|
|
72
|
+
const serviceOnly = command.match(/aws\s+(\S+)/);
|
|
73
|
+
if (serviceOnly) return serviceOnly[1];
|
|
74
|
+
return "";
|
|
75
|
+
}
|
|
76
|
+
function filterStsIdentity(raw, level) {
|
|
77
|
+
try {
|
|
78
|
+
const data = JSON.parse(raw);
|
|
79
|
+
if (level === "ultra") {
|
|
80
|
+
return { output: `${data.Account} ${data.Arn?.split("/").pop() || ""}`, strategy: "aws:sts:ultra" };
|
|
81
|
+
}
|
|
82
|
+
return { output: `Account: ${data.Account}
|
|
83
|
+
Arn: ${data.Arn}
|
|
84
|
+
UserId: ${data.UserId}`, strategy: "aws:sts" };
|
|
85
|
+
} catch {
|
|
86
|
+
return { output: raw, strategy: "aws:sts:passthrough" };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function filterEc2Instances(raw, level) {
|
|
90
|
+
try {
|
|
91
|
+
const data = JSON.parse(raw);
|
|
92
|
+
const instances = [];
|
|
93
|
+
for (const reservation of data.Reservations || []) {
|
|
94
|
+
for (const inst of reservation.Instances || []) {
|
|
95
|
+
const name = inst.Tags?.find((t) => t.Key === "Name")?.Value || "";
|
|
96
|
+
const id = inst.InstanceId || "";
|
|
97
|
+
const state = inst.State?.Name || "";
|
|
98
|
+
const type = inst.InstanceType || "";
|
|
99
|
+
const ip = inst.PrivateIpAddress || "";
|
|
100
|
+
if (level === "ultra") {
|
|
101
|
+
instances.push(`${id} ${state} ${type}${name ? " " + name : ""}`);
|
|
102
|
+
} else {
|
|
103
|
+
instances.push(`${id} ${state.padEnd(10)} ${type.padEnd(12)} ${ip.padEnd(15)} ${name}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (instances.length === 0) return { output: "no instances", strategy: "aws:ec2:empty" };
|
|
108
|
+
if (level === "ultra") {
|
|
109
|
+
return { output: instances.join("\n"), strategy: "aws:ec2:ultra" };
|
|
110
|
+
}
|
|
111
|
+
const header = `${instances.length} instance(s):`;
|
|
112
|
+
return { output: `${header}
|
|
113
|
+
${instances.join("\n")}`, strategy: "aws:ec2" };
|
|
114
|
+
} catch {
|
|
115
|
+
return filterGenericAws(raw, level);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function filterLambdaFunctions(raw, level) {
|
|
119
|
+
try {
|
|
120
|
+
const data = JSON.parse(raw);
|
|
121
|
+
const functions = data.Functions || [];
|
|
122
|
+
if (functions.length === 0) return { output: "no functions", strategy: "aws:lambda:empty" };
|
|
123
|
+
const lines = functions.map((fn) => {
|
|
124
|
+
const name = fn.FunctionName || "";
|
|
125
|
+
const runtime = fn.Runtime || "";
|
|
126
|
+
const memory = fn.MemorySize || "";
|
|
127
|
+
const timeout = fn.Timeout || "";
|
|
128
|
+
if (level === "ultra") {
|
|
129
|
+
return `${name} ${runtime} ${memory}MB`;
|
|
130
|
+
}
|
|
131
|
+
return `${name.padEnd(40)} ${runtime.padEnd(14)} ${String(memory).padStart(4)}MB ${String(timeout).padStart(3)}s`;
|
|
132
|
+
});
|
|
133
|
+
if (level === "ultra") {
|
|
134
|
+
return { output: `${functions.length} functions:
|
|
135
|
+
${lines.join("\n")}`, strategy: "aws:lambda:ultra" };
|
|
136
|
+
}
|
|
137
|
+
return { output: `${functions.length} function(s):
|
|
138
|
+
${lines.join("\n")}`, strategy: "aws:lambda" };
|
|
139
|
+
} catch {
|
|
140
|
+
return filterGenericAws(raw, level);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function filterLogEvents(raw, level) {
|
|
144
|
+
try {
|
|
145
|
+
const data = JSON.parse(raw);
|
|
146
|
+
const events = data.events || [];
|
|
147
|
+
if (events.length === 0) return { output: "no events", strategy: "aws:logs:empty" };
|
|
148
|
+
const lines = events.map((e) => {
|
|
149
|
+
const ts = new Date(e.timestamp).toISOString().slice(11, 23);
|
|
150
|
+
const msg = (e.message || "").trim();
|
|
151
|
+
return `${ts} ${msg}`;
|
|
152
|
+
});
|
|
153
|
+
const deduped = [];
|
|
154
|
+
let lastPattern = "";
|
|
155
|
+
let repeatCount = 0;
|
|
156
|
+
for (const line of lines) {
|
|
157
|
+
const pattern = line.replace(/\d+/g, "N");
|
|
158
|
+
if (pattern === lastPattern) {
|
|
159
|
+
repeatCount++;
|
|
160
|
+
} else {
|
|
161
|
+
if (repeatCount > 1) deduped.push(` \u2026repeated ${repeatCount}x`);
|
|
162
|
+
deduped.push(line);
|
|
163
|
+
lastPattern = pattern;
|
|
164
|
+
repeatCount = 1;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (repeatCount > 1) deduped.push(` \u2026repeated ${repeatCount}x`);
|
|
168
|
+
const maxLines = level === "ultra" ? 20 : level === "aggressive" ? 40 : 60;
|
|
169
|
+
const shown = deduped.slice(-maxLines);
|
|
170
|
+
const omitted = deduped.length > maxLines ? `\u2026(${deduped.length - maxLines} earlier events omitted)
|
|
171
|
+
` : "";
|
|
172
|
+
return { output: `${omitted}${shown.join("\n")}`, strategy: "aws:logs" };
|
|
173
|
+
} catch {
|
|
174
|
+
return filterGenericAws(raw, level);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function filterCfnEvents(raw, level) {
|
|
178
|
+
try {
|
|
179
|
+
const data = JSON.parse(raw);
|
|
180
|
+
const events = data.StackEvents || [];
|
|
181
|
+
if (events.length === 0) return { output: "no events", strategy: "aws:cfn:empty" };
|
|
182
|
+
const sorted = [...events].sort((a, b) => {
|
|
183
|
+
const aFailed = (a.ResourceStatus || "").includes("FAILED") ? 0 : 1;
|
|
184
|
+
const bFailed = (b.ResourceStatus || "").includes("FAILED") ? 0 : 1;
|
|
185
|
+
if (aFailed !== bFailed) return aFailed - bFailed;
|
|
186
|
+
return new Date(b.Timestamp).getTime() - new Date(a.Timestamp).getTime();
|
|
187
|
+
});
|
|
188
|
+
const lines = sorted.map((e) => {
|
|
189
|
+
const status = e.ResourceStatus || "";
|
|
190
|
+
const logical = e.LogicalResourceId || "";
|
|
191
|
+
const reason = e.ResourceStatusReason || "";
|
|
192
|
+
const isFailed = status.includes("FAILED");
|
|
193
|
+
if (level === "ultra") {
|
|
194
|
+
return `${isFailed ? "\u2717" : "\xB7"} ${logical} ${status}${reason ? ": " + reason.slice(0, 60) : ""}`;
|
|
195
|
+
}
|
|
196
|
+
return `${status.padEnd(28)} ${logical}${reason ? "\n \u2192 " + reason : ""}`;
|
|
197
|
+
});
|
|
198
|
+
const maxLines = level === "ultra" ? 15 : level === "aggressive" ? 25 : 40;
|
|
199
|
+
const shown = lines.slice(0, maxLines).join("\n");
|
|
200
|
+
const extra = lines.length > maxLines ? `
|
|
201
|
+
\u2026+${lines.length - maxLines} more events` : "";
|
|
202
|
+
const failures = events.filter((e) => (e.ResourceStatus || "").includes("FAILED")).length;
|
|
203
|
+
const header = failures > 0 ? `${failures} FAILED, ${events.length} total events:` : `${events.length} events:`;
|
|
204
|
+
return { output: `${header}
|
|
205
|
+
${shown}${extra}`, strategy: "aws:cfn" };
|
|
206
|
+
} catch {
|
|
207
|
+
return filterGenericAws(raw, level);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function filterDynamoDB(raw, level) {
|
|
211
|
+
try {
|
|
212
|
+
const data = JSON.parse(raw);
|
|
213
|
+
const unwrapped = unwrapDynamoTypes(data);
|
|
214
|
+
const output = JSON.stringify(unwrapped, null, level === "ultra" ? 0 : 2);
|
|
215
|
+
return { output, strategy: "aws:dynamodb" };
|
|
216
|
+
} catch {
|
|
217
|
+
return filterGenericAws(raw, level);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function unwrapDynamoTypes(obj) {
|
|
221
|
+
if (obj === null || obj === void 0) return obj;
|
|
222
|
+
if (Array.isArray(obj)) return obj.map(unwrapDynamoTypes);
|
|
223
|
+
if (typeof obj !== "object") return obj;
|
|
224
|
+
const keys = Object.keys(obj);
|
|
225
|
+
if (keys.length === 1) {
|
|
226
|
+
const key = keys[0];
|
|
227
|
+
if (key === "S") return obj.S;
|
|
228
|
+
if (key === "N") return Number(obj.N);
|
|
229
|
+
if (key === "BOOL") return obj.BOOL;
|
|
230
|
+
if (key === "NULL") return null;
|
|
231
|
+
if (key === "L") return obj.L.map(unwrapDynamoTypes);
|
|
232
|
+
if (key === "M") return unwrapDynamoTypes(obj.M);
|
|
233
|
+
if (key === "SS") return obj.SS;
|
|
234
|
+
if (key === "NS") return obj.NS.map(Number);
|
|
235
|
+
if (key === "BS") return obj.BS;
|
|
236
|
+
}
|
|
237
|
+
const result = {};
|
|
238
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
239
|
+
result[k] = unwrapDynamoTypes(v);
|
|
240
|
+
}
|
|
241
|
+
return result;
|
|
242
|
+
}
|
|
243
|
+
function filterIamRoles(raw, level) {
|
|
244
|
+
try {
|
|
245
|
+
const data = JSON.parse(raw);
|
|
246
|
+
const roles = data.Roles || [];
|
|
247
|
+
if (roles.length === 0) return { output: "no roles", strategy: "aws:iam-roles:empty" };
|
|
248
|
+
const lines = roles.map((r) => {
|
|
249
|
+
const name = r.RoleName || "";
|
|
250
|
+
const path = r.Path || "/";
|
|
251
|
+
const created = r.CreateDate ? r.CreateDate.slice(0, 10) : "";
|
|
252
|
+
if (level === "ultra") return name;
|
|
253
|
+
return `${name.padEnd(40)} ${path.padEnd(10)} ${created}`;
|
|
254
|
+
});
|
|
255
|
+
const maxLines = level === "ultra" ? 30 : level === "aggressive" ? 40 : 60;
|
|
256
|
+
const shown = lines.slice(0, maxLines).join("\n");
|
|
257
|
+
const extra = lines.length > maxLines ? `
|
|
258
|
+
\u2026+${lines.length - maxLines} more` : "";
|
|
259
|
+
return { output: `${roles.length} roles:
|
|
260
|
+
${shown}${extra}`, strategy: "aws:iam-roles" };
|
|
261
|
+
} catch {
|
|
262
|
+
return filterGenericAws(raw, level);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function filterIamPolicies(raw, level) {
|
|
266
|
+
try {
|
|
267
|
+
const data = JSON.parse(raw);
|
|
268
|
+
const policies = data.Policies || [];
|
|
269
|
+
if (policies.length === 0) return { output: "no policies", strategy: "aws:iam-policies:empty" };
|
|
270
|
+
const lines = policies.map((p) => {
|
|
271
|
+
if (level === "ultra") return p.PolicyName || "";
|
|
272
|
+
return `${(p.PolicyName || "").padEnd(40)} ${p.Arn || ""}`;
|
|
273
|
+
});
|
|
274
|
+
const maxLines = level === "ultra" ? 30 : 50;
|
|
275
|
+
const shown = lines.slice(0, maxLines).join("\n");
|
|
276
|
+
const extra = lines.length > maxLines ? `
|
|
277
|
+
\u2026+${lines.length - maxLines} more` : "";
|
|
278
|
+
return { output: `${policies.length} policies:
|
|
279
|
+
${shown}${extra}`, strategy: "aws:iam-policies" };
|
|
280
|
+
} catch {
|
|
281
|
+
return filterGenericAws(raw, level);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
function filterS3Ls(raw, level) {
|
|
285
|
+
const lines = raw.split("\n").filter((l) => l.trim());
|
|
286
|
+
if (lines.length === 0) return { output: "empty", strategy: "aws:s3-ls:empty" };
|
|
287
|
+
if (lines.length <= 20) return { output: raw, strategy: "aws:s3-ls:short" };
|
|
288
|
+
if (level === "ultra") {
|
|
289
|
+
return { output: `${lines.length} objects`, strategy: "aws:s3-ls:ultra" };
|
|
290
|
+
}
|
|
291
|
+
const maxLines = level === "aggressive" ? 30 : 50;
|
|
292
|
+
const shown = lines.slice(0, maxLines).join("\n");
|
|
293
|
+
const extra = lines.length > maxLines ? `
|
|
294
|
+
\u2026+${lines.length - maxLines} more objects` : "";
|
|
295
|
+
return { output: `${shown}${extra}`, strategy: "aws:s3-ls" };
|
|
296
|
+
}
|
|
297
|
+
function filterS3Transfer(raw, level) {
|
|
298
|
+
const lines = raw.split("\n").filter((l) => l.trim());
|
|
299
|
+
const meaningful = lines.filter((l) => !l.includes("Completed") && !l.includes("upload:") || l.includes("upload: s3://"));
|
|
300
|
+
if (meaningful.length === 0) return { output: "ok", strategy: "aws:s3-transfer" };
|
|
301
|
+
if (level === "ultra") {
|
|
302
|
+
const count = lines.filter((l) => l.includes("upload:") || l.includes("copy:")).length;
|
|
303
|
+
return { output: `ok ${count} objects`, strategy: "aws:s3-transfer:ultra" };
|
|
304
|
+
}
|
|
305
|
+
return { output: meaningful.slice(0, 20).join("\n"), strategy: "aws:s3-transfer" };
|
|
306
|
+
}
|
|
307
|
+
function filterEcsTasks(raw, level) {
|
|
308
|
+
try {
|
|
309
|
+
const data = JSON.parse(raw);
|
|
310
|
+
const tasks = data.tasks || data.taskArns || [];
|
|
311
|
+
if (tasks.length === 0) return { output: "no tasks", strategy: "aws:ecs-tasks:empty" };
|
|
312
|
+
if (Array.isArray(tasks) && typeof tasks[0] === "string") {
|
|
313
|
+
const short = tasks.map((arn) => arn.split("/").pop());
|
|
314
|
+
return { output: `${tasks.length} tasks:
|
|
315
|
+
${short.join("\n")}`, strategy: "aws:ecs-tasks" };
|
|
316
|
+
}
|
|
317
|
+
const lines = tasks.map((t) => {
|
|
318
|
+
const id = (t.taskArn || "").split("/").pop();
|
|
319
|
+
const status = t.lastStatus || "";
|
|
320
|
+
const group = t.group || "";
|
|
321
|
+
if (level === "ultra") return `${id} ${status}`;
|
|
322
|
+
return `${id} ${status.padEnd(10)} ${group}`;
|
|
323
|
+
});
|
|
324
|
+
return { output: `${tasks.length} tasks:
|
|
325
|
+
${lines.join("\n")}`, strategy: "aws:ecs-tasks" };
|
|
326
|
+
} catch {
|
|
327
|
+
return filterGenericAws(raw, level);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
function filterEcsServices(raw, level) {
|
|
331
|
+
try {
|
|
332
|
+
const data = JSON.parse(raw);
|
|
333
|
+
const services = data.services || [];
|
|
334
|
+
if (services.length === 0) return { output: "no services", strategy: "aws:ecs-services:empty" };
|
|
335
|
+
const lines = services.map((s) => {
|
|
336
|
+
const name = s.serviceName || "";
|
|
337
|
+
const status = s.status || "";
|
|
338
|
+
const running = s.runningCount ?? 0;
|
|
339
|
+
const desired = s.desiredCount ?? 0;
|
|
340
|
+
if (level === "ultra") return `${name} ${running}/${desired}`;
|
|
341
|
+
return `${name.padEnd(30)} ${status.padEnd(8)} ${running}/${desired} tasks`;
|
|
342
|
+
});
|
|
343
|
+
return { output: `${services.length} services:
|
|
344
|
+
${lines.join("\n")}`, strategy: "aws:ecs-services" };
|
|
345
|
+
} catch {
|
|
346
|
+
return filterGenericAws(raw, level);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
function filterSqsQueues(raw, level) {
|
|
350
|
+
try {
|
|
351
|
+
const data = JSON.parse(raw);
|
|
352
|
+
const urls = data.QueueUrls || [];
|
|
353
|
+
if (urls.length === 0) return { output: "no queues", strategy: "aws:sqs:empty" };
|
|
354
|
+
const names = urls.map((url) => url.split("/").pop());
|
|
355
|
+
if (level === "ultra") return { output: `${names.length} queues`, strategy: "aws:sqs:ultra" };
|
|
356
|
+
return { output: `${names.length} queues:
|
|
357
|
+
${names.join("\n")}`, strategy: "aws:sqs" };
|
|
358
|
+
} catch {
|
|
359
|
+
return filterGenericAws(raw, level);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
function filterSnsTopics(raw, level) {
|
|
363
|
+
try {
|
|
364
|
+
const data = JSON.parse(raw);
|
|
365
|
+
const topics = data.Topics || [];
|
|
366
|
+
if (topics.length === 0) return { output: "no topics", strategy: "aws:sns:empty" };
|
|
367
|
+
const arns = topics.map((t) => (t.TopicArn || "").split(":").pop());
|
|
368
|
+
if (level === "ultra") return { output: `${arns.length} topics`, strategy: "aws:sns:ultra" };
|
|
369
|
+
return { output: `${arns.length} topics:
|
|
370
|
+
${arns.join("\n")}`, strategy: "aws:sns" };
|
|
371
|
+
} catch {
|
|
372
|
+
return filterGenericAws(raw, level);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
function filterGenericAws(raw, level) {
|
|
376
|
+
try {
|
|
377
|
+
const data = JSON.parse(raw);
|
|
378
|
+
const stripped = stripAwsVerboseFields(data);
|
|
379
|
+
const indent = level === "ultra" ? 0 : 2;
|
|
380
|
+
const output = JSON.stringify(stripped, null, indent);
|
|
381
|
+
const maxChars = level === "ultra" ? 2e3 : level === "aggressive" ? 5e3 : 1e4;
|
|
382
|
+
if (output.length > maxChars) {
|
|
383
|
+
return { output: output.slice(0, maxChars) + "\n\u2026(truncated)", strategy: "aws:generic:truncated" };
|
|
384
|
+
}
|
|
385
|
+
return { output, strategy: "aws:generic:json" };
|
|
386
|
+
} catch {
|
|
387
|
+
const lines = raw.split("\n");
|
|
388
|
+
const maxLines = level === "ultra" ? 20 : level === "aggressive" ? 40 : 60;
|
|
389
|
+
if (lines.length <= maxLines) return { output: raw, strategy: "aws:generic:text" };
|
|
390
|
+
const shown = lines.slice(0, maxLines).join("\n");
|
|
391
|
+
return { output: `${shown}
|
|
392
|
+
\u2026+${lines.length - maxLines} more lines`, strategy: "aws:generic:truncated" };
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
function stripAwsVerboseFields(obj) {
|
|
396
|
+
if (obj === null || obj === void 0) return obj;
|
|
397
|
+
if (Array.isArray(obj)) return obj.map(stripAwsVerboseFields);
|
|
398
|
+
if (typeof obj !== "object") return obj;
|
|
399
|
+
const STRIP_KEYS = /* @__PURE__ */ new Set([
|
|
400
|
+
"AssumeRolePolicyDocument",
|
|
401
|
+
"PolicyDocument",
|
|
402
|
+
"Document",
|
|
403
|
+
"ResponseMetadata",
|
|
404
|
+
"Marker",
|
|
405
|
+
"IsTruncated"
|
|
406
|
+
]);
|
|
407
|
+
const result = {};
|
|
408
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
409
|
+
if (STRIP_KEYS.has(k)) continue;
|
|
410
|
+
result[k] = stripAwsVerboseFields(v);
|
|
411
|
+
}
|
|
412
|
+
return result;
|
|
413
|
+
}
|
|
414
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
415
|
+
0 && (module.exports = {
|
|
416
|
+
awsFilter
|
|
417
|
+
});
|
|
418
|
+
//# sourceMappingURL=aws.js.map
|