diff --git a/.bandit b/.bandit index 0a9e16e08..18c4631c0 100644 --- a/.bandit +++ b/.bandit @@ -14,14 +14,19 @@ exclude_dirs: skips: - B101 # assert_used - common in tests + - B104 # hardcoded_bind_all_interfaces - test/dev servers bind 0.0.0.0 intentionally - B105 # hardcoded_password_string - false positive on event/policy variable names + - B106 # hardcoded_password_funcarg - false positive on param names (token_type, password) - B108 # hardcoded_tmp_directory - /tmp used for legitimate temp files - B110 # try_except_pass - intentional exception suppression pattern - B112 # try_except_continue - intentional exception-and-continue pattern + - B113 # request_without_timeout - all 21 instances in test files (not production) - B311 # random - used for demo data variance, not cryptographic purposes - B324 # hashlib weak hash - MD5 used for caching fingerprints, not security - B404 # import_subprocess - subprocess use is intentional and reviewed - B601 # paramiko_calls - intentional usage - B603 # subprocess_without_shell_equals_true - we use shell=False + - B605 # start_process_with_a_shell - static commands for system info collection - B607 # start_process_with_partial_path - tool names resolved via PATH intentionally - B608 # hardcoded_sql_expressions - false positive in analysis tooling + - B615 # huggingface_unsafe_download - intentional model downloads from trusted sources diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index 7fdb61004..298ff60e1 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -46,7 +46,8 @@ jobs: run: | source .venv/bin/activate python -m pip install --upgrade pip - python -m pip install black isort flake8 autoflake bandit[toml] + # Pin versions to match .pre-commit-config.yaml (Issue #2128) + python -m pip install black==26.3.1 isort==8.0.1 flake8==7.3.0 autoflake==2.3.3 'bandit[toml]==1.9.4' - name: Check code formatting with Black run: | @@ -69,12 +70,8 @@ jobs: - name: Lint with flake8 run: | source .venv/bin/activate - python3 -m flake8 autobot-backend/ autobot-slm-backend/ autobot-shared/ \ - --max-line-length=100 \ - --extend-ignore=E203,W503 \ - --exclude=node_modules,.venv,venv,__pycache__,.git,temp,logs,reports,archive \ - --statistics \ - --count || { + # Uses .flake8 config for consistency with pre-commit (Issue #2128) + python3 -m flake8 --config=.flake8 autobot-backend/ autobot-slm-backend/ autobot-shared/ || { echo "āš ļø flake8 linting issues found" exit 1 } diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1ebdf103d..c254760ec 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,7 +18,7 @@ repos: # Python code formatting with Black - repo: https://github.com/psf/black - rev: 23.12.1 + rev: 26.3.1 hooks: - id: black args: [--line-length=88] @@ -27,7 +27,7 @@ repos: # Python import sorting with isort - repo: https://github.com/pycqa/isort - rev: 5.13.2 + rev: 8.0.1 hooks: - id: isort args: [--profile=black, --line-length=88] @@ -36,7 +36,7 @@ repos: # Python linting with flake8 # Uses .flake8 config file for consistent settings across local dev and CI - repo: https://github.com/pycqa/flake8 - rev: 7.0.0 + rev: 7.3.0 hooks: - id: flake8 # Uses .flake8 config file in repo root via args @@ -46,7 +46,7 @@ repos: # Remove unused imports and variables with autoflake - repo: https://github.com/PyCQA/autoflake - rev: v2.2.1 + rev: v2.3.3 hooks: - id: autoflake args: [ @@ -89,7 +89,7 @@ repos: # Security checks with bandit - repo: https://github.com/PyCQA/bandit - rev: 1.7.6 + rev: 1.9.4 hooks: - id: bandit args: [-c, .bandit] diff --git a/autobot-backend/agents/agent_optimizer_test.py b/autobot-backend/agents/agent_optimizer_test.py index a579cf660..648c49001 100644 --- a/autobot-backend/agents/agent_optimizer_test.py +++ b/autobot-backend/agents/agent_optimizer_test.py @@ -258,8 +258,7 @@ def test_statistics_tracking(self): # Create larger code blocks to ensure size reduction large_code = "\n".join([f" line_{j} = {j}" for j in range(20)]) with open(test_file, "w", encoding="utf-8") as f: - f.write( - f"""--- + f.write(f"""--- name: agent-{i} --- Content for agent {i}. @@ -276,8 +275,7 @@ def example_function_{i}(): return "result" ``` -Additional text after code block.""" - ) +Additional text after code block.""") # Optimize all stats = self.optimizer.optimize_all() @@ -450,11 +448,9 @@ def test_malformed_agent_file(self): # Create malformed file (missing closing frontmatter) test_file = self.source_dir / "malformed.md" with open(test_file, "w", encoding="utf-8") as f: - f.write( - """--- + f.write("""--- name: malformed -This is malformed frontmatter without closing""" - ) +This is malformed frontmatter without closing""") # Should handle gracefully without crashing result = optimizer.optimize_agent_file(test_file) diff --git a/autobot-backend/agents/interactive_terminal_agent.py b/autobot-backend/agents/interactive_terminal_agent.py index 73ef2e9e6..47b01ea02 100644 --- a/autobot-backend/agents/interactive_terminal_agent.py +++ b/autobot-backend/agents/interactive_terminal_agent.py @@ -302,7 +302,8 @@ async def take_control(self): "chat_id": self.chat_id, "status": "user_control", "message": ( - "šŸŽ® You now have control of the terminal. " "Type commands directly." + "šŸŽ® You now have control of the terminal. " + "Type commands directly." ), }, ) diff --git a/autobot-backend/agents/kb_librarian/librarian.py b/autobot-backend/agents/kb_librarian/librarian.py index f9f0b1fcb..96a21a9c5 100644 --- a/autobot-backend/agents/kb_librarian/librarian.py +++ b/autobot-backend/agents/kb_librarian/librarian.py @@ -477,14 +477,11 @@ async def _store_tool_research_results( if not tools: return - tool_summaries = [ - f""" + tool_summaries = [f""" {i}. {tool['name']} Purpose: {tool.get('purpose', 'N/A')} Installation: {tool.get('installation', 'N/A')[:200]}... -""" - for i, tool in enumerate(tools, 1) - ] +""" for i, tool in enumerate(tools, 1)] summary_content = f""" Tool Research Results: {tool_type} diff --git a/autobot-backend/agents/knowledge_manager.py b/autobot-backend/agents/knowledge_manager.py index 584307dfc..564f41664 100644 --- a/autobot-backend/agents/knowledge_manager.py +++ b/autobot-backend/agents/knowledge_manager.py @@ -426,9 +426,9 @@ async def get_machine_info(self) -> Optional[Dict[str, Any]]: # Access machine profile from MachineAwareSystemKnowledgeManager if hasattr(self._system_manager, "current_machine_profile"): - profile: Optional[ - MachineProfile - ] = self._system_manager.current_machine_profile + profile: Optional[MachineProfile] = ( + self._system_manager.current_machine_profile + ) if profile: return profile.to_dict() diff --git a/autobot-backend/agents/librarian_assistant.py b/autobot-backend/agents/librarian_assistant.py index d484e77f8..4adb1ab68 100644 --- a/autobot-backend/agents/librarian_assistant.py +++ b/autobot-backend/agents/librarian_assistant.py @@ -16,12 +16,12 @@ from datetime import datetime from typing import Any, Callable, Dict, List, Optional +from config import config from knowledge_base import KnowledgeBase from llm_interface import LLMInterface from utils.service_registry import get_service_url from autobot_shared.http_client import get_http_client -from config import config logger = logging.getLogger(__name__) diff --git a/autobot-backend/ai_hardware_accelerator.py b/autobot-backend/ai_hardware_accelerator.py index 36c481f75..5b63cb4ea 100644 --- a/autobot-backend/ai_hardware_accelerator.py +++ b/autobot-backend/ai_hardware_accelerator.py @@ -513,7 +513,9 @@ async def _handle_task_failure( fallback_device = self._get_fallback_device(selected_device) if fallback_device and fallback_device != selected_device: - logger.info("šŸ”„ Retrying task %s on %s", task.task_id, fallback_device.value) + logger.info( + "šŸ”„ Retrying task %s on %s", task.task_id, fallback_device.value + ) fallback_result = await _try_fallback_processing( task, fallback_device, self._process_on_gpu, self._process_on_cpu ) diff --git a/autobot-backend/api/agent.py b/autobot-backend/api/agent.py index bd3065d3e..020dc175e 100644 --- a/autobot-backend/api/agent.py +++ b/autobot-backend/api/agent.py @@ -11,6 +11,7 @@ Consolidated from agent.py and agent_enhanced.py per Issue #708. """ + import asyncio import json import logging diff --git a/autobot-backend/api/analytics_cost.py b/autobot-backend/api/analytics_cost.py index 4070c37a9..dc12223c1 100644 --- a/autobot-backend/api/analytics_cost.py +++ b/autobot-backend/api/analytics_cost.py @@ -551,9 +551,7 @@ def _calculate_alert_status(name: str, data: str, current_costs: dict) -> dict: "status": ( "exceeded" if percent_used >= 100 - else "warning" - if percent_used >= 75 - else "ok" + else "warning" if percent_used >= 75 else "ok" ), "remaining_usd": max(threshold - current, 0), } diff --git a/autobot-backend/api/analytics_debt.py b/autobot-backend/api/analytics_debt.py index dae7d1afa..00044f11c 100644 --- a/autobot-backend/api/analytics_debt.py +++ b/autobot-backend/api/analytics_debt.py @@ -341,9 +341,7 @@ def _process_complexity(complexity_data: Dict[str, Any]) -> List[DebtItem]: severity = ( DebtSeverity.CRITICAL if complexity > 20 - else DebtSeverity.HIGH - if complexity > 15 - else DebtSeverity.MEDIUM + else DebtSeverity.HIGH if complexity > 15 else DebtSeverity.MEDIUM ) debt_items.append( DebtItem( @@ -698,9 +696,7 @@ def _calculate_trend_change(trend_data: List[Dict[str, Any]]) -> tuple: direction = ( "improving" if change["items"] < 0 - else "worsening" - if change["items"] > 0 - else "stable" + else "worsening" if change["items"] > 0 else "stable" ) return change, direction diff --git a/autobot-backend/api/chat.py b/autobot-backend/api/chat.py index 24d29dafb..9b3dff966 100644 --- a/autobot-backend/api/chat.py +++ b/autobot-backend/api/chat.py @@ -11,6 +11,7 @@ Consolidated from chat.py and chat_enhanced.py per Issue #708. """ + import asyncio import json import logging diff --git a/autobot-backend/api/chat_sessions.py b/autobot-backend/api/chat_sessions.py index 49a05003f..34f73a0a9 100644 --- a/autobot-backend/api/chat_sessions.py +++ b/autobot-backend/api/chat_sessions.py @@ -1095,9 +1095,9 @@ def _process_kb_deletion_result(result: dict, kb_cleanup_result: dict) -> None: kb_cleanup_result["facts_preserved"] = result.get("preserved_count", 0) if result.get("errors"): - kb_cleanup_result[ - "cleanup_error" - ] = f"{len(result['errors'])} errors during cleanup" + kb_cleanup_result["cleanup_error"] = ( + f"{len(result['errors'])} errors during cleanup" + ) def _log_kb_cleanup_result( diff --git a/autobot-backend/api/codebase_analytics/endpoints/dependencies.py b/autobot-backend/api/codebase_analytics/endpoints/dependencies.py index 2fb0731c1..6ac3cee77 100644 --- a/autobot-backend/api/codebase_analytics/endpoints/dependencies.py +++ b/autobot-backend/api/codebase_analytics/endpoints/dependencies.py @@ -178,9 +178,7 @@ def _dfs(start: str, node: str, path: List[str], depth: int): severity = ( "high" if len(path) <= 2 - else "medium" - if len(path) <= 4 - else "low" + else "medium" if len(path) <= 4 else "low" ) cycle_path = path + [start] cycles.append( diff --git a/autobot-backend/api/codebase_analytics/endpoints/indexing.py b/autobot-backend/api/codebase_analytics/endpoints/indexing.py index 98733c1ff..a2d5d52cb 100644 --- a/autobot-backend/api/codebase_analytics/endpoints/indexing.py +++ b/autobot-backend/api/codebase_analytics/endpoints/indexing.py @@ -423,8 +423,6 @@ async def cancel_indexing_job(): - task_id: The cancelled job's task ID - message: Status message """ - global _current_indexing_task_id - # All accesses to shared state under lock async with _tasks_lock: if _current_indexing_task_id is None: diff --git a/autobot-backend/api/codebase_analytics/indexing_worker.py b/autobot-backend/api/codebase_analytics/indexing_worker.py index 78af47315..6521a72ed 100644 --- a/autobot-backend/api/codebase_analytics/indexing_worker.py +++ b/autobot-backend/api/codebase_analytics/indexing_worker.py @@ -11,6 +11,7 @@ Usage (internal — called by _run_indexing_subprocess): python indexing_worker.py [source_id] """ + import asyncio import logging import os diff --git a/autobot-backend/api/codebase_analytics/npu_embeddings.py b/autobot-backend/api/codebase_analytics/npu_embeddings.py index b51a7a70e..a5edb6157 100644 --- a/autobot-backend/api/codebase_analytics/npu_embeddings.py +++ b/autobot-backend/api/codebase_analytics/npu_embeddings.py @@ -417,9 +417,9 @@ async def warmup_npu_for_codebase() -> Dict[str, Any]: result["npu_available"] = True result["warmup_time_ms"] = warmup_time result["embedding_dimensions"] = len(embeddings[0]) - result[ - "message" - ] = f"NPU connection warmed up for codebase indexing in {warmup_time:.1f}ms" + result["message"] = ( + f"NPU connection warmed up for codebase indexing in {warmup_time:.1f}ms" + ) # Get device info if client: diff --git a/autobot-backend/api/codebase_analytics/router.py b/autobot-backend/api/codebase_analytics/router.py index d673672b6..b321687ec 100644 --- a/autobot-backend/api/codebase_analytics/router.py +++ b/autobot-backend/api/codebase_analytics/router.py @@ -26,7 +26,11 @@ pattern_analysis, ) from .endpoints import queue as queue_router -from .endpoints import report, sources, stats +from .endpoints import ( + report, + sources, + stats, +) # Create main router — prefix provided by analytics_routers.py registry (#1027) router = APIRouter( diff --git a/autobot-backend/api/data_storage.py b/autobot-backend/api/data_storage.py index 4af8af7ad..cfa7e3911 100644 --- a/autobot-backend/api/data_storage.py +++ b/autobot-backend/api/data_storage.py @@ -10,6 +10,7 @@ - Conversation/transcript management - Database file information """ + import logging import shutil from datetime import datetime diff --git a/autobot-backend/api/knowledge.py b/autobot-backend/api/knowledge.py index 5007f4239..db9b19700 100644 --- a/autobot-backend/api/knowledge.py +++ b/autobot-backend/api/knowledge.py @@ -1319,9 +1319,7 @@ async def get_machine_profile( "cpu_count": psutil.cpu_count(logical=False), "cpu_count_logical": psutil.cpu_count(logical=True), "memory_total_gb": round(psutil.virtual_memory().total / (1024**3), 2), - "memory_available_gb": round( - psutil.virtual_memory().available / (1024**3), 2 - ), + "memory_available_gb": round(psutil.virtual_memory().available / (1024**3), 2), "disk_total_gb": round(psutil.disk_usage("/").total / (1024**3), 2), "disk_free_gb": round(psutil.disk_usage("/").free / (1024**3), 2), } @@ -1739,9 +1737,7 @@ def _process_fact_data(fact_data: dict, cat: str, fact_key: str) -> Optional[dic content = ( content_raw.decode("utf-8") if isinstance(content_raw, bytes) - else str(content_raw) - if content_raw - else "" + else str(content_raw) if content_raw else "" ) fact_title = metadata.get("title", metadata.get("command", "Untitled")) @@ -1993,9 +1989,7 @@ def _extract_fact_content(fact_data: dict) -> str: return ( content_raw.decode("utf-8") if isinstance(content_raw, bytes) - else str(content_raw) - if content_raw - else "" + else str(content_raw) if content_raw else "" ) @@ -2016,9 +2010,7 @@ def _extract_fact_created_at(fact_data: dict) -> str: return ( created_at_raw.decode("utf-8") if isinstance(created_at_raw, bytes) - else str(created_at_raw) - if created_at_raw - else "" + else str(created_at_raw) if created_at_raw else "" ) diff --git a/autobot-backend/api/live_workflow.e2e_test.py b/autobot-backend/api/live_workflow.e2e_test.py index 57a76fab2..70373610f 100644 --- a/autobot-backend/api/live_workflow.e2e_test.py +++ b/autobot-backend/api/live_workflow.e2e_test.py @@ -183,7 +183,9 @@ async def monitor_workflow_progress(session, base_url, workflow_id): break else: - print(f" āŒ Status check failed: {response.status}") # noqa: print + print( + f" āŒ Status check failed: {response.status}" + ) # noqa: print break except Exception as e: diff --git a/autobot-backend/api/merge_conflict_resolution_test.py b/autobot-backend/api/merge_conflict_resolution_test.py index 9ad4099ce..23afcc030 100644 --- a/autobot-backend/api/merge_conflict_resolution_test.py +++ b/autobot-backend/api/merge_conflict_resolution_test.py @@ -26,16 +26,14 @@ @pytest.fixture def conflict_file(): """Create a temporary file with a merge conflict.""" - conflict_content = textwrap.dedent( - """ + conflict_content = textwrap.dedent(""" def hello(): <<<<<<< HEAD return "current" ======= return "incoming" >>>>>>> branch - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(conflict_content) diff --git a/autobot-backend/api/natural_language_search.py b/autobot-backend/api/natural_language_search.py index ba2610aed..ef34e2f03 100644 --- a/autobot-backend/api/natural_language_search.py +++ b/autobot-backend/api/natural_language_search.py @@ -37,9 +37,9 @@ _ASYNC_FUNC_RE = re.compile(r"async\s+def\s+(\w+)") # Issue #336: Keyword heuristics dispatch table for intent classification -KEYWORD_INTENT_FALLBACKS: Dict[ - Tuple[str, ...], "QueryIntent" -] = {} # Populated after enum defined +KEYWORD_INTENT_FALLBACKS: Dict[Tuple[str, ...], "QueryIntent"] = ( + {} +) # Populated after enum defined router = APIRouter(prefix="/nl-search", tags=["natural-language-search", "code-search"]) diff --git a/autobot-backend/api/overseer_handlers.py b/autobot-backend/api/overseer_handlers.py index f15e1d503..3ff148331 100644 --- a/autobot-backend/api/overseer_handlers.py +++ b/autobot-backend/api/overseer_handlers.py @@ -255,9 +255,9 @@ async def save_step_result_to_chat(self, result: StepResult) -> None: try: message_text = self._format_step_message_text(result) step_data = result.to_dict() - step_data[ - "description" - ] = f"Step {result.step_number}: {result.command or 'N/A'}" + step_data["description"] = ( + f"Step {result.step_number}: {result.command or 'N/A'}" + ) await self.chat_history.add_message( sender="assistant", diff --git a/autobot-backend/api/research_browser.py b/autobot-backend/api/research_browser.py index f09c80599..3bcc23b10 100644 --- a/autobot-backend/api/research_browser.py +++ b/autobot-backend/api/research_browser.py @@ -14,13 +14,13 @@ import aiofiles from auth_middleware import check_admin_permission +from config import ConfigManager from constants.network_constants import NetworkConstants from fastapi import APIRouter, Depends, HTTPException from fastapi.responses import JSONResponse, StreamingResponse from pydantic import BaseModel from autobot_shared.error_boundaries import ErrorCategory, with_error_handling -from config import ConfigManager logger = logging.getLogger(__name__) diff --git a/autobot-backend/api/security_endpoints.e2e_test.py b/autobot-backend/api/security_endpoints.e2e_test.py index 16bf4793a..2a7d0d8be 100644 --- a/autobot-backend/api/security_endpoints.e2e_test.py +++ b/autobot-backend/api/security_endpoints.e2e_test.py @@ -39,7 +39,9 @@ async def test_security_endpoints(): response = requests.get("http://localhost:8001/api/hello", timeout=2) if response.status_code == 200: server_ready = True - print(f"āœ… Server ready after {attempt + 1} attempts") # noqa: print + print( + f"āœ… Server ready after {attempt + 1} attempts" + ) # noqa: print break except Exception: pass diff --git a/autobot-backend/api/services.py b/autobot-backend/api/services.py index eeb90232b..2b97eb781 100644 --- a/autobot-backend/api/services.py +++ b/autobot-backend/api/services.py @@ -262,9 +262,7 @@ async def get_services_health(admin_check: bool = Depends(check_admin_permission "overall_status": ( "healthy" if services_data.error_count == 0 - else "degraded" - if services_data.error_count < 2 - else "critical" + else "degraded" if services_data.error_count < 2 else "critical" ), "total_services": services_data.total_count, "healthy_services": services_data.healthy_count, diff --git a/autobot-backend/api/system_validation.py b/autobot-backend/api/system_validation.py index 8051560d0..5673c376c 100644 --- a/autobot-backend/api/system_validation.py +++ b/autobot-backend/api/system_validation.py @@ -158,9 +158,7 @@ async def run_quick_validation(): overall_status = ( "healthy" if overall_score >= 80 - else "degraded" - if overall_score >= 60 - else "unhealthy" + else "degraded" if overall_score >= 60 else "unhealthy" ) return { diff --git a/autobot-backend/api/system_validation_test.py b/autobot-backend/api/system_validation_test.py index 814fc4a8d..ebd22c219 100644 --- a/autobot-backend/api/system_validation_test.py +++ b/autobot-backend/api/system_validation_test.py @@ -103,7 +103,9 @@ async def main(): success = await test_system_validation() if success: - logger.info("āœ… System validation test PASSED - System is ready for production!") + logger.info( + "āœ… System validation test PASSED - System is ready for production!" + ) else: logger.error("āŒ System validation test FAILED - Issues need to be resolved") diff --git a/autobot-backend/api/user_management/users.py b/autobot-backend/api/user_management/users.py index 17b9cc703..6dff0aee0 100644 --- a/autobot-backend/api/user_management/users.py +++ b/autobot-backend/api/user_management/users.py @@ -158,7 +158,9 @@ async def search_users_for_sharing( config = get_deployment_config() if config.mode == DeploymentMode.SINGLE_USER: - logger.debug("search_users_for_sharing: single_user mode, returning unavailable") + logger.debug( + "search_users_for_sharing: single_user mode, returning unavailable" + ) return UserSearchResponse( users=[], available=False, @@ -166,7 +168,9 @@ async def search_users_for_sharing( ) if not config.postgres_enabled: - logger.debug("search_users_for_sharing: postgres disabled, returning unavailable") + logger.debug( + "search_users_for_sharing: postgres disabled, returning unavailable" + ) return UserSearchResponse( users=[], available=False, @@ -204,7 +208,9 @@ async def _search_users_from_db(q: str, limit: int) -> UserSearchResponse: ) for user in users ] - logger.debug("search_users_for_sharing: found %d results for %r", len(results), q) + logger.debug( + "search_users_for_sharing: found %d results for %r", len(results), q + ) return UserSearchResponse( users=results, available=True, diff --git a/autobot-backend/api/workflow.py b/autobot-backend/api/workflow.py index c9d41bff7..708cb4032 100644 --- a/autobot-backend/api/workflow.py +++ b/autobot-backend/api/workflow.py @@ -62,9 +62,9 @@ async def _handle_research_step(ctx: WorkflowStepContext) -> None: query="network security scanning tools", focus="tools" ) result = await research_agent.research_specific_tools(request) - ctx.step[ - "result" - ] = f"Research completed: {result.get('summary', 'Tools researched')}" + ctx.step["result"] = ( + f"Research completed: {result.get('summary', 'Tools researched')}" + ) elif "installation guide" in action_lower: result = await research_agent.get_tool_installation_guide("nmap") guide = result.get("installation_guide", "Guide obtained") @@ -171,9 +171,9 @@ async def _handle_network_discovery_step(ctx: WorkflowStepContext) -> None: result = await network_discovery_agent.execute(ctx.action, discovery_context) status = result.get("status") hosts_found = result.get("hosts_found", 0) - ctx.step[ - "result" - ] = f"Network discovery completed: {status} - Found {hosts_found} hosts" + ctx.step["result"] = ( + f"Network discovery completed: {status} - Found {hosts_found} hosts" + ) ctx.step["discovery_results"] = result @@ -187,31 +187,31 @@ async def _handle_system_commands_step(ctx: WorkflowStepContext) -> None: if "install tool" in action_lower: tool_info = {"name": "nmap", "package_name": "nmap"} result = await cmd_agent.install_tool(tool_info, ctx.workflow_id) - ctx.step[ - "result" - ] = f"Installation result: {result.get('response', 'Tool installed')}" + ctx.step["result"] = ( + f"Installation result: {result.get('response', 'Tool installed')}" + ) elif "verify installation" in action_lower: result = await cmd_agent.execute_command_with_output( "nmap --version", ctx.workflow_id ) - ctx.step[ - "result" - ] = f"Verification result: {result.get('output', 'Tool verified')}" + ctx.step["result"] = ( + f"Verification result: {result.get('output', 'Tool verified')}" + ) else: result = await cmd_agent.execute_command_with_output( ctx.action, ctx.workflow_id ) - ctx.step[ - "result" - ] = f"Command executed: {result.get('output', 'Command completed')}" + ctx.step["result"] = ( + f"Command executed: {result.get('output', 'Command completed')}" + ) async def _handle_fallback_step(ctx: WorkflowStepContext, agent_type: str) -> None: """Handle unknown agent type with fallback (Issue #336 - extracted handler, Issue #322 - context).""" result = await ctx.orchestrator.execute_goal(f"{agent_type}: {ctx.action}") - ctx.step[ - "result" - ] = f"Executed by {agent_type}: {result.get('response', 'Task completed')}" + ctx.step["result"] = ( + f"Executed by {agent_type}: {result.get('response', 'Task completed')}" + ) # Issue #336: Dispatch table for agent step handlers diff --git a/autobot-backend/async_baseline.performance_test.py b/autobot-backend/async_baseline.performance_test.py index 9b750f65f..9c0e4def1 100644 --- a/autobot-backend/async_baseline.performance_test.py +++ b/autobot-backend/async_baseline.performance_test.py @@ -412,7 +412,9 @@ async def test_cross_vm_latency(self, requests: int = 20) -> PerformanceMetrics: Tests inter-VM communication performance (main -> frontend, npu-worker, etc.) """ - logger.info(f"šŸ”— Starting cross-VM latency test ({requests} requests per VM)...") + logger.info( + f"šŸ”— Starting cross-VM latency test ({requests} requests per VM)..." + ) vm_endpoints = { "frontend": f"{ServiceURLs.FRONTEND_VM}/", diff --git a/autobot-backend/autobot_demo.e2e_test.py b/autobot-backend/autobot_demo.e2e_test.py index 2dc00d02e..916b988b9 100644 --- a/autobot-backend/autobot_demo.e2e_test.py +++ b/autobot-backend/autobot_demo.e2e_test.py @@ -93,7 +93,9 @@ async def demo_simple_query(): chat_id = await create_chat_session() response = await send_chat_message(chat_id, "What is 2+2?") - print(f"\nāœ… Response: {response.get('response', 'No response')}") # noqa: print + print( + f"\nāœ… Response: {response.get('response', 'No response')}" + ) # noqa: print print(f"Status: {response.get('status', 'unknown')}") # noqa: print except Exception as e: diff --git a/autobot-backend/celery_app.py b/autobot-backend/celery_app.py index 8df66a130..bf7e619a9 100644 --- a/autobot-backend/celery_app.py +++ b/autobot-backend/celery_app.py @@ -16,9 +16,9 @@ from pathlib import Path from celery import Celery +from config import ConfigManager from autobot_shared.ssot_config import config as ssot_config -from config import ConfigManager # Create singleton config instance for extended config values config = ConfigManager() diff --git a/autobot-backend/chat_history/persist_conversation_dedup_test.py b/autobot-backend/chat_history/persist_conversation_dedup_test.py index 4c5c5df5f..47305784a 100644 --- a/autobot-backend/chat_history/persist_conversation_dedup_test.py +++ b/autobot-backend/chat_history/persist_conversation_dedup_test.py @@ -116,9 +116,9 @@ async def test_same_user_message_appends_response(self, mock_workflow_manager): if last_entry.get("user") == message: existing_response = last_entry.get("assistant", "") if second_response not in existing_response: - last_entry[ - "assistant" - ] = f"{existing_response}\n\n{second_response}" + last_entry["assistant"] = ( + f"{existing_response}\n\n{second_response}" + ) else: session.conversation_history.append( {"user": message, "assistant": second_response} diff --git a/autobot-backend/chat_workflow/llm_handler.py b/autobot-backend/chat_workflow/llm_handler.py index 7c82c393a..256fc8cdd 100644 --- a/autobot-backend/chat_workflow/llm_handler.py +++ b/autobot-backend/chat_workflow/llm_handler.py @@ -171,14 +171,10 @@ def _get_system_prompt(self, language=None) -> str: return preamble + prompt + lang_instruction except Exception as e: logger.error("Failed to load system prompt from file: %s", e) - return ( - preamble - + """You are AutoBot. Execute commands using: + return preamble + """You are AutoBot. Execute commands using: desc -NEVER teach commands - ALWAYS execute them.""" - + lang_instruction - ) +NEVER teach commands - ALWAYS execute them.""" + lang_instruction def _build_conversation_context(self, session: WorkflowSession) -> str: """Build conversation context from recent history. @@ -235,9 +231,9 @@ async def _retrieve_knowledge_context( session.metadata["query_intent"] = query_intent.intent.value if enhanced_query and enhanced_query.enhancement_applied: session.metadata["query_enhanced"] = True - session.metadata[ - "context_entities" - ] = enhanced_query.context_entities + session.metadata["context_entities"] = ( + enhanced_query.context_entities + ) else: session.metadata["used_knowledge"] = False session.metadata["query_enhanced"] = False diff --git a/autobot-backend/chat_workflow/manager.py b/autobot-backend/chat_workflow/manager.py index ace2aa991..e42be7732 100644 --- a/autobot-backend/chat_workflow/manager.py +++ b/autobot-backend/chat_workflow/manager.py @@ -1622,9 +1622,12 @@ async def _stream_llm_response( current_segment, current_message_type, ) - async for should_return, should_break, yields, updated in self._iterate_chunk_results( - params, current_state - ): + async for ( + should_return, + should_break, + yields, + updated, + ) in self._iterate_chunk_results(params, current_state): ( llm_response, tool_call_completed, @@ -2587,7 +2590,9 @@ async def _persist_user_message(self, session_id: str, message: str) -> None: message_type="default", session_id=session_id, ) - logger.debug("āœ… Persisted user message immediately: session=%s", session_id) + logger.debug( + "āœ… Persisted user message immediately: session=%s", session_id + ) except Exception as persist_error: logger.error( "Failed to persist user message immediately: %s", persist_error diff --git a/autobot-backend/chat_workflow/tool_handler.py b/autobot-backend/chat_workflow/tool_handler.py index a6a51ecd1..cc15deeca 100644 --- a/autobot-backend/chat_workflow/tool_handler.py +++ b/autobot-backend/chat_workflow/tool_handler.py @@ -613,7 +613,9 @@ async def _handle_pending_approval( ) yield self._build_waiting_message(command, result) - logger.info("šŸ” [APPROVAL POLLING] Waiting for approval of command: %s", command) + logger.info( + "šŸ” [APPROVAL POLLING] Waiting for approval of command: %s", command + ) logger.info( "šŸ” [APPROVAL POLLING] Chat session: %s, Terminal session: %s", session_id, @@ -1027,7 +1029,9 @@ async def _handle_command_error( }, ) else: - additional_response_parts.append(f"\n\nāŒ Command execution failed: {error}") + additional_response_parts.append( + f"\n\nāŒ Command execution failed: {error}" + ) yield WorkflowMessage( type="error", content=f"Command failed: {error}", diff --git a/autobot-backend/code_analysis/auto-tools/accessibility_enhancer.py b/autobot-backend/code_analysis/auto-tools/accessibility_enhancer.py index 1b7bb59a0..8aae838ca 100644 --- a/autobot-backend/code_analysis/auto-tools/accessibility_enhancer.py +++ b/autobot-backend/code_analysis/auto-tools/accessibility_enhancer.py @@ -504,7 +504,9 @@ def scan_and_fix(self) -> None: if not any(skip_dir in vue_file.parts for skip_dir in skip_dirs): filtered_files.append(vue_file) - print(f"šŸ“„ Found {len(filtered_files)} Vue components to analyze") # noqa: print + print( + f"šŸ“„ Found {len(filtered_files)} Vue components to analyze" + ) # noqa: print fixed_count = 0 total_fixes = 0 diff --git a/autobot-backend/code_analysis/auto-tools/logging_standardizer.py b/autobot-backend/code_analysis/auto-tools/logging_standardizer.py index c2eee2113..b75740d93 100644 --- a/autobot-backend/code_analysis/auto-tools/logging_standardizer.py +++ b/autobot-backend/code_analysis/auto-tools/logging_standardizer.py @@ -570,9 +570,7 @@ def _save_report_files(self, report_content: str, output_file: str) -> None: ## Backup Location All modified files have been backed up to: `{}` -""".format( - self.backup_dir - ) +""".format(self.backup_dir) report_path = ( Path(output_file) diff --git a/autobot-backend/code_analysis/auto-tools/performance_optimizer.py b/autobot-backend/code_analysis/auto-tools/performance_optimizer.py index c2674889c..efeff3ec3 100644 --- a/autobot-backend/code_analysis/auto-tools/performance_optimizer.py +++ b/autobot-backend/code_analysis/auto-tools/performance_optimizer.py @@ -347,7 +347,9 @@ def clean_project(self, target_dir: str = None) -> Dict: """Clean console.logs from entire project or specific directory.""" search_root = Path(target_dir) if target_dir else self.project_root - print(f"šŸ” Scanning for console.log statements in: {search_root}") # noqa: print + print( + f"šŸ” Scanning for console.log statements in: {search_root}" + ) # noqa: print print(f"šŸ“ Backups will be saved to: {self.backup_dir}") # noqa: print # Find all files to process diff --git a/autobot-backend/code_analysis/auto-tools/security_deep_sanitizer.py b/autobot-backend/code_analysis/auto-tools/security_deep_sanitizer.py index 2d310dee3..2f77c78c8 100644 --- a/autobot-backend/code_analysis/auto-tools/security_deep_sanitizer.py +++ b/autobot-backend/code_analysis/auto-tools/security_deep_sanitizer.py @@ -681,7 +681,12 @@ def _build_vulnerability_breakdown(self) -> str: content = "" if severity_counts: content += "### Vulnerabilities by Severity:\n\n" - severity_icons = {"CRITICAL": "šŸ”“", "HIGH": "🟠", "MEDIUM": "🟔", "LOW": "🟢"} + severity_icons = { + "CRITICAL": "šŸ”“", + "HIGH": "🟠", + "MEDIUM": "🟔", + "LOW": "🟢", + } for severity in ["CRITICAL", "HIGH", "MEDIUM", "LOW"]: if severity in severity_counts: icon = severity_icons[severity] @@ -711,7 +716,12 @@ def _build_enhancements_and_fixes_section(self) -> str: ] if direct_vulns: content += "### Critical Vulnerabilities Fixed:\n\n" - severity_icon = {"CRITICAL": "šŸ”“", "HIGH": "🟠", "MEDIUM": "🟔", "LOW": "🟢"} + severity_icon = { + "CRITICAL": "šŸ”“", + "HIGH": "🟠", + "MEDIUM": "🟔", + "LOW": "🟢", + } for i, vuln in enumerate(direct_vulns, 1): icon = severity_icon.get(vuln["severity"], "⚪") content += f"**{i}. {vuln['type'].replace('_', ' ').title()}** {icon}\n" diff --git a/autobot-backend/code_analysis/auto-tools/test_security_verification.py b/autobot-backend/code_analysis/auto-tools/test_security_verification.py index a85d2a667..9bbbefbaf 100644 --- a/autobot-backend/code_analysis/auto-tools/test_security_verification.py +++ b/autobot-backend/code_analysis/auto-tools/test_security_verification.py @@ -48,7 +48,9 @@ def test_security_headers(file_path: str) -> bool: logger.info( f" āœ… X-Content-Type-Options: {'Present' if content_type_options else 'Missing'}" ) - logger.info(" āœ… X-Frame-Options: {'Present' if frame_options else 'Missing'}") + logger.info( + " āœ… X-Frame-Options: {'Present' if frame_options else 'Missing'}" + ) return all([csp_present, xss_protection, content_type_options, frame_options]) diff --git a/autobot-backend/code_analysis/scripts/analyze_architecture.py b/autobot-backend/code_analysis/scripts/analyze_architecture.py index 6ac64ae52..bdd442def 100644 --- a/autobot-backend/code_analysis/scripts/analyze_architecture.py +++ b/autobot-backend/code_analysis/scripts/analyze_architecture.py @@ -136,7 +136,12 @@ def _analyze_patterns(results: dict) -> None: if results["architectural_issues"]: print("🚨 **Architectural Issues:**") # noqa: print for issue in results["architectural_issues"]: - severity_emoji = {"critical": "šŸ”“", "high": "🟠", "medium": "🟔", "low": "🟢"} + severity_emoji = { + "critical": "šŸ”“", + "high": "🟠", + "medium": "🟔", + "low": "🟢", + } emoji = severity_emoji.get(issue["severity"], "⚪") print( # noqa: print diff --git a/autobot-backend/code_analysis/scripts/analyze_frontend.py b/autobot-backend/code_analysis/scripts/analyze_frontend.py index c7c17d00b..4583dd546 100644 --- a/autobot-backend/code_analysis/scripts/analyze_frontend.py +++ b/autobot-backend/code_analysis/scripts/analyze_frontend.py @@ -127,7 +127,12 @@ def _print_security_analysis(results: dict) -> None: ] print(" • Top security issues:") # noqa: print for issue in security_issues[:3]: - severity_emoji = {"critical": "šŸ”“", "high": "🟠", "medium": "🟔", "low": "🟢"} + severity_emoji = { + "critical": "šŸ”“", + "high": "🟠", + "medium": "🟔", + "low": "🟢", + } emoji = severity_emoji.get(issue["severity"], "⚪") print( # noqa: print f" {emoji} {issue['description']} ({issue['file_path']}:{issue['line_number']})" @@ -214,7 +219,12 @@ def _print_detailed_issues(results: dict) -> None: ) for issue in sorted_issues[:5]: - severity_emoji = {"critical": "šŸ”“", "high": "🟠", "medium": "🟔", "low": "🟢"} + severity_emoji = { + "critical": "šŸ”“", + "high": "🟠", + "medium": "🟔", + "low": "🟢", + } emoji = severity_emoji.get(issue["severity"], "⚪") print(f" {emoji} {issue['description']}") # noqa: print diff --git a/autobot-backend/code_analysis/src/anti_pattern_detector.py b/autobot-backend/code_analysis/src/anti_pattern_detector.py index b5538086b..8386c9d7f 100644 --- a/autobot-backend/code_analysis/src/anti_pattern_detector.py +++ b/autobot-backend/code_analysis/src/anti_pattern_detector.py @@ -368,9 +368,9 @@ async def _parse_codebase( if module_info: self.modules[module_info.name] = module_info for cls_info in module_info.classes: - self.classes[ - f"{module_info.name}.{cls_info.name}" - ] = cls_info + self.classes[f"{module_info.name}.{cls_info.name}"] = ( + cls_info + ) self.all_defined_names.add(cls_info.name) self.all_defined_names.update(module_info.functions) except Exception as e: @@ -661,9 +661,9 @@ async def _detect_feature_envy(self) -> List[AntiPatternInstance]: issues.append( AntiPatternInstance( pattern_type=AntiPatternType.FEATURE_ENVY, - severity=Severity.MEDIUM - if external_refs < 10 - else Severity.HIGH, + severity=( + Severity.MEDIUM if external_refs < 10 else Severity.HIGH + ), file_path=cls_info.file_path, line_number=method.lineno, entity_name=f"{cls_info.name}.{method.name}", @@ -736,9 +736,11 @@ async def _detect_circular_dependencies(self) -> List[AntiPatternInstance]: AntiPatternInstance( pattern_type=AntiPatternType.CIRCULAR_DEPENDENCY, severity=Severity.HIGH if len(cycle) > 2 else Severity.MEDIUM, - file_path=self.modules[cycle[0]].file_path - if cycle[0] in self.modules - else "", + file_path=( + self.modules[cycle[0]].file_path + if cycle[0] in self.modules + else "" + ), line_number=1, entity_name=cycle[0], description=f"Circular dependency detected: {cycle_str}", @@ -840,9 +842,9 @@ async def _detect_long_parameter_lists(self) -> List[AntiPatternInstance]: issues.append( AntiPatternInstance( pattern_type=AntiPatternType.LONG_PARAMETER_LIST, - severity=Severity.MEDIUM - if param_count < 8 - else Severity.HIGH, + severity=( + Severity.MEDIUM if param_count < 8 else Severity.HIGH + ), file_path=cls_info.file_path, line_number=method.lineno, entity_name=f"{cls_info.name}.{method.name}", @@ -1001,9 +1003,11 @@ async def _detect_data_clumps(self) -> List[AntiPatternInstance]: AntiPatternInstance( pattern_type=AntiPatternType.DATA_CLUMP, severity=Severity.MEDIUM if len(methods) > 5 else Severity.LOW, - file_path=self.classes[methods[0].split(".")[0]].file_path - if methods - else "", + file_path=( + self.classes[methods[0].split(".")[0]].file_path + if methods + else "" + ), line_number=1, entity_name=", ".join(params), description=( @@ -1113,7 +1117,8 @@ def _generate_report( ), ( "dead_code", - "🟢 LOW: Remove Dead Code - " "Delete verified unused classes and functions", + "🟢 LOW: Remove Dead Code - " + "Delete verified unused classes and functions", ), ] diff --git a/autobot-backend/code_analysis/src/api_consistency_analyzer.py b/autobot-backend/code_analysis/src/api_consistency_analyzer.py index e87f94f57..d479d43c3 100644 --- a/autobot-backend/code_analysis/src/api_consistency_analyzer.py +++ b/autobot-backend/code_analysis/src/api_consistency_analyzer.py @@ -13,9 +13,10 @@ from pathlib import Path from typing import Any, Dict, List, Optional -from autobot_shared.redis_client import get_redis_client from config import UnifiedConfig +from autobot_shared.redis_client import get_redis_client + # Initialize unified config config = UnifiedConfig() logger = logging.getLogger(__name__) diff --git a/autobot-backend/code_analysis/src/architectural_pattern_analyzer.py b/autobot-backend/code_analysis/src/architectural_pattern_analyzer.py index dd3e2eb01..7cdfa89ba 100644 --- a/autobot-backend/code_analysis/src/architectural_pattern_analyzer.py +++ b/autobot-backend/code_analysis/src/architectural_pattern_analyzer.py @@ -18,9 +18,10 @@ import time from typing import Any, Dict, List -from autobot_shared.redis_client import get_redis_client from config import UnifiedConfig +from autobot_shared.redis_client import get_redis_client + # Issue #394: Import from architectural_analysis package from .architectural_analysis import ( ArchitecturalComponent, diff --git a/autobot-backend/code_analysis/src/code_analyzer.py b/autobot-backend/code_analysis/src/code_analyzer.py index 1e89df8a8..f532c5782 100644 --- a/autobot-backend/code_analysis/src/code_analyzer.py +++ b/autobot-backend/code_analysis/src/code_analyzer.py @@ -14,11 +14,11 @@ from typing import Any, Dict, List, Optional, Set import numpy as np +from config import UnifiedConfig from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity from autobot_shared.redis_client import get_redis_client -from config import UnifiedConfig # Initialize unified config config = UnifiedConfig() @@ -490,13 +490,15 @@ def _calculate_metrics( metrics = { "total_lines_of_code": total_lines, "duplicate_lines": duplicate_lines, - "duplication_percentage": (duplicate_lines / total_lines * 100) - if total_lines > 0 - else 0, + "duplication_percentage": ( + (duplicate_lines / total_lines * 100) if total_lines > 0 else 0 + ), "average_function_length": total_lines / len(functions) if functions else 0, - "average_complexity": sum(f.complexity for f in functions) / len(functions) - if functions - else 0, + "average_complexity": ( + sum(f.complexity for f in functions) / len(functions) + if functions + else 0 + ), "functions_by_complexity": { "low": len([f for f in functions if f.complexity <= 5]), "medium": len([f for f in functions if 5 < f.complexity <= 10]), diff --git a/autobot-backend/code_analysis/src/code_quality_dashboard.py b/autobot-backend/code_analysis/src/code_quality_dashboard.py index 2f024d7a9..13d9cd8fe 100644 --- a/autobot-backend/code_analysis/src/code_quality_dashboard.py +++ b/autobot-backend/code_analysis/src/code_quality_dashboard.py @@ -15,13 +15,13 @@ from api_consistency_analyzer import APIConsistencyAnalyzer from architectural_pattern_analyzer import ArchitecturalPatternAnalyzer from code_analyzer import CodeAnalyzer +from config import UnifiedConfig from env_analyzer import EnvironmentVariableAnalyzer from performance_analyzer import PerformanceAnalyzer from security_analyzer import SecurityAnalyzer from testing_coverage_analyzer import TestingCoverageAnalyzer from autobot_shared.redis_client import get_redis_client -from config import UnifiedConfig # Initialize unified config config = UnifiedConfig() diff --git a/autobot-backend/code_analysis/src/frontend_analyzer.py b/autobot-backend/code_analysis/src/frontend_analyzer.py index a4e225572..95ca5ae91 100644 --- a/autobot-backend/code_analysis/src/frontend_analyzer.py +++ b/autobot-backend/code_analysis/src/frontend_analyzer.py @@ -18,8 +18,9 @@ sys.path.insert(0, str(autobot_root)) try: - from autobot_shared.redis_client import get_redis_client from config import config + + from autobot_shared.redis_client import get_redis_client except ImportError: # Fallback for standalone usage def get_redis_client(async_client=False): diff --git a/autobot-backend/code_analysis/src/ownership_analyzer.py b/autobot-backend/code_analysis/src/ownership_analyzer.py index e255baa9a..3ce481dbe 100644 --- a/autobot-backend/code_analysis/src/ownership_analyzer.py +++ b/autobot-backend/code_analysis/src/ownership_analyzer.py @@ -29,9 +29,10 @@ sys.path.insert(0, str(_project_root)) try: - from autobot_shared.redis_client import get_redis_client from config import UnifiedConfig + from autobot_shared.redis_client import get_redis_client + _REDIS_AVAILABLE = True _CONFIG_AVAILABLE = True except ImportError: @@ -490,11 +491,11 @@ def _build_dir_ownership_objects( author_name=author_name, author_email=author_data["email"], lines_count=author_data["lines"], - lines_percentage=round( - (author_data["lines"] / total_lines) * 100, 1 - ) - if total_lines > 0 - else 0, + lines_percentage=( + round((author_data["lines"] / total_lines) * 100, 1) + if total_lines > 0 + else 0 + ), commits_count=0, files_touched=list(author_data["files"]), ) @@ -740,17 +741,21 @@ def _calculate_metrics( "knowledge_risk_distribution": dict(risk_dist), "top_contributors": top_contributors, "ownership_concentration": round( - (expertise_scores[0].total_lines_authored / total_lines * 100) - if expertise_scores and total_lines > 0 - else 0, + ( + (expertise_scores[0].total_lines_authored / total_lines * 100) + if expertise_scores and total_lines > 0 + else 0 + ), 1, ), "team_coverage": round( - len([e for e in expertise_scores if e.recency_score > 50]) - / len(expertise_scores) - * 100 - if expertise_scores - else 0, + ( + len([e for e in expertise_scores if e.recency_score > 50]) + / len(expertise_scores) + * 100 + if expertise_scores + else 0 + ), 1, ), } diff --git a/autobot-backend/code_analysis/src/patch_generator.py b/autobot-backend/code_analysis/src/patch_generator.py index 8f8931c38..28ea9d5cd 100644 --- a/autobot-backend/code_analysis/src/patch_generator.py +++ b/autobot-backend/code_analysis/src/patch_generator.py @@ -11,9 +11,10 @@ from dataclasses import dataclass from typing import Any, Dict, List -from autobot_shared.redis_client import get_redis_client from config import UnifiedConfig +from autobot_shared.redis_client import get_redis_client + # Initialize unified config config = UnifiedConfig() logger = logging.getLogger(__name__) diff --git a/autobot-backend/code_analysis/src/performance_analyzer.py b/autobot-backend/code_analysis/src/performance_analyzer.py index 2a672c13b..eb78792f4 100644 --- a/autobot-backend/code_analysis/src/performance_analyzer.py +++ b/autobot-backend/code_analysis/src/performance_analyzer.py @@ -13,9 +13,10 @@ from pathlib import Path from typing import Any, Dict, List, Optional, Tuple -from autobot_shared.redis_client import get_redis_client from config import UnifiedConfig +from autobot_shared.redis_client import get_redis_client + # Initialize unified config config = UnifiedConfig() logger = logging.getLogger(__name__) diff --git a/autobot-backend/code_analysis/src/security_analyzer.py b/autobot-backend/code_analysis/src/security_analyzer.py index 9ec65456f..47048f7e9 100644 --- a/autobot-backend/code_analysis/src/security_analyzer.py +++ b/autobot-backend/code_analysis/src/security_analyzer.py @@ -13,9 +13,10 @@ from pathlib import Path from typing import Any, Dict, List, Optional -from autobot_shared.redis_client import get_redis_client from config import UnifiedConfig +from autobot_shared.redis_client import get_redis_client + # Initialize unified config config = UnifiedConfig() logger = logging.getLogger(__name__) @@ -551,9 +552,9 @@ def _analyze_dangerous_import( vulnerability_type="dangerous_import", severity=severity, description=f"Import of dangerous module: {alias.name} - {desc}", - code_snippet=lines[node.lineno - 1] - if node.lineno <= len(lines) - else "", + code_snippet=( + lines[node.lineno - 1] if node.lineno <= len(lines) else "" + ), cwe_id=cwe, fix_suggestion=f"Consider safer alternatives to {alias.name}", confidence=0.6, diff --git a/autobot-backend/code_analysis/src/testing_coverage_analyzer.py b/autobot-backend/code_analysis/src/testing_coverage_analyzer.py index a6c798429..9d33b614c 100644 --- a/autobot-backend/code_analysis/src/testing_coverage_analyzer.py +++ b/autobot-backend/code_analysis/src/testing_coverage_analyzer.py @@ -13,9 +13,10 @@ from pathlib import Path from typing import Any, Dict, List, Optional -from autobot_shared.redis_client import get_redis_client from config import UnifiedConfig +from autobot_shared.redis_client import get_redis_client + # Initialize unified config config = UnifiedConfig() logger = logging.getLogger(__name__) diff --git a/autobot-backend/code_intelligence/anti_pattern_detection/analyzer.py b/autobot-backend/code_intelligence/anti_pattern_detection/analyzer.py index 5370b4953..77cd5dee1 100644 --- a/autobot-backend/code_intelligence/anti_pattern_detection/analyzer.py +++ b/autobot-backend/code_intelligence/anti_pattern_detection/analyzer.py @@ -655,9 +655,9 @@ async def _find_semantic_anti_pattern_duplicates( "line_start": "line_start", "description": "description", }, - min_similarity=SIMILARITY_MEDIUM - if HAS_ANALYTICS_INFRASTRUCTURE - else 0.7, + min_similarity=( + SIMILARITY_MEDIUM if HAS_ANALYTICS_INFRASTRUCTURE else 0.7 + ), ) except Exception as e: logger.warning("Semantic duplicate detection failed: %s", e) diff --git a/autobot-backend/code_intelligence/code_fingerprinting_test.py b/autobot-backend/code_intelligence/code_fingerprinting_test.py index f6844e7ef..ac5d922c7 100644 --- a/autobot-backend/code_intelligence/code_fingerprinting_test.py +++ b/autobot-backend/code_intelligence/code_fingerprinting_test.py @@ -583,8 +583,7 @@ def temp_codebase(self): # Create some Python files with clones # File 1: Original function file1 = Path(tmpdir) / "module1.py" - file1.write_text( - """ + file1.write_text(""" def calculate_sum(items): total = 0 for item in items: @@ -593,13 +592,11 @@ def calculate_sum(items): def other_function(): pass -""" - ) +""") # File 2: Exact clone (Type 1) file2 = Path(tmpdir) / "module2.py" - file2.write_text( - """ + file2.write_text(""" def calculate_sum(items): total = 0 for item in items: @@ -608,13 +605,11 @@ def calculate_sum(items): def another_function(): pass -""" - ) +""") # File 3: Renamed clone (Type 2) file3 = Path(tmpdir) / "module3.py" - file3.write_text( - """ + file3.write_text(""" def compute_total(data): result = 0 for element in data: @@ -623,8 +618,7 @@ def compute_total(data): def helper(): pass -""" - ) +""") yield tmpdir @@ -820,15 +814,13 @@ def test_detect_clones_function(self): with tempfile.TemporaryDirectory() as tmpdir: # Create a simple Python file file1 = Path(tmpdir) / "test.py" - file1.write_text( - """ + file1.write_text(""" def simple_function(): x = 1 y = 2 z = x + y return z -""" - ) +""") report = detect_clones(tmpdir, min_fragment_lines=3) @@ -872,14 +864,12 @@ def test_excluded_directories(self, detector): (venv_dir / "test.py").write_text("def foo(): pass") # Create file in regular directory - (Path(tmpdir) / "main.py").write_text( - """ + (Path(tmpdir) / "main.py").write_text(""" def main_function(): x = 1 y = 2 return x + y -""" - ) +""") report = detector.detect_clones(tmpdir) @@ -892,12 +882,10 @@ def test_small_fragments_filtered(self): with tempfile.TemporaryDirectory() as tmpdir: file1 = Path(tmpdir) / "small.py" - file1.write_text( - """ + file1.write_text(""" def small(): return 1 -""" - ) +""") report = detector.detect_clones(tmpdir) diff --git a/autobot-backend/code_intelligence/code_generation/generator.py b/autobot-backend/code_intelligence/code_generation/generator.py index 499304910..547daa664 100644 --- a/autobot-backend/code_intelligence/code_generation/generator.py +++ b/autobot-backend/code_intelligence/code_generation/generator.py @@ -314,9 +314,9 @@ def _format_prompt(self, request: RefactoringRequest) -> Tuple[str, str]: "target_name": request.target_name or "", "new_name": request.new_name or "", "pattern_template": request.pattern_template or "", - "constraints": "\n".join(request.constraints) - if request.constraints - else "", + "constraints": ( + "\n".join(request.constraints) if request.constraints else "" + ), "target_code": "", # Could be enhanced } diff --git a/autobot-backend/code_intelligence/code_generation/validator.py b/autobot-backend/code_intelligence/code_generation/validator.py index d7424149f..b00933dbd 100644 --- a/autobot-backend/code_intelligence/code_generation/validator.py +++ b/autobot-backend/code_intelligence/code_generation/validator.py @@ -123,9 +123,9 @@ def validate(cls, code: str, language: str = "python") -> ValidationResult: line_count = len(code.splitlines()) return ValidationResult( - status=ValidationStatus.VALID - if not errors - else ValidationStatus.STYLE_ERROR, + status=( + ValidationStatus.VALID if not errors else ValidationStatus.STYLE_ERROR + ), is_valid=len(errors) == 0, errors=errors, warnings=warnings, diff --git a/autobot-backend/code_intelligence/code_review_engine_test.py b/autobot-backend/code_intelligence/code_review_engine_test.py index f97cd4ca8..46b86a94e 100644 --- a/autobot-backend/code_intelligence/code_review_engine_test.py +++ b/autobot-backend/code_intelligence/code_review_engine_test.py @@ -913,8 +913,7 @@ def test_review_diff_integration(self, tmp_path, sample_diff): """Test diff review integration.""" # Create the file that would result from the diff file_path = tmp_path / "example.py" - file_path.write_text( - """import os + file_path.write_text("""import os password = "mysecret" @@ -923,8 +922,7 @@ def greet(name): if x == None: pass -""" - ) +""") engine = CodeReviewEngine(project_root=str(tmp_path)) result = engine.review_diff(sample_diff) diff --git a/autobot-backend/code_intelligence/conversation_analysis/analyzer.py b/autobot-backend/code_intelligence/conversation_analysis/analyzer.py index 9fab39c9a..e1b569376 100644 --- a/autobot-backend/code_intelligence/conversation_analysis/analyzer.py +++ b/autobot-backend/code_intelligence/conversation_analysis/analyzer.py @@ -499,9 +499,9 @@ def _compute_response_distribution(self) -> Dict[ResponseType, int]: def _extract_flow_patterns(self) -> List[FlowPattern]: """Extract common flow patterns.""" # Group flows by intent sequence (as tuple for hashability) - sequence_groups: Dict[ - Tuple[IntentCategory, ...], List[ConversationFlow] - ] = defaultdict(list) + sequence_groups: Dict[Tuple[IntentCategory, ...], List[ConversationFlow]] = ( + defaultdict(list) + ) for flow in self._flows: # Use first 5 intents as pattern key diff --git a/autobot-backend/code_intelligence/cross_language_patterns/extractors.py b/autobot-backend/code_intelligence/cross_language_patterns/extractors.py index d831bbd1b..86b570b38 100644 --- a/autobot-backend/code_intelligence/cross_language_patterns/extractors.py +++ b/autobot-backend/code_intelligence/cross_language_patterns/extractors.py @@ -247,9 +247,7 @@ def _analyze_class(self, node: ast.ClassDef) -> Optional[Dict[str, Any]]: ( base.id if isinstance(base, ast.Name) - else base.attr - if isinstance(base, ast.Attribute) - else "" + else base.attr if isinstance(base, ast.Attribute) else "" ) for base in node.bases ] diff --git a/autobot-backend/code_intelligence/cross_language_patterns/models.py b/autobot-backend/code_intelligence/cross_language_patterns/models.py index da03be380..ce4b1a83f 100644 --- a/autobot-backend/code_intelligence/cross_language_patterns/models.py +++ b/autobot-backend/code_intelligence/cross_language_patterns/models.py @@ -237,12 +237,12 @@ def to_dict(self) -> Dict[str, Any]: return { "duplication_id": self.duplication_id, "validation_type": self.validation_type, - "python_location": self.python_location.to_dict() - if self.python_location - else None, - "typescript_location": self.typescript_location.to_dict() - if self.typescript_location - else None, + "python_location": ( + self.python_location.to_dict() if self.python_location else None + ), + "typescript_location": ( + self.typescript_location.to_dict() if self.typescript_location else None + ), "python_code": self.python_code, "typescript_code": self.typescript_code, "similarity_score": self.similarity_score, @@ -274,12 +274,12 @@ def to_dict(self) -> Dict[str, Any]: "endpoint_path": self.endpoint_path, "http_method": self.http_method, "mismatch_type": self.mismatch_type, - "backend_location": self.backend_location.to_dict() - if self.backend_location - else None, - "frontend_location": self.frontend_location.to_dict() - if self.frontend_location - else None, + "backend_location": ( + self.backend_location.to_dict() if self.backend_location else None + ), + "frontend_location": ( + self.frontend_location.to_dict() if self.frontend_location else None + ), "backend_definition": self.backend_definition, "frontend_call": self.frontend_call, "severity": self.severity.value, diff --git a/autobot-backend/code_intelligence/llm_pattern_analyzer_test.py b/autobot-backend/code_intelligence/llm_pattern_analyzer_test.py index 288b1393b..3ee17ce3d 100644 --- a/autobot-backend/code_intelligence/llm_pattern_analyzer_test.py +++ b/autobot-backend/code_intelligence/llm_pattern_analyzer_test.py @@ -541,8 +541,7 @@ class TestCodePatternScanner: def test_scan_file_with_llm_calls(self): """Test scanning a file with LLM API calls.""" with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: - f.write( - """ + f.write(""" import openai def generate(): @@ -551,8 +550,7 @@ def generate(): messages=[{"role": "user", "content": "Hello"}] ) return response -""" - ) +""") f.flush() patterns, retries = CodePatternScanner.scan_file(Path(f.name)) @@ -564,15 +562,13 @@ def generate(): def test_scan_file_with_retry_pattern(self): """Test scanning a file with retry patterns.""" with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: - f.write( - """ + f.write(""" from tenacity import retry @retry(max_retries=3) def call_api(): pass -""" - ) +""") f.flush() patterns, retries = CodePatternScanner.scan_file(Path(f.name)) @@ -587,15 +583,13 @@ def test_scan_nonexistent_file(self): def test_detect_streaming_pattern(self): """Test detecting streaming patterns.""" with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: - f.write( - """ + f.write(""" response = client.chat.completions.create( model="gpt-4", messages=messages, stream=True ) -""" - ) +""") f.flush() patterns, _ = CodePatternScanner.scan_file(Path(f.name)) @@ -878,8 +872,7 @@ def test_analyze_directory_with_python_files(self, analyzer, tmp_path): # Create a test file (not matching test* pattern) module_file = src_dir / "llm_module.py" - module_file.write_text( - """ + module_file.write_text(""" import openai def call_llm(): @@ -888,8 +881,7 @@ def call_llm(): messages=[] ) return response -""" - ) +""") result = analyzer.analyze(directories=[src_dir]) # File should be analyzed (not excluded by test* pattern) @@ -1012,8 +1004,7 @@ def test_full_analysis_workflow(self, tmp_path): # Create a file with LLM patterns api_file = src_dir / "api.py" - api_file.write_text( - """ + api_file.write_text(""" import openai from tenacity import retry @@ -1030,8 +1021,7 @@ def get_embedding(text): model="text-embedding-ada-002", input=text ) -""" - ) +""") # Run analysis analyzer = LLMPatternAnalyzer(project_root=tmp_path) diff --git a/autobot-backend/code_intelligence/merge_conflict_resolver_test.py b/autobot-backend/code_intelligence/merge_conflict_resolver_test.py index db3a93cda..b44f2c3ed 100644 --- a/autobot-backend/code_intelligence/merge_conflict_resolver_test.py +++ b/autobot-backend/code_intelligence/merge_conflict_resolver_test.py @@ -32,16 +32,14 @@ class TestConflictParser: def test_parse_simple_conflict(self): """Test parsing a simple conflict.""" - conflict_content = textwrap.dedent( - """ + conflict_content = textwrap.dedent(""" def hello(): <<<<<<< HEAD return "Hello from current" ======= return "Hello from incoming" >>>>>>> branch - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(conflict_content) @@ -59,8 +57,7 @@ def hello(): def test_parse_multiple_conflicts(self): """Test parsing multiple conflicts in same file.""" - conflict_content = textwrap.dedent( - """ + conflict_content = textwrap.dedent(""" def func1(): <<<<<<< HEAD x = 1 @@ -74,8 +71,7 @@ def func2(): ======= y = "b" >>>>>>> branch - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(conflict_content) @@ -90,8 +86,7 @@ def func2(): def test_parse_conflict_with_base(self): """Test parsing conflict with base (diff3 style).""" - conflict_content = textwrap.dedent( - """ + conflict_content = textwrap.dedent(""" def hello(): <<<<<<< HEAD return "current" @@ -100,8 +95,7 @@ def hello(): ======= return "incoming" >>>>>>> branch - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(conflict_content) @@ -143,8 +137,7 @@ class TestConflictSeverity: def test_trivial_severity_whitespace(self): """Test trivial severity for whitespace conflicts.""" - conflict_content = textwrap.dedent( - """ + conflict_content = textwrap.dedent(""" <<<<<<< HEAD def hello(): pass @@ -152,8 +145,7 @@ def hello(): def hello(): pass >>>>>>> branch - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(conflict_content) @@ -166,15 +158,13 @@ def hello(): def test_simple_severity_non_overlapping(self): """Test simple severity for non-overlapping changes.""" - conflict_content = textwrap.dedent( - """ + conflict_content = textwrap.dedent(""" <<<<<<< HEAD x = 1 ======= y = 2 >>>>>>> branch - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(conflict_content) @@ -187,8 +177,7 @@ def test_simple_severity_non_overlapping(self): def test_complex_severity_logic_changes(self): """Test complex severity for logic changes.""" - conflict_content = textwrap.dedent( - """ + conflict_content = textwrap.dedent(""" <<<<<<< HEAD def process(data): if data: @@ -198,8 +187,7 @@ def process(data): while data: yield data >>>>>>> branch - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(conflict_content) @@ -261,8 +249,7 @@ class TestMergeConflictResolver: def test_resolve_trivial_conflict(self): """Test resolution of trivial conflict.""" - conflict_content = textwrap.dedent( - """ + conflict_content = textwrap.dedent(""" <<<<<<< HEAD def hello(): pass @@ -270,8 +257,7 @@ def hello(): def hello(): pass >>>>>>> branch - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(conflict_content) @@ -287,8 +273,7 @@ def hello(): def test_resolve_import_conflict(self): """Test resolution of import conflict.""" - conflict_content = textwrap.dedent( - """ + conflict_content = textwrap.dedent(""" <<<<<<< HEAD import os import sys @@ -296,8 +281,7 @@ def test_resolve_import_conflict(self): import os import json >>>>>>> branch - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(conflict_content) @@ -315,15 +299,13 @@ def test_resolve_import_conflict(self): def test_accept_ours_strategy(self): """Test accept ours resolution strategy.""" - conflict_content = textwrap.dedent( - """ + conflict_content = textwrap.dedent(""" <<<<<<< HEAD x = 1 ======= x = 2 >>>>>>> branch - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(conflict_content) @@ -341,15 +323,13 @@ def test_accept_ours_strategy(self): def test_accept_theirs_strategy(self): """Test accept theirs resolution strategy.""" - conflict_content = textwrap.dedent( - """ + conflict_content = textwrap.dedent(""" <<<<<<< HEAD x = 1 ======= x = 2 >>>>>>> branch - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(conflict_content) @@ -367,8 +347,7 @@ def test_accept_theirs_strategy(self): def test_accept_both_strategy(self): """Test accept both resolution strategy.""" - conflict_content = textwrap.dedent( - """ + conflict_content = textwrap.dedent(""" <<<<<<< HEAD def func1(): pass @@ -376,8 +355,7 @@ def func1(): def func2(): pass >>>>>>> branch - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(conflict_content) @@ -396,8 +374,7 @@ def func2(): def test_safe_mode_requires_review(self): """Test safe mode requires review for complex conflicts.""" - conflict_content = textwrap.dedent( - """ + conflict_content = textwrap.dedent(""" <<<<<<< HEAD def process(data): if data: @@ -408,8 +385,7 @@ def process(data): while data: yield data.pop() >>>>>>> branch - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(conflict_content) @@ -425,8 +401,7 @@ def process(data): def test_validation_detects_errors(self): """Test validation detects syntax errors.""" - conflict_content = textwrap.dedent( - """ + conflict_content = textwrap.dedent(""" <<<<<<< HEAD def hello(): return "current" @@ -434,8 +409,7 @@ def hello(): def hello( return "incoming" >>>>>>> branch - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(conflict_content) diff --git a/autobot-backend/code_intelligence/pattern_analysis/storage.py b/autobot-backend/code_intelligence/pattern_analysis/storage.py index 33e65ed34..31f58569b 100644 --- a/autobot-backend/code_intelligence/pattern_analysis/storage.py +++ b/autobot-backend/code_intelligence/pattern_analysis/storage.py @@ -345,12 +345,12 @@ def _process_search_results( { "id": pattern_id, "similarity": similarity, - "document": results["documents"][0][i] - if results.get("documents") - else "", - "metadata": results["metadatas"][0][i] - if results.get("metadatas") - else {}, + "document": ( + results["documents"][0][i] if results.get("documents") else "" + ), + "metadata": ( + results["metadatas"][0][i] if results.get("metadatas") else {} + ), } ) diff --git a/autobot-backend/code_intelligence/pattern_analysis/types.py b/autobot-backend/code_intelligence/pattern_analysis/types.py index f0715dccb..7248294b4 100644 --- a/autobot-backend/code_intelligence/pattern_analysis/types.py +++ b/autobot-backend/code_intelligence/pattern_analysis/types.py @@ -129,9 +129,9 @@ def to_dict(self) -> Dict[str, Any]: base.update( { "similarity_score": self.similarity_score, - "canonical_code": self.canonical_code[:500] - if self.canonical_code - else "", + "canonical_code": ( + self.canonical_code[:500] if self.canonical_code else "" + ), "code_reduction_potential": self.code_reduction_potential, } ) @@ -247,9 +247,9 @@ def to_dict(self) -> Dict[str, Any]: "pattern_type": self.pattern_type.value, "size": self.size, "patterns": [p.to_dict() for p in self.patterns], - "representative_code": self.representative_code[:500] - if self.representative_code - else "", + "representative_code": ( + self.representative_code[:500] if self.representative_code else "" + ), } diff --git a/autobot-backend/code_intelligence/performance_analysis/analyzer.py b/autobot-backend/code_intelligence/performance_analysis/analyzer.py index 0df9cf42a..fb247e302 100644 --- a/autobot-backend/code_intelligence/performance_analysis/analyzer.py +++ b/autobot-backend/code_intelligence/performance_analysis/analyzer.py @@ -497,9 +497,9 @@ async def _find_semantic_performance_duplicates( "line_start": "line_start", "description": "description", }, - min_similarity=SIMILARITY_MEDIUM - if HAS_ANALYTICS_INFRASTRUCTURE - else 0.7, + min_similarity=( + SIMILARITY_MEDIUM if HAS_ANALYTICS_INFRASTRUCTURE else 0.7 + ), ) except Exception as e: logger.warning("Semantic duplicate detection failed: %s", e) diff --git a/autobot-backend/code_intelligence/performance_analyzer_test.py b/autobot-backend/code_intelligence/performance_analyzer_test.py index 0c302b358..b9d149a8d 100644 --- a/autobot-backend/code_intelligence/performance_analyzer_test.py +++ b/autobot-backend/code_intelligence/performance_analyzer_test.py @@ -34,16 +34,14 @@ class TestNestedLoopDetection: def test_detect_nested_for_loops(self): """Test detection of nested for loops with O(n²) complexity.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def process_matrix(matrix): result = [] for i in range(len(matrix)): for j in range(len(matrix[i])): result.append(matrix[i][j]) return result - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -67,15 +65,13 @@ def process_matrix(matrix): def test_detect_triple_nested_loops(self): """Test detection of triple nested loops with O(n³) complexity.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def process_3d(data): for x in data: for y in x: for z in y: print(z) # noqa: print - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -100,15 +96,13 @@ def process_3d(data): def test_nested_list_comprehension(self): """Test detection of nested list comprehensions.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def flatten(matrix): return [item for row in matrix for item in row] def cross_product(a, b): return [(x, y) for x in a for y in b] - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -132,16 +126,14 @@ class TestNPlusOneQueryDetection: def test_detect_query_in_for_loop(self): """Test detection of database query inside for loop.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def get_user_orders(users, db): results = [] for user in users: orders = db.execute(f"SELECT * FROM orders WHERE user_id = {user.id}") results.append(orders) return results - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -162,13 +154,11 @@ def get_user_orders(users, db): def test_detect_fetch_in_loop(self): """Test detection of fetch operations inside loop.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def process_items(items, cursor): for item in items: cursor.fetchone() - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -191,16 +181,14 @@ class TestAsyncSyncMismatch: def test_detect_time_sleep_in_async(self): """Test detection of time.sleep() in async function.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import time import asyncio async def process_async(): time.sleep(1) # Should use asyncio.sleep return "done" - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -219,13 +207,11 @@ async def process_async(): def test_detect_blocking_io_in_async(self): """Test detection of blocking I/O in async function.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" async def read_file_async(path): with open(path, 'r') as f: # Should use aiofiles return f.read() - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -245,16 +231,14 @@ async def read_file_async(path): def test_detect_sequential_awaits(self): """Test detection of sequential awaits that could be parallel.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" async def fetch_all_data(): result1 = await fetch_users() result2 = await fetch_orders() result3 = await fetch_products() result4 = await fetch_categories() return result1, result2, result3, result4 - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -274,15 +258,13 @@ async def fetch_all_data(): def test_no_false_positive_async_sleep(self): """Test that asyncio.sleep doesn't trigger false positive.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import asyncio async def proper_async(): await asyncio.sleep(1) return "done" - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -303,15 +285,13 @@ class TestStringConcatenation: def test_detect_string_concat_in_loop(self): """Test detection of string concatenation in loop.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def build_output(items): result = "" for item in items: result += str(item) + ", " return result - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -331,15 +311,13 @@ def build_output(items): def test_detect_plus_equals_string(self): """Test detection of += with strings in loop.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def create_html(elements): html = "" for element in elements: html += "
" + element + "
" return html - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -363,14 +341,12 @@ class TestListLookup: def test_detect_list_for_membership(self): """Test detection of list used for membership check.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def check_valid(value): if value in ["apple", "banana", "cherry", "date"]: return True return False - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -394,8 +370,7 @@ class TestHTTPRequestsInLoop: def test_detect_http_in_loop(self): """Test detection of HTTP requests inside loop.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import requests def fetch_all_users(user_ids): @@ -404,8 +379,7 @@ def fetch_all_users(user_ids): response = requests.get(f"/api/users/{user_id}") results.append(response.json()) return results - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -429,8 +403,7 @@ class TestRepeatedComputation: def test_detect_repeated_expensive_calls(self): """Test detection of repeated expensive computations.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def process_data(data): hash1 = hashlib.sha256(data).hexdigest() result1 = process(hash1) @@ -442,8 +415,7 @@ def process_data(data): result3 = check(hash3) return result1, result2, result3 - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -462,27 +434,19 @@ class TestDirectoryAnalysis: def test_analyze_directory(self, tmp_path): """Test analysis of multiple files in directory.""" # Create test file with issues - (tmp_path / "slow.py").write_text( - textwrap.dedent( - """ + (tmp_path / "slow.py").write_text(textwrap.dedent(""" def slow_function(items): for i in items: for j in items: print(i, j) # noqa: print - """ - ) - ) + """)) # Create clean file - (tmp_path / "fast.py").write_text( - textwrap.dedent( - """ + (tmp_path / "fast.py").write_text(textwrap.dedent(""" def fast_function(items): for item in items: print(item) # noqa: print - """ - ) - ) + """)) analyzer = PerformanceAnalyzer(project_root=str(tmp_path)) results = analyzer.analyze_directory() @@ -495,16 +459,12 @@ def test_exclude_patterns(self, tmp_path): """Test that exclude patterns are respected.""" # Create file in excluded directory (tmp_path / "venv").mkdir() - (tmp_path / "venv" / "slow.py").write_text( - textwrap.dedent( - """ + (tmp_path / "venv" / "slow.py").write_text(textwrap.dedent(""" def slow(items): for i in items: for j in items: pass - """ - ) - ) + """)) analyzer = PerformanceAnalyzer( project_root=str(tmp_path), exclude_patterns=["venv"] @@ -520,8 +480,7 @@ class TestSummaryGeneration: def test_get_summary(self): """Test summary generation.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def problematic(items, db): result = "" for item in items: @@ -529,8 +488,7 @@ def problematic(items, db): db.execute(f"SELECT * FROM table WHERE id = {sub}") result += str(sub) return result - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -550,13 +508,11 @@ def problematic(items, db): def test_performance_score_calculation(self): """Test that performance score is calculated correctly.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" async def problematic(): import time time.sleep(1) # CRITICAL issue - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -578,14 +534,12 @@ class TestReportGeneration: def test_json_report_format(self): """Test JSON report generation.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def slow(data): for i in data: for j in data: pass - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -605,14 +559,12 @@ def slow(data): def test_markdown_report_format(self): """Test Markdown report generation.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def slow(data): for i in data: for j in data: pass - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -657,16 +609,12 @@ class TestConvenienceFunction: def test_analyze_performance_function(self, tmp_path): """Test the convenience function.""" - (tmp_path / "test.py").write_text( - textwrap.dedent( - """ + (tmp_path / "test.py").write_text(textwrap.dedent(""" def test(): for i in range(10): for j in range(10): pass - """ - ) - ) + """)) result = analyze_performance(str(tmp_path)) @@ -680,14 +628,12 @@ class TestSeverityLevels: def test_critical_severity_for_blocking_async(self): """Blocking sync operations in async should be CRITICAL.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import time async def blocked(): time.sleep(5) - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -704,13 +650,11 @@ async def blocked(): def test_high_severity_for_n_plus_one(self): """N+1 queries should be HIGH severity.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def fetch_all(items, db): for item in items: db.query(item.id) - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -730,15 +674,13 @@ def fetch_all(items, db): def test_medium_severity_for_string_concat(self): """String concatenation in loop should be MEDIUM severity.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def build(items): s = "" for i in items: s += "x" return s - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -809,14 +751,12 @@ class TestToDict: def test_to_dict_serialization(self): """Test that issues serialize correctly.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def slow(items): for i in items: for j in items: pass - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) diff --git a/autobot-backend/code_intelligence/precommit_analyzer_test.py b/autobot-backend/code_intelligence/precommit_analyzer_test.py index 762327439..85f460d82 100644 --- a/autobot-backend/code_intelligence/precommit_analyzer_test.py +++ b/autobot-backend/code_intelligence/precommit_analyzer_test.py @@ -33,14 +33,12 @@ class TestSecurityChecks: def test_detect_hardcoded_password(self): """Test detection of hardcoded passwords.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" DATABASE_PASSWORD = "super_secret_123" def connect(): return db.connect(password=DATABASE_PASSWORD) - """ - ) + """) analyzer = PrecommitAnalyzer() results = analyzer.analyze_content(code, "config.py") @@ -54,12 +52,10 @@ def connect(): def test_detect_api_key(self): """Test detection of exposed API keys.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" API_KEY = "sk-1234567890abcdef1234567890abcdef" SECRET_KEY = "abcdef1234567890abcdef1234567890" - """ - ) + """) analyzer = PrecommitAnalyzer() results = analyzer.analyze_content(code, "config.py") @@ -71,13 +67,11 @@ def test_detect_api_key(self): def test_detect_private_key(self): """Test detection of private keys in code.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" PRIVATE_KEY = '''-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA0Z... -----END RSA PRIVATE KEY-----''' - """ - ) + """) analyzer = PrecommitAnalyzer() results = analyzer.analyze_content(code, "keys.py") @@ -89,14 +83,12 @@ def test_detect_private_key(self): def test_detect_hardcoded_ip(self): """Test detection of hardcoded IP addresses.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" SERVER_IP = "192.168.1.100" def connect(): return socket.connect(SERVER_IP, 8080) - """ - ) + """) analyzer = PrecommitAnalyzer() results = analyzer.analyze_content(code, "network.py") @@ -108,11 +100,9 @@ def connect(): def test_detect_aws_key(self): """Test detection of AWS access keys.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" AWS_ACCESS_KEY_ID = "AKIAIOSFODNN7EXAMPLE" - """ - ) + """) analyzer = PrecommitAnalyzer() results = analyzer.analyze_content(code, "aws.py") @@ -144,15 +134,13 @@ class TestDebugChecks: def test_detect_console_log(self): """Test detection of console.log statements.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" function processData(data) { console.log("Processing:", data); console.debug("Debug info"); return data; } - """ - ) + """) analyzer = PrecommitAnalyzer() results = analyzer.analyze_content(code, "app.js") @@ -165,14 +153,12 @@ def test_detect_console_log(self): def test_detect_print_statement(self): """Test detection of print statements in Python.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def process_data(items): for item in items: print(f"Processing: {item}") # noqa: print return items - """ - ) + """) analyzer = PrecommitAnalyzer() results = analyzer.analyze_content(code, "process.py") @@ -184,15 +170,13 @@ def process_data(items): def test_detect_debugger_statement(self): """Test detection of debugger statements.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import pdb def buggy_function(x): pdb.set_trace() return x * 2 - """ - ) + """) analyzer = PrecommitAnalyzer() results = analyzer.analyze_content(code, "debug.py") @@ -206,13 +190,11 @@ def buggy_function(x): def test_detect_breakpoint(self): """Test detection of breakpoint() call.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def test_function(x): breakpoint() return x - """ - ) + """) analyzer = PrecommitAnalyzer() results = analyzer.analyze_content(code, "test.py") @@ -225,14 +207,12 @@ def test_function(x): def test_detect_todo_comment(self): """Test detection of TODO/FIXME comments.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def incomplete_function(): # TODO: Implement this properly # FIXME: This is broken pass - """ - ) + """) analyzer = PrecommitAnalyzer() results = analyzer.analyze_content(code, "wip.py") @@ -248,15 +228,13 @@ class TestQualityChecks: def test_detect_empty_except(self): """Test detection of empty except blocks.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def risky_operation(): try: do_something() except: pass - """ - ) + """) analyzer = PrecommitAnalyzer() results = analyzer.analyze_content(code, "handler.py") @@ -269,14 +247,12 @@ def risky_operation(): def test_detect_bare_except(self): """Test detection of bare except clauses.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" try: result = process() except: log_error() - """ - ) + """) analyzer = PrecommitAnalyzer() results = analyzer.analyze_content(code, "handler.py") @@ -289,12 +265,10 @@ def test_detect_bare_except(self): def test_detect_hardcoded_port(self): """Test detection of hardcoded port numbers.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" port = 8080 server_port = 3000 - """ - ) + """) analyzer = PrecommitAnalyzer() results = analyzer.analyze_content(code, "config.py") @@ -339,12 +313,10 @@ class TestFastMode: def test_fast_mode_skips_expensive_checks(self): """Test that fast mode skips expensive checks.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def function_without_docstring(): return 42 - """ - ) + """) # Normal mode should include DOC001 analyzer_normal = PrecommitAnalyzer(fast_mode=False) @@ -547,13 +519,11 @@ class TestSummary: def test_get_summary(self): """Test summary generation.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" PASSWORD = "secret123" print("debug") # noqa: print # TODO: Fix this - """ - ) + """) analyzer = PrecommitAnalyzer() analyzer.results = analyzer.analyze_content(code, "test.py") @@ -595,8 +565,7 @@ class TestSnippetGeneration: def test_snippet_with_context(self): """Test that snippets include context lines.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def function1(): pass @@ -604,8 +573,7 @@ def function1(): def function2(): pass - """ - ) + """) analyzer = PrecommitAnalyzer() results = analyzer.analyze_content(code, "test.py") @@ -632,16 +600,14 @@ def test_empty_content(self): def test_no_issues(self): """Test clean code with no issues.""" - code = textwrap.dedent( - ''' + code = textwrap.dedent(''' """Clean module.""" import os def get_password(): """Get password from environment.""" return os.getenv("PASSWORD") - ''' - ) + ''') analyzer = PrecommitAnalyzer() results = analyzer.analyze_content(code, "clean.py") diff --git a/autobot-backend/code_intelligence/redis_optimizer_test.py b/autobot-backend/code_intelligence/redis_optimizer_test.py index 32b205534..48949adde 100644 --- a/autobot-backend/code_intelligence/redis_optimizer_test.py +++ b/autobot-backend/code_intelligence/redis_optimizer_test.py @@ -30,8 +30,7 @@ class TestRedisOptimizer: def test_detect_sequential_gets(self): """Test detection of sequential GET operations.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import redis async def fetch_user_data(redis_client, user_id): @@ -39,8 +38,7 @@ async def fetch_user_data(redis_client, user_id): email = await redis_client.get(f"user:{user_id}:email") age = await redis_client.get(f"user:{user_id}:age") return {"name": name, "email": email, "age": age} - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -62,14 +60,12 @@ async def fetch_user_data(redis_client, user_id): def test_detect_sequential_sets(self): """Test detection of sequential SET operations.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" async def save_user_data(redis_client, user_id, data): await redis_client.set(f"user:{user_id}:name", data["name"]) await redis_client.set(f"user:{user_id}:email", data["email"]) await redis_client.set(f"user:{user_id}:status", "active") - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -92,16 +88,14 @@ async def save_user_data(redis_client, user_id, data): def test_detect_loop_operations(self): """Test detection of Redis operations inside loops.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" async def process_items(redis_client, items): results = [] for item in items: value = await redis_client.get(f"item:{item}") results.append(value) return results - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -122,8 +116,7 @@ async def process_items(redis_client, items): def test_detect_read_modify_write(self): """Test detection of read-modify-write patterns.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" async def increment_counter(redis_client, key): current = await redis_client.get(key) if current: @@ -132,8 +125,7 @@ async def increment_counter(redis_client, key): new_value = 1 await redis_client.set(key, new_value) return new_value - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -156,15 +148,13 @@ async def increment_counter(redis_client, key): def test_detect_direct_redis_instantiation(self): """Test detection of direct redis.Redis() usage.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import redis def get_data(): client = redis.Redis(host="localhost", port=6379) return client.get("key") - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -184,12 +174,10 @@ def get_data(): def test_detect_missing_expiry(self): """Test detection of SET without TTL.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" async def cache_data(redis_client, key, value): await redis_client.set(key, value) - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -210,8 +198,7 @@ async def cache_data(redis_client, key, value): def test_no_false_positives_for_good_code(self): """Test that good Redis patterns don't trigger warnings.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" from utils.redis_client import get_redis_client async def good_pipeline_usage(): @@ -220,8 +207,7 @@ async def good_pipeline_usage(): pipe.set("key1", "value1") pipe.set("key2", "value2") await pipe.execute() - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -242,30 +228,22 @@ async def good_pipeline_usage(): def test_analyze_directory(self, tmp_path): """Test directory-wide analysis.""" # Create test files - (tmp_path / "good.py").write_text( - textwrap.dedent( - """ + (tmp_path / "good.py").write_text(textwrap.dedent(""" from utils.redis_client import get_redis_client async def good_code(): redis = await get_redis_client(async_client=True) return await redis.get("key") - """ - ) - ) + """)) - (tmp_path / "bad.py").write_text( - textwrap.dedent( - """ + (tmp_path / "bad.py").write_text(textwrap.dedent(""" import redis def bad_code(): client = redis.Redis(host="localhost") for i in range(100): client.get(f"key:{i}") - """ - ) - ) + """)) optimizer = RedisOptimizer(project_root=str(tmp_path)) results = optimizer.analyze_directory() @@ -277,8 +255,7 @@ def bad_code(): def test_get_summary(self): """Test summary generation.""" # Use code that will definitely trigger detection - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import redis async def multiple_issues(): @@ -290,8 +267,7 @@ async def multiple_issues(): b = await redis_client.get("key2") c = await redis_client.get("key3") return a, b, c - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -309,16 +285,12 @@ async def multiple_issues(): def test_analyze_redis_usage_convenience_function(self, tmp_path): """Test the convenience function.""" - (tmp_path / "test.py").write_text( - textwrap.dedent( - """ + (tmp_path / "test.py").write_text(textwrap.dedent(""" async def test_func(redis): a = await redis.get("key1") b = await redis.get("key2") return a, b - """ - ) - ) + """)) result = analyze_redis_usage(str(tmp_path)) @@ -331,12 +303,10 @@ class TestOptimizationTypes: def test_keys_command_detection(self): """Test detection of KEYS command (should use SCAN).""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" async def get_all_keys(redis_client, pattern): return await redis_client.keys(pattern) - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -356,15 +326,13 @@ async def get_all_keys(redis_client, pattern): def test_multiple_related_keys_detection(self): """Test detection of related string keys that could be a hash.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" async def get_user(redis, user_id): name = await redis.get(f"user:{user_id}:name") email = await redis.get(f"user:{user_id}:email") phone = await redis.get(f"user:{user_id}:phone") return {"name": name, "email": email, "phone": phone} - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -390,13 +358,11 @@ class TestSeverityLevels: def test_loop_operations_are_high_severity(self): """Loop operations should be HIGH severity.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" async def process(redis): for i in range(100): await redis.set(f"key:{i}", i) - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -416,14 +382,12 @@ async def process(redis): def test_sequential_operations_are_medium_severity(self): """Sequential GET/SET should be MEDIUM severity.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" async def fetch(redis): a = await redis.get("a") b = await redis.get("b") return a, b - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) diff --git a/autobot-backend/code_intelligence/security/analyzer.py b/autobot-backend/code_intelligence/security/analyzer.py index f25119737..a622c9d2b 100644 --- a/autobot-backend/code_intelligence/security/analyzer.py +++ b/autobot-backend/code_intelligence/security/analyzer.py @@ -433,9 +433,9 @@ async def _find_semantic_security_duplicates( "description": "description", "owasp_category": "owasp_category", }, - min_similarity=SIMILARITY_MEDIUM - if HAS_ANALYTICS_INFRASTRUCTURE - else 0.7, + min_similarity=( + SIMILARITY_MEDIUM if HAS_ANALYTICS_INFRASTRUCTURE else 0.7 + ), ) except Exception as e: logger.warning("Semantic duplicate detection failed: %s", e) diff --git a/autobot-backend/code_intelligence/security/ast_visitor.py b/autobot-backend/code_intelligence/security/ast_visitor.py index 883a29837..69116d527 100644 --- a/autobot-backend/code_intelligence/security/ast_visitor.py +++ b/autobot-backend/code_intelligence/security/ast_visitor.py @@ -11,11 +11,20 @@ import logging from typing import Dict, List, Optional, Set -from .constants import (DEBUG_MODE_VARS, HTTP_METHODS, INSECURE_RANDOM_FUNCS, - LOAD_FUNCS, OWASP_MAPPING, PICKLE_MODULES, - VALIDATION_ATTRS, VALIDATION_FUNCS, - WEAK_HASH_ALGORITHMS, YAML_LOADER_ARGS, - SecuritySeverity, VulnerabilityType) +from .constants import ( + DEBUG_MODE_VARS, + HTTP_METHODS, + INSECURE_RANDOM_FUNCS, + LOAD_FUNCS, + OWASP_MAPPING, + PICKLE_MODULES, + VALIDATION_ATTRS, + VALIDATION_FUNCS, + WEAK_HASH_ALGORITHMS, + YAML_LOADER_ARGS, + SecuritySeverity, + VulnerabilityType, +) from .finding import SecurityFinding logger = logging.getLogger(__name__) diff --git a/autobot-backend/code_intelligence/security_analyzer.py b/autobot-backend/code_intelligence/security_analyzer.py index 6ede6d0a5..3a14c1676 100644 --- a/autobot-backend/code_intelligence/security_analyzer.py +++ b/autobot-backend/code_intelligence/security_analyzer.py @@ -29,7 +29,9 @@ # Issue #554: Import analytics infrastructure for semantic analysis try: from code_intelligence.analytics_infrastructure import ( - SIMILARITY_MEDIUM, SemanticAnalysisMixin) + SIMILARITY_MEDIUM, + SemanticAnalysisMixin, + ) HAS_ANALYTICS_INFRASTRUCTURE = True except ImportError: @@ -1031,7 +1033,9 @@ def get_summary(self) -> Dict[str, Any]: Scores now degrade gracefully instead of immediately hitting 0. """ from code_intelligence.shared.scoring import ( - calculate_score_from_severity_counts, get_risk_level_from_score) + calculate_score_from_severity_counts, + get_risk_level_from_score, + ) by_severity, by_type, by_owasp = self._aggregate_findings_by_category() security_score = calculate_score_from_severity_counts(by_severity) diff --git a/autobot-backend/code_intelligence/security_analyzer_test.py b/autobot-backend/code_intelligence/security_analyzer_test.py index c85aeb37e..63ecf5b6a 100644 --- a/autobot-backend/code_intelligence/security_analyzer_test.py +++ b/autobot-backend/code_intelligence/security_analyzer_test.py @@ -33,13 +33,11 @@ class TestSecurityAnalyzer: def test_detect_sql_injection_format(self): """Test detection of SQL injection via string formatting.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def get_user(cursor, user_id): cursor.execute(f"SELECT * FROM users WHERE id = {user_id}") return cursor.fetchone() - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -61,13 +59,11 @@ def get_user(cursor, user_id): def test_detect_command_injection_eval(self): """Test detection of command injection via eval().""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def process_input(user_input): result = eval(user_input) return result - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -87,14 +83,12 @@ def process_input(user_input): def test_detect_subprocess_shell_true(self): """Test detection of subprocess with shell=True.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import subprocess def run_command(cmd): return subprocess.run(cmd, shell=True) - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -114,14 +108,12 @@ def run_command(cmd): def test_detect_hardcoded_password(self): """Test detection of hardcoded password.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" DATABASE_PASSWORD = "super_secret_password123" def connect(): return db.connect(password=DATABASE_PASSWORD) - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -145,14 +137,12 @@ def connect(): def test_detect_hardcoded_api_key(self): """Test detection of hardcoded API key.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" API_KEY = "sk-1234567890abcdef1234567890abcdef" def call_api(): return requests.get(url, headers={"Authorization": API_KEY}) - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -171,14 +161,12 @@ def call_api(): def test_detect_weak_hash_md5(self): """Test detection of weak MD5 hash usage.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import hashlib def hash_password(password): return hashlib.md5(password.encode()).hexdigest() - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -198,14 +186,12 @@ def hash_password(password): def test_detect_insecure_random(self): """Test detection of insecure random usage.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import random def generate_token(): return random.randint(0, 1000000) - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -225,14 +211,12 @@ def generate_token(): def test_detect_pickle_usage(self): """Test detection of insecure pickle usage.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import pickle def load_data(data): return pickle.loads(data) - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -252,14 +236,12 @@ def load_data(data): def test_detect_yaml_unsafe_load(self): """Test detection of unsafe yaml.load usage.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import yaml def load_config(data): return yaml.load(data) - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -279,14 +261,12 @@ def load_config(data): def test_detect_debug_mode_enabled(self): """Test detection of debug mode enabled.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" DEBUG = True app = Flask(__name__) app.run(debug=DEBUG) - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -305,8 +285,7 @@ def test_detect_debug_mode_enabled(self): def test_no_false_positives_for_env_vars(self): """Test that environment variable usage doesn't trigger false positives.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import os API_KEY = os.getenv("API_KEY") @@ -314,8 +293,7 @@ def test_no_false_positives_for_env_vars(self): def connect(): return db.connect(password=PASSWORD) - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -339,8 +317,7 @@ def connect(): def test_no_false_positives_for_safe_yaml(self): """Test that safe yaml usage doesn't trigger warnings.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import yaml def load_config(data): @@ -348,8 +325,7 @@ def load_config(data): def load_with_loader(data): return yaml.load(data, Loader=yaml.SafeLoader) - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -369,27 +345,19 @@ def load_with_loader(data): def test_analyze_directory(self, tmp_path): """Test directory-wide security analysis.""" # Create test files - (tmp_path / "safe.py").write_text( - textwrap.dedent( - """ + (tmp_path / "safe.py").write_text(textwrap.dedent(""" import os def get_config(): return os.getenv("CONFIG") - """ - ) - ) + """)) - (tmp_path / "vulnerable.py").write_text( - textwrap.dedent( - """ + (tmp_path / "vulnerable.py").write_text(textwrap.dedent(""" import pickle def load(data): return pickle.loads(data) - """ - ) - ) + """)) analyzer = SecurityAnalyzer(project_root=str(tmp_path)) results = analyzer.analyze_directory() @@ -400,8 +368,7 @@ def load(data): def test_get_summary(self): """Test summary generation.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" import pickle import hashlib @@ -410,8 +377,7 @@ def test_get_summary(self): def process(data): obj = pickle.loads(data) return hashlib.md5(PASSWORD.encode()).hexdigest() - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -430,12 +396,10 @@ def process(data): def test_owasp_mapping(self): """Test OWASP Top 10 mapping for findings.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def execute_query(cursor, user_input): cursor.execute(f"SELECT * FROM users WHERE name = '{user_input}'") - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -468,12 +432,10 @@ class TestSecuritySeverity: def test_critical_severity_for_injection(self): """Injection vulnerabilities should be CRITICAL.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" def dangerous(user_input): eval(user_input) - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -493,11 +455,9 @@ def dangerous(user_input): def test_high_severity_for_secrets(self): """Hardcoded secrets should be HIGH severity.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" SECRET_KEY = "my_super_secret_key_12345678" - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -521,14 +481,10 @@ class TestSecurityConvenienceFunction: def test_analyze_security_function(self, tmp_path): """Test the convenience function.""" - (tmp_path / "test.py").write_text( - textwrap.dedent( - """ + (tmp_path / "test.py").write_text(textwrap.dedent(""" def test(): eval("1+1") - """ - ) - ) + """)) result = analyze_security(str(tmp_path)) @@ -542,11 +498,9 @@ class TestSecurityReport: def test_json_report_format(self): """Test JSON report generation.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" PASSWORD = "test123" - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) @@ -564,11 +518,9 @@ def test_json_report_format(self): def test_markdown_report_format(self): """Test Markdown report generation.""" - code = textwrap.dedent( - """ + code = textwrap.dedent(""" PASSWORD = "test123" - """ - ) + """) with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="w") as f: f.write(code) diff --git a/autobot-backend/code_intelligence/shell_analyzer.py b/autobot-backend/code_intelligence/shell_analyzer.py index f78493e1e..57d329518 100644 --- a/autobot-backend/code_intelligence/shell_analyzer.py +++ b/autobot-backend/code_intelligence/shell_analyzer.py @@ -417,9 +417,9 @@ def _create_pattern_issue( current_code=line.strip(), confidence=confidence, potential_false_positive=confidence < 0.80, - false_positive_reason="" - if confidence >= 0.80 - else "Context may justify this pattern", + false_positive_reason=( + "" if confidence >= 0.80 else "Context may justify this pattern" + ), rule_id=rule_id, tags=["shell", category.value], ) diff --git a/autobot-backend/code_intelligence/typescript_analyzer.py b/autobot-backend/code_intelligence/typescript_analyzer.py index 24c168321..c683bfec6 100644 --- a/autobot-backend/code_intelligence/typescript_analyzer.py +++ b/autobot-backend/code_intelligence/typescript_analyzer.py @@ -460,9 +460,11 @@ def _check_blocking_io(self, language: Language) -> None: current_code=line.strip(), confidence=confidence, potential_false_positive=confidence < 0.9, - false_positive_reason="" - if confidence >= 0.9 - else "Context may justify sync operation", + false_positive_reason=( + "" + if confidence >= 0.9 + else "Context may justify sync operation" + ), rule_id=rule_id, tags=["blocking-io", "performance", "async"], ) @@ -587,9 +589,9 @@ def _create_antipattern_issue( current_code=line.strip(), confidence=confidence, potential_false_positive=confidence < 0.75, - false_positive_reason="" - if confidence >= 0.75 - else "Context may make this acceptable", + false_positive_reason=( + "" if confidence >= 0.75 else "Context may make this acceptable" + ), rule_id=rule_id, tags=["anti-pattern", category.value], ) diff --git a/autobot-backend/code_intelligence/vue_analyzer.py b/autobot-backend/code_intelligence/vue_analyzer.py index bdb6b6546..cbdc48d3e 100644 --- a/autobot-backend/code_intelligence/vue_analyzer.py +++ b/autobot-backend/code_intelligence/vue_analyzer.py @@ -498,9 +498,9 @@ def _create_vue_pattern_issue( current_code=line.strip(), confidence=confidence, potential_false_positive=confidence < 0.75, - false_positive_reason="" - if confidence >= 0.75 - else "Context may make this acceptable", + false_positive_reason=( + "" if confidence >= 0.75 else "Context may make this acceptable" + ), rule_id=rule_id, tags=["vue", prefix.split("-")[0], category.value], ) diff --git a/autobot-backend/command_manual_manager.py b/autobot-backend/command_manual_manager.py index 434c469f3..c5ae931ac 100644 --- a/autobot-backend/command_manual_manager.py +++ b/autobot-backend/command_manual_manager.py @@ -61,8 +61,7 @@ def _initialize_database(self): try: with sqlite3.connect(self.db_path) as conn: cursor = conn.cursor() - cursor.execute( - """ + cursor.execute(""" CREATE TABLE IF NOT EXISTS command_manuals ( id INTEGER PRIMARY KEY AUTOINCREMENT, command_name TEXT UNIQUE NOT NULL, @@ -78,28 +77,21 @@ def _initialize_database(self): created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) - """ - ) + """) # Create index for faster searches - cursor.execute( - """ + cursor.execute(""" CREATE INDEX IF NOT EXISTS idx_command_name ON command_manuals(command_name) - """ - ) - cursor.execute( - """ + """) + cursor.execute(""" CREATE INDEX IF NOT EXISTS idx_category ON command_manuals(category) - """ - ) - cursor.execute( - """ + """) + cursor.execute(""" CREATE INDEX IF NOT EXISTS idx_risk_level ON command_manuals(risk_level) - """ - ) + """) conn.commit() logger.info("Command manuals database initialized successfully") diff --git a/autobot-backend/comprehensive_system_validation_test.py b/autobot-backend/comprehensive_system_validation_test.py index 5b7c09686..f1f23f1a3 100644 --- a/autobot-backend/comprehensive_system_validation_test.py +++ b/autobot-backend/comprehensive_system_validation_test.py @@ -652,9 +652,9 @@ def generate_summary_report(self) -> Dict: "failed": failed, "warnings": warnings, "skipped": skipped, - "success_rate": f"{(passed/total_tests*100):.1f}%" - if total_tests > 0 - else "0%", + "success_rate": ( + f"{(passed/total_tests*100):.1f}%" if total_tests > 0 else "0%" + ), }, "execution_info": { "total_duration": f"{total_duration:.2f}s", diff --git a/autobot-backend/computer_vision/collections.py b/autobot-backend/computer_vision/collections.py index 6b12039c4..41b8dd6e0 100644 --- a/autobot-backend/computer_vision/collections.py +++ b/autobot-backend/computer_vision/collections.py @@ -145,7 +145,7 @@ class ProcessingResultExtractor: @staticmethod def extract_text_regions( - result_data: Optional[Dict[str, Any]] + result_data: Optional[Dict[str, Any]], ) -> List[Dict[str, Any]]: """Extract text regions from processing results""" if not result_data: @@ -154,7 +154,7 @@ def extract_text_regions( @staticmethod def extract_dominant_colors( - result_data: Optional[Dict[str, Any]] + result_data: Optional[Dict[str, Any]], ) -> List[Dict[str, Any]]: """Extract dominant colors from processing results""" if not result_data: @@ -163,7 +163,7 @@ def extract_dominant_colors( @staticmethod def extract_layout_structure( - result_data: Optional[Dict[str, Any]] + result_data: Optional[Dict[str, Any]], ) -> Dict[str, Any]: """Extract layout analysis from processing results""" if not result_data: @@ -172,7 +172,7 @@ def extract_layout_structure( @staticmethod def extract_ui_elements( - result_data: Optional[Dict[str, Any]] + result_data: Optional[Dict[str, Any]], ) -> List[Dict[str, Any]]: """Extract detected UI elements from processing results""" if not result_data: diff --git a/autobot-backend/computer_vision/types.py b/autobot-backend/computer_vision/types.py index 139834733..c686a0d31 100644 --- a/autobot-backend/computer_vision/types.py +++ b/autobot-backend/computer_vision/types.py @@ -179,9 +179,9 @@ class ScreenState: automation_opportunities: List[Dict[str, Any]] context_analysis: Dict[str, Any] confidence_score: float - multimodal_analysis: Optional[ - List[Dict[str, Any]] - ] = None # New field for multi-modal processing results + multimodal_analysis: Optional[List[Dict[str, Any]]] = ( + None # New field for multi-modal processing results + ) def get_element_collection(self) -> "UIElementCollection": """Get UI elements as a collection with analysis methods""" diff --git a/autobot-backend/context_aware_decision/decision_engine.py b/autobot-backend/context_aware_decision/decision_engine.py index 0b9bbed61..b170ddcf2 100644 --- a/autobot-backend/context_aware_decision/decision_engine.py +++ b/autobot-backend/context_aware_decision/decision_engine.py @@ -164,9 +164,9 @@ async def _build_automation_decision( {"outcome": "action_completed", "probability": confidence} ], monitoring_criteria=["action_execution_status", "target_element_response"], - fallback_plan={"action": "request_human_takeover"} - if confidence < 0.6 - else None, + fallback_plan=( + {"action": "request_human_takeover"} if confidence < 0.6 else None + ), requires_approval=requires_approval, timestamp=self.time_provider.current_timestamp(), metadata={ @@ -658,9 +658,9 @@ def _build_workflow_optimization_decision( }, expected_outcomes=self._build_optimization_expected_outcomes(confidence), monitoring_criteria=["workflow_performance", "efficiency_metrics"], - fallback_plan={"action": "revert_optimization"} - if best_score < 0.6 - else None, + fallback_plan=( + {"action": "revert_optimization"} if best_score < 0.6 else None + ), requires_approval=best_score < 0.7, timestamp=self.time_provider.current_timestamp(), metadata={ diff --git a/autobot-backend/database/migrations/001_create_conversation_files.py b/autobot-backend/database/migrations/001_create_conversation_files.py index c3552df9c..a5395f876 100644 --- a/autobot-backend/database/migrations/001_create_conversation_files.py +++ b/autobot-backend/database/migrations/001_create_conversation_files.py @@ -324,8 +324,7 @@ def _record_migration(self) -> None: try: # Create migrations tracking table if it doesn't exist - cursor.execute( - """ + cursor.execute(""" CREATE TABLE IF NOT EXISTS schema_migrations ( migration_id INTEGER PRIMARY KEY AUTOINCREMENT, version TEXT NOT NULL UNIQUE, @@ -334,8 +333,7 @@ def _record_migration(self) -> None: status TEXT DEFAULT 'completed', execution_time_ms INTEGER ) - """ - ) + """) # Record this migration (INSERT OR IGNORE for idempotency - safe for concurrent initialization) # If version already exists, silently skip (no error) - critical for multi-VM distributed environment diff --git a/autobot-backend/enhanced_memory_manager_async.py b/autobot-backend/enhanced_memory_manager_async.py index 5c9c03938..c0e49ae93 100644 --- a/autobot-backend/enhanced_memory_manager_async.py +++ b/autobot-backend/enhanced_memory_manager_async.py @@ -171,8 +171,7 @@ async def _create_tasks_table(self, conn) -> None: Issue #620. """ - await conn.execute( - """ + await conn.execute(""" CREATE TABLE IF NOT EXISTS tasks ( task_id TEXT PRIMARY KEY, description TEXT NOT NULL, @@ -192,8 +191,7 @@ async def _create_tasks_table(self, conn) -> None: markdown_reference TEXT, FOREIGN KEY (parent_task_id) REFERENCES tasks(task_id) ) - """ - ) + """) async def _create_execution_records_table(self, conn) -> None: """ @@ -201,8 +199,7 @@ async def _create_execution_records_table(self, conn) -> None: Issue #620. """ - await conn.execute( - """ + await conn.execute(""" CREATE TABLE IF NOT EXISTS execution_records ( record_id TEXT PRIMARY KEY, task_id TEXT NOT NULL, @@ -215,8 +212,7 @@ async def _create_execution_records_table(self, conn) -> None: agent_context TEXT, -- JSON object FOREIGN KEY (task_id) REFERENCES tasks(task_id) ) - """ - ) + """) async def _create_memory_entries_table(self, conn) -> None: """ @@ -224,8 +220,7 @@ async def _create_memory_entries_table(self, conn) -> None: Issue #620. """ - await conn.execute( - """ + await conn.execute(""" CREATE TABLE IF NOT EXISTS memory_entries ( id INTEGER PRIMARY KEY AUTOINCREMENT, category TEXT NOT NULL, @@ -237,8 +232,7 @@ async def _create_memory_entries_table(self, conn) -> None: reference_path TEXT, UNIQUE(category, content_hash) ) - """ - ) + """) async def _create_tables(self, conn) -> None: """ @@ -492,9 +486,9 @@ async def get_tasks_by_status( priority=Priority(row[3]), created_at=datetime.fromtimestamp(row[4]), updated_at=datetime.fromtimestamp(row[5]), - completed_at=datetime.fromtimestamp(row[6]) - if row[6] - else None, + completed_at=( + datetime.fromtimestamp(row[6]) if row[6] else None + ), assigned_agent=row[7], parent_task_id=row[8], tags=json.loads(row[9] or "[]"), diff --git a/autobot-backend/initialization/lifespan.py b/autobot-backend/initialization/lifespan.py index 9c7b6d4bc..f3fa8db84 100644 --- a/autobot-backend/initialization/lifespan.py +++ b/autobot-backend/initialization/lifespan.py @@ -167,7 +167,9 @@ async def _init_conversation_file_manager(app: FastAPI) -> None: await conversation_file_manager.initialize() app.state.conversation_file_manager = conversation_file_manager await update_app_state("conversation_file_manager", conversation_file_manager) - logger.info("āœ… [ 40%] Conversation Files DB: Database initialized and verified") + logger.info( + "āœ… [ 40%] Conversation Files DB: Database initialized and verified" + ) except Exception as conv_file_error: logger.error( f"āŒ CRITICAL: Conversation files database initialization failed: {conv_file_error}" @@ -493,7 +495,8 @@ async def _auto_index_documentation(): # Fire-and-forget: run indexing in background so startup continues logger.info( - "āœ… [ 85%] Doc Index: Collection empty, " "scheduling background indexing..." + "āœ… [ 85%] Doc Index: Collection empty, " + "scheduling background indexing..." ) asyncio.create_task(_run_background_doc_indexing()) diff --git a/autobot-backend/intelligence/intelligent_agent.py b/autobot-backend/intelligence/intelligent_agent.py index b72de78a9..57ac59cd3 100644 --- a/autobot-backend/intelligence/intelligent_agent.py +++ b/autobot-backend/intelligence/intelligent_agent.py @@ -83,9 +83,9 @@ def get_os_info_dict(self) -> Dict[str, Any]: "is_wsl": self.os_info.is_wsl, "package_manager": self.os_info.package_manager, "shell": self.os_info.shell, - "capabilities": list(self.os_info.capabilities) - if self.os_info.capabilities - else [], + "capabilities": ( + list(self.os_info.capabilities) if self.os_info.capabilities else [] + ), } def add_to_context(self, entry_type: str, content: Any, **extra) -> None: diff --git a/autobot-backend/judges/judge_integration_test.py b/autobot-backend/judges/judge_integration_test.py index 968523723..cd2117eab 100644 --- a/autobot-backend/judges/judge_integration_test.py +++ b/autobot-backend/judges/judge_integration_test.py @@ -218,12 +218,12 @@ async def test_step_rejection_by_judge(self, mock_judges): reject_judgment.criterion_scores = [] reject_judgment.improvement_suggestions = ["Use safer alternative"] - mock_judges[ - "workflow_step_judge" - ].evaluate_workflow_step.return_value = reject_judgment - mock_judges[ - "security_risk_judge" - ].evaluate_command_security.return_value = reject_judgment + mock_judges["workflow_step_judge"].evaluate_workflow_step.return_value = ( + reject_judgment + ) + mock_judges["security_risk_judge"].evaluate_command_security.return_value = ( + reject_judgment + ) with patch("api.workflow_automation.JUDGES_AVAILABLE", True), patch( "api.workflow_automation.WorkflowStepJudge", @@ -270,9 +270,9 @@ def test_judge_error_handling(self, mock_judges): from api.workflow_automation import WorkflowAutomationManager # Configure judge to raise exception - mock_judges[ - "workflow_step_judge" - ].evaluate_workflow_step.side_effect = Exception("Judge error") + mock_judges["workflow_step_judge"].evaluate_workflow_step.side_effect = ( + Exception("Judge error") + ) with patch("api.workflow_automation.JUDGES_AVAILABLE", True), patch( "api.workflow_automation.WorkflowStepJudge", @@ -342,9 +342,9 @@ async def test_multi_criteria_evaluation(self, mock_judges): detailed_judgment.criterion_scores = criterion_scores detailed_judgment.improvement_suggestions = [] - mock_judges[ - "workflow_step_judge" - ].evaluate_workflow_step.return_value = detailed_judgment + mock_judges["workflow_step_judge"].evaluate_workflow_step.return_value = ( + detailed_judgment + ) # Test that all criteria are evaluated with patch("api.workflow_automation.JUDGES_AVAILABLE", True), patch( diff --git a/autobot-backend/knowledge/chat_knowledge_system.e2e_test.py b/autobot-backend/knowledge/chat_knowledge_system.e2e_test.py index f0c79a255..12b1b3abd 100644 --- a/autobot-backend/knowledge/chat_knowledge_system.e2e_test.py +++ b/autobot-backend/knowledge/chat_knowledge_system.e2e_test.py @@ -85,8 +85,7 @@ async def test_file_association(self): # Create a temporary test file with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: - f.write( - """ + f.write(""" # Test Python file for chat knowledge system def test_function(): '''Example function for testing''' @@ -94,8 +93,7 @@ def test_function(): if __name__ == "__main__": print(test_function()) # noqa: print -""" - ) +""") test_file_path = f.name self.test_files.append(test_file_path) diff --git a/autobot-backend/knowledge/gpu_kb_integration_test.py b/autobot-backend/knowledge/gpu_kb_integration_test.py index 6f695977c..5d8def03a 100644 --- a/autobot-backend/knowledge/gpu_kb_integration_test.py +++ b/autobot-backend/knowledge/gpu_kb_integration_test.py @@ -47,16 +47,13 @@ async def test_chunker_optimization(): # Test chunking performance print("\n⚔ Testing chunking performance...") # noqa: print - test_text = ( - """ + test_text = """ AutoBot is an advanced Linux administration platform designed for intelligent automation. The system utilizes cutting-edge AI technologies to manage Linux environments efficiently. Through machine learning and natural language processing, AutoBot can understand complex system requirements. The platform provides autonomous decision-making capabilities for routine administrative tasks. Security and reliability are paramount in AutoBot's architectural design. - """ - * 3 - ) # Make text longer for meaningful test + """ * 3 # Make text longer for meaningful test start_time = time.time() diff --git a/autobot-backend/knowledge/kb_optimization_test.py b/autobot-backend/knowledge/kb_optimization_test.py index 1f95fc12c..34f765aaf 100644 --- a/autobot-backend/knowledge/kb_optimization_test.py +++ b/autobot-backend/knowledge/kb_optimization_test.py @@ -111,7 +111,9 @@ async def test_knowledge_base_optimization(): if results["total_chunks"] > 0: chunks_per_second = results["total_chunks"] / processing_time - print(f" ⚔ Performance: {chunks_per_second:.1f} chunks/sec") # noqa: print + print( + f" ⚔ Performance: {chunks_per_second:.1f} chunks/sec" + ) # noqa: print # Test search functionality print("\nšŸ” Testing search with processed document...") # noqa: print diff --git a/autobot-backend/knowledge/knowledge.performance_test.py b/autobot-backend/knowledge/knowledge.performance_test.py index 4f48cc374..12c75f180 100644 --- a/autobot-backend/knowledge/knowledge.performance_test.py +++ b/autobot-backend/knowledge/knowledge.performance_test.py @@ -617,9 +617,9 @@ async def mixed_operation(session, op_id: int): # Category filter url = f"{self.backend_url}/api/knowledge_base/facts/by_category" params = { - "category": categories[op_id % len(categories)] - if categories - else None, + "category": ( + categories[op_id % len(categories)] if categories else None + ), "limit": 50, } start = time.perf_counter() @@ -770,14 +770,14 @@ def generate_performance_report(self, total_duration: float) -> Dict[str, Any]: report["summary"] = { "total_requests": total_requests, "total_successful": total_successful, - "overall_success_rate": (total_successful / total_requests * 100) - if total_requests > 0 - else 0, + "overall_success_rate": ( + (total_successful / total_requests * 100) if total_requests > 0 else 0 + ), "tests_passed": tests_passed, "tests_failed": tests_failed, - "pass_rate": (tests_passed / len(self.results) * 100) - if self.results - else 0, + "pass_rate": ( + (tests_passed / len(self.results) * 100) if self.results else 0 + ), } # Performance analysis for each test @@ -788,15 +788,19 @@ def generate_performance_report(self, total_duration: float) -> Dict[str, Any]: "passed": result.passed, "margin_ms": result.target_ms - result.p95_latency_ms, "margin_percentage": ( - (result.target_ms - result.p95_latency_ms) / result.target_ms * 100 - ) - if result.target_ms > 0 - else 0, + ( + (result.target_ms - result.p95_latency_ms) + / result.target_ms + * 100 + ) + if result.target_ms > 0 + else 0 + ), "success_rate": ( - result.successful_requests / result.total_requests * 100 - ) - if result.total_requests > 0 - else 0, + (result.successful_requests / result.total_requests * 100) + if result.total_requests > 0 + else 0 + ), } # Pass/Fail summary diff --git a/autobot-backend/knowledge/pipeline/cognifiers/summarizer_raptor_test.py b/autobot-backend/knowledge/pipeline/cognifiers/summarizer_raptor_test.py index e1ae558ef..fbbdd6a2b 100644 --- a/autobot-backend/knowledge/pipeline/cognifiers/summarizer_raptor_test.py +++ b/autobot-backend/knowledge/pipeline/cognifiers/summarizer_raptor_test.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Tests for RAPTOR recursive clustering in HierarchicalSummarizer (#2027, #2051).""" + from unittest.mock import AsyncMock, MagicMock, patch import numpy as np diff --git a/autobot-backend/knowledge/pipeline/loaders/chromadb_loader.py b/autobot-backend/knowledge/pipeline/loaders/chromadb_loader.py index 709b3d611..ad1037158 100644 --- a/autobot-backend/knowledge/pipeline/loaders/chromadb_loader.py +++ b/autobot-backend/knowledge/pipeline/loaders/chromadb_loader.py @@ -126,9 +126,11 @@ async def _upsert_summary_batch( { "level": summary.level, "document_id": str(summary.source_document_id), - "parent_summary_id": str(summary.parent_summary_id) - if summary.parent_summary_id - else None, + "parent_summary_id": ( + str(summary.parent_summary_id) + if summary.parent_summary_id + else None + ), "key_topics": ",".join(summary.key_topics), "word_count": summary.word_count, } diff --git a/autobot-backend/knowledge/search_components/context_tracker.py b/autobot-backend/knowledge/search_components/context_tracker.py index ddb81d027..1a71edb1d 100644 --- a/autobot-backend/knowledge/search_components/context_tracker.py +++ b/autobot-backend/knowledge/search_components/context_tracker.py @@ -1,4 +1,5 @@ """Per-query context tracker preventing redundant chunk reads (#1994, #2005).""" + import logging logger = logging.getLogger(__name__) diff --git a/autobot-backend/knowledge/search_components/context_tracker_test.py b/autobot-backend/knowledge/search_components/context_tracker_test.py index de3de2f4b..46cd2efbb 100644 --- a/autobot-backend/knowledge/search_components/context_tracker_test.py +++ b/autobot-backend/knowledge/search_components/context_tracker_test.py @@ -1,4 +1,5 @@ """Tests for ContextTracker (#2005).""" + from knowledge.search_components.context_tracker import ContextTracker diff --git a/autobot-backend/knowledge/search_quality.py b/autobot-backend/knowledge/search_quality.py index 9d0e7d2fd..5b9ba3c3c 100644 --- a/autobot-backend/knowledge/search_quality.py +++ b/autobot-backend/knowledge/search_quality.py @@ -871,9 +871,9 @@ def get_search_performance_stats(self) -> Dict[str, Any]: "total_searches": len(self.events), "unique_queries": len(self.query_counts), "avg_results": self.get_average_results_count(), - "failed_search_rate": failed_count / len(self.events) - if self.events - else 0.0, + "failed_search_rate": ( + failed_count / len(self.events) if self.events else 0.0 + ), "click_through_rate": self.get_click_through_rate(), "avg_duration_ms": sum(durations) / len(durations) if durations else 0, "popular_queries": self.get_popular_queries(5), diff --git a/autobot-backend/knowledge/stats.py b/autobot-backend/knowledge/stats.py index 6d8048634..2f5fbbf24 100644 --- a/autobot-backend/knowledge/stats.py +++ b/autobot-backend/knowledge/stats.py @@ -201,9 +201,11 @@ def _build_consistency_result( fact_drift = actual_facts - stored_facts vector_drift = actual_vectors - stored_vectors return { - "status": "consistent" - if fact_drift == 0 and vector_drift == 0 - else "drift_detected", + "status": ( + "consistent" + if fact_drift == 0 and vector_drift == 0 + else "drift_detected" + ), "stored_facts": stored_facts, "actual_facts": actual_facts, "fact_drift": fact_drift, diff --git a/autobot-backend/knowledge/tags.py b/autobot-backend/knowledge/tags.py index 3a39c63fb..dde89f0ac 100644 --- a/autobot-backend/knowledge/tags.py +++ b/autobot-backend/knowledge/tags.py @@ -892,9 +892,11 @@ async def delete_tag_style(self, tag: str) -> Dict[str, Any]: "success": True, "tag": tag, "deleted": deleted > 0, - "message": "Tag style reset to defaults" - if deleted - else "No custom style existed", + "message": ( + "Tag style reset to defaults" + if deleted + else "No custom style existed" + ), } except Exception as e: diff --git a/autobot-backend/llm_interface.py b/autobot-backend/llm_interface.py index c0d8ffe3f..3aaa8bf9f 100644 --- a/autobot-backend/llm_interface.py +++ b/autobot-backend/llm_interface.py @@ -14,6 +14,9 @@ from llm_interface_pkg import LLMInterface, LLMSettings, ProviderType """ +# Import additional dependencies that may be expected by consumers +from config import ConfigManager + # Re-export everything from the refactored package from llm_interface_pkg import ( # Types; Models; Hardware; Streaming; Mock providers; Main interface; Providers TORCH_AVAILABLE, @@ -38,9 +41,6 @@ palm, ) -# Import additional dependencies that may be expected by consumers -from config import ConfigManager - # Create singleton config instance for backward compatibility config = ConfigManager() diff --git a/autobot-backend/llm_interface_pkg/cache.py b/autobot-backend/llm_interface_pkg/cache.py index bba88064a..17a1e860f 100644 --- a/autobot-backend/llm_interface_pkg/cache.py +++ b/autobot-backend/llm_interface_pkg/cache.py @@ -301,15 +301,21 @@ async def set( if redis_client: # Optimize metadata storage - only keep essential data essential_metadata = { - "request_id": response.metadata.get("request_id") - if response.metadata - else None, - "chunks_received": response.metadata.get("chunks_received") - if response.metadata - else None, - "streaming": response.metadata.get("streaming", False) - if response.metadata - else False, + "request_id": ( + response.metadata.get("request_id") + if response.metadata + else None + ), + "chunks_received": ( + response.metadata.get("chunks_received") + if response.metadata + else None + ), + "streaming": ( + response.metadata.get("streaming", False) + if response.metadata + else False + ), } data = { diff --git a/autobot-backend/llm_interface_pkg/optimization/rate_limiter.py b/autobot-backend/llm_interface_pkg/optimization/rate_limiter.py index 1cc5d6142..4f00c9bf9 100644 --- a/autobot-backend/llm_interface_pkg/optimization/rate_limiter.py +++ b/autobot-backend/llm_interface_pkg/optimization/rate_limiter.py @@ -356,7 +356,7 @@ def with_retry( _handler = handler or RateLimitHandler() def decorator( - func: Callable[..., Coroutine[Any, Any, T]] + func: Callable[..., Coroutine[Any, Any, T]], ) -> Callable[..., Coroutine[Any, Any, T]]: async def wrapper(*args: Any, **kwargs: Any) -> T: return await _handler.execute_with_retry( diff --git a/autobot-backend/markdown_reference_system.py b/autobot-backend/markdown_reference_system.py index dca052c99..ebabadb70 100644 --- a/autobot-backend/markdown_reference_system.py +++ b/autobot-backend/markdown_reference_system.py @@ -55,8 +55,7 @@ def __init__( def _create_documents_table(self, conn: sqlite3.Connection) -> None: """Issue #665: Extracted from _init_markdown_tables to reduce function length.""" - conn.execute( - """ + conn.execute(""" CREATE TABLE IF NOT EXISTS markdown_documents ( file_path TEXT PRIMARY KEY, file_name TEXT NOT NULL, @@ -70,13 +69,11 @@ def _create_documents_table(self, conn: sqlite3.Connection) -> None: tags TEXT, metadata_json TEXT ) - """ - ) + """) def _create_cross_references_table(self, conn: sqlite3.Connection) -> None: """Issue #665: Extracted from _init_markdown_tables to reduce function length.""" - conn.execute( - """ + conn.execute(""" CREATE TABLE IF NOT EXISTS markdown_cross_references ( id INTEGER PRIMARY KEY AUTOINCREMENT, source_file TEXT NOT NULL, @@ -88,13 +85,11 @@ def _create_cross_references_table(self, conn: sqlite3.Connection) -> None: FOREIGN KEY (source_file) REFERENCES markdown_documents(file_path), FOREIGN KEY (target_file) REFERENCES markdown_documents(file_path) ) - """ - ) + """) def _create_sections_table(self, conn: sqlite3.Connection) -> None: """Issue #665: Extracted from _init_markdown_tables to reduce function length.""" - conn.execute( - """ + conn.execute(""" CREATE TABLE IF NOT EXISTS markdown_sections ( id INTEGER PRIMARY KEY AUTOINCREMENT, file_path TEXT NOT NULL, @@ -107,8 +102,7 @@ def _create_sections_table(self, conn: sqlite3.Connection) -> None: created_at TIMESTAMP NOT NULL, FOREIGN KEY (file_path) REFERENCES markdown_documents(file_path) ) - """ - ) + """) def _create_markdown_indexes(self, conn: sqlite3.Connection) -> None: """Issue #665: Extracted from _init_markdown_tables to reduce function length.""" @@ -655,13 +649,11 @@ def _get_document_stats_by_type( Issue #620. """ - cursor = conn.execute( - """ + cursor = conn.execute(""" SELECT document_type, COUNT(*), SUM(word_count), AVG(word_count) FROM markdown_documents GROUP BY document_type - """ - ) + """) doc_stats = {} for row in cursor.fetchall(): doc_stats[row[0]] = { @@ -677,13 +669,11 @@ def _get_reference_stats(self, conn: sqlite3.Connection) -> Dict[str, int]: Issue #620. """ - cursor = conn.execute( - """ + cursor = conn.execute(""" SELECT reference_type, COUNT(*) FROM markdown_cross_references GROUP BY reference_type - """ - ) + """) return {row[0]: row[1] for row in cursor.fetchall()} def _get_section_stats(self, conn: sqlite3.Connection) -> Dict[str, int]: @@ -692,14 +682,12 @@ def _get_section_stats(self, conn: sqlite3.Connection) -> Dict[str, int]: Issue #620. """ - cursor = conn.execute( - """ + cursor = conn.execute(""" SELECT section_level, COUNT(*) FROM markdown_sections GROUP BY section_level ORDER BY section_level - """ - ) + """) return {f"level_{row[0]}": row[1] for row in cursor.fetchall()} def _get_document_totals(self, conn: sqlite3.Connection) -> tuple: @@ -708,15 +696,13 @@ def _get_document_totals(self, conn: sqlite3.Connection) -> tuple: Issue #620. """ - cursor = conn.execute( - """ + cursor = conn.execute(""" SELECT COUNT(*) as total_documents, SUM(word_count) as total_words, COUNT(DISTINCT directory) as total_directories FROM markdown_documents - """ - ) + """) return cursor.fetchone() def get_markdown_statistics(self) -> Dict[str, Any]: diff --git a/autobot-backend/media/image/pipeline.py b/autobot-backend/media/image/pipeline.py index 78ba1e433..e827ffb4a 100644 --- a/autobot-backend/media/image/pipeline.py +++ b/autobot-backend/media/image/pipeline.py @@ -28,7 +28,9 @@ # Optional: existing VisionProcessor for AI-powered analysis try: from multimodal_processor.processors.vision import ( - VISION_MODELS_AVAILABLE, VisionProcessor) + VISION_MODELS_AVAILABLE, + VisionProcessor, + ) _VISION_PROCESSOR_AVAILABLE = VISION_MODELS_AVAILABLE except ImportError: diff --git a/autobot-backend/memory/models.py b/autobot-backend/memory/models.py index 3b5f6cd76..447e8d304 100644 --- a/autobot-backend/memory/models.py +++ b/autobot-backend/memory/models.py @@ -88,9 +88,9 @@ def to_response_dict(self) -> Dict[str, Any]: "priority": self.priority.value, "created_at": self.created_at.isoformat(), "started_at": self.started_at.isoformat() if self.started_at else None, - "completed_at": self.completed_at.isoformat() - if self.completed_at - else None, + "completed_at": ( + self.completed_at.isoformat() if self.completed_at else None + ), "duration_seconds": self.duration_seconds, "agent_type": self.agent_type, "inputs": self.inputs, diff --git a/autobot-backend/memory/storage/general_storage.py b/autobot-backend/memory/storage/general_storage.py index c9b793dbf..edcb88c07 100644 --- a/autobot-backend/memory/storage/general_storage.py +++ b/autobot-backend/memory/storage/general_storage.py @@ -39,8 +39,7 @@ async def initialize(self): """Initialize memory entries table""" try: async with self._get_connection() as conn: - await conn.execute( - """ + await conn.execute(""" CREATE TABLE IF NOT EXISTS memory_entries ( id INTEGER PRIMARY KEY AUTOINCREMENT, category TEXT NOT NULL, @@ -50,22 +49,17 @@ async def initialize(self): reference_path TEXT, embedding BLOB ) - """ - ) + """) # Indexes for common queries - await conn.execute( - """ + await conn.execute(""" CREATE INDEX IF NOT EXISTS idx_memory_category ON memory_entries(category) - """ - ) - await conn.execute( - """ + """) + await conn.execute(""" CREATE INDEX IF NOT EXISTS idx_memory_timestamp ON memory_entries(timestamp) - """ - ) + """) await conn.commit() except aiosqlite.Error as e: @@ -206,13 +200,11 @@ async def get_stats(self) -> Dict[str, Any]: total = (await cursor.fetchone())[0] # Entries by category - cursor = await conn.execute( - """ + cursor = await conn.execute(""" SELECT category, COUNT(*) FROM memory_entries GROUP BY category - """ - ) + """) by_category = {row[0]: row[1] for row in await cursor.fetchall()} return {"total_entries": total, "by_category": by_category} diff --git a/autobot-backend/memory/storage/task_storage.py b/autobot-backend/memory/storage/task_storage.py index 2db5a4fd1..9943136d5 100644 --- a/autobot-backend/memory/storage/task_storage.py +++ b/autobot-backend/memory/storage/task_storage.py @@ -79,8 +79,7 @@ async def initialize(self): """Initialize task execution history table""" try: async with self._get_connection() as conn: - await conn.execute( - """ + await conn.execute(""" CREATE TABLE IF NOT EXISTS task_execution_history ( task_id TEXT PRIMARY KEY, task_name TEXT NOT NULL, @@ -101,28 +100,21 @@ async def initialize(self): subtask_ids_json TEXT, metadata_json TEXT ) - """ - ) + """) # Indexes for common queries - await conn.execute( - """ + await conn.execute(""" CREATE INDEX IF NOT EXISTS idx_task_status ON task_execution_history(status) - """ - ) - await conn.execute( - """ + """) + await conn.execute(""" CREATE INDEX IF NOT EXISTS idx_task_created ON task_execution_history(created_at) - """ - ) - await conn.execute( - """ + """) + await conn.execute(""" CREATE INDEX IF NOT EXISTS idx_task_agent ON task_execution_history(agent_type) - """ - ) + """) await conn.commit() except aiosqlite.Error as e: @@ -268,23 +260,19 @@ async def get_stats(self) -> Dict[str, Any]: total = (await cursor.fetchone())[0] # Tasks by status - cursor = await conn.execute( - """ + cursor = await conn.execute(""" SELECT status, COUNT(*) FROM task_execution_history GROUP BY status - """ - ) + """) by_status = {row[0]: row[1] for row in await cursor.fetchall()} # Tasks by priority - cursor = await conn.execute( - """ + cursor = await conn.execute(""" SELECT priority, COUNT(*) FROM task_execution_history GROUP BY priority - """ - ) + """) by_priority = {row[0]: row[1] for row in await cursor.fetchall()} return { diff --git a/autobot-backend/memory_package_test.py b/autobot-backend/memory_package_test.py index 6487d4104..5726d616e 100644 --- a/autobot-backend/memory_package_test.py +++ b/autobot-backend/memory_package_test.py @@ -228,7 +228,9 @@ def test_6_backward_compatibility_enhanced(): task_id2 = manager.log_task_execution(record2) assert task_id2 == "bc-002" - print("āœ… PASSED: EnhancedMemoryManager backward compatibility works") # noqa: print + print( + "āœ… PASSED: EnhancedMemoryManager backward compatibility works" + ) # noqa: print async def test_7_backward_compatibility_longterm(): @@ -254,7 +256,9 @@ async def test_7_backward_compatibility_longterm(): assert len(memories) == 1 assert memories[0].content == "Test content" - print("āœ… PASSED: LongTermMemoryManager backward compatibility works") # noqa: print + print( + "āœ… PASSED: LongTermMemoryManager backward compatibility works" + ) # noqa: print def test_8_sync_wrappers(): diff --git a/autobot-backend/migrations/versions/20251224_001_initial_user_management.py b/autobot-backend/migrations/versions/20251224_001_initial_user_management.py index 3aa227516..73bbd88cd 100644 --- a/autobot-backend/migrations/versions/20251224_001_initial_user_management.py +++ b/autobot-backend/migrations/versions/20251224_001_initial_user_management.py @@ -7,6 +7,7 @@ Revises: Create Date: 2024-12-24 """ + from typing import Sequence, Union import sqlalchemy as sa diff --git a/autobot-backend/migrations/versions/20260216_002_secrets_hierarchical_access.py b/autobot-backend/migrations/versions/20260216_002_secrets_hierarchical_access.py index 5a6a3b8e2..a5437717e 100644 --- a/autobot-backend/migrations/versions/20260216_002_secrets_hierarchical_access.py +++ b/autobot-backend/migrations/versions/20260216_002_secrets_hierarchical_access.py @@ -9,6 +9,7 @@ Issue #685: Add org_id and team_ids for hierarchical secret access """ + from typing import Sequence, Union import sqlalchemy as sa diff --git a/autobot-backend/models/completion_feedback.py b/autobot-backend/models/completion_feedback.py index 8bc132744..e5e48c339 100644 --- a/autobot-backend/models/completion_feedback.py +++ b/autobot-backend/models/completion_feedback.py @@ -56,9 +56,9 @@ def to_dict(self) -> Dict: "id": self.id, "timestamp": self.timestamp.isoformat() if self.timestamp else None, "user_id": self.user_id, - "context": self.context[:100] + "..." - if len(self.context) > 100 - else self.context, + "context": ( + self.context[:100] + "..." if len(self.context) > 100 else self.context + ), "suggestion": self.suggestion, "language": self.language, "file_path": self.file_path, diff --git a/autobot-backend/models/knowledge_import_tracking.py b/autobot-backend/models/knowledge_import_tracking.py index 30a1a348f..347c99fcb 100644 --- a/autobot-backend/models/knowledge_import_tracking.py +++ b/autobot-backend/models/knowledge_import_tracking.py @@ -5,6 +5,7 @@ Knowledge Base Import Tracking Model Tracks which files have been imported into the knowledge base """ + import hashlib from datetime import datetime from pathlib import Path @@ -26,8 +27,7 @@ def _ensure_table(self): conn = sqlite3.connect(self.db_path) cursor = conn.cursor() - cursor.execute( - """ + cursor.execute(""" CREATE TABLE IF NOT EXISTS imported_files ( id INTEGER PRIMARY KEY AUTOINCREMENT, file_path TEXT UNIQUE NOT NULL, @@ -41,26 +41,19 @@ def _ensure_table(self): facts_count INTEGER DEFAULT 0, metadata TEXT ) - """ - ) + """) - cursor.execute( - """ + cursor.execute(""" CREATE INDEX IF NOT EXISTS idx_file_path ON imported_files(file_path) - """ - ) + """) - cursor.execute( - """ + cursor.execute(""" CREATE INDEX IF NOT EXISTS idx_import_status ON imported_files(import_status) - """ - ) + """) - cursor.execute( - """ + cursor.execute(""" CREATE INDEX IF NOT EXISTS idx_category ON imported_files(category) - """ - ) + """) conn.commit() conn.close() @@ -217,14 +210,12 @@ def get_import_status( (category,), ) else: - cursor.execute( - """ + cursor.execute(""" SELECT file_path, file_hash, file_size, category, import_status, imported_at, last_checked, error_message, facts_count FROM imported_files ORDER BY imported_at DESC - """ - ) + """) columns = [ "file_path", @@ -249,8 +240,7 @@ def get_statistics(self): conn = sqlite3.connect(self.db_path) cursor = conn.cursor() - cursor.execute( - """ + cursor.execute(""" SELECT COUNT(*) as total_files, SUM(CASE WHEN import_status = 'imported' THEN 1 ELSE 0 END) as imported, @@ -259,8 +249,7 @@ def get_statistics(self): SUM(facts_count) as total_facts, SUM(file_size) as total_size FROM imported_files - """ - ) + """) result = cursor.fetchone() conn.close() diff --git a/autobot-backend/monitoring/monitoring_and_alerts_test.py b/autobot-backend/monitoring/monitoring_and_alerts_test.py index c27fd53e6..1ab313321 100644 --- a/autobot-backend/monitoring/monitoring_and_alerts_test.py +++ b/autobot-backend/monitoring/monitoring_and_alerts_test.py @@ -211,9 +211,11 @@ async def test_health_monitoring_endpoints(self): status = "PASS" message = "Health endpoint accessible with valid JSON" details = { - "response_keys": list(data.keys()) - if isinstance(data, dict) - else "non-dict" + "response_keys": ( + list(data.keys()) + if isinstance(data, dict) + else "non-dict" + ) } except json.JSONDecodeError: status = "WARNING" @@ -853,9 +855,9 @@ async def test_incident_response_automation(self): "trigger": scenario["trigger"], "expected_actions": scenario["expected_actions"], "incident_triggered": incident_triggered, - "response_initiated": response_initiated - if incident_triggered - else None, + "response_initiated": ( + response_initiated if incident_triggered else None + ), } except Exception as e: diff --git a/autobot-backend/multimodal_processor/processor.py b/autobot-backend/multimodal_processor/processor.py index 00b012b07..e43769d4e 100644 --- a/autobot-backend/multimodal_processor/processor.py +++ b/autobot-backend/multimodal_processor/processor.py @@ -752,9 +752,11 @@ def get_stats(self) -> Dict[str, Any]: }, "voice": { "whisper_available": self.voice_processor.whisper_model is not None, - "wav2vec_available": self.voice_processor.wav2vec_model is not None - if hasattr(self.voice_processor, "wav2vec_model") - else False, + "wav2vec_available": ( + self.voice_processor.wav2vec_model is not None + if hasattr(self.voice_processor, "wav2vec_model") + else False + ), "enabled": self.voice_processor.enabled, }, } diff --git a/autobot-backend/multimodal_processor_impl.py b/autobot-backend/multimodal_processor_impl.py index 8acd477e8..c5e4bd35f 100644 --- a/autobot-backend/multimodal_processor_impl.py +++ b/autobot-backend/multimodal_processor_impl.py @@ -446,9 +446,9 @@ def _build_combined_result( modality_type=input_data.modality_type, intent=input_data.intent, success=success, - confidence=combined_result.get("confidence", 0.5) - if combined_result - else 0.0, + confidence=( + combined_result.get("confidence", 0.5) if combined_result else 0.0 + ), result_data=combined_result, processing_time=processing_time, error_message=error_message, diff --git a/autobot-backend/npu_integration.py b/autobot-backend/npu_integration.py index ca8da1d0a..2c181acb6 100644 --- a/autobot-backend/npu_integration.py +++ b/autobot-backend/npu_integration.py @@ -152,9 +152,9 @@ def __init__( """ self.npu_endpoint = npu_endpoint or get_service_url("npu-worker") self._use_auth = use_auth if use_auth is not None else USE_AUTHENTICATED_CLIENT - self._http_client: Optional[ - Union[HTTPClientManager, "ServiceHTTPClient"] - ] = None + self._http_client: Optional[Union[HTTPClientManager, "ServiceHTTPClient"]] = ( + None + ) self._auth_client_initialized = False self.available = False self._check_availability_task = None diff --git a/autobot-backend/npu_semantic_search.py b/autobot-backend/npu_semantic_search.py index 084adfd5d..6ac674b14 100644 --- a/autobot-backend/npu_semantic_search.py +++ b/autobot-backend/npu_semantic_search.py @@ -963,7 +963,9 @@ async def _initialize_chromadb(self): "description": f"AutoBot {modality} embeddings", }, ) - logger.info(f"āœ… Created new ChromaDB collection: {collection_name}") + logger.info( + f"āœ… Created new ChromaDB collection: {collection_name}" + ) self.collections[modality] = collection diff --git a/autobot-backend/orchestration/current_status.e2e_test.py b/autobot-backend/orchestration/current_status.e2e_test.py index 13f0b298a..50ff634ba 100644 --- a/autobot-backend/orchestration/current_status.e2e_test.py +++ b/autobot-backend/orchestration/current_status.e2e_test.py @@ -52,7 +52,9 @@ async def test_current_status(): complexity = await orchestrator.classify_request_complexity(msg) print(f" āœ… '{msg[:30]}...' → {complexity.value}") # noqa: print except Exception as e: - print(f" āŒ Classification failed for '{msg[:30]}...': {e}") # noqa: print + print( + f" āŒ Classification failed for '{msg[:30]}...': {e}" + ) # noqa: print # Test 3: Workflow Planning print("\n3. Workflow Planning Test:") # noqa: print diff --git a/autobot-backend/orchestration/final_workflow.e2e_test.py b/autobot-backend/orchestration/final_workflow.e2e_test.py index 03b7683a4..5bb6df720 100644 --- a/autobot-backend/orchestration/final_workflow.e2e_test.py +++ b/autobot-backend/orchestration/final_workflow.e2e_test.py @@ -56,7 +56,9 @@ async def final_workflow_test(): print("5. Workflow Response Creation Test:") # noqa: print workflow_response = await orchestrator.create_workflow_response(user_message) response_steps = workflow_response.get("workflow_steps", []) - print(f" āœ… Workflow response contains {len(response_steps)} steps") # noqa: print + print( + f" āœ… Workflow response contains {len(response_steps)} steps" + ) # noqa: print assert len(response_steps) > 0, "Workflow response should contain steps" assert ( len(response_steps) == 8 diff --git a/autobot-backend/phase8_control_panel_test.py b/autobot-backend/phase8_control_panel_test.py index 12e45ceb4..808ee0025 100644 --- a/autobot-backend/phase8_control_panel_test.py +++ b/autobot-backend/phase8_control_panel_test.py @@ -37,7 +37,9 @@ def test_api_connectivity(): print(f"āŒ API returned status code: {response.status_code}") # noqa: print return False except requests.exceptions.ConnectionError: - print("āŒ Cannot connect to backend API at http://localhost:8001") # noqa: print + print( + "āŒ Cannot connect to backend API at http://localhost:8001" + ) # noqa: print return False except Exception as e: print(f"āŒ API connectivity test failed: {e}") # noqa: print @@ -182,7 +184,9 @@ def test_api_endpoints(): capabilities = response.json() print(f"āœ… Streaming capabilities: {capabilities}") # noqa: print else: - print(f"āŒ Capabilities check failed: {response.status_code}") # noqa: print + print( + f"āŒ Capabilities check failed: {response.status_code}" + ) # noqa: print except Exception as e: print(f"āŒ Capabilities check error: {e}") # noqa: print diff --git a/autobot-backend/phase_progression_manager.py b/autobot-backend/phase_progression_manager.py index fb1e0ff40..c0e7bf06b 100644 --- a/autobot-backend/phase_progression_manager.py +++ b/autobot-backend/phase_progression_manager.py @@ -632,9 +632,9 @@ async def _attempt_phase_progression( rules = self.progression_rules.get(phase_name, {}) prerequisites_met, _ = await self._validate_prerequisites(rules) if not prerequisites_met: - progression_result[ - "reason" - ] = f"Prerequisites not met: {rules.get('prerequisites', [])}" + progression_result["reason"] = ( + f"Prerequisites not met: {rules.get('prerequisites', [])}" + ) return progression_result if await self._create_phase_infrastructure(phase_name, rules): diff --git a/autobot-backend/planner/types.py b/autobot-backend/planner/types.py index 4878a2980..6d9e62881 100644 --- a/autobot-backend/planner/types.py +++ b/autobot-backend/planner/types.py @@ -81,9 +81,9 @@ def to_dict(self) -> dict: "depends_on": self.depends_on, "blocks": self.blocks, "started_at": self.started_at.isoformat() if self.started_at else None, - "completed_at": self.completed_at.isoformat() - if self.completed_at - else None, + "completed_at": ( + self.completed_at.isoformat() if self.completed_at else None + ), "reflection": self.reflection, "tools_used": self.tools_used, "action_event_ids": self.action_event_ids, @@ -261,9 +261,9 @@ def to_dict(self) -> dict: "current_step_number": self.current_step_number, "created_at": self.created_at.isoformat(), "started_at": self.started_at.isoformat() if self.started_at else None, - "completed_at": self.completed_at.isoformat() - if self.completed_at - else None, + "completed_at": ( + self.completed_at.isoformat() if self.completed_at else None + ), "version": self.version, "update_history": self.update_history, "total_steps": self.total_steps, diff --git a/autobot-backend/project_state_manager.py b/autobot-backend/project_state_manager.py index d9776bf1c..685414d8d 100644 --- a/autobot-backend/project_state_manager.py +++ b/autobot-backend/project_state_manager.py @@ -127,8 +127,7 @@ def __init__(self, db_path: str = None): def _create_project_phases_table(self, cursor: sqlite3.Cursor) -> None: """Create project_phases table.""" - cursor.execute( - """ + cursor.execute(""" CREATE TABLE IF NOT EXISTS project_phases ( phase_id TEXT PRIMARY KEY, name TEXT NOT NULL, @@ -140,13 +139,11 @@ def _create_project_phases_table(self, cursor: sqlite3.Cursor) -> None: created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) - """ - ) + """) def _create_phase_capabilities_table(self, cursor: sqlite3.Cursor) -> None: """Create phase_capabilities table.""" - cursor.execute( - """ + cursor.execute(""" CREATE TABLE IF NOT EXISTS phase_capabilities ( id INTEGER PRIMARY KEY AUTOINCREMENT, phase_id TEXT NOT NULL, @@ -160,13 +157,11 @@ def _create_phase_capabilities_table(self, cursor: sqlite3.Cursor) -> None: validation_details TEXT, FOREIGN KEY (phase_id) REFERENCES project_phases (phase_id) ) - """ - ) + """) def _create_validation_results_table(self, cursor: sqlite3.Cursor) -> None: """Create validation_results table.""" - cursor.execute( - """ + cursor.execute(""" CREATE TABLE IF NOT EXISTS validation_results ( id INTEGER PRIMARY KEY AUTOINCREMENT, phase_id TEXT NOT NULL, @@ -178,20 +173,17 @@ def _create_validation_results_table(self, cursor: sqlite3.Cursor) -> None: timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (phase_id) REFERENCES project_phases (phase_id) ) - """ - ) + """) def _create_project_state_table(self, cursor: sqlite3.Cursor) -> None: """Create project_state table.""" - cursor.execute( - """ + cursor.execute(""" CREATE TABLE IF NOT EXISTS project_state ( key TEXT PRIMARY KEY, value TEXT NOT NULL, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) - """ - ) + """) def _init_database(self): """Initialize SQLite database for state tracking""" diff --git a/autobot-backend/project_state_tracking/reports.py b/autobot-backend/project_state_tracking/reports.py index b93c66a20..f62eea2eb 100644 --- a/autobot-backend/project_state_tracking/reports.py +++ b/autobot-backend/project_state_tracking/reports.py @@ -177,9 +177,7 @@ def build_phase_status_section(summary: Dict[str, Any]) -> List[str]: status_icon = ( "āœ…" if phase_data["completion_percentage"] >= 95 - else "šŸ”„" - if phase_data["completion_percentage"] >= 50 - else "ā³" + else "šŸ”„" if phase_data["completion_percentage"] >= 50 else "ā³" ) lines.append( f"- {status_icon} **{phase_name}**: " @@ -244,9 +242,7 @@ def calculate_trends( trend = ( "increasing" if last_value > first_value - else "decreasing" - if last_value < first_value - else "stable" + else "decreasing" if last_value < first_value else "stable" ) trends[metric.value] = { "current": last_value, diff --git a/autobot-backend/project_state_tracking/tracker.py b/autobot-backend/project_state_tracking/tracker.py index 32fab8d96..7be9265ee 100644 --- a/autobot-backend/project_state_tracking/tracker.py +++ b/autobot-backend/project_state_tracking/tracker.py @@ -572,9 +572,9 @@ async def export_state_data(self, output_path: str, format: str = "json"): summary, output_path, format, - report_generator=self.generate_state_report - if format == "markdown" - else None, + report_generator=( + self.generate_state_report if format == "markdown" else None + ), ) diff --git a/autobot-backend/secure_sandbox_executor.py b/autobot-backend/secure_sandbox_executor.py index 286e550ca..0f63facc2 100644 --- a/autobot-backend/secure_sandbox_executor.py +++ b/autobot-backend/secure_sandbox_executor.py @@ -19,9 +19,9 @@ from enum import Enum from typing import Any, Dict, List, Optional, Tuple, Union -import docker from docker.errors import DockerException, ImageNotFound +import docker from autobot_shared.redis_client import get_redis_client logger = logging.getLogger(__name__) diff --git a/autobot-backend/security/config_security_test.py b/autobot-backend/security/config_security_test.py index fb35ebf79..c198e3e12 100644 --- a/autobot-backend/security/config_security_test.py +++ b/autobot-backend/security/config_security_test.py @@ -156,12 +156,10 @@ def test_config_file_permissions_handling(self): # Create a config file with restricted permissions with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: - f.write( - """ + f.write(""" llm: orchestrator_llm: "test_model" -""" - ) +""") restricted_file = f.name try: diff --git a/autobot-backend/security/enterprise/security_policy_manager.py b/autobot-backend/security/enterprise/security_policy_manager.py index a4226c9f7..c1f4c2e87 100644 --- a/autobot-backend/security/enterprise/security_policy_manager.py +++ b/autobot-backend/security/enterprise/security_policy_manager.py @@ -924,9 +924,9 @@ def _calculate_policy_coverage(self, framework_mappings: Dict) -> Dict[str, Dict "required_controls": controls, "active_policies": len(active_policies), "policy_names": [p.name for p in active_policies], - "coverage_percentage": len(active_policies) / len(controls) * 100 - if controls - else 100, + "coverage_percentage": ( + len(active_policies) / len(controls) * 100 if controls else 100 + ), } return coverage diff --git a/autobot-backend/security/enterprise/threat_detection/models.py b/autobot-backend/security/enterprise/threat_detection/models.py index c183f969b..8ccf20609 100644 --- a/autobot-backend/security/enterprise/threat_detection/models.py +++ b/autobot-backend/security/enterprise/threat_detection/models.py @@ -382,9 +382,7 @@ def get_risk_assessment(self, event_history: EventHistory) -> Dict: "risk_level": ( "high" if self.risk_score > 0.7 - else "medium" - if self.risk_score > 0.4 - else "low" + else "medium" if self.risk_score > 0.4 else "low" ), "profile_age_days": (datetime.utcnow() - self.last_updated).days, "total_actions": sum(self.baseline_actions.values()), diff --git a/autobot-backend/security/input_validator_test.py b/autobot-backend/security/input_validator_test.py index a2a4912fa..bae73237c 100644 --- a/autobot-backend/security/input_validator_test.py +++ b/autobot-backend/security/input_validator_test.py @@ -3,7 +3,6 @@ # Author: mrveiss """Tests for Input Validator - Issue #712.""" - from security.input_validator import ( WebResearchInputValidator, get_input_validator, diff --git a/autobot-backend/security/security_edge_cases_test.py b/autobot-backend/security/security_edge_cases_test.py index 1891b7381..bfaa779ff 100644 --- a/autobot-backend/security/security_edge_cases_test.py +++ b/autobot-backend/security/security_edge_cases_test.py @@ -437,8 +437,8 @@ async def test_malformed_input_handling(self): # Binary data b"\x00\x01\x02\xff", # Unicode edge cases - "\U0001F4A9\U0001F631\U0001F4AF", # Emojis - "\u202E" + "normal text", # Right-to-left override + "\U0001f4a9\U0001f631\U0001f4af", # Emojis + "\u202e" + "normal text", # Right-to-left override ] for malformed_input in malformed_inputs: diff --git a/autobot-backend/services/agent_terminal/models.py b/autobot-backend/services/agent_terminal/models.py index a44c158de..747f1921e 100644 --- a/autobot-backend/services/agent_terminal/models.py +++ b/autobot-backend/services/agent_terminal/models.py @@ -44,9 +44,9 @@ class AgentTerminalSession: pending_approval: Optional[Metadata] = None metadata: Metadata = field(default_factory=dict) pty_session_id: Optional[str] = None # PTY session for terminal display - running_command_task: Optional[ - asyncio.Task - ] = None # Track running command for cancellation + running_command_task: Optional[asyncio.Task] = ( + None # Track running command for cancellation + ) # === Issue #372: Feature Envy Reduction Methods === diff --git a/autobot-backend/services/gateway/types.py b/autobot-backend/services/gateway/types.py index 4df993696..e6ce53f36 100644 --- a/autobot-backend/services/gateway/types.py +++ b/autobot-backend/services/gateway/types.py @@ -107,9 +107,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "UnifiedMessage": message_type=MessageType(data["message_type"]), content=data.get("content"), metadata=data.get("metadata", {}), - created_at=datetime.fromisoformat(data["created_at"]) - if "created_at" in data - else datetime.utcnow(), + created_at=( + datetime.fromisoformat(data["created_at"]) + if "created_at" in data + else datetime.utcnow() + ), ) diff --git a/autobot-backend/services/llm_cost_tracker.py b/autobot-backend/services/llm_cost_tracker.py index eec7f673c..b69157794 100644 --- a/autobot-backend/services/llm_cost_tracker.py +++ b/autobot-backend/services/llm_cost_tracker.py @@ -931,9 +931,7 @@ async def get_cost_trends(self, days: int = 30) -> Dict[str, Any]: "trend": ( "increasing" if growth_rate > 5 - else "decreasing" - if growth_rate < -5 - else "stable" + else "decreasing" if growth_rate < -5 else "stable" ), "growth_rate_percent": round(growth_rate, 2), "avg_daily_cost": summary.get("avg_daily_cost", 0), diff --git a/autobot-backend/services/mesh_brain/edge_learner.py b/autobot-backend/services/mesh_brain/edge_learner.py index 111eb433e..4315c6720 100644 --- a/autobot-backend/services/mesh_brain/edge_learner.py +++ b/autobot-backend/services/mesh_brain/edge_learner.py @@ -15,20 +15,15 @@ class MeshDB(Protocol): """Protocol for mesh database operations required by EdgeLearner.""" - async def get_edge(self, node_a: str, node_b: str) -> dict | None: - ... + async def get_edge(self, node_a: str, node_b: str) -> dict | None: ... - async def update_edge(self, edge_id: str, **kwargs) -> None: - ... + async def update_edge(self, edge_id: str, **kwargs) -> None: ... - async def create_edge(self, from_node: str, to_node: str, **kwargs) -> None: - ... + async def create_edge(self, from_node: str, to_node: str, **kwargs) -> None: ... - async def get_co_access_count(self, node_a: str, node_b: str) -> int: - ... + async def get_co_access_count(self, node_a: str, node_b: str) -> int: ... - async def update_access_count(self, node_ids: list[str]) -> None: - ... + async def update_access_count(self, node_ids: list[str]) -> None: ... class EdgeLearner: diff --git a/autobot-backend/services/mesh_brain/edge_sync.py b/autobot-backend/services/mesh_brain/edge_sync.py index b163a7db6..daa2b0d9b 100644 --- a/autobot-backend/services/mesh_brain/edge_sync.py +++ b/autobot-backend/services/mesh_brain/edge_sync.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """PostgreSQL to Redis edge sync for Neural Mesh retrieval (#1994, #2029).""" + import logging from typing import Protocol @@ -11,8 +12,7 @@ class MeshDB(Protocol): """Protocol for mesh database operations.""" - async def fetch_edges(self, min_weight: float) -> list[dict]: - ... + async def fetch_edges(self, min_weight: float) -> list[dict]: ... class MeshEdgeSync: diff --git a/autobot-backend/services/mesh_brain/mesh_db.py b/autobot-backend/services/mesh_brain/mesh_db.py index 3836f493b..a9c1bce1e 100644 --- a/autobot-backend/services/mesh_brain/mesh_db.py +++ b/autobot-backend/services/mesh_brain/mesh_db.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Async PostgreSQL client for Neural Mesh RAG graph operations (#2055).""" + import logging from typing import Any, Optional @@ -29,13 +30,11 @@ async def create_node( raptor_level: int = 0, ) -> str: """Insert a mesh node and return its UUID string (#2055).""" - sql = text( - """ + sql = text(""" INSERT INTO mesh_nodes (chunk_id, source_file, node_type, raptor_level) VALUES (:chunk_id, :source_file, :node_type, :raptor_level) RETURNING id::text - """ - ) + """) async with self.engine.begin() as conn: row = await conn.execute( sql, @@ -54,14 +53,12 @@ async def update_access_count(self, node_ids: list[str]) -> None: """Increment access_count and set last_accessed for the given node UUIDs (#2055).""" if not node_ids: return - sql = text( - """ + sql = text(""" UPDATE mesh_nodes SET access_count = access_count + 1, last_accessed = NOW() WHERE id = ANY(:node_ids::uuid[]) - """ - ) + """) async with self.engine.begin() as conn: await conn.execute(sql, {"node_ids": node_ids}) logger.debug("Updated access_count for %d nodes", len(node_ids)) @@ -79,13 +76,11 @@ async def create_edge( origin: str, ) -> str: """Insert a mesh edge and return its UUID string (#2055).""" - sql = text( - """ + sql = text(""" INSERT INTO mesh_edges (from_node, to_node, edge_type, weight, origin) VALUES (:from_node::uuid, :to_node::uuid, :edge_type, :weight, :origin) RETURNING id::text - """ - ) + """) async with self.engine.begin() as conn: row = await conn.execute( sql, @@ -115,8 +110,7 @@ async def get_edge( ) -> Optional[dict]: """Return the first matching edge as a dict, or None if absent (#2055).""" if edge_type is not None: - sql = text( - """ + sql = text(""" SELECT id::text, from_node::text, to_node::text, edge_type, weight, origin, co_access_count, last_reinforced FROM mesh_edges @@ -124,24 +118,21 @@ async def get_edge( AND to_node = :to_node::uuid AND edge_type = :edge_type LIMIT 1 - """ - ) + """) params: dict[str, Any] = { "from_node": from_node, "to_node": to_node, "edge_type": edge_type, } else: - sql = text( - """ + sql = text(""" SELECT id::text, from_node::text, to_node::text, edge_type, weight, origin, co_access_count, last_reinforced FROM mesh_edges WHERE from_node = :from_node::uuid AND to_node = :to_node::uuid LIMIT 1 - """ - ) + """) params = {"from_node": from_node, "to_node": to_node} async with self.engine.connect() as conn: @@ -178,8 +169,7 @@ async def get_neighbors( max_hops: int = 1, ) -> list[dict]: """Return direct neighbors of node_id above min_weight (max_hops=1 only) (#2055).""" - sql = text( - """ + sql = text(""" SELECT e.id::text AS edge_id, e.to_node::text AS neighbor_id, e.edge_type, @@ -189,8 +179,7 @@ async def get_neighbors( WHERE e.from_node = :node_id::uuid AND e.weight >= :min_weight ORDER BY e.weight DESC - """ - ) + """) async with self.engine.connect() as conn: rows = await conn.execute( sql, {"node_id": node_id, "min_weight": min_weight} @@ -199,30 +188,26 @@ async def get_neighbors( async def fetch_edges(self, min_weight: float = 0.5) -> list[dict]: """Return all edges above min_weight. Satisfies MeshEdgeSync Protocol (#2029, #2055).""" - sql = text( - """ + sql = text(""" SELECT id::text, from_node::text, to_node::text, edge_type, weight, origin FROM mesh_edges WHERE weight >= :min_weight ORDER BY weight DESC - """ - ) + """) async with self.engine.connect() as conn: rows = await conn.execute(sql, {"min_weight": min_weight}) return [dict(r) for r in rows.mappings()] async def get_co_access_count(self, node_a: str, node_b: str) -> int: """Return the co_access_count for the edge between node_a and node_b (#2055).""" - sql = text( - """ + sql = text(""" SELECT COALESCE(co_access_count, 0) FROM mesh_edges WHERE from_node = :node_a::uuid AND to_node = :node_b::uuid LIMIT 1 - """ - ) + """) async with self.engine.connect() as conn: row = await conn.execute(sql, {"node_a": node_a, "node_b": node_b}) return row.scalar() or 0 @@ -240,8 +225,7 @@ async def log_evolution( actor: str, ) -> None: """Append an audit entry to mesh_evolution_log (#2055).""" - sql = text( - """ + sql = text(""" INSERT INTO mesh_evolution_log (event_type, entity_id, old_value, new_value, actor) VALUES @@ -250,8 +234,7 @@ async def log_evolution( :old_value::jsonb, :new_value::jsonb, :actor) - """ - ) + """) import json async with self.engine.begin() as conn: @@ -260,12 +243,12 @@ async def log_evolution( { "event_type": event_type, "entity_id": entity_id, - "old_value": json.dumps(old_value) - if old_value is not None - else None, - "new_value": json.dumps(new_value) - if new_value is not None - else None, + "old_value": ( + json.dumps(old_value) if old_value is not None else None + ), + "new_value": ( + json.dumps(new_value) if new_value is not None else None + ), "actor": actor, }, ) diff --git a/autobot-backend/services/mesh_brain/ppr.py b/autobot-backend/services/mesh_brain/ppr.py index b7e49ce4e..ff83b33c6 100644 --- a/autobot-backend/services/mesh_brain/ppr.py +++ b/autobot-backend/services/mesh_brain/ppr.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Personalized PageRank over the mesh graph for importance-weighted expansion (#1994, #2057).""" + import logging from typing import Protocol diff --git a/autobot-backend/services/neural_mesh_retriever.py b/autobot-backend/services/neural_mesh_retriever.py index a638d64b1..fccc7ffe4 100644 --- a/autobot-backend/services/neural_mesh_retriever.py +++ b/autobot-backend/services/neural_mesh_retriever.py @@ -9,6 +9,7 @@ COMPLEX -> full pipeline: hybrid + anchor lookup + PPR + rerank MULTI_HOP -> same as COMPLEX """ + import asyncio import logging import time diff --git a/autobot-backend/services/neural_mesh_retriever_test.py b/autobot-backend/services/neural_mesh_retriever_test.py index 3e263dd27..03c4d6be4 100644 --- a/autobot-backend/services/neural_mesh_retriever_test.py +++ b/autobot-backend/services/neural_mesh_retriever_test.py @@ -6,6 +6,7 @@ All external dependencies are replaced with AsyncMock / MagicMock so the tests run without a database, Redis, or model server. """ + from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/autobot-backend/services/nl_database_service.py b/autobot-backend/services/nl_database_service.py index 6e55da791..1802269f3 100644 --- a/autobot-backend/services/nl_database_service.py +++ b/autobot-backend/services/nl_database_service.py @@ -655,14 +655,12 @@ async def _fetch_postgresql_schema(self, db_url: str) -> str: conn = await asyncpg.connect(db_url) try: - rows = await conn.fetch( - """ + rows = await conn.fetch(""" SELECT table_name, column_name, data_type, is_nullable FROM information_schema.columns WHERE table_schema = 'public' ORDER BY table_name, ordinal_position - """ - ) + """) # Build CREATE TABLE statements from column info tables: Dict[str, List[str]] = {} for row in rows: diff --git a/autobot-backend/services/pattern_extractor_test.py b/autobot-backend/services/pattern_extractor_test.py index 63a83f916..da669afc6 100644 --- a/autobot-backend/services/pattern_extractor_test.py +++ b/autobot-backend/services/pattern_extractor_test.py @@ -27,8 +27,7 @@ def temp_codebase(): # Create sample Python file sample_py = backend / "sample.py" - sample_py.write_text( - ''' + sample_py.write_text(''' """Sample module for testing.""" import logging @@ -63,16 +62,14 @@ async def create_user(self, name: str) -> Dict: user = {"name": name} self.cache[name] = user return user -''' - ) +''') # Create sample TypeScript file frontend = base / "autobot-frontend" / "src" frontend.mkdir(parents=True) sample_ts = frontend / "composable.ts" - sample_ts.write_text( - """ + sample_ts.write_text(""" export interface User { id: number name: string @@ -90,8 +87,7 @@ async def create_user(self, name: str) -> Dict: return { users, fetchUsers } } -""" - ) +""") yield base diff --git a/autobot-backend/services/secrets_service.py b/autobot-backend/services/secrets_service.py index d8988bbd2..f021e59f3 100644 --- a/autobot-backend/services/secrets_service.py +++ b/autobot-backend/services/secrets_service.py @@ -100,8 +100,7 @@ def _init_database(self): def _create_secrets_table(self, cursor: sqlite3.Cursor): """Create the secrets table if it doesn't exist""" - cursor.execute( - """ + cursor.execute(""" CREATE TABLE IF NOT EXISTS secrets ( id TEXT PRIMARY KEY, name TEXT NOT NULL, @@ -120,8 +119,7 @@ def _create_secrets_table(self, cursor: sqlite3.Cursor): is_active BOOLEAN DEFAULT 1, UNIQUE(name, scope, chat_id) ) - """ - ) + """) def _create_secrets_indexes(self, cursor: sqlite3.Cursor): """Create indexes for the secrets table""" @@ -133,8 +131,7 @@ def _create_secrets_indexes(self, cursor: sqlite3.Cursor): def _create_audit_table(self, cursor: sqlite3.Cursor): """Create the audit log table if it doesn't exist""" - cursor.execute( - """ + cursor.execute(""" CREATE TABLE IF NOT EXISTS secrets_audit ( id TEXT PRIMARY KEY, secret_id TEXT NOT NULL, @@ -144,8 +141,7 @@ def _create_audit_table(self, cursor: sqlite3.Cursor): details TEXT, FOREIGN KEY (secret_id) REFERENCES secrets(id) ) - """ - ) + """) def _encrypt_value(self, value: str) -> str: """Encrypt a secret value""" diff --git a/autobot-backend/services/temporal_invalidation_service.py b/autobot-backend/services/temporal_invalidation_service.py index 435e5ad96..8edef74a5 100644 --- a/autobot-backend/services/temporal_invalidation_service.py +++ b/autobot-backend/services/temporal_invalidation_service.py @@ -15,12 +15,12 @@ from enum import Enum from typing import Any, Dict, List, Optional, Tuple +from config import config_manager from models.atomic_fact import AtomicFact, FactType, TemporalType from services.fact_extraction_service import FactExtractionService from autobot_shared.logging_manager import get_llm_logger from autobot_shared.redis_client import get_redis_client -from config import config_manager logger = get_llm_logger("temporal_invalidation") diff --git a/autobot-backend/services/wake_word_service.py b/autobot-backend/services/wake_word_service.py index e955422b5..023abc167 100644 --- a/autobot-backend/services/wake_word_service.py +++ b/autobot-backend/services/wake_word_service.py @@ -138,9 +138,9 @@ def __init__(self, config: Optional[WakeWordConfig] = None): # Initialize adaptive thresholds for wake_word in self.config.wake_words: - self._adaptive_thresholds[ - wake_word.lower() - ] = self.config.confidence_threshold + self._adaptive_thresholds[wake_word.lower()] = ( + self.config.confidence_threshold + ) logger.info( "WakeWordDetector initialized with %d wake words", @@ -153,9 +153,9 @@ def add_wake_word(self, wake_word: str) -> bool: wake_word_lower = wake_word.lower().strip() if wake_word_lower not in {w.lower() for w in self.config.wake_words}: self.config.wake_words.append(wake_word_lower) - self._adaptive_thresholds[ - wake_word_lower - ] = self.config.confidence_threshold + self._adaptive_thresholds[wake_word_lower] = ( + self.config.confidence_threshold + ) logger.info("Added wake word: %s", wake_word) return True return False @@ -492,9 +492,9 @@ def update_config(self, updates: Metadata) -> None: if "wake_words" in updates: for wake_word in self.config.wake_words: if wake_word.lower() not in self._adaptive_thresholds: - self._adaptive_thresholds[ - wake_word.lower() - ] = self.config.confidence_threshold + self._adaptive_thresholds[wake_word.lower()] = ( + self.config.confidence_threshold + ) def enable(self) -> None: """Enable wake word detection""" diff --git a/autobot-backend/services/workflow_automation/models.py b/autobot-backend/services/workflow_automation/models.py index ef48fc8a7..48932888c 100644 --- a/autobot-backend/services/workflow_automation/models.py +++ b/autobot-backend/services/workflow_automation/models.py @@ -148,9 +148,9 @@ def to_status_dict(self) -> Metadata: "status": self.status.value, "requires_confirmation": self.requires_confirmation, "started_at": self.started_at.isoformat() if self.started_at else None, - "completed_at": self.completed_at.isoformat() - if self.completed_at - else None, + "completed_at": ( + self.completed_at.isoformat() if self.completed_at else None + ), } @@ -202,9 +202,9 @@ def to_status_dict(self) -> Metadata: "active_service": self.active_service, "created_at": self.created_at.isoformat() if self.created_at else None, "started_at": self.started_at.isoformat() if self.started_at else None, - "completed_at": self.completed_at.isoformat() - if self.completed_at - else None, + "completed_at": ( + self.completed_at.isoformat() if self.completed_at else None + ), "steps": [step.to_status_dict() for step in self.steps], "user_interventions": self.user_interventions, } diff --git a/autobot-backend/skills/builtin/autonomous_skill_development.py b/autobot-backend/skills/builtin/autonomous_skill_development.py index 767c181b9..411b925fe 100644 --- a/autobot-backend/skills/builtin/autonomous_skill_development.py +++ b/autobot-backend/skills/builtin/autonomous_skill_development.py @@ -12,6 +12,7 @@ SEMI_AUTO — gap detected → generate → create pending approval → notify admin LOCKED — gap is logged only, no generation """ + import logging from typing import Any, Dict diff --git a/autobot-backend/skills/builtin/autonomous_skill_development_test.py b/autobot-backend/skills/builtin/autonomous_skill_development_test.py index bf3f33acc..ef470e536 100644 --- a/autobot-backend/skills/builtin/autonomous_skill_development_test.py +++ b/autobot-backend/skills/builtin/autonomous_skill_development_test.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Tests for the Autonomous Skill Development builtin skill (Issue #951).""" + from unittest.mock import AsyncMock, patch import pytest diff --git a/autobot-backend/skills/builtin/community_growth.py b/autobot-backend/skills/builtin/community_growth.py index 072e8859e..bd34e0f91 100644 --- a/autobot-backend/skills/builtin/community_growth.py +++ b/autobot-backend/skills/builtin/community_growth.py @@ -195,9 +195,9 @@ def _sync_search() -> List[Dict[str, Any]]: "url": f"https://reddit.com{post.permalink}", "subreddit": sub_name, "score": post.score, - "body_snippet": post.selftext[:200] - if post.selftext - else "", + "body_snippet": ( + post.selftext[:200] if post.selftext else "" + ), } ) return results diff --git a/autobot-backend/skills/db.py b/autobot-backend/skills/db.py index ad0cd1028..ce11b3185 100644 --- a/autobot-backend/skills/db.py +++ b/autobot-backend/skills/db.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Skills DB engine — uses autobot_data.db (same as main backend).""" + import os import threading diff --git a/autobot-backend/skills/gap_detector.py b/autobot-backend/skills/gap_detector.py index 35a08d69a..e3121d7fd 100644 --- a/autobot-backend/skills/gap_detector.py +++ b/autobot-backend/skills/gap_detector.py @@ -7,6 +7,7 @@ Identifies when AutoBot lacks a capability by monitoring agent outputs and failed tool calls. """ + import logging import re from dataclasses import dataclass diff --git a/autobot-backend/skills/gap_detector_test.py b/autobot-backend/skills/gap_detector_test.py index de96f5de2..9166c99f2 100644 --- a/autobot-backend/skills/gap_detector_test.py +++ b/autobot-backend/skills/gap_detector_test.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Tests for the Skill Gap Detector (Phase 4).""" + from skills.gap_detector import GapTrigger, SkillGapDetector diff --git a/autobot-backend/skills/generator.py b/autobot-backend/skills/generator.py index cf8cc62e1..b50fe9cfb 100644 --- a/autobot-backend/skills/generator.py +++ b/autobot-backend/skills/generator.py @@ -7,6 +7,7 @@ Uses the LLM to generate SKILL.md + skill.py for a detected capability gap. Structured output ensures valid manifests every time. """ + import logging import re from typing import Any, Dict diff --git a/autobot-backend/skills/generator_test.py b/autobot-backend/skills/generator_test.py index 6d3a2ad72..a91353ec7 100644 --- a/autobot-backend/skills/generator_test.py +++ b/autobot-backend/skills/generator_test.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Tests for Skill Generator and Validator (Phase 5).""" + from unittest.mock import AsyncMock import pytest diff --git a/autobot-backend/skills/governance.py b/autobot-backend/skills/governance.py index ca48258ee..7d9a555bf 100644 --- a/autobot-backend/skills/governance.py +++ b/autobot-backend/skills/governance.py @@ -7,6 +7,7 @@ Enforces FULL_AUTO / SEMI_AUTO / LOCKED modes for skill activation. Creates approval records and notifies SLM admin via Redis pub/sub. """ + import json import logging import uuid diff --git a/autobot-backend/skills/governance_test.py b/autobot-backend/skills/governance_test.py index 3dfd9afee..5c1fb7161 100644 --- a/autobot-backend/skills/governance_test.py +++ b/autobot-backend/skills/governance_test.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Tests for the Governance Engine and Skill Promoter (Phase 6 / Issue #951).""" + import os import tempfile from unittest.mock import AsyncMock, patch diff --git a/autobot-backend/skills/mcp_process.py b/autobot-backend/skills/mcp_process.py index 59e465a06..5c60a9035 100644 --- a/autobot-backend/skills/mcp_process.py +++ b/autobot-backend/skills/mcp_process.py @@ -7,6 +7,7 @@ Manages skill.py MCP server subprocesses. Each active skill runs as a persistent subprocess communicating via stdin/stdout MCP protocol. """ + import asyncio import json import logging diff --git a/autobot-backend/skills/mcp_process_test.py b/autobot-backend/skills/mcp_process_test.py index b849e44de..9ce1a2143 100644 --- a/autobot-backend/skills/mcp_process_test.py +++ b/autobot-backend/skills/mcp_process_test.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Tests for MCPProcessManager.""" + import pytest from skills.mcp_process import MCPProcessManager, get_mcp_manager diff --git a/autobot-backend/skills/models.py b/autobot-backend/skills/models.py index d1a6f9a16..6ddf12627 100644 --- a/autobot-backend/skills/models.py +++ b/autobot-backend/skills/models.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Skills System DB Models""" + import uuid from datetime import datetime, timezone from enum import Enum diff --git a/autobot-backend/skills/models_test.py b/autobot-backend/skills/models_test.py index 5aad0fef4..4ae0c06f4 100644 --- a/autobot-backend/skills/models_test.py +++ b/autobot-backend/skills/models_test.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Unit tests for Skills System DB models.""" + from skills.models import ( GovernanceConfig, GovernanceMode, diff --git a/autobot-backend/skills/promoter.py b/autobot-backend/skills/promoter.py index 33af19eed..1ed25102a 100644 --- a/autobot-backend/skills/promoter.py +++ b/autobot-backend/skills/promoter.py @@ -7,6 +7,7 @@ Writes an approved draft skill to autobot-backend/skills/builtin/ and optionally commits it to git. """ + import asyncio import logging import os diff --git a/autobot-backend/skills/sync/__init__.py b/autobot-backend/skills/sync/__init__.py index 6e554c25a..7df8dd47f 100644 --- a/autobot-backend/skills/sync/__init__.py +++ b/autobot-backend/skills/sync/__init__.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Skill repository sync implementations (Phase 3).""" + from skills.sync.git_sync import GitRepoSync from skills.sync.local_sync import LocalDirSync from skills.sync.mcp_sync import MCPClientSync diff --git a/autobot-backend/skills/sync/base_sync.py b/autobot-backend/skills/sync/base_sync.py index e295bf99c..20a2bc779 100644 --- a/autobot-backend/skills/sync/base_sync.py +++ b/autobot-backend/skills/sync/base_sync.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Base sync interface for skill repositories (Phase 3).""" + import re from abc import ABC, abstractmethod from typing import Any, Dict, List diff --git a/autobot-backend/skills/sync/git_sync.py b/autobot-backend/skills/sync/git_sync.py index e474c955a..e641cb9d5 100644 --- a/autobot-backend/skills/sync/git_sync.py +++ b/autobot-backend/skills/sync/git_sync.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Git repository skill sync (Phase 3).""" + import asyncio import logging import os diff --git a/autobot-backend/skills/sync/local_sync.py b/autobot-backend/skills/sync/local_sync.py index 08ee8c66a..a5711eff7 100644 --- a/autobot-backend/skills/sync/local_sync.py +++ b/autobot-backend/skills/sync/local_sync.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Local directory skill repo sync (Phase 3).""" + import logging import os from typing import Any, Dict, List, Optional diff --git a/autobot-backend/skills/sync/mcp_sync.py b/autobot-backend/skills/sync/mcp_sync.py index 77a4f8e9e..8a4d09c4a 100644 --- a/autobot-backend/skills/sync/mcp_sync.py +++ b/autobot-backend/skills/sync/mcp_sync.py @@ -6,6 +6,7 @@ Connects to a remote MCP HTTP server, lists its tools, and wraps each as a local skill package. """ + import asyncio import logging from typing import Any, Dict, List diff --git a/autobot-backend/skills/sync/sync_test.py b/autobot-backend/skills/sync/sync_test.py index d051842e2..db71ffca9 100644 --- a/autobot-backend/skills/sync/sync_test.py +++ b/autobot-backend/skills/sync/sync_test.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Tests for the skill repo sync engine (Phase 3).""" + import os import tempfile import textwrap @@ -10,8 +11,7 @@ from skills.models import SkillState from skills.sync.local_sync import LocalDirSync -SAMPLE_SKILL_MD = textwrap.dedent( - """\ +SAMPLE_SKILL_MD = textwrap.dedent("""\ --- name: sample-skill version: 1.0.0 @@ -20,8 +20,7 @@ --- # Sample Skill Do a thing. -""" -) +""") SAMPLE_SKILL_PY = "# skill.py placeholder" diff --git a/autobot-backend/skills/validator.py b/autobot-backend/skills/validator.py index 873c7d51b..f9e3e8c0f 100644 --- a/autobot-backend/skills/validator.py +++ b/autobot-backend/skills/validator.py @@ -7,6 +7,7 @@ Validates a generated skill package before storing as a draft. Checks: SKILL.md frontmatter, Python syntax, MCP server starts. """ + import ast import logging import re diff --git a/autobot-backend/takeover_manager.e2e_test.py b/autobot-backend/takeover_manager.e2e_test.py index be3ddc8ef..423d72f5d 100644 --- a/autobot-backend/takeover_manager.e2e_test.py +++ b/autobot-backend/takeover_manager.e2e_test.py @@ -598,9 +598,7 @@ async def print_test_summary(self): status_icon = ( "āœ…" if test_result["status"] == "PASSED" - else "āŒ" - if test_result["status"] == "FAILED" - else "ā“" + else "āŒ" if test_result["status"] == "FAILED" else "ā“" ) logger.info(f" {status_icon} {feature}") @@ -681,7 +679,9 @@ async def run_demo_workflow(): logger.info( "šŸ“‹ Workflow includes 5 steps with confirmation points for system modifications" ) - logger.info("šŸŽÆ This demonstrates the complete session takeover system capabilities") + logger.info( + "šŸŽÆ This demonstrates the complete session takeover system capabilities" + ) # Get workflow status status = demo_manager.get_workflow_status(workflow_id) diff --git a/autobot-backend/tests/llm_interface_pkg/test_hardware.py b/autobot-backend/tests/llm_interface_pkg/test_hardware.py index 280ce39e4..fede6fcc2 100644 --- a/autobot-backend/tests/llm_interface_pkg/test_hardware.py +++ b/autobot-backend/tests/llm_interface_pkg/test_hardware.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Tests for hardware detection. Issue #1950.""" + from unittest.mock import patch from llm_interface_pkg.hardware import HardwareDetector diff --git a/autobot-backend/tests/utils/model_optimization/test_memory_estimation.py b/autobot-backend/tests/utils/model_optimization/test_memory_estimation.py index 5de03706e..8deaed90c 100644 --- a/autobot-backend/tests/utils/model_optimization/test_memory_estimation.py +++ b/autobot-backend/tests/utils/model_optimization/test_memory_estimation.py @@ -8,6 +8,7 @@ - _parse_parameter_billions() for all documented string formats - ModelInfo.fits_resource_constraints() with SystemResources and dict resources """ + import pytest from utils.model_optimization.types import ( ModelInfo, diff --git a/autobot-backend/tests/utils/model_optimization/test_vram_estimation.py b/autobot-backend/tests/utils/model_optimization/test_vram_estimation.py index 549c5f1e7..1d4ac1fda 100644 --- a/autobot-backend/tests/utils/model_optimization/test_vram_estimation.py +++ b/autobot-backend/tests/utils/model_optimization/test_vram_estimation.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Tests for VRAM-aware model selection. Issue #1966.""" + import pytest from utils.model_optimization.types import ( ModelInfo, diff --git a/autobot-backend/tests/utils/test_experiment_tracker.py b/autobot-backend/tests/utils/test_experiment_tracker.py index 917264eb6..b29fcb740 100644 --- a/autobot-backend/tests/utils/test_experiment_tracker.py +++ b/autobot-backend/tests/utils/test_experiment_tracker.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Tests for experiment tracking. Inspired by flash-moe results.tsv.""" + import json from unittest.mock import AsyncMock, patch diff --git a/autobot-backend/tests/utils/test_pipeline_profiler.py b/autobot-backend/tests/utils/test_pipeline_profiler.py index 4122b41f0..10df6895c 100644 --- a/autobot-backend/tests/utils/test_pipeline_profiler.py +++ b/autobot-backend/tests/utils/test_pipeline_profiler.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 mrveiss # Author: mrveiss """Tests for pipeline profiler. Inspired by flash-moe per-layer timing.""" + import asyncio import pytest diff --git a/autobot-backend/utils/background_task_manager.py b/autobot-backend/utils/background_task_manager.py index fe4c759f1..6c3893adc 100644 --- a/autobot-backend/utils/background_task_manager.py +++ b/autobot-backend/utils/background_task_manager.py @@ -276,9 +276,7 @@ async def complete_task(self, task_id: str, result: Any) -> None: task["result"] = result await self._save_to_redis(task_id) sid = (task.get("params") or {}).get("source_id", "") - await self._save_latest_result( - result, task["completed_at"], source_id=sid - ) + await self._save_latest_result(result, task["completed_at"], source_id=sid) async def _save_latest_result( self, result: Any, completed_at: str, source_id: str = "" diff --git a/autobot-backend/utils/command_utils.py b/autobot-backend/utils/command_utils.py index 0b16e5db7..0fccc089f 100644 --- a/autobot-backend/utils/command_utils.py +++ b/autobot-backend/utils/command_utils.py @@ -23,6 +23,7 @@ async for chunk in execute_shell_command_streaming("long_running_cmd"): logger.info(chunk.content) # Process each chunk """ + import asyncio import logging from asyncio import Queue as AsyncQueue diff --git a/autobot-backend/utils/config_manager_test.py b/autobot-backend/utils/config_manager_test.py index 9741b88ed..a6bd12b2d 100644 --- a/autobot-backend/utils/config_manager_test.py +++ b/autobot-backend/utils/config_manager_test.py @@ -30,8 +30,7 @@ def test_config_file_loading(self): """Test loading configuration from YAML file""" # Create temporary config file with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: - f.write( - """ + f.write(""" llm: orchestrator_llm: "custom_ollama" openai: @@ -39,8 +38,7 @@ def test_config_file_loading(self): redis: host: "test_redis" port: 9999 -""" - ) +""") config_file = f.name try: diff --git a/autobot-backend/utils/escape_character_handling_test.py b/autobot-backend/utils/escape_character_handling_test.py index 32ecc7754..3263e032c 100644 --- a/autobot-backend/utils/escape_character_handling_test.py +++ b/autobot-backend/utils/escape_character_handling_test.py @@ -74,7 +74,7 @@ def test_ansi_escape_sequences(): }, { "name": "Control characters", - "input": "Hello\x07\x08World\x7F", + "input": "Hello\x07\x08World\x7f", "expected": "HelloWorld", }, { diff --git a/autobot-backend/utils/gpu_optimization/monitoring.py b/autobot-backend/utils/gpu_optimization/monitoring.py index d22931820..ccb97d979 100644 --- a/autobot-backend/utils/gpu_optimization/monitoring.py +++ b/autobot-backend/utils/gpu_optimization/monitoring.py @@ -281,10 +281,10 @@ async def monitor_gpu_acceleration_efficiency( efficiency_report["overall_efficiency"] = _calculate_overall_efficiency( efficiency_report["efficiency_scores"] ) - efficiency_report[ - "optimization_opportunities" - ] = identify_optimization_opportunities( - gpu_metrics, capabilities, current_optimizations + efficiency_report["optimization_opportunities"] = ( + identify_optimization_opportunities( + gpu_metrics, capabilities, current_optimizations + ) ) logger.info( diff --git a/autobot-backend/utils/gpu_performance_test.py b/autobot-backend/utils/gpu_performance_test.py index 6eaf754a9..fd80e1ac5 100644 --- a/autobot-backend/utils/gpu_performance_test.py +++ b/autobot-backend/utils/gpu_performance_test.py @@ -17,8 +17,7 @@ from utils.semantic_chunker import AutoBotSemanticChunker # Sample text for performance testing -TEST_TEXT = ( - """ +TEST_TEXT = """ Artificial intelligence has revolutionized countless industries and aspects of human life. Machine learning algorithms can now process vast amounts of data with unprecedented speed and accuracy. Neural networks, inspired by the human brain, have enabled computers to recognize patterns, understand language, and make complex decisions. @@ -42,9 +41,7 @@ Future developments in quantum computing may further accelerate AI capabilities. Quantum algorithms could solve certain computational problems exponentially faster than classical computers. The intersection of quantum computing and artificial intelligence represents an exciting frontier in technology. -""" - * 3 -) # Triple the text for more substantial processing +""" * 3 # Triple the text for more substantial processing async def measure_gpu_utilization(): diff --git a/autobot-backend/utils/hardware_acceleration_manager.py b/autobot-backend/utils/hardware_acceleration_manager.py index 8f09dc9e2..c957f3459 100644 --- a/autobot-backend/utils/hardware_acceleration_manager.py +++ b/autobot-backend/utils/hardware_acceleration_manager.py @@ -6,7 +6,6 @@ Re-exports the HardwareAccelerationManager from the main hardware_acceleration module. """ - # Re-export the HardwareAccelerationManager from the main module from hardware_acceleration import HardwareAccelerationManager diff --git a/autobot-backend/utils/hardware_metrics_test.py b/autobot-backend/utils/hardware_metrics_test.py index a59baf47e..923009599 100644 --- a/autobot-backend/utils/hardware_metrics_test.py +++ b/autobot-backend/utils/hardware_metrics_test.py @@ -494,13 +494,15 @@ async def test_optimization_engine(self): "efficiency_monitoring": efficiency_success, "config_updates": config_update_success, "multimodal_optimization": optimization_success, - "optimization_result": { - "success": optimization_result.success, - "performance_improvement": optimization_result.performance_improvement, - "applied_optimizations": optimization_result.applied_optimizations, - } - if optimization_success - else None, + "optimization_result": ( + { + "success": optimization_result.success, + "performance_improvement": optimization_result.performance_improvement, + "applied_optimizations": optimization_result.applied_optimizations, + } + if optimization_success + else None + ), "success": efficiency_success and config_update_success, } @@ -634,9 +636,9 @@ async def test_configuration_management(self): self.test_results["configuration_management"] = { "gpu_config_accessible": config_accessible, "baselines_configured": baselines_configured, - "config_updates_work": update_success and change_applied - if config_accessible - else False, + "config_updates_work": ( + update_success and change_applied if config_accessible else False + ), "baseline_count": len(baselines), "success": config_accessible and baselines_configured, } @@ -670,14 +672,16 @@ async def generate_test_report(self): "total_tests": total_tests, "successful_tests": successful_tests, "failed_tests": total_tests - successful_tests, - "success_rate": round((successful_tests / total_tests) * 100, 1) - if total_tests > 0 - else 0, - "overall_status": "PASS" - if successful_tests == total_tests - else "PARTIAL" - if successful_tests > 0 - else "FAIL", + "success_rate": ( + round((successful_tests / total_tests) * 100, 1) + if total_tests > 0 + else 0 + ), + "overall_status": ( + "PASS" + if successful_tests == total_tests + else "PARTIAL" if successful_tests > 0 else "FAIL" + ), "test_results": self.test_results, "alerts_received": self.alerts_received, "system_info": { diff --git a/autobot-backend/utils/llm_config_sync.py b/autobot-backend/utils/llm_config_sync.py index 187de4200..824f27951 100644 --- a/autobot-backend/utils/llm_config_sync.py +++ b/autobot-backend/utils/llm_config_sync.py @@ -281,9 +281,9 @@ async def full_synchronization() -> Metadata: ) # Step 2: Populate available models list - results[ - "models_result" - ] = await LLMConfigurationSynchronizer.ensure_models_populated() + results["models_result"] = ( + await LLMConfigurationSynchronizer.ensure_models_populated() + ) # Determine overall status sync_ok = results["sync_result"]["status"] in [ diff --git a/autobot-backend/utils/model_optimization/model_selection.py b/autobot-backend/utils/model_optimization/model_selection.py index 54826b7c9..d42383eee 100644 --- a/autobot-backend/utils/model_optimization/model_selection.py +++ b/autobot-backend/utils/model_optimization/model_selection.py @@ -11,8 +11,13 @@ import logging from typing import List -from .types import (ModelInfo, ModelPerformanceLevel, SystemResources, - TaskComplexity, TaskRequest) +from .types import ( + ModelInfo, + ModelPerformanceLevel, + SystemResources, + TaskComplexity, + TaskRequest, +) logger = logging.getLogger(__name__) diff --git a/autobot-backend/utils/monitoring_alerts.py b/autobot-backend/utils/monitoring_alerts.py index f984ce893..c73f6d1e4 100644 --- a/autobot-backend/utils/monitoring_alerts.py +++ b/autobot-backend/utils/monitoring_alerts.py @@ -271,9 +271,9 @@ def __init__(self): self.alert_rules: Dict[str, AlertRule] = {} self.active_alerts: Dict[str, Alert] = {} self.notification_channels: Dict[str, AlertNotificationChannel] = {} - self.metric_history: Dict[ - str, List[Tuple[float, float]] - ] = {} # metric_path -> [(timestamp, value)] + self.metric_history: Dict[str, List[Tuple[float, float]]] = ( + {} + ) # metric_path -> [(timestamp, value)] self.redis_client = None self.running = False self.check_interval = 30 # seconds @@ -836,7 +836,9 @@ def acknowledge_alert(self, rule_id: str, acknowledged_by: str = "system"): f"Could not update alert acknowledgment in Redis: {e}" ) - logger.info(f"šŸ‘¤ Alert acknowledged: {alert.rule_name} by {acknowledged_by}") + logger.info( + f"šŸ‘¤ Alert acknowledged: {alert.rule_name} by {acknowledged_by}" + ) return True return False diff --git a/autobot-backend/utils/monitoring_alerts_test.py b/autobot-backend/utils/monitoring_alerts_test.py index 434b9aba3..7cbbaaaab 100644 --- a/autobot-backend/utils/monitoring_alerts_test.py +++ b/autobot-backend/utils/monitoring_alerts_test.py @@ -173,7 +173,9 @@ async def test_monitoring_alerts(): ) success = await log_channel.send_alert(test_notification_alert) - logger.info(f"šŸ“ Log channel test: {'āœ… Success' if success else 'āŒ Failed'}") + logger.info( + f"šŸ“ Log channel test: {'āœ… Success' if success else 'āŒ Failed'}" + ) recovery_success = await log_channel.send_recovery(test_notification_alert) logger.info( diff --git a/autobot-backend/utils/redis_immediate_test.py b/autobot-backend/utils/redis_immediate_test.py index ed653064e..1e20ac7a2 100644 --- a/autobot-backend/utils/redis_immediate_test.py +++ b/autobot-backend/utils/redis_immediate_test.py @@ -326,5 +326,7 @@ async def test_redis_connection_immediate( ) return None except Exception as e: - logger.error(f"āŒ Redis connection test error for database {database}: {str(e)}") + logger.error( + f"āŒ Redis connection test error for database {database}: {str(e)}" + ) return None diff --git a/autobot-backend/utils/request_batcher.py b/autobot-backend/utils/request_batcher.py index 465759550..b638553bf 100644 --- a/autobot-backend/utils/request_batcher.py +++ b/autobot-backend/utils/request_batcher.py @@ -669,9 +669,9 @@ def _parse_batch_response( # Look for request ID in response if request.id in response: # Extract relevant portion (simplified) - individual_responses[ - request.id - ] = f"Response for {request.id}: {response[:200]}..." + individual_responses[request.id] = ( + f"Response for {request.id}: {response[:200]}..." + ) else: individual_responses[request.id] = response diff --git a/autobot-backend/utils/resource_factory.py b/autobot-backend/utils/resource_factory.py index 8dda3edf8..646b3669e 100644 --- a/autobot-backend/utils/resource_factory.py +++ b/autobot-backend/utils/resource_factory.py @@ -126,7 +126,6 @@ async def get_chat_history_manager(request: Request = None): # Fallback to module-level import and creation from chat_history import ChatHistoryManager - from config import config as global_config_manager logger.info( diff --git a/autobot-backend/utils/system_metrics.py b/autobot-backend/utils/system_metrics.py index 068907817..6cae83b82 100644 --- a/autobot-backend/utils/system_metrics.py +++ b/autobot-backend/utils/system_metrics.py @@ -543,9 +543,7 @@ async def get_metric_summary(self) -> Dict[str, Any]: "status": ( "healthy" if overall_health > 0.8 - else "degraded" - if overall_health > 0.5 - else "critical" + else "degraded" if overall_health > 0.5 else "critical" ), } diff --git a/autobot-backend/utils/websocket_heartbeat.py b/autobot-backend/utils/websocket_heartbeat.py index c503737f1..a0bf1a3ae 100644 --- a/autobot-backend/utils/websocket_heartbeat.py +++ b/autobot-backend/utils/websocket_heartbeat.py @@ -149,9 +149,9 @@ async def _check_connection_health(self, connection_id: str, current_time: float else: # Reset state and try again async with self._lock: - self.connection_states[ - connection_id - ] = ConnectionState.CONNECTED + self.connection_states[connection_id] = ( + ConnectionState.CONNECTED + ) async def _send_heartbeat( self, connection_id: str, websocket: WebSocket, current_time: float diff --git a/autobot-backend/workflow_scheduler.e2e_test.py b/autobot-backend/workflow_scheduler.e2e_test.py index 9aba589e0..527cb0a77 100644 --- a/autobot-backend/workflow_scheduler.e2e_test.py +++ b/autobot-backend/workflow_scheduler.e2e_test.py @@ -220,7 +220,9 @@ async def test_queue_operations(): # Test set max concurrent workflow_scheduler.queue.set_max_concurrent(5) updated_status = workflow_scheduler.queue.get_queue_status() - print(f"āœ… Max concurrent set to: {updated_status['max_concurrent']}") # noqa: print + print( + f"āœ… Max concurrent set to: {updated_status['max_concurrent']}" + ) # noqa: print # Test 3: List queued and running workflows print("\nšŸ“ Test 3: List Queue Contents...") # noqa: print diff --git a/autobot-infrastructure/shared/scripts/hooks/pre-commit-function-length b/autobot-infrastructure/shared/scripts/hooks/pre-commit-function-length index ce6f7b726..f7cfcc0b4 100644 --- a/autobot-infrastructure/shared/scripts/hooks/pre-commit-function-length +++ b/autobot-infrastructure/shared/scripts/hooks/pre-commit-function-length @@ -52,7 +52,8 @@ get_staged_files() { grep -E '\.py$' | \ grep -v -E '(__pycache__|node_modules|\.venv|venv|archive|temp)' | \ grep -v -E '(test_|_test\.py|tests/)' | \ - grep -v -E '__init__\.py$' || true + grep -v -E '__init__\.py$' | \ + grep -v -E '(migrations/)' || true } main() { diff --git a/autobot-infrastructure/shared/scripts/hooks/pre-commit-no-print-console b/autobot-infrastructure/shared/scripts/hooks/pre-commit-no-print-console index 99a764364..bdbcbe020 100755 --- a/autobot-infrastructure/shared/scripts/hooks/pre-commit-no-print-console +++ b/autobot-infrastructure/shared/scripts/hooks/pre-commit-no-print-console @@ -39,7 +39,8 @@ get_staged_python_files() { grep -v -E '(_test\.py$|\.e2e_test\.py$|\.integration_test\.py$|\.performance_test\.py$)' | \ grep -v -E '(conftest\.py$|test_.*\.py$)' | \ grep -v -E '(autobot-infrastructure/)' | \ - grep -v -E '(code_analysis/)' || true # code_analysis tools use print() for CLI output + grep -v -E '(code_analysis/)' | \ + grep -v -E '(ansible/)' || true # code_analysis: CLI output; ansible: deployed copies with doctest examples } # Get staged TypeScript/Vue files (production code only) diff --git a/autobot-slm-backend/ansible/autobot@172.16.168.19/http_client.py b/autobot-slm-backend/ansible/autobot@172.16.168.19/http_client.py index abbebb220..f9889905d 100644 --- a/autobot-slm-backend/ansible/autobot@172.16.168.19/http_client.py +++ b/autobot-slm-backend/ansible/autobot@172.16.168.19/http_client.py @@ -13,7 +13,6 @@ import aiohttp from aiohttp import ClientSession, ClientTimeout, TCPConnector - from backend.constants.threshold_constants import TimingConstants logger = logging.getLogger(__name__) diff --git a/autobot-slm-backend/ansible/autobot@172.16.168.19/redis_client.py b/autobot-slm-backend/ansible/autobot@172.16.168.19/redis_client.py index 10ead426d..703d79a28 100644 --- a/autobot-slm-backend/ansible/autobot@172.16.168.19/redis_client.py +++ b/autobot-slm-backend/ansible/autobot@172.16.168.19/redis_client.py @@ -85,7 +85,6 @@ import redis import redis.asyncio as async_redis - from backend.utils.redis_management.config import ( PoolConfig, RedisConfig, diff --git a/autobot-slm-backend/ansible/autobot@172.16.168.20/http_client.py b/autobot-slm-backend/ansible/autobot@172.16.168.20/http_client.py index abbebb220..f9889905d 100644 --- a/autobot-slm-backend/ansible/autobot@172.16.168.20/http_client.py +++ b/autobot-slm-backend/ansible/autobot@172.16.168.20/http_client.py @@ -13,7 +13,6 @@ import aiohttp from aiohttp import ClientSession, ClientTimeout, TCPConnector - from backend.constants.threshold_constants import TimingConstants logger = logging.getLogger(__name__) diff --git a/autobot-slm-backend/ansible/autobot@172.16.168.20/redis_client.py b/autobot-slm-backend/ansible/autobot@172.16.168.20/redis_client.py index 10ead426d..703d79a28 100644 --- a/autobot-slm-backend/ansible/autobot@172.16.168.20/redis_client.py +++ b/autobot-slm-backend/ansible/autobot@172.16.168.20/redis_client.py @@ -85,7 +85,6 @@ import redis import redis.asyncio as async_redis - from backend.utils.redis_management.config import ( PoolConfig, RedisConfig, diff --git a/autobot-slm-backend/ansible/autobot@172.16.168.21/http_client.py b/autobot-slm-backend/ansible/autobot@172.16.168.21/http_client.py index abbebb220..f9889905d 100644 --- a/autobot-slm-backend/ansible/autobot@172.16.168.21/http_client.py +++ b/autobot-slm-backend/ansible/autobot@172.16.168.21/http_client.py @@ -13,7 +13,6 @@ import aiohttp from aiohttp import ClientSession, ClientTimeout, TCPConnector - from backend.constants.threshold_constants import TimingConstants logger = logging.getLogger(__name__) diff --git a/autobot-slm-backend/ansible/autobot@172.16.168.21/redis_client.py b/autobot-slm-backend/ansible/autobot@172.16.168.21/redis_client.py index 10ead426d..703d79a28 100644 --- a/autobot-slm-backend/ansible/autobot@172.16.168.21/redis_client.py +++ b/autobot-slm-backend/ansible/autobot@172.16.168.21/redis_client.py @@ -85,7 +85,6 @@ import redis import redis.asyncio as async_redis - from backend.utils.redis_management.config import ( PoolConfig, RedisConfig, diff --git a/autobot-slm-backend/ansible/autobot@172.16.168.22/http_client.py b/autobot-slm-backend/ansible/autobot@172.16.168.22/http_client.py index abbebb220..f9889905d 100644 --- a/autobot-slm-backend/ansible/autobot@172.16.168.22/http_client.py +++ b/autobot-slm-backend/ansible/autobot@172.16.168.22/http_client.py @@ -13,7 +13,6 @@ import aiohttp from aiohttp import ClientSession, ClientTimeout, TCPConnector - from backend.constants.threshold_constants import TimingConstants logger = logging.getLogger(__name__) diff --git a/autobot-slm-backend/ansible/autobot@172.16.168.22/redis_client.py b/autobot-slm-backend/ansible/autobot@172.16.168.22/redis_client.py index 10ead426d..703d79a28 100644 --- a/autobot-slm-backend/ansible/autobot@172.16.168.22/redis_client.py +++ b/autobot-slm-backend/ansible/autobot@172.16.168.22/redis_client.py @@ -85,7 +85,6 @@ import redis import redis.asyncio as async_redis - from backend.utils.redis_management.config import ( PoolConfig, RedisConfig, diff --git a/autobot-slm-backend/ansible/autobot@172.16.168.23/http_client.py b/autobot-slm-backend/ansible/autobot@172.16.168.23/http_client.py index abbebb220..f9889905d 100644 --- a/autobot-slm-backend/ansible/autobot@172.16.168.23/http_client.py +++ b/autobot-slm-backend/ansible/autobot@172.16.168.23/http_client.py @@ -13,7 +13,6 @@ import aiohttp from aiohttp import ClientSession, ClientTimeout, TCPConnector - from backend.constants.threshold_constants import TimingConstants logger = logging.getLogger(__name__) diff --git a/autobot-slm-backend/ansible/autobot@172.16.168.23/redis_client.py b/autobot-slm-backend/ansible/autobot@172.16.168.23/redis_client.py index 10ead426d..703d79a28 100644 --- a/autobot-slm-backend/ansible/autobot@172.16.168.23/redis_client.py +++ b/autobot-slm-backend/ansible/autobot@172.16.168.23/redis_client.py @@ -85,7 +85,6 @@ import redis import redis.asyncio as async_redis - from backend.utils.redis_management.config import ( PoolConfig, RedisConfig, diff --git a/autobot-slm-backend/ansible/autobot@172.16.168.24/http_client.py b/autobot-slm-backend/ansible/autobot@172.16.168.24/http_client.py index abbebb220..f9889905d 100644 --- a/autobot-slm-backend/ansible/autobot@172.16.168.24/http_client.py +++ b/autobot-slm-backend/ansible/autobot@172.16.168.24/http_client.py @@ -13,7 +13,6 @@ import aiohttp from aiohttp import ClientSession, ClientTimeout, TCPConnector - from backend.constants.threshold_constants import TimingConstants logger = logging.getLogger(__name__) diff --git a/autobot-slm-backend/ansible/autobot@172.16.168.24/redis_client.py b/autobot-slm-backend/ansible/autobot@172.16.168.24/redis_client.py index 10ead426d..703d79a28 100644 --- a/autobot-slm-backend/ansible/autobot@172.16.168.24/redis_client.py +++ b/autobot-slm-backend/ansible/autobot@172.16.168.24/redis_client.py @@ -85,7 +85,6 @@ import redis import redis.asyncio as async_redis - from backend.utils.redis_management.config import ( PoolConfig, RedisConfig, diff --git a/autobot-slm-backend/ansible/roles/npu-worker/templates/npu-worker.py.j2 b/autobot-slm-backend/ansible/roles/npu-worker/templates/npu-worker.py.j2 index 1551106a1..9ce487674 100644 --- a/autobot-slm-backend/ansible/roles/npu-worker/templates/npu-worker.py.j2 +++ b/autobot-slm-backend/ansible/roles/npu-worker/templates/npu-worker.py.j2 @@ -10,7 +10,7 @@ Handles model inference requests using OpenVINO. import logging import os from pathlib import Path -from typing import Dict, Any +from typing import Any, Dict import uvicorn from fastapi import FastAPI diff --git a/autobot-slm-backend/ansible/roles/slm_agent/files/slm/agent/agent.py b/autobot-slm-backend/ansible/roles/slm_agent/files/slm/agent/agent.py index ed6f36e31..3071dd95d 100644 --- a/autobot-slm-backend/ansible/roles/slm_agent/files/slm/agent/agent.py +++ b/autobot-slm-backend/ansible/roles/slm_agent/files/slm/agent/agent.py @@ -132,8 +132,7 @@ def _init_buffer_db(self): """Initialize SQLite buffer database.""" Path(self.buffer_db).parent.mkdir(parents=True, exist_ok=True) conn = sqlite3.connect(self.buffer_db) - conn.execute( - """ + conn.execute(""" CREATE TABLE IF NOT EXISTS event_buffer ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp TEXT NOT NULL, @@ -141,8 +140,7 @@ def _init_buffer_db(self): data TEXT NOT NULL, synced INTEGER DEFAULT 0 ) - """ - ) + """) conn.commit() conn.close() logger.info("Event buffer initialized at %s", self.buffer_db) diff --git a/autobot-slm-backend/ansible/roles/slm_agent/files/slm/agent/health_collector.py b/autobot-slm-backend/ansible/roles/slm_agent/files/slm/agent/health_collector.py index 130c037c4..c0e0809ae 100644 --- a/autobot-slm-backend/ansible/roles/slm_agent/files/slm/agent/health_collector.py +++ b/autobot-slm-backend/ansible/roles/slm_agent/files/slm/agent/health_collector.py @@ -58,9 +58,9 @@ def collect(self) -> Dict: "cpu_percent": psutil.cpu_percent(interval=0.1), "memory_percent": psutil.virtual_memory().percent, "disk_percent": psutil.disk_usage("/").percent, - "load_avg": list(os.getloadavg()) - if hasattr(os, "getloadavg") - else [0.0, 0.0, 0.0], + "load_avg": ( + list(os.getloadavg()) if hasattr(os, "getloadavg") else [0.0, 0.0, 0.0] + ), "uptime_seconds": int(datetime.now().timestamp() - psutil.boot_time()), } diff --git a/autobot-slm-backend/api/config.py b/autobot-slm-backend/api/config.py index ab93449f8..7bf485b08 100644 --- a/autobot-slm-backend/api/config.py +++ b/autobot-slm-backend/api/config.py @@ -13,10 +13,6 @@ from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Query, status -from sqlalchemy import select -from sqlalchemy.ext.asyncio import AsyncSession -from typing_extensions import Annotated - from models.database import Node, NodeConfig from models.schemas import ( NodeConfigBulkResponse, @@ -25,6 +21,9 @@ ) from services.auth import get_current_user from services.database import get_db +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession +from typing_extensions import Annotated logger = logging.getLogger(__name__) diff --git a/autobot-slm-backend/api/discovery.py b/autobot-slm-backend/api/discovery.py index 905f1a3b3..d8cc7e9a3 100644 --- a/autobot-slm-backend/api/discovery.py +++ b/autobot-slm-backend/api/discovery.py @@ -10,14 +10,13 @@ import logging from fastapi import APIRouter, Depends, HTTPException, Query, status -from sqlalchemy import select -from sqlalchemy.ext.asyncio import AsyncSession -from typing_extensions import Annotated - from models.database import Node, Service, ServiceStatus from models.schemas import ServiceDiscoveryListResponse, ServiceDiscoveryResponse from services.auth import get_current_user from services.database import get_db +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession +from typing_extensions import Annotated logger = logging.getLogger(__name__) router = APIRouter(prefix="/discover", tags=["discovery"]) diff --git a/autobot-slm-backend/api/health.py b/autobot-slm-backend/api/health.py index 57e2e757a..be081ea00 100644 --- a/autobot-slm-backend/api/health.py +++ b/autobot-slm-backend/api/health.py @@ -11,14 +11,13 @@ import psutil from fastapi import APIRouter, Depends -from sqlalchemy import func, select -from sqlalchemy.ext.asyncio import AsyncSession -from typing_extensions import Annotated - from models.database import Node, NodeStatus from models.schemas import HealthResponse, SystemMetrics from services.auth import get_current_user from services.database import get_db +from sqlalchemy import func, select +from sqlalchemy.ext.asyncio import AsyncSession +from typing_extensions import Annotated logger = logging.getLogger(__name__) router = APIRouter(tags=["health"]) diff --git a/autobot-slm-backend/api/monitoring.py b/autobot-slm-backend/api/monitoring.py index 39811c16f..0d9a874e3 100644 --- a/autobot-slm-backend/api/monitoring.py +++ b/autobot-slm-backend/api/monitoring.py @@ -449,9 +449,7 @@ def _get_hostname(nodes: Dict[str, Any], node_id: str) -> str: return ( node.hostname if hasattr(node, "hostname") - else node - if isinstance(node, str) - else "unknown" + else node if isinstance(node, str) else "unknown" ) diff --git a/autobot-slm-backend/api/performance.py b/autobot-slm-backend/api/performance.py index 3064b1e7a..c52484764 100644 --- a/autobot-slm-backend/api/performance.py +++ b/autobot-slm-backend/api/performance.py @@ -431,9 +431,9 @@ async def get_performance_overview( avg_latency_ms=sum(durations) / len(durations), p95_latency_ms=_calculate_percentile(durations, 95), p99_latency_ms=_calculate_percentile(durations, 99), - throughput_rpm=len(traces) / time_span_minutes - if time_span_minutes > 0 - else 0.0, + throughput_rpm=( + len(traces) / time_span_minutes if time_span_minutes > 0 else 0.0 + ), error_rate_percent=(errors / len(traces)) * 100, total_traces=len(traces), active_slos=active_slos, @@ -723,9 +723,9 @@ async def get_node_metrics( p95_latency_ms=_calculate_percentile(durations, 95), p99_latency_ms=_calculate_percentile(durations, 99), error_rate_percent=(errors / len(traces)) * 100, - throughput_rpm=len(traces) / time_span_minutes - if time_span_minutes > 0 - else 0.0, + throughput_rpm=( + len(traces) / time_span_minutes if time_span_minutes > 0 else 0.0 + ), total_traces=len(traces), ) diff --git a/autobot-slm-backend/api/setup_wizard.py b/autobot-slm-backend/api/setup_wizard.py index cf8b1aab7..daa5ff180 100644 --- a/autobot-slm-backend/api/setup_wizard.py +++ b/autobot-slm-backend/api/setup_wizard.py @@ -281,8 +281,6 @@ async def _run_provisioning_task( node_ids: Optional[list[str]], ) -> None: """Run Ansible provisioning in background (#1384).""" - global _provision_state - _write_provision_log( f"\n{'=' * 60}\n" f"Provisioning started at {time.strftime('%Y-%m-%d %H:%M:%S')}\n" diff --git a/autobot-slm-backend/api/sso_auth.py b/autobot-slm-backend/api/sso_auth.py index f1d29cf31..c02fcfc22 100644 --- a/autobot-slm-backend/api/sso_auth.py +++ b/autobot-slm-backend/api/sso_auth.py @@ -131,9 +131,11 @@ async def oauth_callback( (), { "username": user.username, - "is_admin": user.is_platform_admin - if hasattr(user, "is_platform_admin") - else False, + "is_admin": ( + user.is_platform_admin + if hasattr(user, "is_platform_admin") + else False + ), }, )() @@ -173,9 +175,11 @@ async def ldap_login( (), { "username": user.username, - "is_admin": user.is_platform_admin - if hasattr(user, "is_platform_admin") - else False, + "is_admin": ( + user.is_platform_admin + if hasattr(user, "is_platform_admin") + else False + ), }, )() @@ -225,9 +229,11 @@ async def saml_callback( (), { "username": user.username, - "is_admin": user.is_platform_admin - if hasattr(user, "is_platform_admin") - else False, + "is_admin": ( + user.is_platform_admin + if hasattr(user, "is_platform_admin") + else False + ), }, )() diff --git a/autobot-slm-backend/migrations/add_agents.py b/autobot-slm-backend/migrations/add_agents.py index fd26bf567..b2f6323a5 100644 --- a/autobot-slm-backend/migrations/add_agents.py +++ b/autobot-slm-backend/migrations/add_agents.py @@ -31,8 +31,7 @@ def migrate(db_url: str) -> None: return # Create agents table - cursor.execute( - """ + cursor.execute(""" CREATE TABLE agents ( id SERIAL PRIMARY KEY, agent_id VARCHAR(64) UNIQUE NOT NULL, @@ -50,8 +49,7 @@ def migrate(db_url: str) -> None: created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) - """ - ) + """) logger.info("Created agents table") # Create indexes @@ -62,13 +60,11 @@ def migrate(db_url: str) -> None: logger.info("Created indexes") # Seed default agent - cursor.execute( - """ + cursor.execute(""" INSERT INTO agents (agent_id, name, description, llm_provider, llm_model, is_default) VALUES ('default', 'Default Agent', 'Fallback agent for unconfigured requests', 'ollama', 'mistral:7b-instruct', TRUE) - """ - ) + """) logger.info("Seeded default agent") conn.commit() diff --git a/autobot-slm-backend/migrations/add_events_certificates_updates_tables.py b/autobot-slm-backend/migrations/add_events_certificates_updates_tables.py index 7998463ff..91f93069b 100644 --- a/autobot-slm-backend/migrations/add_events_certificates_updates_tables.py +++ b/autobot-slm-backend/migrations/add_events_certificates_updates_tables.py @@ -28,8 +28,7 @@ def migrate(db_url: str) -> None: # Create node_events table if not table_exists(cursor, "node_events"): logger.info("Creating node_events table...") - cursor.execute( - """ + cursor.execute(""" CREATE TABLE node_events ( id SERIAL PRIMARY KEY, event_id VARCHAR(64) UNIQUE NOT NULL, @@ -40,8 +39,7 @@ def migrate(db_url: str) -> None: details JSONB DEFAULT '{}', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) - """ - ) + """) create_index_if_not_exists( cursor, "idx_node_events_node_id", "node_events", "node_id" ) @@ -58,8 +56,7 @@ def migrate(db_url: str) -> None: # Create certificates table if not table_exists(cursor, "certificates"): logger.info("Creating certificates table...") - cursor.execute( - """ + cursor.execute(""" CREATE TABLE certificates ( id SERIAL PRIMARY KEY, certificate_id VARCHAR(64) UNIQUE NOT NULL, @@ -72,8 +69,7 @@ def migrate(db_url: str) -> None: created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) - """ - ) + """) create_index_if_not_exists( cursor, "idx_certificates_node_id", "certificates", "node_id" ) @@ -84,8 +80,7 @@ def migrate(db_url: str) -> None: # Create update_info table if not table_exists(cursor, "update_info"): logger.info("Creating update_info table...") - cursor.execute( - """ + cursor.execute(""" CREATE TABLE update_info ( id SERIAL PRIMARY KEY, update_id VARCHAR(64) UNIQUE NOT NULL, @@ -99,8 +94,7 @@ def migrate(db_url: str) -> None: applied_at TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) - """ - ) + """) create_index_if_not_exists( cursor, "idx_update_info_node_id", "update_info", "node_id" ) diff --git a/autobot-slm-backend/migrations/add_external_agents.py b/autobot-slm-backend/migrations/add_external_agents.py index 389cbdb8a..636d04376 100644 --- a/autobot-slm-backend/migrations/add_external_agents.py +++ b/autobot-slm-backend/migrations/add_external_agents.py @@ -23,8 +23,7 @@ def migrate(db_url: str) -> None: if not table_exists(cursor, "external_agents"): logger.info("Creating external_agents table...") - cursor.execute( - """ + cursor.execute(""" CREATE TABLE external_agents ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, @@ -45,8 +44,7 @@ def migrate(db_url: str) -> None: created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) - """ - ) + """) create_index_if_not_exists( cursor, "idx_external_agents_base_url", diff --git a/autobot-slm-backend/migrations/add_fleet_sync_jobs_table.py b/autobot-slm-backend/migrations/add_fleet_sync_jobs_table.py index b6570dded..c891702a1 100644 --- a/autobot-slm-backend/migrations/add_fleet_sync_jobs_table.py +++ b/autobot-slm-backend/migrations/add_fleet_sync_jobs_table.py @@ -24,8 +24,7 @@ def _create_fleet_sync_jobs(cursor) -> None: return logger.info("Creating fleet_sync_jobs table...") - cursor.execute( - """ + cursor.execute(""" CREATE TABLE fleet_sync_jobs ( id SERIAL PRIMARY KEY, job_id VARCHAR(64) UNIQUE NOT NULL, @@ -39,8 +38,7 @@ def _create_fleet_sync_jobs(cursor) -> None: created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, completed_at TIMESTAMP ) - """ - ) + """) create_index_if_not_exists( cursor, "idx_fleet_sync_jobs_status", "fleet_sync_jobs", "status" ) @@ -57,8 +55,7 @@ def _create_fleet_sync_node_states(cursor) -> None: return logger.info("Creating fleet_sync_node_states table...") - cursor.execute( - """ + cursor.execute(""" CREATE TABLE fleet_sync_node_states ( id SERIAL PRIMARY KEY, job_id VARCHAR(64) NOT NULL @@ -71,8 +68,7 @@ def _create_fleet_sync_node_states(cursor) -> None: started_at TIMESTAMP, completed_at TIMESTAMP ) - """ - ) + """) create_index_if_not_exists( cursor, "idx_fleet_sync_node_states_job", diff --git a/autobot-slm-backend/migrations/add_node_credentials_table.py b/autobot-slm-backend/migrations/add_node_credentials_table.py index 16274eece..c589fa819 100644 --- a/autobot-slm-backend/migrations/add_node_credentials_table.py +++ b/autobot-slm-backend/migrations/add_node_credentials_table.py @@ -24,8 +24,7 @@ def migrate(db_url: str) -> None: if not table_exists(cursor, "node_credentials"): logger.info("Creating node_credentials table...") - cursor.execute( - """ + cursor.execute(""" CREATE TABLE node_credentials ( id SERIAL PRIMARY KEY, credential_id VARCHAR(64) UNIQUE NOT NULL, @@ -45,8 +44,7 @@ def migrate(db_url: str) -> None: updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(node_id, credential_type, name) ) - """ - ) + """) # Create indexes create_index_if_not_exists( diff --git a/autobot-slm-backend/migrations/add_replications_table.py b/autobot-slm-backend/migrations/add_replications_table.py index fc1ff9dc6..fc513141a 100644 --- a/autobot-slm-backend/migrations/add_replications_table.py +++ b/autobot-slm-backend/migrations/add_replications_table.py @@ -25,8 +25,7 @@ def migrate(db_url: str) -> None: # Create replications table if not table_exists(cursor, "replications"): logger.info("Creating replications table...") - cursor.execute( - """ + cursor.execute(""" CREATE TABLE replications ( id SERIAL PRIMARY KEY, replication_id VARCHAR(64) UNIQUE NOT NULL, @@ -42,8 +41,7 @@ def migrate(db_url: str) -> None: created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) - """ - ) + """) create_index_if_not_exists( cursor, "idx_replications_source_node", "replications", "source_node_id" ) @@ -60,8 +58,7 @@ def migrate(db_url: str) -> None: # Create update_info table if it doesn't exist if not table_exists(cursor, "update_info"): logger.info("Creating update_info table...") - cursor.execute( - """ + cursor.execute(""" CREATE TABLE update_info ( id SERIAL PRIMARY KEY, update_id VARCHAR(64) UNIQUE NOT NULL, @@ -75,8 +72,7 @@ def migrate(db_url: str) -> None: applied_at TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) - """ - ) + """) create_index_if_not_exists( cursor, "idx_update_info_node_id", "update_info", "node_id" ) diff --git a/autobot-slm-backend/migrations/add_service_discovery.py b/autobot-slm-backend/migrations/add_service_discovery.py index 9151fb816..0a2227c36 100644 --- a/autobot-slm-backend/migrations/add_service_discovery.py +++ b/autobot-slm-backend/migrations/add_service_discovery.py @@ -18,7 +18,6 @@ import sys import psycopg2 - from migrations.utils import ( add_column_if_not_exists, create_index_if_not_exists, @@ -84,8 +83,7 @@ def migrate(db_url: str) -> None: # 2. Create node_configs table logger.info("Creating node_configs table...") if not table_exists(cursor, "node_configs"): - cursor.execute( - """ + cursor.execute(""" CREATE TABLE node_configs ( id SERIAL PRIMARY KEY, node_id VARCHAR(64), @@ -96,8 +94,7 @@ def migrate(db_url: str) -> None: updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(node_id, config_key) ) - """ - ) + """) create_index_if_not_exists( cursor, "ix_node_configs_node_id", "node_configs", "node_id" ) @@ -108,8 +105,7 @@ def migrate(db_url: str) -> None: # 3. Create service_conflicts table logger.info("Creating service_conflicts table...") if not table_exists(cursor, "service_conflicts"): - cursor.execute( - """ + cursor.execute(""" CREATE TABLE service_conflicts ( id SERIAL PRIMARY KEY, service_name_a VARCHAR(128) NOT NULL, @@ -119,8 +115,7 @@ def migrate(db_url: str) -> None: created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(service_name_a, service_name_b) ) - """ - ) + """) create_index_if_not_exists( cursor, "ix_service_conflicts_a", "service_conflicts", "service_name_a" ) diff --git a/autobot-slm-backend/migrations/add_services_table.py b/autobot-slm-backend/migrations/add_services_table.py index 73975ae4c..4a5f9a51e 100644 --- a/autobot-slm-backend/migrations/add_services_table.py +++ b/autobot-slm-backend/migrations/add_services_table.py @@ -24,8 +24,7 @@ def migrate(db_url: str) -> None: if not table_exists(cursor, "services"): logger.info("Creating services table...") - cursor.execute( - """ + cursor.execute(""" CREATE TABLE services ( id SERIAL PRIMARY KEY, node_id VARCHAR(64) NOT NULL, @@ -43,8 +42,7 @@ def migrate(db_url: str) -> None: updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(node_id, service_name) ) - """ - ) + """) create_index_if_not_exists( cursor, "idx_services_node_id", "services", "node_id" ) diff --git a/autobot-slm-backend/migrations/rename_users_to_slm_users.py b/autobot-slm-backend/migrations/rename_users_to_slm_users.py index 3aeb09c83..8fae56978 100644 --- a/autobot-slm-backend/migrations/rename_users_to_slm_users.py +++ b/autobot-slm-backend/migrations/rename_users_to_slm_users.py @@ -40,15 +40,13 @@ def migrate(db_url: str) -> None: # Check whether a table named 'users' with an INTEGER PK exists. # If user_management has already created a UUID-PK 'users' table we # must not touch it. - cur.execute( - """ + cur.execute(""" SELECT data_type FROM information_schema.columns WHERE table_name = 'users' AND column_name = 'id' AND table_schema = 'public' - """ - ) + """) row = cur.fetchone() if row is None: @@ -73,12 +71,10 @@ def migrate(db_url: str) -> None: # Rename the associated sequence if it follows the default naming # convention (users_id_seq -> slm_users_id_seq). - cur.execute( - """ + cur.execute(""" SELECT relname FROM pg_class WHERE relname = 'users_id_seq' AND relkind = 'S' - """ - ) + """) if cur.fetchone(): cur.execute("ALTER SEQUENCE users_id_seq RENAME TO slm_users_id_seq") logger.info("Renamed sequence 'users_id_seq' -> 'slm_users_id_seq'") diff --git a/autobot-slm-backend/migrations/runner.py b/autobot-slm-backend/migrations/runner.py index ec3e1e4ab..adade8ae2 100644 --- a/autobot-slm-backend/migrations/runner.py +++ b/autobot-slm-backend/migrations/runner.py @@ -98,15 +98,13 @@ def get_connection(db_url: str = None) -> psycopg2.extensions.connection: def ensure_migrations_table(conn: psycopg2.extensions.connection) -> None: """Create migrations tracking table if it doesn't exist (#786).""" with conn.cursor() as cur: - cur.execute( - """ + cur.execute(""" CREATE TABLE IF NOT EXISTS migrations_applied ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL UNIQUE, applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) - """ - ) + """) conn.commit() diff --git a/autobot-slm-backend/models/schemas.py b/autobot-slm-backend/models/schemas.py index 7b0f49fea..9b2a8fd06 100644 --- a/autobot-slm-backend/models/schemas.py +++ b/autobot-slm-backend/models/schemas.py @@ -138,9 +138,9 @@ class NodeCreate(BaseModel): hostname: str ansible_name: Optional[str] = None # Ansible inventory name (#1814) ip_address: str - node_id: Optional[ - str - ] = None # Custom node_id; if not provided, derived from hostname + node_id: Optional[str] = ( + None # Custom node_id; if not provided, derived from hostname + ) roles: List[str] = Field(default_factory=list) ssh_user: Optional[str] = "autobot" ssh_port: Optional[int] = 22 diff --git a/autobot-slm-backend/monitoring/ai_performance_analytics.py b/autobot-slm-backend/monitoring/ai_performance_analytics.py index 587f57691..faeaea921 100644 --- a/autobot-slm-backend/monitoring/ai_performance_analytics.py +++ b/autobot-slm-backend/monitoring/ai_performance_analytics.py @@ -664,9 +664,9 @@ async def analyze_performance_trends(self) -> Dict[str, Any]: if llm_trend is not None: trends["llm"] = llm_trend - trends[ - "recommendations" - ] = await self._generate_performance_recommendations(trends) + trends["recommendations"] = ( + await self._generate_performance_recommendations(trends) + ) return trends diff --git a/autobot-slm-backend/monitoring/business_intelligence_dashboard.py b/autobot-slm-backend/monitoring/business_intelligence_dashboard.py index 081f457a1..7d829c951 100644 --- a/autobot-slm-backend/monitoring/business_intelligence_dashboard.py +++ b/autobot-slm-backend/monitoring/business_intelligence_dashboard.py @@ -960,9 +960,7 @@ def _prepare_dashboard_template_vars( health_color = ( "#28a745" if health_score >= 80 - else "#ffc107" - if health_score >= 60 - else "#dc3545" + else "#ffc107" if health_score >= 60 else "#dc3545" ) roi_percent = round(summary.get("total_roi_percent", 0), 1) diff --git a/autobot-slm-backend/monitoring/comprehensive_monitoring_controller.py b/autobot-slm-backend/monitoring/comprehensive_monitoring_controller.py index a1d3094cc..453873e56 100644 --- a/autobot-slm-backend/monitoring/comprehensive_monitoring_controller.py +++ b/autobot-slm-backend/monitoring/comprehensive_monitoring_controller.py @@ -78,7 +78,9 @@ def setup_logging(self): def _signal_handler(self, signum, frame): """Handle shutdown signals gracefully.""" - self.logger.info(f"šŸ“” Received signal {signum}, initiating graceful shutdown...") + self.logger.info( + f"šŸ“” Received signal {signum}, initiating graceful shutdown..." + ) self.shutdown_requested = True async def initialize_all_systems(self): diff --git a/autobot-slm-backend/monitoring/performance_dashboard.py b/autobot-slm-backend/monitoring/performance_dashboard.py index cf26342f4..b184ed8a2 100644 --- a/autobot-slm-backend/monitoring/performance_dashboard.py +++ b/autobot-slm-backend/monitoring/performance_dashboard.py @@ -592,9 +592,11 @@ async def get_system_status(self, request): "services": { "healthy": healthy_services, "total": total_services, - "availability": (healthy_services / total_services * 100) - if total_services > 0 - else 0, + "availability": ( + (healthy_services / total_services * 100) + if total_services > 0 + else 0 + ), }, "alerts": len(alerts), "timestamp": datetime.now().isoformat(), diff --git a/autobot-slm-backend/services/agent_seeder.py b/autobot-slm-backend/services/agent_seeder.py index 8e4b17c26..405701fc3 100644 --- a/autobot-slm-backend/services/agent_seeder.py +++ b/autobot-slm-backend/services/agent_seeder.py @@ -10,6 +10,7 @@ Called by main.py lifespan via _seed_default_agents(). """ + import logging from models.database import Agent diff --git a/autobot-slm-backend/services/blue_green.py b/autobot-slm-backend/services/blue_green.py index bd41ae275..d3696d20a 100644 --- a/autobot-slm-backend/services/blue_green.py +++ b/autobot-slm-backend/services/blue_green.py @@ -22,13 +22,12 @@ from typing import Dict, List, Optional, Tuple import httpx +from config import settings from models.database import BlueGreenDeployment, BlueGreenStatus, Node, NodeStatus from models.schemas import BlueGreenCreate, BlueGreenResponse, EligibleNodeResponse from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession -from config import settings - logger = logging.getLogger(__name__) # Minimum resource headroom required for role borrowing (percent) diff --git a/autobot-slm-backend/services/database.py b/autobot-slm-backend/services/database.py index 5f85bbe0b..7118bd687 100644 --- a/autobot-slm-backend/services/database.py +++ b/autobot-slm-backend/services/database.py @@ -12,11 +12,10 @@ from contextlib import asynccontextmanager from typing import AsyncGenerator +from config import settings from models.database import Base, Setting from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine -from config import settings - logger = logging.getLogger(__name__) diff --git a/autobot-slm-backend/services/deployment.py b/autobot-slm-backend/services/deployment.py index 603af0f92..761a41489 100644 --- a/autobot-slm-backend/services/deployment.py +++ b/autobot-slm-backend/services/deployment.py @@ -16,13 +16,12 @@ from pathlib import Path from typing import Dict, List, Optional, Tuple -from sqlalchemy import select -from sqlalchemy.ext.asyncio import AsyncSession - from config import settings from models.database import Deployment, DeploymentStatus, Node, NodeStatus from models.schemas import DeploymentCreate, DeploymentResponse from services.encryption import decrypt_data +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession logger = logging.getLogger(__name__) diff --git a/autobot-slm-backend/services/git_tracker.py b/autobot-slm-backend/services/git_tracker.py index 35a65f77e..d719e2064 100644 --- a/autobot-slm-backend/services/git_tracker.py +++ b/autobot-slm-backend/services/git_tracker.py @@ -336,9 +336,11 @@ async def version_check_task( if result["has_update"]: logger.info( "Update available: local=%s, remote=%s", - result["local_commit"][:12] - if result["local_commit"] - else "unknown", + ( + result["local_commit"][:12] + if result["local_commit"] + else "unknown" + ), result["remote_commit"][:12], ) else: diff --git a/autobot-slm-backend/services/schedule_executor.py b/autobot-slm-backend/services/schedule_executor.py index 36480201c..5c131f6ab 100644 --- a/autobot-slm-backend/services/schedule_executor.py +++ b/autobot-slm-backend/services/schedule_executor.py @@ -381,7 +381,7 @@ def stop_schedule_executor(): Should be called during application shutdown. """ - global _executor_running, _executor_task + global _executor_running _executor_running = False diff --git a/autobot-slm-backend/services/tls_credentials.py b/autobot-slm-backend/services/tls_credentials.py index 878df9487..0bb8c0492 100644 --- a/autobot-slm-backend/services/tls_credentials.py +++ b/autobot-slm-backend/services/tls_credentials.py @@ -18,9 +18,6 @@ from cryptography import x509 from cryptography.hazmat.primitives import serialization -from sqlalchemy import select -from sqlalchemy.ext.asyncio import AsyncSession - from models.database import CredentialType, Node, NodeCredential from models.schemas import ( TLSCertificateInfo, @@ -29,6 +26,8 @@ TLSEndpointResponse, ) from services.encryption import get_encryption_service +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession logger = logging.getLogger(__name__) diff --git a/autobot-slm-backend/services/vnc_credentials.py b/autobot-slm-backend/services/vnc_credentials.py index 30048d706..e6338448d 100644 --- a/autobot-slm-backend/services/vnc_credentials.py +++ b/autobot-slm-backend/services/vnc_credentials.py @@ -13,9 +13,6 @@ from datetime import datetime, timedelta from typing import Dict, List, Optional, Tuple -from sqlalchemy import select -from sqlalchemy.ext.asyncio import AsyncSession - from config import settings from models.database import Node, NodeCredential from models.schemas import ( @@ -26,6 +23,8 @@ VNCEndpointResponse, ) from services.encryption import decrypt_data, encrypt_data +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession logger = logging.getLogger(__name__) diff --git a/autobot-slm-backend/slm/agent/agent.py b/autobot-slm-backend/slm/agent/agent.py index ed6f36e31..3071dd95d 100644 --- a/autobot-slm-backend/slm/agent/agent.py +++ b/autobot-slm-backend/slm/agent/agent.py @@ -132,8 +132,7 @@ def _init_buffer_db(self): """Initialize SQLite buffer database.""" Path(self.buffer_db).parent.mkdir(parents=True, exist_ok=True) conn = sqlite3.connect(self.buffer_db) - conn.execute( - """ + conn.execute(""" CREATE TABLE IF NOT EXISTS event_buffer ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp TEXT NOT NULL, @@ -141,8 +140,7 @@ def _init_buffer_db(self): data TEXT NOT NULL, synced INTEGER DEFAULT 0 ) - """ - ) + """) conn.commit() conn.close() logger.info("Event buffer initialized at %s", self.buffer_db) diff --git a/autobot-slm-backend/slm/agent/health_collector.py b/autobot-slm-backend/slm/agent/health_collector.py index 130c037c4..c0e0809ae 100644 --- a/autobot-slm-backend/slm/agent/health_collector.py +++ b/autobot-slm-backend/slm/agent/health_collector.py @@ -58,9 +58,9 @@ def collect(self) -> Dict: "cpu_percent": psutil.cpu_percent(interval=0.1), "memory_percent": psutil.virtual_memory().percent, "disk_percent": psutil.disk_usage("/").percent, - "load_avg": list(os.getloadavg()) - if hasattr(os, "getloadavg") - else [0.0, 0.0, 0.0], + "load_avg": ( + list(os.getloadavg()) if hasattr(os, "getloadavg") else [0.0, 0.0, 0.0] + ), "uptime_seconds": int(datetime.now().timestamp() - psutil.boot_time()), } diff --git a/autobot-slm-backend/tests/services/code_version_test.py b/autobot-slm-backend/tests/services/code_version_test.py index a7bad9222..ef851281f 100644 --- a/autobot-slm-backend/tests/services/code_version_test.py +++ b/autobot-slm-backend/tests/services/code_version_test.py @@ -244,9 +244,9 @@ def test_heartbeat_response_update_available_true(self): status="ok", update_available=update_available, latest_version=latest_version if update_available else None, - update_url=f"/api/nodes/{node_id}/code-package" - if update_available - else None, + update_url=( + f"/api/nodes/{node_id}/code-package" if update_available else None + ), ) assert response.update_available is True @@ -269,9 +269,9 @@ def test_heartbeat_response_update_available_false(self): status="ok", update_available=update_available, latest_version=latest_version if update_available else None, - update_url=None - if not update_available - else "/api/nodes/test-node/code-package", + update_url=( + None if not update_available else "/api/nodes/test-node/code-package" + ), ) assert response.update_available is False