igel-qe-core 1.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/dist/cli/index.js +38 -0
- package/dist/mcp/server.js +104 -0
- package/knowledge_base/__init__.py +3 -0
- package/knowledge_base/__pycache__/__init__.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/__pycache__/confidence.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/config.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/config.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/config.cpython-38.pyc +0 -0
- package/knowledge_base/__pycache__/context_fusion.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/context_fusion.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/feedback_analytics.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/feedback_applier.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/feedback_cli.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/feedback_curator.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/feedback_handler.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/generate.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/generate_qcapps134.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/input_classifier.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/input_classifier.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/kg_extractor.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/knowledge_graph.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/knowledge_graph.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/manual_tc_parser.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/manual_tc_parser.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/precedence.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/prompts.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/prompts.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/reranker.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/reranker.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/retrieval_debug.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/retrieval_debug.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/retriever.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/retriever.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/server.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/tc_transformer.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/tc_transformer.cpython-37.pyc +0 -0
- package/knowledge_base/__pycache__/test_generator.cpython-314.pyc +0 -0
- package/knowledge_base/__pycache__/test_generator.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__init__.py +6 -0
- package/knowledge_base/agents/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/fusion_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/fusion_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/graph.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/graph.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/healing_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/intent_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/intent_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/kg_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/kg_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/memory_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/memory_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/rca_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/reflection_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/reflection_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/regression_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/retrieval_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/retrieval_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/script_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/script_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/state.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/state.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/temporal_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/temporal_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/__pycache__/validation_agent.cpython-37.pyc +0 -0
- package/knowledge_base/agents/__pycache__/validation_agent.cpython-38.pyc +0 -0
- package/knowledge_base/agents/automation_design_agent.py +123 -0
- package/knowledge_base/agents/code_intelligence_agent.py +147 -0
- package/knowledge_base/agents/confidence_agent.py +94 -0
- package/knowledge_base/agents/execution_validation_agent.py +129 -0
- package/knowledge_base/agents/feedback_agent.py +56 -0
- package/knowledge_base/agents/fusion_agent.py +113 -0
- package/knowledge_base/agents/graph.py +152 -0
- package/knowledge_base/agents/healing_agent.py +62 -0
- package/knowledge_base/agents/intent_agent.py +76 -0
- package/knowledge_base/agents/kg_agent.py +91 -0
- package/knowledge_base/agents/memory_agent.py +62 -0
- package/knowledge_base/agents/rca_agent.py +53 -0
- package/knowledge_base/agents/reflection_agent.py +62 -0
- package/knowledge_base/agents/regression_agent.py +81 -0
- package/knowledge_base/agents/requirement_agent.py +71 -0
- package/knowledge_base/agents/retrieval_agent.py +66 -0
- package/knowledge_base/agents/scenario_agent.py +81 -0
- package/knowledge_base/agents/script_agent.py +121 -0
- package/knowledge_base/agents/script_generator_agent.py +77 -0
- package/knowledge_base/agents/state.py +53 -0
- package/knowledge_base/agents/temporal_agent.py +48 -0
- package/knowledge_base/agents/testcase_agent.py +111 -0
- package/knowledge_base/agents/validation_agent.py +49 -0
- package/knowledge_base/agents/workflow_engine.py +87 -0
- package/knowledge_base/alembic/README.md +104 -0
- package/knowledge_base/alembic/__pycache__/env.cpython-37.pyc +0 -0
- package/knowledge_base/alembic/__pycache__/env.cpython-38.pyc +0 -0
- package/knowledge_base/alembic/env.py +76 -0
- package/knowledge_base/alembic/script.py.mako +5 -0
- package/knowledge_base/alembic/versions/.gitkeep +26 -0
- package/knowledge_base/alembic/versions/001_phase0_feedback.py +122 -0
- package/knowledge_base/alembic/versions/002_feedback_promotions.py +60 -0
- package/knowledge_base/alembic/versions/003_enterprise_hardening.py +74 -0
- package/knowledge_base/alembic/versions/__pycache__/001_phase0_feedback.cpython-37.pyc +0 -0
- package/knowledge_base/alembic/versions/__pycache__/001_phase0_feedback.cpython-38.pyc +0 -0
- package/knowledge_base/alembic/versions/__pycache__/002_feedback_promotions.cpython-37.pyc +0 -0
- package/knowledge_base/alembic/versions/__pycache__/002_feedback_promotions.cpython-38.pyc +0 -0
- package/knowledge_base/api/__init__.py +1 -0
- package/knowledge_base/api/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/api/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/api/__pycache__/middleware.cpython-38.pyc +0 -0
- package/knowledge_base/api/__pycache__/server.cpython-37.pyc +0 -0
- package/knowledge_base/api/__pycache__/server.cpython-38.pyc +0 -0
- package/knowledge_base/api/middleware.py +78 -0
- package/knowledge_base/api/server.py +778 -0
- package/knowledge_base/chunking/__init__.py +0 -0
- package/knowledge_base/chunking/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/chunking/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/chunking/__pycache__/chunker.cpython-37.pyc +0 -0
- package/knowledge_base/chunking/__pycache__/chunker.cpython-38.pyc +0 -0
- package/knowledge_base/chunking/__pycache__/validators.cpython-37.pyc +0 -0
- package/knowledge_base/chunking/__pycache__/validators.cpython-38.pyc +0 -0
- package/knowledge_base/chunking/chunker.py +402 -0
- package/knowledge_base/chunking/validators.py +144 -0
- package/knowledge_base/cli/__init__.py +1 -0
- package/knowledge_base/cli/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/cli/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/cli/__pycache__/feedback_cli.cpython-37.pyc +0 -0
- package/knowledge_base/cli/__pycache__/feedback_cli.cpython-38.pyc +0 -0
- package/knowledge_base/cli/__pycache__/generate.cpython-37.pyc +0 -0
- package/knowledge_base/cli/__pycache__/generate.cpython-38.pyc +0 -0
- package/knowledge_base/cli/__pycache__/generate_qcapps134.cpython-37.pyc +0 -0
- package/knowledge_base/cli/feedback_cli.py +121 -0
- package/knowledge_base/cli/generate.py +308 -0
- package/knowledge_base/cli/generate_qcapps134.py +391 -0
- package/knowledge_base/config/.env +100 -0
- package/knowledge_base/config/.env.example +75 -0
- package/knowledge_base/config/__init__.py +5 -0
- package/knowledge_base/config/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/config/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/config/__pycache__/settings.cpython-37.pyc +0 -0
- package/knowledge_base/config/__pycache__/settings.cpython-38.pyc +0 -0
- package/knowledge_base/config/settings.py +280 -0
- package/knowledge_base/connectors/__init__.py +5 -0
- package/knowledge_base/connectors/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/base.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/base.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/bitbucket_connector.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/bitbucket_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/community_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/confluence_connector.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/confluence_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/jira_connector.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/jira_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/kb_igel_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/playwright_fetcher.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/query_bridge.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/search_backends.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/serviceNow_connector.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/serviceNow_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/sync_scheduler.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/sync_scheduler.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/teamcity_connector.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/teamcity_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/testRail_connector.cpython-37.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/testRail_connector.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/__pycache__/web_fetcher.cpython-38.pyc +0 -0
- package/knowledge_base/connectors/base.py +44 -0
- package/knowledge_base/connectors/bitbucket_connector.py +25 -0
- package/knowledge_base/connectors/community_connector.py +112 -0
- package/knowledge_base/connectors/confluence_connector.py +165 -0
- package/knowledge_base/connectors/jira_connector.py +174 -0
- package/knowledge_base/connectors/kb_igel_connector.py +145 -0
- package/knowledge_base/connectors/playwright_fetcher.py +50 -0
- package/knowledge_base/connectors/query_bridge.py +170 -0
- package/knowledge_base/connectors/search_backends.py +368 -0
- package/knowledge_base/connectors/serviceNow_connector.py +25 -0
- package/knowledge_base/connectors/sync_scheduler.py +111 -0
- package/knowledge_base/connectors/teamcity_connector.py +25 -0
- package/knowledge_base/connectors/testRail_connector.py +25 -0
- package/knowledge_base/connectors/web_fetcher.py +280 -0
- package/knowledge_base/core/__init__.py +8 -0
- package/knowledge_base/core/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/core/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/core/__pycache__/cache.cpython-38.pyc +0 -0
- package/knowledge_base/core/__pycache__/circuit_breaker.cpython-38.pyc +0 -0
- package/knowledge_base/core/__pycache__/confidence.cpython-37.pyc +0 -0
- package/knowledge_base/core/__pycache__/confidence.cpython-38.pyc +0 -0
- package/knowledge_base/core/__pycache__/logging_setup.cpython-38.pyc +0 -0
- package/knowledge_base/core/__pycache__/metrics.cpython-38.pyc +0 -0
- package/knowledge_base/core/__pycache__/precedence.cpython-37.pyc +0 -0
- package/knowledge_base/core/__pycache__/precedence.cpython-38.pyc +0 -0
- package/knowledge_base/core/__pycache__/request_context.cpython-38.pyc +0 -0
- package/knowledge_base/core/cache.py +98 -0
- package/knowledge_base/core/circuit_breaker.py +33 -0
- package/knowledge_base/core/confidence.py +254 -0
- package/knowledge_base/core/logging_setup.py +39 -0
- package/knowledge_base/core/metrics.py +63 -0
- package/knowledge_base/core/precedence.py +354 -0
- package/knowledge_base/core/request_context.py +54 -0
- package/knowledge_base/db/__init__.py +0 -0
- package/knowledge_base/db/__pycache__/__init__.cpython-314.pyc +0 -0
- package/knowledge_base/db/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/db/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/db/__pycache__/client.cpython-314.pyc +0 -0
- package/knowledge_base/db/__pycache__/client.cpython-37.pyc +0 -0
- package/knowledge_base/db/__pycache__/client.cpython-38.pyc +0 -0
- package/knowledge_base/db/__pycache__/connector_sync.cpython-38.pyc +0 -0
- package/knowledge_base/db/__pycache__/feedback_schema.cpython-37.pyc +0 -0
- package/knowledge_base/db/__pycache__/feedback_schema.cpython-38.pyc +0 -0
- package/knowledge_base/db/__pycache__/kg_introspect.cpython-314.pyc +0 -0
- package/knowledge_base/db/__pycache__/kg_introspect.cpython-37.pyc +0 -0
- package/knowledge_base/db/__pycache__/kg_introspect.cpython-38.pyc +0 -0
- package/knowledge_base/db/__pycache__/schema.cpython-37.pyc +0 -0
- package/knowledge_base/db/__pycache__/schema.cpython-38.pyc +0 -0
- package/knowledge_base/db/client.py +100 -0
- package/knowledge_base/db/connector_sync.py +43 -0
- package/knowledge_base/db/feedback_schema.py +548 -0
- package/knowledge_base/db/igel_schema.py +150 -0
- package/knowledge_base/db/kg_introspect.py +116 -0
- package/knowledge_base/db/migrations.py +22 -0
- package/knowledge_base/db/schema.py +649 -0
- package/knowledge_base/deploy/Dockerfile +23 -0
- package/knowledge_base/deploy/feedback_automation.sh +18 -0
- package/knowledge_base/deploy/firecrawl-docker.sh +50 -0
- package/knowledge_base/deploy/igel-testgen.service +26 -0
- package/knowledge_base/deploy/install_reranker.sh +92 -0
- package/knowledge_base/deploy/requirements.txt +68 -0
- package/knowledge_base/deploy/run_server.sh +35 -0
- package/knowledge_base/docs/TEST_GENERATION_GUIDE.md +174 -0
- package/knowledge_base/embeddings/__init__.py +0 -0
- package/knowledge_base/embeddings/__pycache__/__init__.cpython-314.pyc +0 -0
- package/knowledge_base/embeddings/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/embeddings/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/embeddings/__pycache__/azure_embedder.cpython-314.pyc +0 -0
- package/knowledge_base/embeddings/__pycache__/azure_embedder.cpython-37.pyc +0 -0
- package/knowledge_base/embeddings/__pycache__/azure_embedder.cpython-38.pyc +0 -0
- package/knowledge_base/embeddings/azure_embedder.py +99 -0
- package/knowledge_base/eval/__init__.py +33 -0
- package/knowledge_base/eval/__main__.py +172 -0
- package/knowledge_base/eval/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/eval/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/eval/__pycache__/__main__.cpython-37.pyc +0 -0
- package/knowledge_base/eval/__pycache__/baseline.cpython-37.pyc +0 -0
- package/knowledge_base/eval/__pycache__/baseline.cpython-38.pyc +0 -0
- package/knowledge_base/eval/__pycache__/harness.cpython-37.pyc +0 -0
- package/knowledge_base/eval/__pycache__/harness.cpython-38.pyc +0 -0
- package/knowledge_base/eval/__pycache__/scorers.cpython-37.pyc +0 -0
- package/knowledge_base/eval/__pycache__/scorers.cpython-38.pyc +0 -0
- package/knowledge_base/eval/baseline.py +213 -0
- package/knowledge_base/eval/harness.py +400 -0
- package/knowledge_base/eval/queries_50.json +302 -0
- package/knowledge_base/eval/scorers.py +494 -0
- package/knowledge_base/exemplars/README.md +7 -0
- package/knowledge_base/exemplars/__pycache__/pytest_reference_snippet.cpython-37.pyc +0 -0
- package/knowledge_base/exemplars/gold_manual_concise_snippet.md +8 -0
- package/knowledge_base/exemplars/gold_manual_detailed_snippet.md +7 -0
- package/knowledge_base/exemplars/pytest_reference_snippet.py +37 -0
- package/knowledge_base/feedback/__init__.py +10 -0
- package/knowledge_base/feedback/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/analytics.cpython-37.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/analytics.cpython-38.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/applier.cpython-37.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/applier.cpython-38.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/curator.cpython-37.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/curator.cpython-38.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/handler.cpython-37.pyc +0 -0
- package/knowledge_base/feedback/__pycache__/handler.cpython-38.pyc +0 -0
- package/knowledge_base/feedback/analytics.py +72 -0
- package/knowledge_base/feedback/applier.py +93 -0
- package/knowledge_base/feedback/curator.py +49 -0
- package/knowledge_base/feedback/handler.py +151 -0
- package/knowledge_base/generation/__init__.py +5 -0
- package/knowledge_base/generation/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/generation/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/generation/__pycache__/input_classifier.cpython-37.pyc +0 -0
- package/knowledge_base/generation/__pycache__/input_classifier.cpython-38.pyc +0 -0
- package/knowledge_base/generation/__pycache__/manual_tc_parser.cpython-37.pyc +0 -0
- package/knowledge_base/generation/__pycache__/manual_tc_parser.cpython-38.pyc +0 -0
- package/knowledge_base/generation/__pycache__/prompts.cpython-37.pyc +0 -0
- package/knowledge_base/generation/__pycache__/prompts.cpython-38.pyc +0 -0
- package/knowledge_base/generation/__pycache__/tc_transformer.cpython-37.pyc +0 -0
- package/knowledge_base/generation/__pycache__/test_generator.cpython-37.pyc +0 -0
- package/knowledge_base/generation/__pycache__/test_generator.cpython-38.pyc +0 -0
- package/knowledge_base/generation/input_classifier.py +148 -0
- package/knowledge_base/generation/manual_tc_parser.py +180 -0
- package/knowledge_base/generation/prompts.py +755 -0
- package/knowledge_base/generation/tc_transformer.py +368 -0
- package/knowledge_base/generation/test_generator.py +553 -0
- package/knowledge_base/graph_db/__init__.py +5 -0
- package/knowledge_base/graph_db/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/graphiti_client.cpython-37.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/kg_traversal.cpython-37.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/migrate_kg.cpython-37.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/neo4j_client.cpython-37.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/neo4j_client.cpython-38.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/schema.cpython-37.pyc +0 -0
- package/knowledge_base/graph_db/__pycache__/temporal_ingest.cpython-37.pyc +0 -0
- package/knowledge_base/graph_db/graphiti_client.py +127 -0
- package/knowledge_base/graph_db/kg_traversal.py +192 -0
- package/knowledge_base/graph_db/migrate_kg.py +93 -0
- package/knowledge_base/graph_db/neo4j_client.py +116 -0
- package/knowledge_base/graph_db/schema.py +22 -0
- package/knowledge_base/graph_db/temporal_ingest.py +59 -0
- package/knowledge_base/ingestion/__init__.py +1 -0
- package/knowledge_base/ingestion/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/ingest.cpython-37.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/ingest.cpython-38.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/ingest_images.cpython-37.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/ingest_images.cpython-38.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/kg_extractor.cpython-37.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/kg_extractor.cpython-38.pyc +0 -0
- package/knowledge_base/ingestion/__pycache__/web_ingest.cpython-38.pyc +0 -0
- package/knowledge_base/ingestion/ingest.py +346 -0
- package/knowledge_base/ingestion/ingest_images.py +330 -0
- package/knowledge_base/ingestion/kg_extractor.py +358 -0
- package/knowledge_base/ingestion/web_ingest.py +83 -0
- package/knowledge_base/intelligence/__init__.py +1 -0
- package/knowledge_base/intelligence/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/intelligence/__pycache__/execution_ingest.cpython-37.pyc +0 -0
- package/knowledge_base/intelligence/__pycache__/predictive_engine.cpython-37.pyc +0 -0
- package/knowledge_base/intelligence/__pycache__/risk_scorer.cpython-37.pyc +0 -0
- package/knowledge_base/intelligence/execution_ingest.py +34 -0
- package/knowledge_base/intelligence/predictive_engine.py +7 -0
- package/knowledge_base/intelligence/risk_scorer.py +8 -0
- package/knowledge_base/memory/__init__.py +6 -0
- package/knowledge_base/memory/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/memory/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/memory/__pycache__/cognee_client.cpython-37.pyc +0 -0
- package/knowledge_base/memory/__pycache__/cognee_client.cpython-38.pyc +0 -0
- package/knowledge_base/memory/__pycache__/ingest_memory.cpython-37.pyc +0 -0
- package/knowledge_base/memory/__pycache__/memory_types.cpython-37.pyc +0 -0
- package/knowledge_base/memory/__pycache__/memory_types.cpython-38.pyc +0 -0
- package/knowledge_base/memory/cognee_client.py +164 -0
- package/knowledge_base/memory/ingest_memory.py +60 -0
- package/knowledge_base/memory/memory_types.py +23 -0
- package/knowledge_base/models/test_requirement.py +84 -0
- package/knowledge_base/parsers/__init__.py +0 -0
- package/knowledge_base/parsers/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/csv_parser.cpython-37.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/csv_parser.cpython-38.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/doc_parser.cpython-37.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/doc_parser.cpython-38.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/html_parser.cpython-38.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/image_extractor.cpython-37.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/image_extractor.cpython-38.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/markdown_parser.cpython-37.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/markdown_parser.cpython-38.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/pdf_parser.cpython-37.pyc +0 -0
- package/knowledge_base/parsers/__pycache__/pdf_parser.cpython-38.pyc +0 -0
- package/knowledge_base/parsers/csv_parser.py +126 -0
- package/knowledge_base/parsers/doc_parser.py +176 -0
- package/knowledge_base/parsers/html_parser.py +151 -0
- package/knowledge_base/parsers/image_extractor.py +370 -0
- package/knowledge_base/parsers/markdown_parser.py +116 -0
- package/knowledge_base/parsers/pdf_parser.py +178 -0
- package/knowledge_base/retrieval/__init__.py +1 -0
- package/knowledge_base/retrieval/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/context_fusion.cpython-37.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/context_fusion.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/knowledge_graph.cpython-37.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/knowledge_graph.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/reranker.cpython-37.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/reranker.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/retrieval_debug.cpython-37.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/retrieval_debug.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/retriever.cpython-37.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/retriever.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/unified_query.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/__pycache__/web_retriever.cpython-38.pyc +0 -0
- package/knowledge_base/retrieval/context_fusion.py +264 -0
- package/knowledge_base/retrieval/knowledge_graph.py +267 -0
- package/knowledge_base/retrieval/reranker.py +308 -0
- package/knowledge_base/retrieval/retrieval_debug.py +69 -0
- package/knowledge_base/retrieval/retriever.py +885 -0
- package/knowledge_base/retrieval/unified_query.py +189 -0
- package/knowledge_base/retrieval/web_retriever.py +337 -0
- package/knowledge_base/validators/__init__.py +1 -0
- package/knowledge_base/validators/__pycache__/__init__.cpython-314.pyc +0 -0
- package/knowledge_base/validators/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/validators/__pycache__/step_fidelity.cpython-314.pyc +0 -0
- package/knowledge_base/validators/__pycache__/step_fidelity.cpython-37.pyc +0 -0
- package/knowledge_base/validators/step_fidelity.py +88 -0
- package/knowledge_base/vision/__init__.py +0 -0
- package/knowledge_base/vision/__pycache__/__init__.cpython-37.pyc +0 -0
- package/knowledge_base/vision/__pycache__/__init__.cpython-38.pyc +0 -0
- package/knowledge_base/vision/__pycache__/image_describer.cpython-37.pyc +0 -0
- package/knowledge_base/vision/__pycache__/image_describer.cpython-38.pyc +0 -0
- package/knowledge_base/vision/image_describer.py +202 -0
- package/package.json +31 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
const program = new Command();
|
|
5
|
+
program
|
|
6
|
+
.name("igel-qe")
|
|
7
|
+
.description("IGEL QE Developer Experience CLI")
|
|
8
|
+
.version("1.0.0");
|
|
9
|
+
program
|
|
10
|
+
.command("init")
|
|
11
|
+
.description("Bootstrap the Python AI Platform Layer")
|
|
12
|
+
.action(async () => {
|
|
13
|
+
console.log(chalk.blue("Initializing IGEL QE AI Platform..."));
|
|
14
|
+
const steps = [
|
|
15
|
+
"1. Checking Python version...",
|
|
16
|
+
"2. Creating virtual environment...",
|
|
17
|
+
"3. Installing Python dependencies...",
|
|
18
|
+
"4. Verifying PostgreSQL & pgvector...",
|
|
19
|
+
"5. Configuring MCP Server...",
|
|
20
|
+
"6. Building initial Code Index & Asset Registry..."
|
|
21
|
+
];
|
|
22
|
+
for (const step of steps) {
|
|
23
|
+
console.log(chalk.yellow(step));
|
|
24
|
+
// Simulate step execution for demonstration
|
|
25
|
+
await new Promise(r => setTimeout(r, 500));
|
|
26
|
+
console.log(chalk.green(` ✓ Done`));
|
|
27
|
+
}
|
|
28
|
+
console.log(chalk.bold.green("\nIGEL QE AI Platform successfully initialized!"));
|
|
29
|
+
console.log(`You can now use GitHub Copilot to invoke MCP tools or run commands via this CLI.`);
|
|
30
|
+
});
|
|
31
|
+
program
|
|
32
|
+
.command("sync")
|
|
33
|
+
.description("Trigger a delta sync of the automation codebase")
|
|
34
|
+
.action(() => {
|
|
35
|
+
console.log(chalk.blue("Triggering delta sync..."));
|
|
36
|
+
// Would IPC call the Python BitbucketSyncAgent
|
|
37
|
+
});
|
|
38
|
+
program.parse();
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const server = new Server({
|
|
8
|
+
name: "igel-qe-mcp",
|
|
9
|
+
version: "1.0.0",
|
|
10
|
+
}, {
|
|
11
|
+
capabilities: {
|
|
12
|
+
tools: {}
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
// Helper to bridge to the Python AI Platform Layer
|
|
16
|
+
async function callPythonEngine(workflowName, args) {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
// In a real implementation, this would call a unified Python IPC script
|
|
19
|
+
// For demonstration, we just return a simulated response.
|
|
20
|
+
resolve(JSON.stringify({
|
|
21
|
+
status: "success",
|
|
22
|
+
workflow: workflowName,
|
|
23
|
+
message: `Dispatched to Python AI Platform: ${workflowName}`
|
|
24
|
+
}));
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
28
|
+
tools: [
|
|
29
|
+
{
|
|
30
|
+
name: "generate_test_cases",
|
|
31
|
+
description: "Extract requirement understanding, generate business rules, and create manual test cases for a Jira/Xray issue.",
|
|
32
|
+
inputSchema: {
|
|
33
|
+
type: "object",
|
|
34
|
+
properties: {
|
|
35
|
+
jira_key: { type: "string", description: "The Jira issue key (e.g., IGEL-1234)" }
|
|
36
|
+
},
|
|
37
|
+
required: ["jira_key"]
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "generate_automation",
|
|
42
|
+
description: "Design an automation plan from the Asset Registry and generate pytest automation scripts for approved test cases.",
|
|
43
|
+
inputSchema: {
|
|
44
|
+
type: "object",
|
|
45
|
+
properties: {
|
|
46
|
+
jira_key: { type: "string", description: "The Jira issue key whose approved test cases should be automated." }
|
|
47
|
+
},
|
|
48
|
+
required: ["jira_key"]
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "sync_bitbucket",
|
|
53
|
+
description: "Trigger a Delta Sync to parse changed Python files and update the Asset Registry and Code Intelligence graphs.",
|
|
54
|
+
inputSchema: {
|
|
55
|
+
type: "object",
|
|
56
|
+
properties: {
|
|
57
|
+
commit_hash: { type: "string", description: "The new Bitbucket commit hash to sync." }
|
|
58
|
+
},
|
|
59
|
+
required: ["commit_hash"]
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: "impact_analysis",
|
|
64
|
+
description: "Analyze the regression impact of changed code assets on existing test requirements and scripts.",
|
|
65
|
+
inputSchema: {
|
|
66
|
+
type: "object",
|
|
67
|
+
properties: {
|
|
68
|
+
changed_files: {
|
|
69
|
+
type: "array",
|
|
70
|
+
items: { type: "string" },
|
|
71
|
+
description: "List of changed file paths."
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
required: ["changed_files"]
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: "submit_feedback",
|
|
79
|
+
description: "Submit granular feedback at the requirement, scenario, test case, or test step level to improve future generations.",
|
|
80
|
+
inputSchema: {
|
|
81
|
+
type: "object",
|
|
82
|
+
properties: {
|
|
83
|
+
level: { type: "string", enum: ["requirement", "scenario", "testcase", "teststep"] },
|
|
84
|
+
target_id: { type: "string" },
|
|
85
|
+
feedback_type: { type: "string", enum: ["correction", "rejection", "enhancement", "approval"] },
|
|
86
|
+
user_comment: { type: "string" }
|
|
87
|
+
},
|
|
88
|
+
required: ["level", "target_id", "feedback_type"]
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}));
|
|
93
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
94
|
+
const result = await callPythonEngine(request.params.name, request.params.arguments);
|
|
95
|
+
return {
|
|
96
|
+
content: [{ type: "text", text: result }]
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
async function main() {
|
|
100
|
+
const transport = new StdioServerTransport();
|
|
101
|
+
await server.connect(transport);
|
|
102
|
+
console.error("IGEL QE MCP Server running on stdio");
|
|
103
|
+
}
|
|
104
|
+
main().catch(console.error);
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
from typing import List, Dict, Any
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
from knowledge_base.config import cfg
|
|
6
|
+
from knowledge_base.agents.requirement_agent import _get_llm_client
|
|
7
|
+
from knowledge_base.db.client import get_conn
|
|
8
|
+
from knowledge_base.embeddings.azure_embedder import get_embedding
|
|
9
|
+
from knowledge_base.models.test_requirement import TestCaseWithConfidence
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
class AutomationPlan(BaseModel):
|
|
14
|
+
page_objects: List[str] = Field(default_factory=list)
|
|
15
|
+
fixtures: List[str] = Field(default_factory=list)
|
|
16
|
+
utilities: List[str] = Field(default_factory=list)
|
|
17
|
+
|
|
18
|
+
_SYSTEM_PROMPT = """You are an expert IGEL Quality Engineering Automation Architect.
|
|
19
|
+
Your task is to design an Automation Plan for a given set of approved test cases.
|
|
20
|
+
You will be provided with a list of available Page Objects, Fixtures, and Utilities from the Asset Registry.
|
|
21
|
+
You must ONLY select items from the provided available lists. Do NOT invent new page objects or fixtures.
|
|
22
|
+
Output MUST be valid JSON matching this schema:
|
|
23
|
+
{
|
|
24
|
+
"page_objects": ["string"],
|
|
25
|
+
"fixtures": ["string"],
|
|
26
|
+
"utilities": ["string"]
|
|
27
|
+
}
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def _semantic_search_assets(query: str, limit: int = 20) -> Dict[str, List[str]]:
|
|
31
|
+
"""Retrieve relevant assets from the Asset Registry based on semantic similarity to the query."""
|
|
32
|
+
try:
|
|
33
|
+
embedding = get_embedding(query)
|
|
34
|
+
assets = {"page_object": [], "fixture": [], "utility": [], "base_class": [], "api_client": []}
|
|
35
|
+
|
|
36
|
+
with get_conn() as conn:
|
|
37
|
+
with conn.cursor() as cur:
|
|
38
|
+
# Top 20 most similar assets overall
|
|
39
|
+
cur.execute(
|
|
40
|
+
"""
|
|
41
|
+
SELECT asset_type, name, description, 1 - (embedding <=> %s::vector) AS similarity
|
|
42
|
+
FROM igel_asset_registry
|
|
43
|
+
ORDER BY embedding <=> %s::vector ASC
|
|
44
|
+
LIMIT %s
|
|
45
|
+
""",
|
|
46
|
+
(embedding, embedding, limit)
|
|
47
|
+
)
|
|
48
|
+
for row in cur.fetchall():
|
|
49
|
+
asset_type, name, description, similarity = row
|
|
50
|
+
if asset_type in assets:
|
|
51
|
+
assets[asset_type].append(f"{name} ({description[:100]}...)")
|
|
52
|
+
|
|
53
|
+
return assets
|
|
54
|
+
except Exception as e:
|
|
55
|
+
logger.error(f"Semantic search failed: {e}")
|
|
56
|
+
return {"page_object": [], "fixture": [], "utility": []}
|
|
57
|
+
|
|
58
|
+
def design_automation_plan(test_cases: List[TestCaseWithConfidence]) -> AutomationPlan:
|
|
59
|
+
"""Generate an automation plan restricting script generation to known assets."""
|
|
60
|
+
client = _get_llm_client()
|
|
61
|
+
|
|
62
|
+
# Filter only approved TCs
|
|
63
|
+
approved_tcs = [tc.test_case for tc in test_cases if tc.is_approved]
|
|
64
|
+
if not approved_tcs:
|
|
65
|
+
logger.warning("No approved test cases provided for automation design.")
|
|
66
|
+
return AutomationPlan()
|
|
67
|
+
|
|
68
|
+
# Build query text from TC titles and steps
|
|
69
|
+
query_parts = []
|
|
70
|
+
for tc in approved_tcs:
|
|
71
|
+
query_parts.append(tc.title)
|
|
72
|
+
query_parts.extend([s.action for s in tc.steps])
|
|
73
|
+
|
|
74
|
+
search_query = " ".join(query_parts)
|
|
75
|
+
|
|
76
|
+
# Fetch potential assets from DB
|
|
77
|
+
available_assets = _semantic_search_assets(search_query)
|
|
78
|
+
|
|
79
|
+
# Prompt construction
|
|
80
|
+
user_prompt = "Approved Test Cases to Automate:\n"
|
|
81
|
+
for tc in approved_tcs:
|
|
82
|
+
user_prompt += f"- {tc.title}\n"
|
|
83
|
+
|
|
84
|
+
user_prompt += "\nAvailable Page Objects / API Clients:\n"
|
|
85
|
+
for p in available_assets.get("page_object", []) + available_assets.get("api_client", []):
|
|
86
|
+
user_prompt += f"- {p}\n"
|
|
87
|
+
|
|
88
|
+
user_prompt += "\nAvailable Fixtures:\n"
|
|
89
|
+
for f in available_assets.get("fixture", []):
|
|
90
|
+
user_prompt += f"- {f}\n"
|
|
91
|
+
|
|
92
|
+
user_prompt += "\nAvailable Utilities:\n"
|
|
93
|
+
for u in available_assets.get("utility", []):
|
|
94
|
+
user_prompt += f"- {u}\n"
|
|
95
|
+
|
|
96
|
+
user_prompt += "\nDesign the optimal automation plan using ONLY the provided available assets."
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
response = client.chat.completions.create(
|
|
100
|
+
model=cfg.AZURE_DEPLOYMENT,
|
|
101
|
+
messages=[
|
|
102
|
+
{"role": "system", "content": _SYSTEM_PROMPT},
|
|
103
|
+
{"role": "user", "content": user_prompt},
|
|
104
|
+
],
|
|
105
|
+
response_format={"type": "json_object"},
|
|
106
|
+
temperature=0.1,
|
|
107
|
+
max_tokens=1000,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
content = response.choices[0].message.content or "{}"
|
|
111
|
+
data = json.loads(content)
|
|
112
|
+
|
|
113
|
+
plan = AutomationPlan(
|
|
114
|
+
page_objects=data.get("page_objects", []),
|
|
115
|
+
fixtures=data.get("fixtures", []),
|
|
116
|
+
utilities=data.get("utilities", [])
|
|
117
|
+
)
|
|
118
|
+
logger.info(f"Designed Automation Plan with {len(plan.page_objects)} POs, {len(plan.fixtures)} fixtures")
|
|
119
|
+
return plan
|
|
120
|
+
|
|
121
|
+
except Exception as e:
|
|
122
|
+
logger.error(f"Failed to design automation plan: {e}")
|
|
123
|
+
return AutomationPlan()
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
import hashlib
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import List, Dict, Any, Optional
|
|
6
|
+
|
|
7
|
+
from knowledge_base.db.client import get_conn
|
|
8
|
+
from knowledge_base.embeddings.azure_embedder import get_embedding
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
class CodeIntelligenceAgent:
|
|
13
|
+
"""Agent responsible for AST parsing and populating the Automation Asset Registry."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, repo_path: Path):
|
|
16
|
+
self.repo_path = repo_path
|
|
17
|
+
|
|
18
|
+
def _hash_file(self, file_path: Path) -> str:
|
|
19
|
+
"""Compute SHA-256 hash of a file."""
|
|
20
|
+
hasher = hashlib.sha256()
|
|
21
|
+
with open(file_path, 'rb') as f:
|
|
22
|
+
hasher.update(f.read())
|
|
23
|
+
return hasher.hexdigest()
|
|
24
|
+
|
|
25
|
+
def index_file(self, file_path: Path) -> int:
|
|
26
|
+
"""Parse a Python file and index its assets (classes, functions, fixtures)."""
|
|
27
|
+
if not file_path.name.endswith(".py"):
|
|
28
|
+
return 0
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
32
|
+
content = f.read()
|
|
33
|
+
|
|
34
|
+
file_hash = self._hash_file(file_path)
|
|
35
|
+
rel_path = str(file_path.relative_to(self.repo_path))
|
|
36
|
+
|
|
37
|
+
# Check if file changed
|
|
38
|
+
with get_conn() as conn:
|
|
39
|
+
with conn.cursor() as cur:
|
|
40
|
+
cur.execute(
|
|
41
|
+
"SELECT file_hash FROM igel_asset_registry WHERE file_path = %s LIMIT 1",
|
|
42
|
+
(rel_path,)
|
|
43
|
+
)
|
|
44
|
+
row = cur.fetchone()
|
|
45
|
+
if row and row[0] == file_hash:
|
|
46
|
+
logger.debug(f"File {rel_path} unchanged, skipping.")
|
|
47
|
+
return 0
|
|
48
|
+
|
|
49
|
+
# Delete old assets for this file before re-indexing
|
|
50
|
+
cur.execute("DELETE FROM igel_asset_registry WHERE file_path = %s", (rel_path,))
|
|
51
|
+
conn.commit()
|
|
52
|
+
|
|
53
|
+
tree = ast.parse(content)
|
|
54
|
+
assets_found = 0
|
|
55
|
+
|
|
56
|
+
for node in ast.walk(tree):
|
|
57
|
+
# Page Objects / API Clients / Base Classes
|
|
58
|
+
if isinstance(node, ast.ClassDef):
|
|
59
|
+
docstring = ast.get_docstring(node) or ""
|
|
60
|
+
asset_type = "page_object"
|
|
61
|
+
if "Api" in node.name or "Client" in node.name:
|
|
62
|
+
asset_type = "api_client"
|
|
63
|
+
elif "Base" in node.name:
|
|
64
|
+
asset_type = "base_class"
|
|
65
|
+
|
|
66
|
+
self._store_asset(
|
|
67
|
+
name=node.name,
|
|
68
|
+
asset_type=asset_type,
|
|
69
|
+
file_path=rel_path,
|
|
70
|
+
description=docstring,
|
|
71
|
+
signature=f"class {node.name}",
|
|
72
|
+
file_hash=file_hash
|
|
73
|
+
)
|
|
74
|
+
assets_found += 1
|
|
75
|
+
|
|
76
|
+
# Fixtures / Utilities
|
|
77
|
+
elif isinstance(node, ast.FunctionDef):
|
|
78
|
+
is_fixture = any(
|
|
79
|
+
isinstance(d, ast.Attribute) and d.attr == "fixture"
|
|
80
|
+
for d in node.decorator_list
|
|
81
|
+
) or any(
|
|
82
|
+
isinstance(d, ast.Call) and isinstance(d.func, ast.Attribute) and d.func.attr == "fixture"
|
|
83
|
+
for d in node.decorator_list
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
if is_fixture:
|
|
87
|
+
docstring = ast.get_docstring(node) or ""
|
|
88
|
+
self._store_asset(
|
|
89
|
+
name=node.name,
|
|
90
|
+
asset_type="fixture",
|
|
91
|
+
file_path=rel_path,
|
|
92
|
+
description=docstring,
|
|
93
|
+
signature=f"def {node.name}()",
|
|
94
|
+
file_hash=file_hash
|
|
95
|
+
)
|
|
96
|
+
assets_found += 1
|
|
97
|
+
elif "util" in rel_path or "helper" in rel_path:
|
|
98
|
+
docstring = ast.get_docstring(node) or ""
|
|
99
|
+
self._store_asset(
|
|
100
|
+
name=node.name,
|
|
101
|
+
asset_type="utility",
|
|
102
|
+
file_path=rel_path,
|
|
103
|
+
description=docstring,
|
|
104
|
+
signature=f"def {node.name}()",
|
|
105
|
+
file_hash=file_hash
|
|
106
|
+
)
|
|
107
|
+
assets_found += 1
|
|
108
|
+
|
|
109
|
+
logger.info(f"Indexed {assets_found} assets in {rel_path}")
|
|
110
|
+
return assets_found
|
|
111
|
+
|
|
112
|
+
except SyntaxError as e:
|
|
113
|
+
logger.error(f"Syntax error in {file_path}: {e}")
|
|
114
|
+
return 0
|
|
115
|
+
except Exception as e:
|
|
116
|
+
logger.error(f"Failed to index {file_path}: {e}")
|
|
117
|
+
return 0
|
|
118
|
+
|
|
119
|
+
def _store_asset(self, name: str, asset_type: str, file_path: str, description: str, signature: str, file_hash: str):
|
|
120
|
+
"""Embed and store the asset in the registry."""
|
|
121
|
+
search_text = f"{asset_type} {name}\n{description}"
|
|
122
|
+
try:
|
|
123
|
+
# Vectorize the semantic description
|
|
124
|
+
embedding = get_embedding(search_text)
|
|
125
|
+
|
|
126
|
+
with get_conn() as conn:
|
|
127
|
+
with conn.cursor() as cur:
|
|
128
|
+
cur.execute(
|
|
129
|
+
"""
|
|
130
|
+
INSERT INTO igel_asset_registry
|
|
131
|
+
(asset_type, name, file_path, description, signature, embedding, file_hash)
|
|
132
|
+
VALUES (%s, %s, %s, %s, %s, %s::vector, %s)
|
|
133
|
+
""",
|
|
134
|
+
(asset_type, name, file_path, description, signature, embedding, file_hash)
|
|
135
|
+
)
|
|
136
|
+
conn.commit()
|
|
137
|
+
except Exception as e:
|
|
138
|
+
logger.error(f"Failed to store asset {name}: {e}")
|
|
139
|
+
|
|
140
|
+
def index_repo(self) -> int:
|
|
141
|
+
"""Walk the repository and index all Python files."""
|
|
142
|
+
total_assets = 0
|
|
143
|
+
for py_file in self.repo_path.rglob("*.py"):
|
|
144
|
+
if "venv" in str(py_file) or ".tox" in str(py_file) or "node_modules" in str(py_file):
|
|
145
|
+
continue
|
|
146
|
+
total_assets += self.index_file(py_file)
|
|
147
|
+
return total_assets
|