promptAId/operations
0
1#!/usr/bin/env python32"""3Configuration Navigator for Operations System4 5This script helps you navigate and understand your config-driven architecture.6Use it to explore, validate, and modify configurations at both global and tool levels.7 8Usage:9 python scripts/config_navigator.py --help10 python scripts/config_navigator.py --list-all11 python scripts/config_navigator.py --show agent.response_templates12 python scripts/config_navigator.py --show omirl.tasks13"""14 15import os16import sys17import yaml18import argparse19from pathlib import Path20from typing import Dict, Any, List21 22 23class ConfigNavigator:24 """Navigate the config-driven architecture"""25 26 def __init__(self, project_root: Path = None):27 if project_root is None:28 project_root = Path(__file__).parent.parent29 self.project_root = project_root30 self.agent_config_dir = project_root / "agent" / "config"31 self.tools_dir = project_root / "tools"32 33 def list_all_configs(self) -> Dict[str, List[str]]:34 """List all available configuration files"""35 configs = {36 "π Global Agent Configs": [],37 "π§ Tool-Specific Configs": []38 }39 40 # Global configs41 if self.agent_config_dir.exists():42 for config_file in self.agent_config_dir.glob("*.yaml"):43 configs["π Global Agent Configs"].append(f"agent.{config_file.stem}")44 45 # Tool configs46 if self.tools_dir.exists():47 for tool_dir in self.tools_dir.iterdir():48 if tool_dir.is_dir():49 tool_config_dir = tool_dir / "config"50 if tool_config_dir.exists():51 for config_file in tool_config_dir.glob("*.yaml"):52 configs["π§ Tool-Specific Configs"].append(f"{tool_dir.name}.{config_file.stem}")53 54 return configs55 56 def load_config(self, config_path: str) -> Dict[str, Any]:57 """Load a specific configuration file"""58 try:59 if "." not in config_path:60 raise ValueError("Config path must be in format 'namespace.config_name'")61 62 namespace, config_name = config_path.split(".", 1)63 64 if namespace == "agent":65 file_path = self.agent_config_dir / f"{config_name}.yaml"66 else:67 # Assume it's a tool name68 file_path = self.tools_dir / namespace / "config" / f"{config_name}.yaml"69 70 if not file_path.exists():71 raise FileNotFoundError(f"Config file not found: {file_path}")72 73 with open(file_path, 'r', encoding='utf-8') as f:74 return yaml.safe_load(f)75 76 except Exception as e:77 print(f"β Error loading config '{config_path}': {e}")78 return {}79 80 def show_config_structure(self, config_path: str, max_depth: int = 3):81 """Show the structure of a configuration file"""82 config = self.load_config(config_path)83 if not config:84 return85 86 print(f"\nπ **Configuration: {config_path}**")87 print("=" * 60)88 self._print_dict_structure(config, max_depth=max_depth)89 90 def _print_dict_structure(self, obj: Any, indent: int = 0, max_depth: int = 3, current_depth: int = 0):91 """Recursively print dictionary structure"""92 if current_depth >= max_depth:93 print(" " * indent + "...")94 return95 96 if isinstance(obj, dict):97 for key, value in obj.items():98 if isinstance(value, dict):99 print(" " * indent + f"π {key}:")100 self._print_dict_structure(value, indent + 1, max_depth, current_depth + 1)101 elif isinstance(value, list):102 print(" " * indent + f"π {key}: [{len(value)} items]")103 if value and current_depth < max_depth - 1:104 if isinstance(value[0], str):105 # Show first few string items106 sample = value[:3]107 print(" " * (indent + 1) + f"β³ {sample}{'...' if len(value) > 3 else ''}")108 else:109 self._print_dict_structure(value[0], indent + 1, max_depth, current_depth + 1)110 else:111 value_str = str(value)112 if len(value_str) > 50:113 value_str = value_str[:47] + "..."114 print(" " * indent + f"π {key}: {value_str}")115 elif isinstance(obj, list) and obj:116 for i, item in enumerate(obj[:3]): # Show first 3 items117 print(" " * indent + f"[{i}]:")118 self._print_dict_structure(item, indent + 1, max_depth, current_depth + 1)119 if len(obj) > 3:120 print(" " * indent + f"... and {len(obj) - 3} more items")121 122 def find_in_configs(self, search_term: str) -> List[tuple]:123 """Search for a term across all configurations"""124 results = []125 all_configs = self.list_all_configs()126 127 for category, configs in all_configs.items():128 for config_path in configs:129 config = self.load_config(config_path)130 if self._search_in_dict(config, search_term.lower()):131 results.append((config_path, category))132 133 return results134 135 def _search_in_dict(self, obj: Any, search_term: str) -> bool:136 """Recursively search for a term in a dictionary"""137 if isinstance(obj, dict):138 for key, value in obj.items():139 if search_term in key.lower() or self._search_in_dict(value, search_term):140 return True141 elif isinstance(obj, list):142 for item in obj:143 if self._search_in_dict(item, search_term):144 return True145 elif isinstance(obj, str):146 return search_term in obj.lower()147 148 return False149 150 def validate_configs(self) -> Dict[str, List[str]]:151 """Validate all configuration files"""152 results = {"β
Valid": [], "β Invalid": []}153 all_configs = self.list_all_configs()154 155 for category, configs in all_configs.items():156 for config_path in configs:157 try:158 config = self.load_config(config_path)159 if config:160 results["β
Valid"].append(config_path)161 else:162 results["β Invalid"].append(f"{config_path} (empty)")163 except Exception as e:164 results["β Invalid"].append(f"{config_path} ({str(e)})")165 166 return results167 168 def show_config_relationships(self):169 """Show how configurations relate to each other"""170 print("\nπ **Configuration Relationships**")171 print("=" * 60)172 173 print("\nπ **Control Flow:**")174 print("1. π£οΈ User Request")175 print("2. π§ llm_router_config.yaml β Route to tool")176 print("3. π§ tool_registry.yaml β Find tool capabilities")177 print("4. βοΈ tool/config/*.yaml β Execute with parameters")178 print("5. π response_templates.yaml β Format response")179 180 print("\nπ **Shared Data:**")181 print("β’ geography.yaml β Used by all tools for validation")182 print("β’ response_templates.yaml β Used by all tools for responses")183 184 print("\nπ§ **Tool-Specific:**")185 print("β’ tools/{tool}/config/tasks.yaml β What the tool can do")186 print("β’ tools/{tool}/config/parameters.yaml β Tool parameters")187 print("β’ tools/{tool}/config/validation_rules.yaml β Input validation")188 189 190def main():191 parser = argparse.ArgumentParser(192 description="Navigate the config-driven architecture",193 formatter_class=argparse.RawDescriptionHelpFormatter,194 epilog="""195Examples:196 %(prog)s --list-all # List all configs197 %(prog)s --show agent.response_templates # Show agent response templates198 %(prog)s --show omirl.tasks # Show OMIRL tasks config199 %(prog)s --search "precipitazione" # Search for term in all configs200 %(prog)s --validate # Validate all configs201 %(prog)s --relationships # Show config relationships202 """203 )204 205 parser.add_argument("--list-all", action="store_true", 206 help="List all available configuration files")207 parser.add_argument("--show", metavar="CONFIG_PATH",208 help="Show structure of specific config (e.g., agent.response_templates)")209 parser.add_argument("--search", metavar="TERM",210 help="Search for a term across all configurations")211 parser.add_argument("--validate", action="store_true",212 help="Validate all configuration files")213 parser.add_argument("--relationships", action="store_true",214 help="Show configuration relationships")215 parser.add_argument("--depth", type=int, default=3,216 help="Maximum depth for structure display (default: 3)")217 218 args = parser.parse_args()219 220 navigator = ConfigNavigator()221 222 if args.list_all:223 print("\nπΊοΈ **Available Configurations**")224 print("=" * 60)225 configs = navigator.list_all_configs()226 for category, config_list in configs.items():227 print(f"\n{category}:")228 for config in config_list:229 print(f" β’ {config}")230 231 elif args.show:232 navigator.show_config_structure(args.show, max_depth=args.depth)233 234 elif args.search:235 print(f"\nπ **Search Results for '{args.search}'**")236 print("=" * 60)237 results = navigator.find_in_configs(args.search)238 if results:239 for config_path, category in results:240 print(f"π {config_path} ({category})")241 else:242 print("No results found.")243 244 elif args.validate:245 print("\nβ
**Configuration Validation**")246 print("=" * 60)247 results = navigator.validate_configs()248 for status, configs in results.items():249 print(f"\n{status}:")250 for config in configs:251 print(f" β’ {config}")252 253 elif args.relationships:254 navigator.show_config_relationships()255 256 else:257 parser.print_help()258 259 260if __name__ == "__main__":261 main()262 