kynjal-cli 3.1.3 → 4.0.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/.claude/agents/core/coder.md +1 -1
- package/.claude/agents/core/planner.md +2 -2
- package/.claude/agents/core/researcher.md +1 -1
- package/.claude/agents/core/reviewer.md +1 -1
- package/.claude/agents/core/tester.md +1 -1
- package/.claude/agents/data/data-ml-model.md +4 -4
- package/.claude/agents/development/dev-backend-api.md +4 -4
- package/.claude/agents/documentation/docs-api-openapi.md +4 -4
- package/.claude/agents/github/code-review-swarm.md +2 -2
- package/.claude/agents/github/issue-tracker.md +2 -2
- package/.claude/agents/github/pr-manager.md +2 -2
- package/.claude/agents/github/release-manager.md +2 -2
- package/.claude/agents/github/workflow-automation.md +2 -2
- package/.claude/agents/sparc/architecture.md +3 -3
- package/.claude/agents/sparc/pseudocode.md +2 -2
- package/.claude/agents/sparc/refinement.md +3 -3
- package/.claude/agents/sparc/specification.md +2 -2
- package/.claude/agents/swarm/adaptive-coordinator.md +1 -1
- package/.claude/agents/swarm/hierarchical-coordinator.md +1 -1
- package/.claude/agents/swarm/mesh-coordinator.md +1 -1
- package/.claude/agents/templates/base-template-generator.md +25 -4
- package/.claude/agents/templates/sparc-coordinator.md +3 -3
- package/.claude/helpers/auto-commit.sh +1 -1
- package/.claude/helpers/auto-memory-hook.mjs +27 -9
- package/.claude/helpers/hook-handler.cjs +58 -18
- package/.claude/helpers/statusline.cjs +14 -33
- package/.claude/helpers/statusline.js +3 -3
- package/.claude/settings.json +9 -9
- package/.claude/skills/reasoningbank-intelligence/SKILL.md +2 -2
- package/.claude/skills/swarm-orchestration/SKILL.md +1 -1
- package/README.md +383 -170
- package/bin/cli.js +6 -6
- package/bin/mcp-server.js +1 -1
- package/bin/preinstall.cjs +2 -0
- package/dist/src/appliance/gguf-engine.js +664 -0
- package/dist/src/appliance/gguf-engine.js.map +1 -0
- package/dist/src/appliance/ruvllm-bridge.js +492 -0
- package/dist/src/appliance/ruvllm-bridge.js.map +1 -0
- package/dist/src/appliance/rvfa-builder.js +383 -0
- package/dist/src/appliance/rvfa-builder.js.map +1 -0
- package/dist/src/appliance/rvfa-distribution.js +533 -0
- package/dist/src/appliance/rvfa-distribution.js.map +1 -0
- package/dist/src/appliance/rvfa-format.js +465 -0
- package/dist/src/appliance/rvfa-format.js.map +1 -0
- package/dist/src/appliance/rvfa-runner.js +373 -0
- package/dist/src/appliance/rvfa-runner.js.map +1 -0
- package/dist/src/appliance/rvfa-signing.js +469 -0
- package/dist/src/appliance/rvfa-signing.js.map +1 -0
- package/dist/src/benchmarks/pretrain/index.js +542 -331
- package/dist/src/benchmarks/pretrain/index.js.map +1 -1
- package/dist/src/commands/agent.d.ts.map +1 -1
- package/dist/src/commands/agent.js +725 -502
- package/dist/src/commands/agent.js.map +1 -1
- package/dist/src/commands/analyze.js +1548 -1218
- package/dist/src/commands/analyze.js.map +1 -1
- package/dist/src/commands/appliance-advanced.d.ts +9 -0
- package/dist/src/commands/appliance-advanced.d.ts.map +1 -0
- package/dist/src/commands/appliance-advanced.js +324 -0
- package/dist/src/commands/appliance-advanced.js.map +1 -0
- package/dist/src/commands/appliance.d.ts +8 -0
- package/dist/src/commands/appliance.d.ts.map +1 -0
- package/dist/src/commands/appliance.js +581 -0
- package/dist/src/commands/appliance.js.map +1 -0
- package/dist/src/commands/benchmark.js +523 -372
- package/dist/src/commands/benchmark.js.map +1 -1
- package/dist/src/commands/claims.js +364 -274
- package/dist/src/commands/claims.js.map +1 -1
- package/dist/src/commands/cleanup.d.ts +13 -0
- package/dist/src/commands/cleanup.d.ts.map +1 -0
- package/dist/src/commands/cleanup.js +262 -0
- package/dist/src/commands/cleanup.js.map +1 -0
- package/dist/src/commands/completions.js +118 -477
- package/dist/src/commands/completions.js.map +1 -1
- package/dist/src/commands/config.js +303 -237
- package/dist/src/commands/config.js.map +1 -1
- package/dist/src/commands/daemon.d.ts.map +1 -1
- package/dist/src/commands/daemon.js +597 -425
- package/dist/src/commands/daemon.js.map +1 -1
- package/dist/src/commands/deployment.js +275 -194
- package/dist/src/commands/deployment.js.map +1 -1
- package/dist/src/commands/doctor.d.ts.map +1 -1
- package/dist/src/commands/doctor.js +690 -460
- package/dist/src/commands/doctor.js.map +1 -1
- package/dist/src/commands/embeddings.js +1543 -1293
- package/dist/src/commands/embeddings.js.map +1 -1
- package/dist/src/commands/guidance.js +596 -449
- package/dist/src/commands/guidance.js.map +1 -1
- package/dist/src/commands/hive-mind.js +938 -854
- package/dist/src/commands/hive-mind.js.map +1 -1
- package/dist/src/commands/hooks.d.ts.map +1 -1
- package/dist/src/commands/hooks.js +3677 -2570
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/commands/index.js +322 -122
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/init.d.ts +1 -1
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +943 -787
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/issues.js +558 -383
- package/dist/src/commands/issues.js.map +1 -1
- package/dist/src/commands/mcp.d.ts.map +1 -1
- package/dist/src/commands/mcp.js +605 -475
- package/dist/src/commands/mcp.js.map +1 -1
- package/dist/src/commands/memory.d.ts.map +1 -1
- package/dist/src/commands/memory.js +1031 -814
- package/dist/src/commands/memory.js.map +1 -1
- package/dist/src/commands/migrate.js +347 -282
- package/dist/src/commands/migrate.js.map +1 -1
- package/dist/src/commands/neural.d.ts.map +1 -1
- package/dist/src/commands/neural.js +1563 -1283
- package/dist/src/commands/neural.js.map +1 -1
- package/dist/src/commands/performance.js +643 -497
- package/dist/src/commands/performance.js.map +1 -1
- package/dist/src/commands/plugins.js +841 -668
- package/dist/src/commands/plugins.js.map +1 -1
- package/dist/src/commands/process.js +447 -392
- package/dist/src/commands/process.js.map +1 -1
- package/dist/src/commands/progress.js +256 -162
- package/dist/src/commands/progress.js.map +1 -1
- package/dist/src/commands/providers.js +220 -150
- package/dist/src/commands/providers.js.map +1 -1
- package/dist/src/commands/route.js +665 -520
- package/dist/src/commands/route.js.map +1 -1
- package/dist/src/commands/ruvector/backup.js +651 -505
- package/dist/src/commands/ruvector/backup.js.map +1 -1
- package/dist/src/commands/ruvector/benchmark.js +401 -349
- package/dist/src/commands/ruvector/benchmark.js.map +1 -1
- package/dist/src/commands/ruvector/import.js +267 -225
- package/dist/src/commands/ruvector/import.js.map +1 -1
- package/dist/src/commands/ruvector/index.js +75 -37
- package/dist/src/commands/ruvector/index.js.map +1 -1
- package/dist/src/commands/ruvector/init.js +359 -336
- package/dist/src/commands/ruvector/init.js.map +1 -1
- package/dist/src/commands/ruvector/migrate.js +322 -335
- package/dist/src/commands/ruvector/migrate.js.map +1 -1
- package/dist/src/commands/ruvector/optimize.js +431 -375
- package/dist/src/commands/ruvector/optimize.js.map +1 -1
- package/dist/src/commands/ruvector/setup.js +117 -703
- package/dist/src/commands/ruvector/setup.js.map +1 -1
- package/dist/src/commands/ruvector/status.js +419 -364
- package/dist/src/commands/ruvector/status.js.map +1 -1
- package/dist/src/commands/security.d.ts.map +1 -1
- package/dist/src/commands/security.js +610 -456
- package/dist/src/commands/security.js.map +1 -1
- package/dist/src/commands/session.d.ts +1 -1
- package/dist/src/commands/session.js +627 -505
- package/dist/src/commands/session.js.map +1 -1
- package/dist/src/commands/start.d.ts +1 -1
- package/dist/src/commands/start.js +368 -271
- package/dist/src/commands/start.js.map +1 -1
- package/dist/src/commands/status.d.ts +1 -1
- package/dist/src/commands/status.d.ts.map +1 -1
- package/dist/src/commands/status.js +492 -379
- package/dist/src/commands/status.js.map +1 -1
- package/dist/src/commands/swarm.js +488 -408
- package/dist/src/commands/swarm.js.map +1 -1
- package/dist/src/commands/task.d.ts +1 -1
- package/dist/src/commands/task.js +539 -424
- package/dist/src/commands/task.js.map +1 -1
- package/dist/src/commands/transfer-store.js +412 -322
- package/dist/src/commands/transfer-store.js.map +1 -1
- package/dist/src/commands/update.js +291 -196
- package/dist/src/commands/update.js.map +1 -1
- package/dist/src/commands/workflow.js +486 -386
- package/dist/src/commands/workflow.js.map +1 -1
- package/dist/src/config-adapter.js +40 -39
- package/dist/src/config-adapter.js.map +1 -1
- package/dist/src/index.js +416 -312
- package/dist/src/index.js.map +1 -1
- package/dist/src/infrastructure/in-memory-repositories.js +507 -246
- package/dist/src/infrastructure/in-memory-repositories.js.map +1 -1
- package/dist/src/init/claudemd-generator.js +78 -368
- package/dist/src/init/claudemd-generator.js.map +1 -1
- package/dist/src/init/executor.js +1019 -1345
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/helpers-generator.js +60 -635
- package/dist/src/init/helpers-generator.js.map +1 -1
- package/dist/src/init/index.d.ts +1 -1
- package/dist/src/init/index.d.ts.map +1 -1
- package/dist/src/init/index.js +1 -1
- package/dist/src/init/index.js.map +1 -1
- package/dist/src/init/mcp-generator.d.ts +0 -1
- package/dist/src/init/mcp-generator.d.ts.map +1 -1
- package/dist/src/init/mcp-generator.js +62 -42
- package/dist/src/init/mcp-generator.js.map +1 -1
- package/dist/src/init/settings-generator.d.ts.map +1 -1
- package/dist/src/init/settings-generator.js +167 -100
- package/dist/src/init/settings-generator.js.map +1 -1
- package/dist/src/init/statusline-generator.d.ts +16 -8
- package/dist/src/init/statusline-generator.d.ts.map +1 -1
- package/dist/src/init/statusline-generator.js +20 -1300
- package/dist/src/init/statusline-generator.js.map +1 -1
- package/dist/src/init/types.d.ts +15 -5
- package/dist/src/init/types.d.ts.map +1 -1
- package/dist/src/init/types.js +66 -76
- package/dist/src/init/types.js.map +1 -1
- package/dist/src/mcp-client.js +130 -76
- package/dist/src/mcp-client.js.map +1 -1
- package/dist/src/mcp-server.js +758 -445
- package/dist/src/mcp-server.js.map +1 -1
- package/dist/src/mcp-tools/agent-tools.js +492 -391
- package/dist/src/mcp-tools/agent-tools.js.map +1 -1
- package/dist/src/mcp-tools/agentdb-tools.d.ts +30 -0
- package/dist/src/mcp-tools/agentdb-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/agentdb-tools.js +758 -0
- package/dist/src/mcp-tools/agentdb-tools.js.map +1 -0
- package/dist/src/mcp-tools/analyze-tools.js +236 -172
- package/dist/src/mcp-tools/analyze-tools.js.map +1 -1
- package/dist/src/mcp-tools/auto-install.js +142 -80
- package/dist/src/mcp-tools/auto-install.js.map +1 -1
- package/dist/src/mcp-tools/browser-tools.js +375 -252
- package/dist/src/mcp-tools/browser-tools.js.map +1 -1
- package/dist/src/mcp-tools/claims-tools.js +565 -473
- package/dist/src/mcp-tools/claims-tools.js.map +1 -1
- package/dist/src/mcp-tools/config-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/config-tools.js +284 -190
- package/dist/src/mcp-tools/config-tools.js.map +1 -1
- package/dist/src/mcp-tools/coordination-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/coordination-tools.js +600 -349
- package/dist/src/mcp-tools/coordination-tools.js.map +1 -1
- package/dist/src/mcp-tools/daa-tools.js +367 -289
- package/dist/src/mcp-tools/daa-tools.js.map +1 -1
- package/dist/src/mcp-tools/embeddings-tools.js +693 -582
- package/dist/src/mcp-tools/embeddings-tools.js.map +1 -1
- package/dist/src/mcp-tools/github-tools.js +312 -261
- package/dist/src/mcp-tools/github-tools.js.map +1 -1
- package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hive-mind-tools.js +718 -423
- package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.js +2726 -1978
- package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
- package/dist/src/mcp-tools/index.d.ts +2 -0
- package/dist/src/mcp-tools/index.d.ts.map +1 -1
- package/dist/src/mcp-tools/index.js +2 -0
- package/dist/src/mcp-tools/index.js.map +1 -1
- package/dist/src/mcp-tools/memory-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/memory-tools.js +514 -329
- package/dist/src/mcp-tools/memory-tools.js.map +1 -1
- package/dist/src/mcp-tools/neural-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/neural-tools.js +428 -326
- package/dist/src/mcp-tools/neural-tools.js.map +1 -1
- package/dist/src/mcp-tools/performance-tools.js +480 -420
- package/dist/src/mcp-tools/performance-tools.js.map +1 -1
- package/dist/src/mcp-tools/progress-tools.js +278 -204
- package/dist/src/mcp-tools/progress-tools.js.map +1 -1
- package/dist/src/mcp-tools/ruvllm-tools.d.ts +9 -0
- package/dist/src/mcp-tools/ruvllm-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/ruvllm-tools.js +399 -0
- package/dist/src/mcp-tools/ruvllm-tools.js.map +1 -0
- package/dist/src/mcp-tools/security-tools.js +429 -297
- package/dist/src/mcp-tools/security-tools.js.map +1 -1
- package/dist/src/mcp-tools/session-tools.js +234 -185
- package/dist/src/mcp-tools/session-tools.js.map +1 -1
- package/dist/src/mcp-tools/swarm-tools.d.ts +2 -1
- package/dist/src/mcp-tools/swarm-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/swarm-tools.js +303 -64
- package/dist/src/mcp-tools/swarm-tools.js.map +1 -1
- package/dist/src/mcp-tools/system-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/system-tools.js +352 -200
- package/dist/src/mcp-tools/system-tools.js.map +1 -1
- package/dist/src/mcp-tools/task-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/task-tools.js +357 -189
- package/dist/src/mcp-tools/task-tools.js.map +1 -1
- package/dist/src/mcp-tools/terminal-tools.js +196 -148
- package/dist/src/mcp-tools/terminal-tools.js.map +1 -1
- package/dist/src/mcp-tools/transfer-tools.js +333 -186
- package/dist/src/mcp-tools/transfer-tools.js.map +1 -1
- package/dist/src/mcp-tools/wasm-agent-tools.d.ts +9 -0
- package/dist/src/mcp-tools/wasm-agent-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/wasm-agent-tools.js +377 -0
- package/dist/src/mcp-tools/wasm-agent-tools.js.map +1 -0
- package/dist/src/mcp-tools/workflow-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/workflow-tools.js +471 -335
- package/dist/src/mcp-tools/workflow-tools.js.map +1 -1
- package/dist/src/memory/ewc-consolidation.js +345 -173
- package/dist/src/memory/ewc-consolidation.js.map +1 -1
- package/dist/src/memory/intelligence.js +841 -359
- package/dist/src/memory/intelligence.js.map +1 -1
- package/dist/src/memory/memory-bridge.js +1964 -0
- package/dist/src/memory/memory-bridge.js.map +1 -0
- package/dist/src/memory/memory-initializer.js +1895 -1602
- package/dist/src/memory/memory-initializer.js.map +1 -1
- package/dist/src/memory/sona-optimizer.js +329 -199
- package/dist/src/memory/sona-optimizer.js.map +1 -1
- package/dist/src/output.d.ts +2 -2
- package/dist/src/output.d.ts.map +1 -1
- package/dist/src/output.js +273 -242
- package/dist/src/output.js.map +1 -1
- package/dist/src/parser.js +217 -124
- package/dist/src/parser.js.map +1 -1
- package/dist/src/plugins/manager.js +531 -278
- package/dist/src/plugins/manager.js.map +1 -1
- package/dist/src/plugins/store/discovery.js +362 -275
- package/dist/src/plugins/store/discovery.js.map +1 -1
- package/dist/src/plugins/store/index.js +105 -48
- package/dist/src/plugins/store/index.js.map +1 -1
- package/dist/src/plugins/store/search.js +107 -69
- package/dist/src/plugins/store/search.js.map +1 -1
- package/dist/src/plugins/tests/demo-plugin-store.js +160 -113
- package/dist/src/plugins/tests/demo-plugin-store.js.map +1 -1
- package/dist/src/plugins/tests/standalone-test.js +223 -172
- package/dist/src/plugins/tests/standalone-test.js.map +1 -1
- package/dist/src/plugins/tests/test-plugin-store.js +228 -190
- package/dist/src/plugins/tests/test-plugin-store.js.map +1 -1
- package/dist/src/production/circuit-breaker.js +126 -62
- package/dist/src/production/circuit-breaker.js.map +1 -1
- package/dist/src/production/error-handler.js +156 -86
- package/dist/src/production/error-handler.js.map +1 -1
- package/dist/src/production/monitoring.js +220 -139
- package/dist/src/production/monitoring.js.map +1 -1
- package/dist/src/production/rate-limiter.js +93 -74
- package/dist/src/production/rate-limiter.js.map +1 -1
- package/dist/src/production/retry.js +167 -75
- package/dist/src/production/retry.js.map +1 -1
- package/dist/src/prompt.js +560 -436
- package/dist/src/prompt.js.map +1 -1
- package/dist/src/runtime/headless.js +289 -200
- package/dist/src/runtime/headless.js.map +1 -1
- package/dist/src/ruvector/agent-wasm.js +511 -0
- package/dist/src/ruvector/agent-wasm.js.map +1 -0
- package/dist/src/ruvector/ast-analyzer.js +232 -145
- package/dist/src/ruvector/ast-analyzer.js.map +1 -1
- package/dist/src/ruvector/coverage-router.js +419 -287
- package/dist/src/ruvector/coverage-router.js.map +1 -1
- package/dist/src/ruvector/coverage-tools.js +101 -56
- package/dist/src/ruvector/coverage-tools.js.map +1 -1
- package/dist/src/ruvector/diff-classifier.js +451 -324
- package/dist/src/ruvector/diff-classifier.js.map +1 -1
- package/dist/src/ruvector/enhanced-model-router.js +337 -251
- package/dist/src/ruvector/enhanced-model-router.js.map +1 -1
- package/dist/src/ruvector/flash-attention.js +254 -223
- package/dist/src/ruvector/flash-attention.js.map +1 -1
- package/dist/src/ruvector/graph-analyzer.js +680 -486
- package/dist/src/ruvector/graph-analyzer.js.map +1 -1
- package/dist/src/ruvector/index.js +113 -27
- package/dist/src/ruvector/index.js.map +1 -1
- package/dist/src/ruvector/lora-adapter.js +248 -155
- package/dist/src/ruvector/lora-adapter.js.map +1 -1
- package/dist/src/ruvector/model-router.js +248 -175
- package/dist/src/ruvector/model-router.js.map +1 -1
- package/dist/src/ruvector/moe-router.js +286 -228
- package/dist/src/ruvector/moe-router.js.map +1 -1
- package/dist/src/ruvector/q-learning-router.js +338 -257
- package/dist/src/ruvector/q-learning-router.js.map +1 -1
- package/dist/src/ruvector/ruvllm-wasm.js +527 -0
- package/dist/src/ruvector/ruvllm-wasm.js.map +1 -0
- package/dist/src/ruvector/semantic-router.js +67 -60
- package/dist/src/ruvector/semantic-router.js.map +1 -1
- package/dist/src/ruvector/vector-db.js +205 -119
- package/dist/src/ruvector/vector-db.js.map +1 -1
- package/dist/src/services/agentic-flow-bridge.js +168 -0
- package/dist/src/services/agentic-flow-bridge.js.map +1 -0
- package/dist/src/services/claim-service.js +940 -615
- package/dist/src/services/claim-service.js.map +1 -1
- package/dist/src/services/container-worker-pool.js +669 -399
- package/dist/src/services/container-worker-pool.js.map +1 -1
- package/dist/src/services/headless-worker-executor.js +467 -441
- package/dist/src/services/headless-worker-executor.js.map +1 -1
- package/dist/src/services/index.d.ts +5 -5
- package/dist/src/services/index.d.ts.map +1 -1
- package/dist/src/services/index.js +4 -4
- package/dist/src/services/index.js.map +1 -1
- package/dist/src/services/registry-api.js +201 -93
- package/dist/src/services/registry-api.js.map +1 -1
- package/dist/src/services/ruvector-training.js +414 -144
- package/dist/src/services/ruvector-training.js.map +1 -1
- package/dist/src/services/worker-daemon.js +928 -531
- package/dist/src/services/worker-daemon.js.map +1 -1
- package/dist/src/services/worker-queue.js +550 -331
- package/dist/src/services/worker-queue.js.map +1 -1
- package/dist/src/suggest.js +55 -45
- package/dist/src/suggest.js.map +1 -1
- package/dist/src/transfer/anonymization/index.js +37 -29
- package/dist/src/transfer/anonymization/index.js.map +1 -1
- package/dist/src/transfer/deploy-seraphine.d.ts +1 -1
- package/dist/src/transfer/deploy-seraphine.js +156 -129
- package/dist/src/transfer/deploy-seraphine.js.map +1 -1
- package/dist/src/transfer/export.js +142 -84
- package/dist/src/transfer/export.js.map +1 -1
- package/dist/src/transfer/index.d.ts +1 -1
- package/dist/src/transfer/index.d.ts.map +1 -1
- package/dist/src/transfer/index.js +2 -0
- package/dist/src/transfer/index.js.map +1 -1
- package/dist/src/transfer/ipfs/client.js +337 -179
- package/dist/src/transfer/ipfs/client.js.map +1 -1
- package/dist/src/transfer/ipfs/upload.js +434 -290
- package/dist/src/transfer/ipfs/upload.js.map +1 -1
- package/dist/src/transfer/models/seraphine.js +58 -58
- package/dist/src/transfer/models/seraphine.js.map +1 -1
- package/dist/src/transfer/serialization/cfp.js +37 -33
- package/dist/src/transfer/serialization/cfp.js.map +1 -1
- package/dist/src/transfer/storage/gcs.js +248 -139
- package/dist/src/transfer/storage/gcs.js.map +1 -1
- package/dist/src/transfer/store/discovery.js +353 -243
- package/dist/src/transfer/store/discovery.js.map +1 -1
- package/dist/src/transfer/store/download.js +365 -243
- package/dist/src/transfer/store/download.js.map +1 -1
- package/dist/src/transfer/store/index.js +130 -63
- package/dist/src/transfer/store/index.js.map +1 -1
- package/dist/src/transfer/store/publish.js +258 -184
- package/dist/src/transfer/store/publish.js.map +1 -1
- package/dist/src/transfer/store/registry.js +73 -51
- package/dist/src/transfer/store/registry.js.map +1 -1
- package/dist/src/transfer/store/search.js +96 -64
- package/dist/src/transfer/store/search.js.map +1 -1
- package/dist/src/transfer/store/tests/standalone-test.js +231 -174
- package/dist/src/transfer/store/tests/standalone-test.js.map +1 -1
- package/dist/src/transfer/test-seraphine.js +130 -95
- package/dist/src/transfer/test-seraphine.js.map +1 -1
- package/dist/src/transfer/tests/test-store.js +239 -194
- package/dist/src/transfer/tests/test-store.js.map +1 -1
- package/dist/src/types.js +56 -27
- package/dist/src/types.js.map +1 -1
- package/dist/src/update/checker.js +183 -106
- package/dist/src/update/checker.js.map +1 -1
- package/dist/src/update/executor.js +198 -135
- package/dist/src/update/executor.js.map +1 -1
- package/dist/src/update/index.js +85 -38
- package/dist/src/update/index.js.map +1 -1
- package/dist/src/update/rate-limiter.js +31 -19
- package/dist/src/update/rate-limiter.js.map +1 -1
- package/dist/src/update/validator.js +64 -38
- package/dist/src/update/validator.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -10
- package/.claude/agents/custom/accessibility-auditor.yaml +0 -56
- package/.claude/agents/custom/design-architect.yaml +0 -48
- package/.claude/agents/custom/ui-developer.yaml +0 -46
- package/.claude/agents/custom/ux-researcher.yaml +0 -60
- package/dist/src/benchmarks/pretrain/index.d.ts +0 -58
- package/dist/src/benchmarks/pretrain/index.d.ts.map +0 -1
- package/dist/src/commands/index.d.ts +0 -108
- package/dist/src/commands/index.d.ts.map +0 -1
- package/dist/src/config-adapter.d.ts +0 -15
- package/dist/src/config-adapter.d.ts.map +0 -1
- package/dist/src/index.d.ts +0 -76
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/infrastructure/in-memory-repositories.d.ts +0 -68
- package/dist/src/infrastructure/in-memory-repositories.d.ts.map +0 -1
- package/dist/src/init/claudemd-generator.d.ts +0 -25
- package/dist/src/init/claudemd-generator.d.ts.map +0 -1
- package/dist/src/init/executor.d.ts +0 -41
- package/dist/src/init/executor.d.ts.map +0 -1
- package/dist/src/init/helpers-generator.d.ts +0 -60
- package/dist/src/init/helpers-generator.d.ts.map +0 -1
- package/dist/src/mcp-client.d.ts +0 -92
- package/dist/src/mcp-client.d.ts.map +0 -1
- package/dist/src/mcp-server.d.ts +0 -161
- package/dist/src/mcp-server.d.ts.map +0 -1
- package/dist/src/mcp-tools/auto-install.d.ts +0 -83
- package/dist/src/mcp-tools/auto-install.d.ts.map +0 -1
- package/dist/src/mcp-tools/types.d.ts +0 -31
- package/dist/src/mcp-tools/types.d.ts.map +0 -1
- package/dist/src/memory/ewc-consolidation.d.ts +0 -271
- package/dist/src/memory/ewc-consolidation.d.ts.map +0 -1
- package/dist/src/memory/intelligence.d.ts +0 -285
- package/dist/src/memory/intelligence.d.ts.map +0 -1
- package/dist/src/memory/memory-initializer.d.ts +0 -396
- package/dist/src/memory/memory-initializer.d.ts.map +0 -1
- package/dist/src/memory/sona-optimizer.d.ts +0 -227
- package/dist/src/memory/sona-optimizer.d.ts.map +0 -1
- package/dist/src/parser.d.ts +0 -41
- package/dist/src/parser.d.ts.map +0 -1
- package/dist/src/plugins/manager.d.ts +0 -133
- package/dist/src/plugins/manager.d.ts.map +0 -1
- package/dist/src/plugins/store/discovery.d.ts +0 -88
- package/dist/src/plugins/store/discovery.d.ts.map +0 -1
- package/dist/src/plugins/store/index.d.ts +0 -76
- package/dist/src/plugins/store/index.d.ts.map +0 -1
- package/dist/src/plugins/store/search.d.ts +0 -46
- package/dist/src/plugins/store/search.d.ts.map +0 -1
- package/dist/src/plugins/store/types.d.ts +0 -274
- package/dist/src/plugins/store/types.d.ts.map +0 -1
- package/dist/src/production/circuit-breaker.d.ts +0 -101
- package/dist/src/production/circuit-breaker.d.ts.map +0 -1
- package/dist/src/production/error-handler.d.ts +0 -92
- package/dist/src/production/error-handler.d.ts.map +0 -1
- package/dist/src/production/monitoring.d.ts +0 -161
- package/dist/src/production/monitoring.d.ts.map +0 -1
- package/dist/src/production/rate-limiter.d.ts +0 -80
- package/dist/src/production/rate-limiter.d.ts.map +0 -1
- package/dist/src/production/retry.d.ts +0 -48
- package/dist/src/production/retry.d.ts.map +0 -1
- package/dist/src/prompt.d.ts +0 -44
- package/dist/src/prompt.d.ts.map +0 -1
- package/dist/src/runtime/headless.d.ts +0 -60
- package/dist/src/runtime/headless.d.ts.map +0 -1
- package/dist/src/ruvector/ast-analyzer.d.ts +0 -67
- package/dist/src/ruvector/ast-analyzer.d.ts.map +0 -1
- package/dist/src/ruvector/coverage-router.d.ts +0 -160
- package/dist/src/ruvector/coverage-router.d.ts.map +0 -1
- package/dist/src/ruvector/diff-classifier.d.ts +0 -175
- package/dist/src/ruvector/diff-classifier.d.ts.map +0 -1
- package/dist/src/ruvector/enhanced-model-router.d.ts +0 -146
- package/dist/src/ruvector/enhanced-model-router.d.ts.map +0 -1
- package/dist/src/ruvector/flash-attention.d.ts +0 -195
- package/dist/src/ruvector/flash-attention.d.ts.map +0 -1
- package/dist/src/ruvector/graph-analyzer.d.ts +0 -187
- package/dist/src/ruvector/graph-analyzer.d.ts.map +0 -1
- package/dist/src/ruvector/index.d.ts +0 -34
- package/dist/src/ruvector/index.d.ts.map +0 -1
- package/dist/src/ruvector/lora-adapter.d.ts +0 -218
- package/dist/src/ruvector/lora-adapter.d.ts.map +0 -1
- package/dist/src/ruvector/model-router.d.ts +0 -220
- package/dist/src/ruvector/model-router.d.ts.map +0 -1
- package/dist/src/ruvector/moe-router.d.ts +0 -206
- package/dist/src/ruvector/moe-router.d.ts.map +0 -1
- package/dist/src/ruvector/q-learning-router.d.ts +0 -211
- package/dist/src/ruvector/q-learning-router.d.ts.map +0 -1
- package/dist/src/ruvector/semantic-router.d.ts +0 -77
- package/dist/src/ruvector/semantic-router.d.ts.map +0 -1
- package/dist/src/ruvector/vector-db.d.ts +0 -69
- package/dist/src/ruvector/vector-db.d.ts.map +0 -1
- package/dist/src/services/claim-service.d.ts +0 -204
- package/dist/src/services/claim-service.d.ts.map +0 -1
- package/dist/src/services/container-worker-pool.d.ts +0 -197
- package/dist/src/services/container-worker-pool.d.ts.map +0 -1
- package/dist/src/services/headless-worker-executor.d.ts +0 -304
- package/dist/src/services/headless-worker-executor.d.ts.map +0 -1
- package/dist/src/services/registry-api.d.ts +0 -58
- package/dist/src/services/registry-api.d.ts.map +0 -1
- package/dist/src/services/ruvector-training.d.ts +0 -213
- package/dist/src/services/ruvector-training.d.ts.map +0 -1
- package/dist/src/services/worker-daemon.d.ts +0 -203
- package/dist/src/services/worker-daemon.d.ts.map +0 -1
- package/dist/src/services/worker-queue.d.ts +0 -194
- package/dist/src/services/worker-queue.d.ts.map +0 -1
- package/dist/src/suggest.d.ts +0 -53
- package/dist/src/suggest.d.ts.map +0 -1
- package/dist/src/transfer/export.d.ts +0 -25
- package/dist/src/transfer/export.d.ts.map +0 -1
- package/dist/src/transfer/ipfs/client.d.ts +0 -109
- package/dist/src/transfer/ipfs/client.d.ts.map +0 -1
- package/dist/src/transfer/ipfs/upload.d.ts +0 -95
- package/dist/src/transfer/ipfs/upload.d.ts.map +0 -1
- package/dist/src/transfer/models/seraphine.d.ts +0 -72
- package/dist/src/transfer/models/seraphine.d.ts.map +0 -1
- package/dist/src/transfer/serialization/cfp.d.ts +0 -49
- package/dist/src/transfer/serialization/cfp.d.ts.map +0 -1
- package/dist/src/transfer/storage/gcs.d.ts +0 -82
- package/dist/src/transfer/storage/gcs.d.ts.map +0 -1
- package/dist/src/transfer/store/discovery.d.ts +0 -84
- package/dist/src/transfer/store/discovery.d.ts.map +0 -1
- package/dist/src/transfer/store/download.d.ts +0 -70
- package/dist/src/transfer/store/download.d.ts.map +0 -1
- package/dist/src/transfer/store/index.d.ts +0 -84
- package/dist/src/transfer/store/index.d.ts.map +0 -1
- package/dist/src/transfer/store/publish.d.ts +0 -76
- package/dist/src/transfer/store/publish.d.ts.map +0 -1
- package/dist/src/transfer/store/search.d.ts +0 -54
- package/dist/src/transfer/store/search.d.ts.map +0 -1
- package/dist/src/transfer/types.d.ts +0 -245
- package/dist/src/transfer/types.d.ts.map +0 -1
- package/dist/src/types.d.ts +0 -198
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/update/checker.d.ts +0 -34
- package/dist/src/update/checker.d.ts.map +0 -1
- package/dist/src/update/executor.d.ts +0 -32
- package/dist/src/update/executor.d.ts.map +0 -1
- package/dist/src/update/index.d.ts +0 -33
- package/dist/src/update/index.d.ts.map +0 -1
- package/dist/src/update/rate-limiter.d.ts +0 -20
- package/dist/src/update/rate-limiter.d.ts.map +0 -1
- package/dist/src/update/validator.d.ts +0 -17
- package/dist/src/update/validator.d.ts.map +0 -1
|
@@ -11,6 +11,62 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @module @claude-flow/cli/ruvector/graph-analyzer
|
|
13
13
|
*/
|
|
14
|
+
var __assign = (this && this.__assign) || function () {
|
|
15
|
+
__assign = Object.assign || function(t) {
|
|
16
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
17
|
+
s = arguments[i];
|
|
18
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
19
|
+
t[p] = s[p];
|
|
20
|
+
}
|
|
21
|
+
return t;
|
|
22
|
+
};
|
|
23
|
+
return __assign.apply(this, arguments);
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
35
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
36
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
37
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
38
|
+
function step(op) {
|
|
39
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
40
|
+
while (_) try {
|
|
41
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
42
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
43
|
+
switch (op[0]) {
|
|
44
|
+
case 0: case 1: t = op; break;
|
|
45
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
46
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
47
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
48
|
+
default:
|
|
49
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
50
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
51
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
52
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
53
|
+
if (t[2]) _.ops.pop();
|
|
54
|
+
_.trys.pop(); continue;
|
|
55
|
+
}
|
|
56
|
+
op = body.call(thisArg, _);
|
|
57
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
58
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
62
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
63
|
+
if (ar || !(i in from)) {
|
|
64
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
65
|
+
ar[i] = from[i];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
69
|
+
};
|
|
14
70
|
import { readFile, readdir, stat } from 'fs/promises';
|
|
15
71
|
import { join, relative, extname, dirname, basename } from 'path';
|
|
16
72
|
// ============================================================================
|
|
@@ -19,13 +75,13 @@ import { join, relative, extname, dirname, basename } from 'path';
|
|
|
19
75
|
/**
|
|
20
76
|
* Cache for dependency graphs (5 minute TTL)
|
|
21
77
|
*/
|
|
22
|
-
|
|
23
|
-
|
|
78
|
+
var graphCache = new Map();
|
|
79
|
+
var GRAPH_CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
24
80
|
/**
|
|
25
81
|
* Cache for analysis results (2 minute TTL)
|
|
26
82
|
*/
|
|
27
|
-
|
|
28
|
-
|
|
83
|
+
var analysisResultCache = new Map();
|
|
84
|
+
var ANALYSIS_CACHE_TTL_MS = 2 * 60 * 1000; // 2 minutes
|
|
29
85
|
/**
|
|
30
86
|
* Clear all graph caches
|
|
31
87
|
*/
|
|
@@ -39,53 +95,64 @@ export function clearGraphCaches() {
|
|
|
39
95
|
export function getGraphCacheStats() {
|
|
40
96
|
return {
|
|
41
97
|
graphCacheSize: graphCache.size,
|
|
42
|
-
analysisCacheSize: analysisResultCache.size
|
|
98
|
+
analysisCacheSize: analysisResultCache.size
|
|
43
99
|
};
|
|
44
100
|
}
|
|
45
|
-
|
|
46
|
-
|
|
101
|
+
var ruVectorGraph = null;
|
|
102
|
+
var ruVectorLoadAttempted = false;
|
|
47
103
|
/**
|
|
48
104
|
* Attempt to load ruvector graph algorithms
|
|
49
105
|
*/
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
106
|
+
function loadRuVector() {
|
|
107
|
+
return __awaiter(this, void 0, Promise, function () {
|
|
108
|
+
var ruvectorModule, wasmModule, ruvector_1, _a, wasm, analyzer_1, _b;
|
|
109
|
+
return __generator(this, function (_c) {
|
|
110
|
+
switch (_c.label) {
|
|
111
|
+
case 0:
|
|
112
|
+
if (ruVectorLoadAttempted)
|
|
113
|
+
return [2 /*return*/, ruVectorGraph];
|
|
114
|
+
ruVectorLoadAttempted = true;
|
|
115
|
+
ruvectorModule = 'ruvector';
|
|
116
|
+
wasmModule = '@ruvector/wasm';
|
|
117
|
+
_c.label = 1;
|
|
118
|
+
case 1:
|
|
119
|
+
_c.trys.push([1, 3, , 8]);
|
|
120
|
+
return [4 /*yield*/, import(/* webpackIgnore: true */ ruvectorModule)["catch"](function () { return null; })];
|
|
121
|
+
case 2:
|
|
122
|
+
ruvector_1 = _c.sent();
|
|
123
|
+
if (ruvector_1 && typeof ruvector_1.hooks_graph_mincut === 'function' && typeof ruvector_1.hooks_graph_cluster === 'function') {
|
|
124
|
+
ruVectorGraph = {
|
|
125
|
+
mincut: function (nodes, edges) { return ruvector_1.hooks_graph_mincut(nodes, edges); },
|
|
126
|
+
louvain: function (nodes, edges) { return ruvector_1.hooks_graph_cluster(nodes, edges); }
|
|
127
|
+
};
|
|
128
|
+
return [2 /*return*/, ruVectorGraph];
|
|
129
|
+
}
|
|
130
|
+
return [3 /*break*/, 8];
|
|
131
|
+
case 3:
|
|
132
|
+
_a = _c.sent();
|
|
133
|
+
_c.label = 4;
|
|
134
|
+
case 4:
|
|
135
|
+
_c.trys.push([4, 6, , 7]);
|
|
136
|
+
return [4 /*yield*/, import(/* webpackIgnore: true */ wasmModule)["catch"](function () { return null; })];
|
|
137
|
+
case 5:
|
|
138
|
+
wasm = _c.sent();
|
|
139
|
+
if (wasm && wasm.GraphAnalyzer) {
|
|
140
|
+
analyzer_1 = new wasm.GraphAnalyzer();
|
|
141
|
+
ruVectorGraph = {
|
|
142
|
+
mincut: function (nodes, edges) { return analyzer_1.mincut(nodes, edges); },
|
|
143
|
+
louvain: function (nodes, edges) { return analyzer_1.louvain(nodes, edges); }
|
|
144
|
+
};
|
|
145
|
+
return [2 /*return*/, ruVectorGraph];
|
|
146
|
+
}
|
|
147
|
+
return [3 /*break*/, 7];
|
|
148
|
+
case 6:
|
|
149
|
+
_b = _c.sent();
|
|
150
|
+
return [3 /*break*/, 7];
|
|
151
|
+
case 7: return [3 /*break*/, 8];
|
|
152
|
+
case 8: return [2 /*return*/, null];
|
|
82
153
|
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Fallback will be used
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return null;
|
|
154
|
+
});
|
|
155
|
+
});
|
|
89
156
|
}
|
|
90
157
|
// ============================================================================
|
|
91
158
|
// Import/Require Parser
|
|
@@ -94,30 +161,30 @@ async function loadRuVector() {
|
|
|
94
161
|
* Extract imports from TypeScript/JavaScript file
|
|
95
162
|
*/
|
|
96
163
|
function extractImports(content, _filePath) {
|
|
97
|
-
|
|
164
|
+
var imports = [];
|
|
98
165
|
// ES6 import statements
|
|
99
|
-
|
|
100
|
-
|
|
166
|
+
var esImportRegex = /import\s+(?:(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)\s*,?\s*)*\s*from\s*['"]([^'"]+)['"]/g;
|
|
167
|
+
var match;
|
|
101
168
|
while ((match = esImportRegex.exec(content)) !== null) {
|
|
102
169
|
imports.push({ path: match[1], type: 'import' });
|
|
103
170
|
}
|
|
104
171
|
// Side-effect imports: import 'module'
|
|
105
|
-
|
|
172
|
+
var sideEffectRegex = /import\s+['"]([^'"]+)['"]/g;
|
|
106
173
|
while ((match = sideEffectRegex.exec(content)) !== null) {
|
|
107
174
|
imports.push({ path: match[1], type: 'import' });
|
|
108
175
|
}
|
|
109
176
|
// CommonJS require
|
|
110
|
-
|
|
177
|
+
var requireRegex = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
111
178
|
while ((match = requireRegex.exec(content)) !== null) {
|
|
112
179
|
imports.push({ path: match[1], type: 'require' });
|
|
113
180
|
}
|
|
114
181
|
// Dynamic imports
|
|
115
|
-
|
|
182
|
+
var dynamicImportRegex = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
116
183
|
while ((match = dynamicImportRegex.exec(content)) !== null) {
|
|
117
184
|
imports.push({ path: match[1], type: 'dynamic' });
|
|
118
185
|
}
|
|
119
186
|
// Re-exports: export * from 'module'
|
|
120
|
-
|
|
187
|
+
var reExportRegex = /export\s+(?:\*|\{[^}]*\})\s+from\s*['"]([^'"]+)['"]/g;
|
|
121
188
|
while ((match = reExportRegex.exec(content)) !== null) {
|
|
122
189
|
imports.push({ path: match[1], type: 're-export' });
|
|
123
190
|
}
|
|
@@ -127,18 +194,18 @@ function extractImports(content, _filePath) {
|
|
|
127
194
|
* Extract exports from TypeScript/JavaScript file
|
|
128
195
|
*/
|
|
129
196
|
function extractExports(content) {
|
|
130
|
-
|
|
197
|
+
var exports = [];
|
|
131
198
|
// Named exports
|
|
132
|
-
|
|
133
|
-
|
|
199
|
+
var namedExportRegex = /export\s+(?:const|let|var|function|class|interface|type|enum)\s+(\w+)/g;
|
|
200
|
+
var match;
|
|
134
201
|
while ((match = namedExportRegex.exec(content)) !== null) {
|
|
135
202
|
exports.push(match[1]);
|
|
136
203
|
}
|
|
137
204
|
// Export list: export { a, b, c }
|
|
138
|
-
|
|
205
|
+
var exportListRegex = /export\s+\{([^}]+)\}/g;
|
|
139
206
|
while ((match = exportListRegex.exec(content)) !== null) {
|
|
140
|
-
|
|
141
|
-
exports.push(
|
|
207
|
+
var names = match[1].split(',').map(function (n) { return n.trim().split(/\s+as\s+/)[0].trim(); });
|
|
208
|
+
exports.push.apply(exports, names.filter(function (n) { return n; }));
|
|
142
209
|
}
|
|
143
210
|
// Default export
|
|
144
211
|
if (/export\s+default/.test(content)) {
|
|
@@ -154,8 +221,8 @@ function resolveImportPath(importPath, fromFile, rootDir) {
|
|
|
154
221
|
if (!importPath.startsWith('.') && !importPath.startsWith('/')) {
|
|
155
222
|
return null;
|
|
156
223
|
}
|
|
157
|
-
|
|
158
|
-
|
|
224
|
+
var fromDir = dirname(fromFile);
|
|
225
|
+
var resolved;
|
|
159
226
|
if (importPath.startsWith('/')) {
|
|
160
227
|
resolved = join(rootDir, importPath);
|
|
161
228
|
}
|
|
@@ -163,12 +230,13 @@ function resolveImportPath(importPath, fromFile, rootDir) {
|
|
|
163
230
|
resolved = join(fromDir, importPath);
|
|
164
231
|
}
|
|
165
232
|
// Handle extension-less imports
|
|
166
|
-
|
|
233
|
+
var ext = extname(resolved);
|
|
167
234
|
if (!ext) {
|
|
168
235
|
// Try common extensions
|
|
169
|
-
|
|
170
|
-
for (
|
|
171
|
-
|
|
236
|
+
var extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
|
|
237
|
+
for (var _i = 0, extensions_1 = extensions; _i < extensions_1.length; _i++) {
|
|
238
|
+
var tryExt = extensions_1[_i];
|
|
239
|
+
var tryPath = resolved + tryExt;
|
|
172
240
|
return tryPath; // Return normalized, existence check done later
|
|
173
241
|
}
|
|
174
242
|
// Could be index file
|
|
@@ -182,161 +250,209 @@ function resolveImportPath(importPath, fromFile, rootDir) {
|
|
|
182
250
|
/**
|
|
183
251
|
* Build dependency graph from source directory (with caching)
|
|
184
252
|
*/
|
|
185
|
-
export
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const exclude = options.exclude || ['node_modules', 'dist', 'build', '.git', '__tests__', '*.test.*', '*.spec.*'];
|
|
199
|
-
const maxDepth = options.maxDepth ?? 10;
|
|
200
|
-
/**
|
|
201
|
-
* Check if path should be excluded
|
|
202
|
-
*/
|
|
203
|
-
function shouldExclude(path) {
|
|
204
|
-
const name = basename(path);
|
|
205
|
-
return exclude.some(pattern => {
|
|
206
|
-
if (pattern.includes('*')) {
|
|
207
|
-
const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
|
|
208
|
-
return regex.test(name);
|
|
209
|
-
}
|
|
210
|
-
return name === pattern || path.includes(`/${pattern}/`);
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Recursively scan directory for source files
|
|
215
|
-
*/
|
|
216
|
-
async function scanDir(dir, depth) {
|
|
217
|
-
if (depth > maxDepth)
|
|
218
|
-
return;
|
|
219
|
-
try {
|
|
220
|
-
const entries = await readdir(dir, { withFileTypes: true });
|
|
221
|
-
for (const entry of entries) {
|
|
222
|
-
const fullPath = join(dir, entry.name);
|
|
223
|
-
const relPath = relative(rootDir, fullPath);
|
|
224
|
-
if (shouldExclude(fullPath))
|
|
225
|
-
continue;
|
|
226
|
-
if (entry.isDirectory()) {
|
|
227
|
-
await scanDir(fullPath, depth + 1);
|
|
253
|
+
export function buildDependencyGraph(rootDir, options) {
|
|
254
|
+
var _a;
|
|
255
|
+
if (options === void 0) { options = {}; }
|
|
256
|
+
return __awaiter(this, void 0, Promise, function () {
|
|
257
|
+
/**
|
|
258
|
+
* Check if path should be excluded
|
|
259
|
+
*/
|
|
260
|
+
function shouldExclude(path) {
|
|
261
|
+
var name = basename(path);
|
|
262
|
+
return exclude.some(function (pattern) {
|
|
263
|
+
if (pattern.includes('*')) {
|
|
264
|
+
var regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
|
|
265
|
+
return regex.test(name);
|
|
228
266
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if (include.includes(ext)) {
|
|
232
|
-
await processFile(fullPath, relPath);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
catch {
|
|
238
|
-
// Directory not readable, skip
|
|
267
|
+
return name === pattern || path.includes("/" + pattern + "/");
|
|
268
|
+
});
|
|
239
269
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
270
|
+
/**
|
|
271
|
+
* Recursively scan directory for source files
|
|
272
|
+
*/
|
|
273
|
+
function scanDir(dir, depth) {
|
|
274
|
+
return __awaiter(this, void 0, Promise, function () {
|
|
275
|
+
var entries, _i, entries_1, entry, fullPath, relPath, ext, _a;
|
|
276
|
+
return __generator(this, function (_b) {
|
|
277
|
+
switch (_b.label) {
|
|
278
|
+
case 0:
|
|
279
|
+
if (depth > maxDepth)
|
|
280
|
+
return [2 /*return*/];
|
|
281
|
+
_b.label = 1;
|
|
282
|
+
case 1:
|
|
283
|
+
_b.trys.push([1, 9, , 10]);
|
|
284
|
+
return [4 /*yield*/, readdir(dir, { withFileTypes: true })];
|
|
285
|
+
case 2:
|
|
286
|
+
entries = _b.sent();
|
|
287
|
+
_i = 0, entries_1 = entries;
|
|
288
|
+
_b.label = 3;
|
|
289
|
+
case 3:
|
|
290
|
+
if (!(_i < entries_1.length)) return [3 /*break*/, 8];
|
|
291
|
+
entry = entries_1[_i];
|
|
292
|
+
fullPath = join(dir, entry.name);
|
|
293
|
+
relPath = relative(rootDir, fullPath);
|
|
294
|
+
if (shouldExclude(fullPath))
|
|
295
|
+
return [3 /*break*/, 7];
|
|
296
|
+
if (!entry.isDirectory()) return [3 /*break*/, 5];
|
|
297
|
+
return [4 /*yield*/, scanDir(fullPath, depth + 1)];
|
|
298
|
+
case 4:
|
|
299
|
+
_b.sent();
|
|
300
|
+
return [3 /*break*/, 7];
|
|
301
|
+
case 5:
|
|
302
|
+
if (!entry.isFile()) return [3 /*break*/, 7];
|
|
303
|
+
ext = extname(entry.name);
|
|
304
|
+
if (!include.includes(ext)) return [3 /*break*/, 7];
|
|
305
|
+
return [4 /*yield*/, processFile(fullPath, relPath)];
|
|
306
|
+
case 6:
|
|
307
|
+
_b.sent();
|
|
308
|
+
_b.label = 7;
|
|
309
|
+
case 7:
|
|
310
|
+
_i++;
|
|
311
|
+
return [3 /*break*/, 3];
|
|
312
|
+
case 8: return [3 /*break*/, 10];
|
|
313
|
+
case 9:
|
|
314
|
+
_a = _b.sent();
|
|
315
|
+
return [3 /*break*/, 10];
|
|
316
|
+
case 10: return [2 /*return*/];
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
});
|
|
275
320
|
}
|
|
276
|
-
|
|
277
|
-
|
|
321
|
+
/**
|
|
322
|
+
* Process a single source file
|
|
323
|
+
*/
|
|
324
|
+
function processFile(fullPath, relPath) {
|
|
325
|
+
return __awaiter(this, void 0, Promise, function () {
|
|
326
|
+
var content, fileStats, imports, exportsList, node, _i, imports_1, imp, resolved, targetRel, _a;
|
|
327
|
+
return __generator(this, function (_b) {
|
|
328
|
+
switch (_b.label) {
|
|
329
|
+
case 0:
|
|
330
|
+
_b.trys.push([0, 3, , 4]);
|
|
331
|
+
return [4 /*yield*/, readFile(fullPath, 'utf-8')];
|
|
332
|
+
case 1:
|
|
333
|
+
content = _b.sent();
|
|
334
|
+
return [4 /*yield*/, stat(fullPath)];
|
|
335
|
+
case 2:
|
|
336
|
+
fileStats = _b.sent();
|
|
337
|
+
imports = extractImports(content, fullPath);
|
|
338
|
+
exportsList = extractExports(content);
|
|
339
|
+
node = {
|
|
340
|
+
id: relPath,
|
|
341
|
+
path: relPath,
|
|
342
|
+
name: basename(relPath, extname(relPath)),
|
|
343
|
+
type: 'file',
|
|
344
|
+
imports: imports.map(function (i) { return i.path; }),
|
|
345
|
+
exports: exportsList,
|
|
346
|
+
size: fileStats.size,
|
|
347
|
+
complexity: estimateComplexity(content)
|
|
348
|
+
};
|
|
349
|
+
nodes.set(relPath, node);
|
|
350
|
+
// Create edges for imports
|
|
351
|
+
for (_i = 0, imports_1 = imports; _i < imports_1.length; _i++) {
|
|
352
|
+
imp = imports_1[_i];
|
|
353
|
+
resolved = resolveImportPath(imp.path, fullPath, rootDir);
|
|
354
|
+
if (resolved) {
|
|
355
|
+
targetRel = relative(rootDir, resolved);
|
|
356
|
+
edges.push({
|
|
357
|
+
source: relPath,
|
|
358
|
+
target: targetRel,
|
|
359
|
+
type: imp.type,
|
|
360
|
+
weight: imp.type === 're-export' ? 2 : 1
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return [3 /*break*/, 4];
|
|
365
|
+
case 3:
|
|
366
|
+
_a = _b.sent();
|
|
367
|
+
return [3 /*break*/, 4];
|
|
368
|
+
case 4: return [2 /*return*/];
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
});
|
|
278
372
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
373
|
+
var cacheKey, cached, startTime, nodes, edges, include, exclude, maxDepth, normalizedEdges, _i, edges_1, edge, targetKey, extensions, baseTarget, _b, extensions_2, ext, graph;
|
|
374
|
+
return __generator(this, function (_c) {
|
|
375
|
+
switch (_c.label) {
|
|
376
|
+
case 0:
|
|
377
|
+
cacheKey = rootDir + ":" + JSON.stringify(options);
|
|
378
|
+
if (!options.skipCache) {
|
|
379
|
+
cached = graphCache.get(cacheKey);
|
|
380
|
+
if (cached && Date.now() - cached.timestamp < GRAPH_CACHE_TTL_MS) {
|
|
381
|
+
return [2 /*return*/, cached.graph];
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
startTime = Date.now();
|
|
385
|
+
nodes = new Map();
|
|
386
|
+
edges = [];
|
|
387
|
+
include = options.include || ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
|
|
388
|
+
exclude = options.exclude || ['node_modules', 'dist', 'build', '.git', '__tests__', '*.test.*', '*.spec.*'];
|
|
389
|
+
maxDepth = (_a = options.maxDepth) !== null && _a !== void 0 ? _a : 10;
|
|
390
|
+
// Build the graph
|
|
391
|
+
return [4 /*yield*/, scanDir(rootDir, 0)];
|
|
392
|
+
case 1:
|
|
393
|
+
// Build the graph
|
|
394
|
+
_c.sent();
|
|
395
|
+
normalizedEdges = [];
|
|
396
|
+
for (_i = 0, edges_1 = edges; _i < edges_1.length; _i++) {
|
|
397
|
+
edge = edges_1[_i];
|
|
398
|
+
targetKey = edge.target;
|
|
399
|
+
if (!nodes.has(targetKey)) {
|
|
400
|
+
extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
|
|
401
|
+
baseTarget = targetKey.replace(/\.[^.]+$/, '');
|
|
402
|
+
for (_b = 0, extensions_2 = extensions; _b < extensions_2.length; _b++) {
|
|
403
|
+
ext = extensions_2[_b];
|
|
404
|
+
if (nodes.has(baseTarget + ext)) {
|
|
405
|
+
targetKey = baseTarget + ext;
|
|
406
|
+
break;
|
|
407
|
+
}
|
|
408
|
+
// Try index files
|
|
409
|
+
if (nodes.has(join(baseTarget, 'index' + ext))) {
|
|
410
|
+
targetKey = join(baseTarget, 'index' + ext);
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
if (nodes.has(targetKey)) {
|
|
416
|
+
normalizedEdges.push(__assign(__assign({}, edge), { target: targetKey }));
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
graph = {
|
|
420
|
+
nodes: nodes,
|
|
421
|
+
edges: normalizedEdges,
|
|
422
|
+
metadata: {
|
|
423
|
+
rootDir: rootDir,
|
|
424
|
+
totalFiles: nodes.size,
|
|
425
|
+
totalEdges: normalizedEdges.length,
|
|
426
|
+
buildTime: Date.now() - startTime
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
// Cache the result
|
|
430
|
+
graphCache.set(cacheKey, { graph: graph, timestamp: Date.now() });
|
|
431
|
+
return [2 /*return*/, graph];
|
|
301
432
|
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
normalizedEdges.push({ ...edge, target: targetKey });
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
const graph = {
|
|
308
|
-
nodes,
|
|
309
|
-
edges: normalizedEdges,
|
|
310
|
-
metadata: {
|
|
311
|
-
rootDir,
|
|
312
|
-
totalFiles: nodes.size,
|
|
313
|
-
totalEdges: normalizedEdges.length,
|
|
314
|
-
buildTime: Date.now() - startTime,
|
|
315
|
-
},
|
|
316
|
-
};
|
|
317
|
-
// Cache the result
|
|
318
|
-
graphCache.set(cacheKey, { graph, timestamp: Date.now() });
|
|
319
|
-
return graph;
|
|
433
|
+
});
|
|
434
|
+
});
|
|
320
435
|
}
|
|
321
436
|
/**
|
|
322
437
|
* Estimate cyclomatic complexity from code
|
|
323
438
|
*/
|
|
324
439
|
function estimateComplexity(content) {
|
|
325
|
-
|
|
440
|
+
var complexity = 1;
|
|
326
441
|
// Count branching statements
|
|
327
|
-
|
|
442
|
+
var patterns = [
|
|
328
443
|
/\bif\s*\(/g,
|
|
329
444
|
/\belse\s+if\s*\(/g,
|
|
330
445
|
/\bfor\s*\(/g,
|
|
331
446
|
/\bwhile\s*\(/g,
|
|
332
447
|
/\bcase\s+/g,
|
|
333
448
|
/\bcatch\s*\(/g,
|
|
334
|
-
/\?\s*[^:]+:/g,
|
|
449
|
+
/\?\s*[^:]+:/g,
|
|
335
450
|
/&&/g,
|
|
336
451
|
/\|\|/g,
|
|
337
452
|
];
|
|
338
|
-
for (
|
|
339
|
-
|
|
453
|
+
for (var _i = 0, patterns_1 = patterns; _i < patterns_1.length; _i++) {
|
|
454
|
+
var pattern = patterns_1[_i];
|
|
455
|
+
var matches = content.match(pattern);
|
|
340
456
|
if (matches)
|
|
341
457
|
complexity += matches.length;
|
|
342
458
|
}
|
|
@@ -350,44 +466,49 @@ function estimateComplexity(content) {
|
|
|
350
466
|
* Finds minimum cut with deterministic result
|
|
351
467
|
*/
|
|
352
468
|
function fallbackMinCut(nodes, edges) {
|
|
469
|
+
var _a, _b;
|
|
353
470
|
if (nodes.length < 2) {
|
|
354
471
|
return {
|
|
355
472
|
cutValue: 0,
|
|
356
473
|
partition1: nodes,
|
|
357
474
|
partition2: [],
|
|
358
|
-
cutEdges: []
|
|
475
|
+
cutEdges: []
|
|
359
476
|
};
|
|
360
477
|
}
|
|
361
478
|
// Build adjacency map with weights
|
|
362
|
-
|
|
363
|
-
for (
|
|
479
|
+
var adj = new Map();
|
|
480
|
+
for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) {
|
|
481
|
+
var node = nodes_1[_i];
|
|
364
482
|
adj.set(node, new Map());
|
|
365
483
|
}
|
|
366
|
-
for (
|
|
484
|
+
for (var _c = 0, edges_2 = edges; _c < edges_2.length; _c++) {
|
|
485
|
+
var _d = edges_2[_c], u = _d[0], v = _d[1], w = _d[2];
|
|
367
486
|
if (adj.has(u) && adj.has(v)) {
|
|
368
487
|
adj.get(u).set(v, (adj.get(u).get(v) || 0) + w);
|
|
369
488
|
adj.get(v).set(u, (adj.get(v).get(u) || 0) + w);
|
|
370
489
|
}
|
|
371
490
|
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
491
|
+
var bestCut = Infinity;
|
|
492
|
+
var bestPartition1 = [];
|
|
493
|
+
var bestPartition2 = [];
|
|
494
|
+
var bestCutEdges = [];
|
|
376
495
|
// Run multiple iterations for better results
|
|
377
|
-
|
|
378
|
-
|
|
496
|
+
var iterations = Math.min(nodes.length * 2, 20);
|
|
497
|
+
var _loop_1 = function (iter) {
|
|
379
498
|
// Start from different nodes
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
499
|
+
var startNode = nodes[iter % nodes.length];
|
|
500
|
+
var inSet = new Set([startNode]);
|
|
501
|
+
var remaining = new Set(nodes.filter(function (n) { return n !== startNode; }));
|
|
383
502
|
while (remaining.size > 1) {
|
|
384
503
|
// Find node with maximum connectivity to current set
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
for (
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
504
|
+
var maxNode = '';
|
|
505
|
+
var maxConn = -1;
|
|
506
|
+
for (var _g = 0, _h = Array.from(remaining); _g < _h.length; _g++) {
|
|
507
|
+
var node = _h[_g];
|
|
508
|
+
var conn = 0;
|
|
509
|
+
for (var _j = 0, _k = Array.from(inSet); _j < _k.length; _j++) {
|
|
510
|
+
var inNode = _k[_j];
|
|
511
|
+
conn += ((_a = adj.get(node)) === null || _a === void 0 ? void 0 : _a.get(inNode)) || 0;
|
|
391
512
|
}
|
|
392
513
|
if (conn > maxConn) {
|
|
393
514
|
maxConn = conn;
|
|
@@ -396,15 +517,16 @@ function fallbackMinCut(nodes, edges) {
|
|
|
396
517
|
}
|
|
397
518
|
if (!maxNode)
|
|
398
519
|
break;
|
|
399
|
-
remaining
|
|
520
|
+
remaining["delete"](maxNode);
|
|
400
521
|
inSet.add(maxNode);
|
|
401
522
|
}
|
|
402
523
|
if (remaining.size === 1) {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
for (
|
|
407
|
-
|
|
524
|
+
var lastNode = Array.from(remaining)[0];
|
|
525
|
+
var cutValue = 0;
|
|
526
|
+
var cutEdges = [];
|
|
527
|
+
for (var _l = 0, _m = Array.from(inSet); _l < _m.length; _l++) {
|
|
528
|
+
var inNode = _m[_l];
|
|
529
|
+
var weight = ((_b = adj.get(lastNode)) === null || _b === void 0 ? void 0 : _b.get(inNode)) || 0;
|
|
408
530
|
if (weight > 0) {
|
|
409
531
|
cutValue += weight;
|
|
410
532
|
cutEdges.push([lastNode, inNode]);
|
|
@@ -417,17 +539,21 @@ function fallbackMinCut(nodes, edges) {
|
|
|
417
539
|
bestCutEdges = cutEdges;
|
|
418
540
|
}
|
|
419
541
|
}
|
|
542
|
+
};
|
|
543
|
+
for (var iter = 0; iter < iterations; iter++) {
|
|
544
|
+
_loop_1(iter);
|
|
420
545
|
}
|
|
421
546
|
// If we didn't find a good cut, split roughly in half
|
|
422
547
|
if (bestCut === Infinity) {
|
|
423
|
-
|
|
548
|
+
var mid = Math.floor(nodes.length / 2);
|
|
424
549
|
bestPartition1 = nodes.slice(0, mid);
|
|
425
550
|
bestPartition2 = nodes.slice(mid);
|
|
426
551
|
bestCut = 0;
|
|
427
552
|
bestCutEdges = [];
|
|
428
|
-
for (
|
|
429
|
-
|
|
430
|
-
|
|
553
|
+
for (var _e = 0, edges_3 = edges; _e < edges_3.length; _e++) {
|
|
554
|
+
var _f = edges_3[_e], u = _f[0], v = _f[1], w = _f[2];
|
|
555
|
+
var uIn1 = bestPartition1.includes(u);
|
|
556
|
+
var vIn1 = bestPartition1.includes(v);
|
|
431
557
|
if (uIn1 !== vIn1) {
|
|
432
558
|
bestCut += w;
|
|
433
559
|
bestCutEdges.push([u, v]);
|
|
@@ -438,7 +564,7 @@ function fallbackMinCut(nodes, edges) {
|
|
|
438
564
|
cutValue: bestCut,
|
|
439
565
|
partition1: bestPartition1,
|
|
440
566
|
partition2: bestPartition2,
|
|
441
|
-
cutEdges: bestCutEdges
|
|
567
|
+
cutEdges: bestCutEdges
|
|
442
568
|
};
|
|
443
569
|
}
|
|
444
570
|
// ============================================================================
|
|
@@ -453,12 +579,14 @@ function fallbackLouvain(nodes, edges) {
|
|
|
453
579
|
return { communities: [], modularity: 0 };
|
|
454
580
|
}
|
|
455
581
|
// Build adjacency map
|
|
456
|
-
|
|
457
|
-
for (
|
|
582
|
+
var adj = new Map();
|
|
583
|
+
for (var _i = 0, nodes_2 = nodes; _i < nodes_2.length; _i++) {
|
|
584
|
+
var node = nodes_2[_i];
|
|
458
585
|
adj.set(node, new Map());
|
|
459
586
|
}
|
|
460
|
-
|
|
461
|
-
for (
|
|
587
|
+
var totalWeight = 0;
|
|
588
|
+
for (var _a = 0, edges_4 = edges; _a < edges_4.length; _a++) {
|
|
589
|
+
var _b = edges_4[_a], u = _b[0], v = _b[1], w = _b[2];
|
|
462
590
|
if (adj.has(u) && adj.has(v)) {
|
|
463
591
|
adj.get(u).set(v, (adj.get(u).get(v) || 0) + w);
|
|
464
592
|
adj.get(v).set(u, (adj.get(v).get(u) || 0) + w);
|
|
@@ -468,57 +596,64 @@ function fallbackLouvain(nodes, edges) {
|
|
|
468
596
|
if (totalWeight === 0) {
|
|
469
597
|
// No edges, each node is its own community
|
|
470
598
|
return {
|
|
471
|
-
communities: nodes.map((n, i)
|
|
472
|
-
modularity: 0
|
|
599
|
+
communities: nodes.map(function (n, i) { return ({ id: i, members: [n] }); }),
|
|
600
|
+
modularity: 0
|
|
473
601
|
};
|
|
474
602
|
}
|
|
475
603
|
// Initialize: each node in its own community
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
for (
|
|
604
|
+
var community = new Map();
|
|
605
|
+
var nextCommunityId = 0;
|
|
606
|
+
for (var _c = 0, nodes_3 = nodes; _c < nodes_3.length; _c++) {
|
|
607
|
+
var node = nodes_3[_c];
|
|
479
608
|
community.set(node, nextCommunityId++);
|
|
480
609
|
}
|
|
481
610
|
// Calculate node degree
|
|
482
|
-
|
|
483
|
-
for (
|
|
484
|
-
|
|
485
|
-
|
|
611
|
+
var degree = new Map();
|
|
612
|
+
for (var _d = 0, nodes_4 = nodes; _d < nodes_4.length; _d++) {
|
|
613
|
+
var node = nodes_4[_d];
|
|
614
|
+
var d = 0;
|
|
615
|
+
for (var _e = 0, _f = Array.from(adj.get(node).entries()); _e < _f.length; _e++) {
|
|
616
|
+
var _g = _f[_e], w = _g[1];
|
|
486
617
|
d += w;
|
|
487
618
|
}
|
|
488
619
|
degree.set(node, d);
|
|
489
620
|
}
|
|
490
621
|
// Louvain phase 1: local moving
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
622
|
+
var improved = true;
|
|
623
|
+
var maxIterations = 10;
|
|
624
|
+
var iteration = 0;
|
|
494
625
|
while (improved && iteration < maxIterations) {
|
|
495
626
|
improved = false;
|
|
496
627
|
iteration++;
|
|
497
|
-
for (
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
628
|
+
for (var _h = 0, nodes_5 = nodes; _h < nodes_5.length; _h++) {
|
|
629
|
+
var node = nodes_5[_h];
|
|
630
|
+
var currentCommunity = community.get(node);
|
|
631
|
+
var nodeAdj = adj.get(node);
|
|
632
|
+
var nodeDegree = degree.get(node);
|
|
501
633
|
// Calculate modularity gain for moving to each neighbor's community
|
|
502
|
-
|
|
503
|
-
for (
|
|
504
|
-
|
|
634
|
+
var communityWeights = new Map();
|
|
635
|
+
for (var _j = 0, _k = Array.from(nodeAdj.entries()); _j < _k.length; _j++) {
|
|
636
|
+
var _l = _k[_j], neighbor = _l[0], weight = _l[1];
|
|
637
|
+
var neighborCommunity = community.get(neighbor);
|
|
505
638
|
communityWeights.set(neighborCommunity, (communityWeights.get(neighborCommunity) || 0) + weight);
|
|
506
639
|
}
|
|
507
640
|
// Calculate community totals
|
|
508
|
-
|
|
509
|
-
for (
|
|
641
|
+
var communityTotal = new Map();
|
|
642
|
+
for (var _m = 0, _o = Array.from(community.entries()); _m < _o.length; _m++) {
|
|
643
|
+
var _p = _o[_m], n = _p[0], c = _p[1];
|
|
510
644
|
communityTotal.set(c, (communityTotal.get(c) || 0) + (degree.get(n) || 0));
|
|
511
645
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
for (
|
|
646
|
+
var bestCommunity = currentCommunity;
|
|
647
|
+
var bestGain = 0;
|
|
648
|
+
for (var _q = 0, _r = Array.from(communityWeights.entries()); _q < _r.length; _q++) {
|
|
649
|
+
var _s = _r[_q], targetCommunity = _s[0], edgeWeight = _s[1];
|
|
515
650
|
if (targetCommunity === currentCommunity)
|
|
516
651
|
continue;
|
|
517
652
|
// Calculate modularity gain
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
653
|
+
var currentTotal = communityTotal.get(currentCommunity) || 0;
|
|
654
|
+
var targetTotal = communityTotal.get(targetCommunity) || 0;
|
|
655
|
+
var currentEdges = communityWeights.get(currentCommunity) || 0;
|
|
656
|
+
var gain = (edgeWeight - currentEdges) / totalWeight -
|
|
522
657
|
(nodeDegree * (targetTotal - currentTotal + nodeDegree)) / (totalWeight * totalWeight);
|
|
523
658
|
if (gain > bestGain) {
|
|
524
659
|
bestGain = gain;
|
|
@@ -532,32 +667,35 @@ function fallbackLouvain(nodes, edges) {
|
|
|
532
667
|
}
|
|
533
668
|
}
|
|
534
669
|
// Collect communities
|
|
535
|
-
|
|
536
|
-
for (
|
|
670
|
+
var communityMembers = new Map();
|
|
671
|
+
for (var _t = 0, _u = Array.from(community.entries()); _t < _u.length; _t++) {
|
|
672
|
+
var _v = _u[_t], node = _v[0], comm = _v[1];
|
|
537
673
|
if (!communityMembers.has(comm)) {
|
|
538
674
|
communityMembers.set(comm, []);
|
|
539
675
|
}
|
|
540
676
|
communityMembers.get(comm).push(node);
|
|
541
677
|
}
|
|
542
678
|
// Renumber communities
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
for (
|
|
546
|
-
|
|
679
|
+
var communities = [];
|
|
680
|
+
var id = 0;
|
|
681
|
+
for (var _w = 0, _x = Array.from(communityMembers.values()); _w < _x.length; _w++) {
|
|
682
|
+
var members = _x[_w];
|
|
683
|
+
communities.push({ id: id++, members: members });
|
|
547
684
|
}
|
|
548
685
|
// Calculate modularity
|
|
549
|
-
|
|
550
|
-
for (
|
|
551
|
-
|
|
552
|
-
|
|
686
|
+
var modularity = 0;
|
|
687
|
+
for (var _y = 0, edges_5 = edges; _y < edges_5.length; _y++) {
|
|
688
|
+
var _z = edges_5[_y], u = _z[0], v = _z[1], w = _z[2];
|
|
689
|
+
var cu = community.get(u);
|
|
690
|
+
var cv = community.get(v);
|
|
553
691
|
if (cu === cv) {
|
|
554
|
-
|
|
555
|
-
|
|
692
|
+
var du = degree.get(u);
|
|
693
|
+
var dv = degree.get(v);
|
|
556
694
|
modularity += w - (du * dv) / totalWeight;
|
|
557
695
|
}
|
|
558
696
|
}
|
|
559
697
|
modularity /= totalWeight;
|
|
560
|
-
return { communities, modularity };
|
|
698
|
+
return { communities: communities, modularity: modularity };
|
|
561
699
|
}
|
|
562
700
|
// ============================================================================
|
|
563
701
|
// Circular Dependency Detection
|
|
@@ -566,17 +704,19 @@ function fallbackLouvain(nodes, edges) {
|
|
|
566
704
|
* Detect circular dependencies using DFS
|
|
567
705
|
*/
|
|
568
706
|
export function detectCircularDependencies(graph) {
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
707
|
+
var cycles = [];
|
|
708
|
+
var visited = new Set();
|
|
709
|
+
var recursionStack = new Set();
|
|
710
|
+
var path = [];
|
|
573
711
|
// Build adjacency list
|
|
574
|
-
|
|
575
|
-
for (
|
|
712
|
+
var adjList = new Map();
|
|
713
|
+
for (var _i = 0, _a = Array.from(graph.nodes.keys()); _i < _a.length; _i++) {
|
|
714
|
+
var node = _a[_i];
|
|
576
715
|
adjList.set(node, []);
|
|
577
716
|
}
|
|
578
|
-
for (
|
|
579
|
-
|
|
717
|
+
for (var _b = 0, _c = graph.edges; _b < _c.length; _b++) {
|
|
718
|
+
var edge = _c[_b];
|
|
719
|
+
var list = adjList.get(edge.source);
|
|
580
720
|
if (list) {
|
|
581
721
|
list.push(edge.target);
|
|
582
722
|
}
|
|
@@ -585,28 +725,30 @@ export function detectCircularDependencies(graph) {
|
|
|
585
725
|
visited.add(node);
|
|
586
726
|
recursionStack.add(node);
|
|
587
727
|
path.push(node);
|
|
588
|
-
|
|
589
|
-
for (
|
|
728
|
+
var neighbors = adjList.get(node) || [];
|
|
729
|
+
for (var _i = 0, neighbors_1 = neighbors; _i < neighbors_1.length; _i++) {
|
|
730
|
+
var neighbor = neighbors_1[_i];
|
|
590
731
|
if (!visited.has(neighbor)) {
|
|
591
732
|
dfs(neighbor);
|
|
592
733
|
}
|
|
593
734
|
else if (recursionStack.has(neighbor)) {
|
|
594
735
|
// Found cycle
|
|
595
|
-
|
|
596
|
-
|
|
736
|
+
var cycleStart = path.indexOf(neighbor);
|
|
737
|
+
var cycle = path.slice(cycleStart);
|
|
597
738
|
cycle.push(neighbor); // Complete the cycle
|
|
598
|
-
|
|
739
|
+
var severity = getCycleSeverity(cycle, graph);
|
|
599
740
|
cycles.push({
|
|
600
|
-
cycle,
|
|
601
|
-
severity,
|
|
602
|
-
suggestion: getCycleSuggestion(cycle, graph)
|
|
741
|
+
cycle: cycle,
|
|
742
|
+
severity: severity,
|
|
743
|
+
suggestion: getCycleSuggestion(cycle, graph)
|
|
603
744
|
});
|
|
604
745
|
}
|
|
605
746
|
}
|
|
606
|
-
recursionStack
|
|
747
|
+
recursionStack["delete"](node);
|
|
607
748
|
path.pop();
|
|
608
749
|
}
|
|
609
|
-
for (
|
|
750
|
+
for (var _d = 0, _e = Array.from(graph.nodes.keys()); _d < _e.length; _d++) {
|
|
751
|
+
var node = _e[_d];
|
|
610
752
|
if (!visited.has(node)) {
|
|
611
753
|
dfs(node);
|
|
612
754
|
}
|
|
@@ -617,7 +759,7 @@ function getCycleSeverity(cycle, _graph) {
|
|
|
617
759
|
// High severity if cycle involves many files or core modules
|
|
618
760
|
if (cycle.length > 5)
|
|
619
761
|
return 'high';
|
|
620
|
-
if (cycle.some(n
|
|
762
|
+
if (cycle.some(function (n) { return n.includes('index') || n.includes('core'); }))
|
|
621
763
|
return 'high';
|
|
622
764
|
if (cycle.length > 3)
|
|
623
765
|
return 'medium';
|
|
@@ -625,21 +767,21 @@ function getCycleSeverity(cycle, _graph) {
|
|
|
625
767
|
}
|
|
626
768
|
function getCycleSuggestion(cycle, graph) {
|
|
627
769
|
if (cycle.length === 2) {
|
|
628
|
-
return
|
|
770
|
+
return "Consider extracting shared code into a separate module to break the cycle between " + cycle[0] + " and " + cycle[1];
|
|
629
771
|
}
|
|
630
772
|
// Find the weakest link (least important edge)
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
for (
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
773
|
+
var weakestEdge = '';
|
|
774
|
+
var minImports = Infinity;
|
|
775
|
+
for (var i = 0; i < cycle.length - 1; i++) {
|
|
776
|
+
var from = cycle[i];
|
|
777
|
+
var to = cycle[i + 1];
|
|
778
|
+
var fromNode = graph.nodes.get(from);
|
|
637
779
|
if (fromNode && fromNode.imports.length < minImports) {
|
|
638
780
|
minImports = fromNode.imports.length;
|
|
639
|
-
weakestEdge =
|
|
781
|
+
weakestEdge = from + " -> " + to;
|
|
640
782
|
}
|
|
641
783
|
}
|
|
642
|
-
return
|
|
784
|
+
return "Break the cycle by refactoring the dependency: " + weakestEdge + ". Consider dependency injection or extracting interfaces.";
|
|
643
785
|
}
|
|
644
786
|
// ============================================================================
|
|
645
787
|
// Main Analysis Functions
|
|
@@ -647,103 +789,131 @@ function getCycleSuggestion(cycle, graph) {
|
|
|
647
789
|
/**
|
|
648
790
|
* Analyze graph boundaries using MinCut algorithm
|
|
649
791
|
*/
|
|
650
|
-
export
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
792
|
+
export function analyzeMinCutBoundaries(graph, numPartitions) {
|
|
793
|
+
if (numPartitions === void 0) { numPartitions = 2; }
|
|
794
|
+
return __awaiter(this, void 0, Promise, function () {
|
|
795
|
+
var nodes, edges, boundaries, ruVector, result, subEdges, subResult;
|
|
796
|
+
return __generator(this, function (_a) {
|
|
797
|
+
switch (_a.label) {
|
|
798
|
+
case 0:
|
|
799
|
+
nodes = Array.from(graph.nodes.keys());
|
|
800
|
+
edges = graph.edges.map(function (e) { return [e.source, e.target, e.weight]; });
|
|
801
|
+
boundaries = [];
|
|
802
|
+
return [4 /*yield*/, loadRuVector()];
|
|
803
|
+
case 1:
|
|
804
|
+
ruVector = _a.sent();
|
|
805
|
+
if (ruVector) {
|
|
806
|
+
result = ruVector.mincut(nodes, edges);
|
|
807
|
+
}
|
|
808
|
+
else {
|
|
809
|
+
result = fallbackMinCut(nodes, edges);
|
|
810
|
+
}
|
|
811
|
+
boundaries.push({
|
|
812
|
+
cutValue: result.cutValue,
|
|
813
|
+
partition1: result.partition1,
|
|
814
|
+
partition2: result.partition2,
|
|
815
|
+
cutEdges: result.cutEdges.map(function (_a) {
|
|
816
|
+
var s = _a[0], t = _a[1];
|
|
817
|
+
var edge = graph.edges.find(function (e) { return e.source === s && e.target === t; });
|
|
818
|
+
return edge || { source: s, target: t, type: 'import', weight: 1 };
|
|
819
|
+
}),
|
|
820
|
+
suggestion: generateBoundarySuggestion(result.partition1, result.partition2, graph)
|
|
821
|
+
});
|
|
822
|
+
// Recursively partition if needed
|
|
823
|
+
if (numPartitions > 2 && result.partition1.length > 2) {
|
|
824
|
+
subEdges = edges.filter(function (_a) {
|
|
825
|
+
var u = _a[0], v = _a[1];
|
|
826
|
+
return result.partition1.includes(u) && result.partition1.includes(v);
|
|
827
|
+
});
|
|
828
|
+
subResult = ruVector
|
|
829
|
+
? ruVector.mincut(result.partition1, subEdges)
|
|
830
|
+
: fallbackMinCut(result.partition1, subEdges);
|
|
831
|
+
if (subResult.cutValue > 0) {
|
|
832
|
+
boundaries.push({
|
|
833
|
+
cutValue: subResult.cutValue,
|
|
834
|
+
partition1: subResult.partition1,
|
|
835
|
+
partition2: subResult.partition2,
|
|
836
|
+
cutEdges: subResult.cutEdges.map(function (_a) {
|
|
837
|
+
var s = _a[0], t = _a[1];
|
|
838
|
+
var edge = graph.edges.find(function (e) { return e.source === s && e.target === t; });
|
|
839
|
+
return edge || { source: s, target: t, type: 'import', weight: 1 };
|
|
840
|
+
}),
|
|
841
|
+
suggestion: generateBoundarySuggestion(subResult.partition1, subResult.partition2, graph)
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
return [2 /*return*/, boundaries];
|
|
846
|
+
}
|
|
847
|
+
});
|
|
673
848
|
});
|
|
674
|
-
// Recursively partition if needed
|
|
675
|
-
if (numPartitions > 2 && result.partition1.length > 2) {
|
|
676
|
-
const subEdges = edges.filter(([u, v]) => result.partition1.includes(u) && result.partition1.includes(v));
|
|
677
|
-
const subResult = ruVector
|
|
678
|
-
? ruVector.mincut(result.partition1, subEdges)
|
|
679
|
-
: fallbackMinCut(result.partition1, subEdges);
|
|
680
|
-
if (subResult.cutValue > 0) {
|
|
681
|
-
boundaries.push({
|
|
682
|
-
cutValue: subResult.cutValue,
|
|
683
|
-
partition1: subResult.partition1,
|
|
684
|
-
partition2: subResult.partition2,
|
|
685
|
-
cutEdges: subResult.cutEdges.map(([s, t]) => {
|
|
686
|
-
const edge = graph.edges.find(e => e.source === s && e.target === t);
|
|
687
|
-
return edge || { source: s, target: t, type: 'import', weight: 1 };
|
|
688
|
-
}),
|
|
689
|
-
suggestion: generateBoundarySuggestion(subResult.partition1, subResult.partition2, graph),
|
|
690
|
-
});
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
return boundaries;
|
|
694
849
|
}
|
|
695
850
|
function generateBoundarySuggestion(partition1, partition2, _graph) {
|
|
696
851
|
// Analyze the partitions to suggest organization
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
852
|
+
var p1Dirs = partition1.map(function (p) { return dirname(p); }).filter(function (d) { return d !== '.'; });
|
|
853
|
+
var p2Dirs = partition2.map(function (p) { return dirname(p); }).filter(function (d) { return d !== '.'; });
|
|
854
|
+
var p1DirsSet = new Set(p1Dirs);
|
|
855
|
+
var p2DirsSet = new Set(p2Dirs);
|
|
701
856
|
if (p1DirsSet.size === 1 && p2DirsSet.size === 1) {
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
return
|
|
857
|
+
var dir1 = p1Dirs[0];
|
|
858
|
+
var dir2 = p2Dirs[0];
|
|
859
|
+
return "Natural boundary detected between " + dir1 + "/ and " + dir2 + "/. These could be separate packages.";
|
|
705
860
|
}
|
|
706
861
|
if (partition1.length > partition2.length * 3) {
|
|
707
|
-
return
|
|
862
|
+
return "Consider extracting " + partition2.length + " files into a separate module. They have minimal coupling to the rest.";
|
|
708
863
|
}
|
|
709
|
-
return
|
|
864
|
+
return "Found " + partition1.length + " and " + partition2.length + " file groups with minimal coupling. Consider organizing into separate modules.";
|
|
710
865
|
}
|
|
711
866
|
/**
|
|
712
867
|
* Analyze module communities using Louvain algorithm
|
|
713
868
|
*/
|
|
714
|
-
export
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
869
|
+
export function analyzeModuleCommunities(graph) {
|
|
870
|
+
return __awaiter(this, void 0, Promise, function () {
|
|
871
|
+
var nodes, edges, ruVector, result;
|
|
872
|
+
return __generator(this, function (_a) {
|
|
873
|
+
switch (_a.label) {
|
|
874
|
+
case 0:
|
|
875
|
+
nodes = Array.from(graph.nodes.keys());
|
|
876
|
+
edges = graph.edges.map(function (e) { return [e.source, e.target, e.weight]; });
|
|
877
|
+
return [4 /*yield*/, loadRuVector()];
|
|
878
|
+
case 1:
|
|
879
|
+
ruVector = _a.sent();
|
|
880
|
+
result = ruVector ? ruVector.louvain(nodes, edges) : fallbackLouvain(nodes, edges);
|
|
881
|
+
return [2 /*return*/, result.communities.map(function (comm) {
|
|
882
|
+
// Find the most connected node as central
|
|
883
|
+
var maxConnections = 0;
|
|
884
|
+
var centralNode = comm.members[0];
|
|
885
|
+
var _loop_2 = function (member) {
|
|
886
|
+
var connections = graph.edges.filter(function (e) {
|
|
887
|
+
return (e.source === member && comm.members.includes(e.target)) ||
|
|
888
|
+
(e.target === member && comm.members.includes(e.source));
|
|
889
|
+
}).length;
|
|
890
|
+
if (connections > maxConnections) {
|
|
891
|
+
maxConnections = connections;
|
|
892
|
+
centralNode = member;
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
for (var _i = 0, _a = comm.members; _i < _a.length; _i++) {
|
|
896
|
+
var member = _a[_i];
|
|
897
|
+
_loop_2(member);
|
|
898
|
+
}
|
|
899
|
+
// Calculate cohesion (internal edges / total possible edges)
|
|
900
|
+
var internalEdges = graph.edges.filter(function (e) { return comm.members.includes(e.source) && comm.members.includes(e.target); }).length;
|
|
901
|
+
var possibleEdges = (comm.members.length * (comm.members.length - 1)) / 2;
|
|
902
|
+
var cohesion = possibleEdges > 0 ? internalEdges / possibleEdges : 1;
|
|
903
|
+
// Suggest name based on common directory
|
|
904
|
+
var dirs = comm.members.map(function (m) { return dirname(m); });
|
|
905
|
+
var commonDir = findCommonPrefix(dirs);
|
|
906
|
+
var suggestedName = commonDir || basename(centralNode, extname(centralNode));
|
|
907
|
+
return {
|
|
908
|
+
id: comm.id,
|
|
909
|
+
members: comm.members,
|
|
910
|
+
cohesion: cohesion,
|
|
911
|
+
centralNode: centralNode,
|
|
912
|
+
suggestedName: suggestedName
|
|
913
|
+
};
|
|
914
|
+
})];
|
|
730
915
|
}
|
|
731
|
-
}
|
|
732
|
-
// Calculate cohesion (internal edges / total possible edges)
|
|
733
|
-
const internalEdges = graph.edges.filter(e => comm.members.includes(e.source) && comm.members.includes(e.target)).length;
|
|
734
|
-
const possibleEdges = (comm.members.length * (comm.members.length - 1)) / 2;
|
|
735
|
-
const cohesion = possibleEdges > 0 ? internalEdges / possibleEdges : 1;
|
|
736
|
-
// Suggest name based on common directory
|
|
737
|
-
const dirs = comm.members.map(m => dirname(m));
|
|
738
|
-
const commonDir = findCommonPrefix(dirs);
|
|
739
|
-
const suggestedName = commonDir || basename(centralNode, extname(centralNode));
|
|
740
|
-
return {
|
|
741
|
-
id: comm.id,
|
|
742
|
-
members: comm.members,
|
|
743
|
-
cohesion,
|
|
744
|
-
centralNode,
|
|
745
|
-
suggestedName,
|
|
746
|
-
};
|
|
916
|
+
});
|
|
747
917
|
});
|
|
748
918
|
}
|
|
749
919
|
function findCommonPrefix(strings) {
|
|
@@ -751,94 +921,108 @@ function findCommonPrefix(strings) {
|
|
|
751
921
|
return '';
|
|
752
922
|
if (strings.length === 1)
|
|
753
923
|
return strings[0];
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
924
|
+
var sorted = __spreadArray([], strings, true).sort();
|
|
925
|
+
var first = sorted[0];
|
|
926
|
+
var last = sorted[sorted.length - 1];
|
|
927
|
+
var i = 0;
|
|
758
928
|
while (i < first.length && first[i] === last[i]) {
|
|
759
929
|
i++;
|
|
760
930
|
}
|
|
761
|
-
|
|
931
|
+
var prefix = first.slice(0, i);
|
|
762
932
|
// Return the last complete directory segment
|
|
763
|
-
|
|
933
|
+
var lastSlash = prefix.lastIndexOf('/');
|
|
764
934
|
return lastSlash > 0 ? prefix.slice(0, lastSlash) : '';
|
|
765
935
|
}
|
|
766
936
|
/**
|
|
767
937
|
* Full graph analysis (with caching)
|
|
768
938
|
*/
|
|
769
|
-
export
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
const degrees = new Map();
|
|
783
|
-
for (const node of Array.from(graph.nodes.keys())) {
|
|
784
|
-
degrees.set(node, 0);
|
|
785
|
-
}
|
|
786
|
-
for (const edge of graph.edges) {
|
|
787
|
-
degrees.set(edge.source, (degrees.get(edge.source) || 0) + 1);
|
|
788
|
-
degrees.set(edge.target, (degrees.get(edge.target) || 0) + 1);
|
|
789
|
-
}
|
|
790
|
-
const degreeValues = Array.from(degrees.values());
|
|
791
|
-
const avgDegree = degreeValues.length > 0 ? degreeValues.reduce((a, b) => a + b, 0) / degreeValues.length : 0;
|
|
792
|
-
const maxDegree = degreeValues.length > 0 ? Math.max(...degreeValues) : 0;
|
|
793
|
-
const density = nodeCount > 1 ? (2 * edgeCount) / (nodeCount * (nodeCount - 1)) : 0;
|
|
794
|
-
// Count connected components
|
|
795
|
-
const visited = new Set();
|
|
796
|
-
let componentCount = 0;
|
|
797
|
-
function dfs(node) {
|
|
798
|
-
visited.add(node);
|
|
799
|
-
for (const edge of graph.edges) {
|
|
800
|
-
if (edge.source === node && !visited.has(edge.target)) {
|
|
801
|
-
dfs(edge.target);
|
|
802
|
-
}
|
|
803
|
-
if (edge.target === node && !visited.has(edge.source)) {
|
|
804
|
-
dfs(edge.source);
|
|
939
|
+
export function analyzeGraph(rootDir, options) {
|
|
940
|
+
if (options === void 0) { options = {}; }
|
|
941
|
+
return __awaiter(this, void 0, Promise, function () {
|
|
942
|
+
function dfs(node) {
|
|
943
|
+
visited.add(node);
|
|
944
|
+
for (var _i = 0, _a = graph.edges; _i < _a.length; _i++) {
|
|
945
|
+
var edge = _a[_i];
|
|
946
|
+
if (edge.source === node && !visited.has(edge.target)) {
|
|
947
|
+
dfs(edge.target);
|
|
948
|
+
}
|
|
949
|
+
if (edge.target === node && !visited.has(edge.source)) {
|
|
950
|
+
dfs(edge.source);
|
|
951
|
+
}
|
|
805
952
|
}
|
|
806
953
|
}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
954
|
+
var cacheKey, cached, graph, nodeCount, edgeCount, degrees, _i, _a, node, _b, _c, edge, degreeValues, avgDegree, maxDegree, density, visited, componentCount, _d, _e, node, circularDependencies, boundaries, communities, result;
|
|
955
|
+
return __generator(this, function (_f) {
|
|
956
|
+
switch (_f.label) {
|
|
957
|
+
case 0:
|
|
958
|
+
cacheKey = "analysis:" + rootDir + ":" + JSON.stringify(options);
|
|
959
|
+
if (!options.skipCache) {
|
|
960
|
+
cached = analysisResultCache.get(cacheKey);
|
|
961
|
+
if (cached && Date.now() - cached.timestamp < ANALYSIS_CACHE_TTL_MS) {
|
|
962
|
+
return [2 /*return*/, cached.result];
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
return [4 /*yield*/, buildDependencyGraph(rootDir, { skipCache: options.skipCache })];
|
|
966
|
+
case 1:
|
|
967
|
+
graph = _f.sent();
|
|
968
|
+
nodeCount = graph.nodes.size;
|
|
969
|
+
edgeCount = graph.edges.length;
|
|
970
|
+
degrees = new Map();
|
|
971
|
+
for (_i = 0, _a = Array.from(graph.nodes.keys()); _i < _a.length; _i++) {
|
|
972
|
+
node = _a[_i];
|
|
973
|
+
degrees.set(node, 0);
|
|
974
|
+
}
|
|
975
|
+
for (_b = 0, _c = graph.edges; _b < _c.length; _b++) {
|
|
976
|
+
edge = _c[_b];
|
|
977
|
+
degrees.set(edge.source, (degrees.get(edge.source) || 0) + 1);
|
|
978
|
+
degrees.set(edge.target, (degrees.get(edge.target) || 0) + 1);
|
|
979
|
+
}
|
|
980
|
+
degreeValues = Array.from(degrees.values());
|
|
981
|
+
avgDegree = degreeValues.length > 0 ? degreeValues.reduce(function (a, b) { return a + b; }, 0) / degreeValues.length : 0;
|
|
982
|
+
maxDegree = degreeValues.length > 0 ? Math.max.apply(Math, degreeValues) : 0;
|
|
983
|
+
density = nodeCount > 1 ? (2 * edgeCount) / (nodeCount * (nodeCount - 1)) : 0;
|
|
984
|
+
visited = new Set();
|
|
985
|
+
componentCount = 0;
|
|
986
|
+
for (_d = 0, _e = Array.from(graph.nodes.keys()); _d < _e.length; _d++) {
|
|
987
|
+
node = _e[_d];
|
|
988
|
+
if (!visited.has(node)) {
|
|
989
|
+
componentCount++;
|
|
990
|
+
dfs(node);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
circularDependencies = detectCircularDependencies(graph);
|
|
994
|
+
if (!(options.includeBoundaries !== false)) return [3 /*break*/, 3];
|
|
995
|
+
return [4 /*yield*/, analyzeMinCutBoundaries(graph, options.numPartitions)];
|
|
996
|
+
case 2:
|
|
997
|
+
boundaries = _f.sent();
|
|
998
|
+
_f.label = 3;
|
|
999
|
+
case 3:
|
|
1000
|
+
if (!(options.includeModules !== false)) return [3 /*break*/, 5];
|
|
1001
|
+
return [4 /*yield*/, analyzeModuleCommunities(graph)];
|
|
1002
|
+
case 4:
|
|
1003
|
+
communities = _f.sent();
|
|
1004
|
+
_f.label = 5;
|
|
1005
|
+
case 5:
|
|
1006
|
+
result = {
|
|
1007
|
+
graph: graph,
|
|
1008
|
+
boundaries: boundaries,
|
|
1009
|
+
communities: communities,
|
|
1010
|
+
circularDependencies: circularDependencies,
|
|
1011
|
+
statistics: {
|
|
1012
|
+
nodeCount: nodeCount,
|
|
1013
|
+
edgeCount: edgeCount,
|
|
1014
|
+
avgDegree: avgDegree,
|
|
1015
|
+
maxDegree: maxDegree,
|
|
1016
|
+
density: density,
|
|
1017
|
+
componentCount: componentCount
|
|
1018
|
+
}
|
|
1019
|
+
};
|
|
1020
|
+
// Cache the result
|
|
1021
|
+
analysisResultCache.set(cacheKey, { result: result, timestamp: Date.now() });
|
|
1022
|
+
return [2 /*return*/, result];
|
|
1023
|
+
}
|
|
1024
|
+
});
|
|
1025
|
+
});
|
|
842
1026
|
}
|
|
843
1027
|
// ============================================================================
|
|
844
1028
|
// DOT Format Export
|
|
@@ -846,56 +1030,62 @@ export async function analyzeGraph(rootDir, options = {}) {
|
|
|
846
1030
|
/**
|
|
847
1031
|
* Export graph to DOT format for visualization
|
|
848
1032
|
*/
|
|
849
|
-
export function exportToDot(result, options
|
|
850
|
-
|
|
851
|
-
|
|
1033
|
+
export function exportToDot(result, options) {
|
|
1034
|
+
if (options === void 0) { options = {}; }
|
|
1035
|
+
var graph = result.graph, communities = result.communities, circularDependencies = result.circularDependencies;
|
|
1036
|
+
var lines = ['digraph DependencyGraph {'];
|
|
852
1037
|
lines.push(' rankdir=LR;');
|
|
853
1038
|
lines.push(' node [shape=box, style=rounded];');
|
|
854
1039
|
lines.push('');
|
|
855
1040
|
// Generate colors for communities
|
|
856
|
-
|
|
1041
|
+
var communityColors = new Map();
|
|
857
1042
|
if (options.colorByCommunity && communities) {
|
|
858
|
-
|
|
1043
|
+
var colors = [
|
|
859
1044
|
'#e6194b', '#3cb44b', '#ffe119', '#4363d8', '#f58231',
|
|
860
1045
|
'#911eb4', '#42d4f4', '#f032e6', '#bfef45', '#fabed4',
|
|
861
1046
|
];
|
|
862
|
-
for (
|
|
863
|
-
|
|
864
|
-
|
|
1047
|
+
for (var _i = 0, communities_1 = communities; _i < communities_1.length; _i++) {
|
|
1048
|
+
var comm = communities_1[_i];
|
|
1049
|
+
var color = colors[comm.id % colors.length];
|
|
1050
|
+
for (var _a = 0, _b = comm.members; _a < _b.length; _a++) {
|
|
1051
|
+
var member = _b[_a];
|
|
865
1052
|
communityColors.set(member, color);
|
|
866
1053
|
}
|
|
867
1054
|
}
|
|
868
1055
|
}
|
|
869
1056
|
// Find nodes in cycles
|
|
870
|
-
|
|
1057
|
+
var nodesInCycles = new Set();
|
|
871
1058
|
if (options.highlightCycles && circularDependencies) {
|
|
872
|
-
for (
|
|
873
|
-
|
|
1059
|
+
for (var _c = 0, circularDependencies_1 = circularDependencies; _c < circularDependencies_1.length; _c++) {
|
|
1060
|
+
var cycle = circularDependencies_1[_c];
|
|
1061
|
+
for (var _d = 0, _e = cycle.cycle; _d < _e.length; _d++) {
|
|
1062
|
+
var node = _e[_d];
|
|
874
1063
|
nodesInCycles.add(node);
|
|
875
1064
|
}
|
|
876
1065
|
}
|
|
877
1066
|
}
|
|
878
1067
|
// Output nodes
|
|
879
1068
|
lines.push(' // Nodes');
|
|
880
|
-
for (
|
|
881
|
-
|
|
1069
|
+
for (var _f = 0, _g = Array.from(graph.nodes.entries()); _f < _g.length; _f++) {
|
|
1070
|
+
var _h = _g[_f], id = _h[0], node = _h[1];
|
|
1071
|
+
var attrs = [];
|
|
882
1072
|
if (options.includeLabels !== false) {
|
|
883
|
-
attrs.push(
|
|
1073
|
+
attrs.push("label=\"" + node.name + "\"");
|
|
884
1074
|
}
|
|
885
1075
|
if (communityColors.has(id)) {
|
|
886
|
-
attrs.push(
|
|
1076
|
+
attrs.push("fillcolor=\"" + communityColors.get(id) + "\"", 'style="filled,rounded"');
|
|
887
1077
|
}
|
|
888
1078
|
if (nodesInCycles.has(id)) {
|
|
889
1079
|
attrs.push('color=red', 'penwidth=2');
|
|
890
1080
|
}
|
|
891
|
-
|
|
892
|
-
lines.push(
|
|
1081
|
+
var attrStr = attrs.length > 0 ? " [" + attrs.join(', ') + "]" : '';
|
|
1082
|
+
lines.push(" \"" + id + "\"" + attrStr + ";");
|
|
893
1083
|
}
|
|
894
1084
|
lines.push('');
|
|
895
1085
|
// Output edges
|
|
896
1086
|
lines.push(' // Edges');
|
|
897
|
-
|
|
898
|
-
|
|
1087
|
+
var _loop_3 = function (edge) {
|
|
1088
|
+
var attrs = [];
|
|
899
1089
|
if (edge.type === 'dynamic') {
|
|
900
1090
|
attrs.push('style=dashed');
|
|
901
1091
|
}
|
|
@@ -904,8 +1094,8 @@ export function exportToDot(result, options = {}) {
|
|
|
904
1094
|
}
|
|
905
1095
|
// Check if edge is part of a cycle
|
|
906
1096
|
if (options.highlightCycles) {
|
|
907
|
-
|
|
908
|
-
for (
|
|
1097
|
+
var isCycleEdge = circularDependencies.some(function (cd) {
|
|
1098
|
+
for (var i = 0; i < cd.cycle.length - 1; i++) {
|
|
909
1099
|
if (cd.cycle[i] === edge.source && cd.cycle[i + 1] === edge.target) {
|
|
910
1100
|
return true;
|
|
911
1101
|
}
|
|
@@ -916,8 +1106,12 @@ export function exportToDot(result, options = {}) {
|
|
|
916
1106
|
attrs.push('color=red', 'penwidth=2');
|
|
917
1107
|
}
|
|
918
1108
|
}
|
|
919
|
-
|
|
920
|
-
lines.push(
|
|
1109
|
+
var attrStr = attrs.length > 0 ? " [" + attrs.join(', ') + "]" : '';
|
|
1110
|
+
lines.push(" \"" + edge.source + "\" -> \"" + edge.target + "\"" + attrStr + ";");
|
|
1111
|
+
};
|
|
1112
|
+
for (var _j = 0, _k = graph.edges; _j < _k.length; _j++) {
|
|
1113
|
+
var edge = _k[_j];
|
|
1114
|
+
_loop_3(edge);
|
|
921
1115
|
}
|
|
922
1116
|
lines.push('}');
|
|
923
1117
|
return lines.join('\n');
|