agentops-cockpit 0.9.5__py3-none-any.whl → 0.9.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. agent_ops_cockpit/agent.py +44 -77
  2. agent_ops_cockpit/cache/semantic_cache.py +10 -21
  3. agent_ops_cockpit/cli/main.py +105 -153
  4. agent_ops_cockpit/eval/load_test.py +33 -50
  5. agent_ops_cockpit/eval/quality_climber.py +88 -93
  6. agent_ops_cockpit/eval/red_team.py +84 -25
  7. agent_ops_cockpit/mcp_server.py +26 -93
  8. agent_ops_cockpit/ops/arch_review.py +221 -147
  9. agent_ops_cockpit/ops/auditors/base.py +50 -0
  10. agent_ops_cockpit/ops/auditors/behavioral.py +31 -0
  11. agent_ops_cockpit/ops/auditors/compliance.py +35 -0
  12. agent_ops_cockpit/ops/auditors/dependency.py +48 -0
  13. agent_ops_cockpit/ops/auditors/finops.py +48 -0
  14. agent_ops_cockpit/ops/auditors/graph.py +49 -0
  15. agent_ops_cockpit/ops/auditors/pivot.py +51 -0
  16. agent_ops_cockpit/ops/auditors/reasoning.py +67 -0
  17. agent_ops_cockpit/ops/auditors/reliability.py +53 -0
  18. agent_ops_cockpit/ops/auditors/security.py +87 -0
  19. agent_ops_cockpit/ops/auditors/sme_v12.py +76 -0
  20. agent_ops_cockpit/ops/auditors/sovereignty.py +74 -0
  21. agent_ops_cockpit/ops/auditors/sre_a2a.py +179 -0
  22. agent_ops_cockpit/ops/benchmarker.py +97 -0
  23. agent_ops_cockpit/ops/cost_optimizer.py +15 -24
  24. agent_ops_cockpit/ops/discovery.py +214 -0
  25. agent_ops_cockpit/ops/evidence_bridge.py +30 -63
  26. agent_ops_cockpit/ops/frameworks.py +124 -1
  27. agent_ops_cockpit/ops/git_portal.py +74 -0
  28. agent_ops_cockpit/ops/mcp_hub.py +19 -42
  29. agent_ops_cockpit/ops/orchestrator.py +477 -277
  30. agent_ops_cockpit/ops/policy_engine.py +38 -38
  31. agent_ops_cockpit/ops/reliability.py +121 -52
  32. agent_ops_cockpit/ops/remediator.py +54 -0
  33. agent_ops_cockpit/ops/secret_scanner.py +34 -22
  34. agent_ops_cockpit/ops/swarm.py +17 -27
  35. agent_ops_cockpit/ops/ui_auditor.py +67 -6
  36. agent_ops_cockpit/ops/watcher.py +41 -70
  37. agent_ops_cockpit/ops/watchlist.json +30 -0
  38. agent_ops_cockpit/optimizer.py +161 -384
  39. agent_ops_cockpit/tests/test_arch_review.py +6 -6
  40. agent_ops_cockpit/tests/test_discovery.py +96 -0
  41. agent_ops_cockpit/tests/test_ops_core.py +56 -0
  42. agent_ops_cockpit/tests/test_orchestrator_fleet.py +73 -0
  43. agent_ops_cockpit/tests/test_persona_architect.py +75 -0
  44. agent_ops_cockpit/tests/test_persona_finops.py +31 -0
  45. agent_ops_cockpit/tests/test_persona_security.py +55 -0
  46. agent_ops_cockpit/tests/test_persona_sre.py +43 -0
  47. agent_ops_cockpit/tests/test_persona_ux.py +42 -0
  48. agent_ops_cockpit/tests/test_quality_climber.py +2 -2
  49. agent_ops_cockpit/tests/test_remediator.py +75 -0
  50. agent_ops_cockpit/tests/test_ui_auditor.py +52 -0
  51. agentops_cockpit-0.9.8.dist-info/METADATA +172 -0
  52. agentops_cockpit-0.9.8.dist-info/RECORD +71 -0
  53. agent_ops_cockpit/tests/test_optimizer.py +0 -68
  54. agent_ops_cockpit/tests/test_red_team.py +0 -35
  55. agent_ops_cockpit/tests/test_secret_scanner.py +0 -24
  56. agentops_cockpit-0.9.5.dist-info/METADATA +0 -246
  57. agentops_cockpit-0.9.5.dist-info/RECORD +0 -47
  58. {agentops_cockpit-0.9.5.dist-info → agentops_cockpit-0.9.8.dist-info}/WHEEL +0 -0
  59. {agentops_cockpit-0.9.5.dist-info → agentops_cockpit-0.9.8.dist-info}/entry_points.txt +0 -0
  60. {agentops_cockpit-0.9.5.dist-info → agentops_cockpit-0.9.8.dist-info}/licenses/LICENSE +0 -0
@@ -8,24 +8,24 @@ from rich.table import Table
8
8
  from rich.panel import Panel
9
9
  from rich.syntax import Syntax
10
10
  from packaging import version
11
-
12
- # Import the evidence bridge
13
11
  try:
14
12
  from agent_ops_cockpit.ops.evidence_bridge import get_package_evidence, get_compatibility_report
15
13
  except ImportError:
16
- # Fallback for local execution
17
14
  try:
18
15
  from backend.ops.evidence_bridge import get_package_evidence, get_compatibility_report
19
16
  except ImportError:
20
- # Final fallback
21
- def get_package_evidence(pkg): return {}
22
- def get_compatibility_report(imports): return []
23
17
 
24
- app = typer.Typer(help="AgentOps Cockpit: The Agent Optimizer CLI")
18
+ def get_package_evidence(pkg):
19
+ return {}
20
+
21
+ def get_compatibility_report(imports):
22
+ return []
23
+ app = typer.Typer(help='AgentOps Cockpit: The Agent Optimizer CLI')
25
24
  console = Console()
26
25
 
27
26
  class OptimizationIssue:
28
- def __init__(self, id: str, title: str, impact: str, savings: str, description: str, diff: str, package: str = None, fix_pattern: str = None):
27
+
28
+ def __init__(self, id: str, title: str, impact: str, savings: str, description: str, diff: str, package: str=None, fix_pattern: str=None):
29
29
  self.id = id
30
30
  self.title = title
31
31
  self.impact = impact
@@ -36,450 +36,227 @@ class OptimizationIssue:
36
36
  self.fix_pattern = fix_pattern
37
37
  self.evidence = None
38
38
 
39
- def analyze_code(content: str, file_path: str = "agent.py", versions: Dict[str, str] = None) -> List[OptimizationIssue]:
39
+ def analyze_code(content: str, file_path: str='agent.py', versions: Dict[str, str]=None) -> List[OptimizationIssue]:
40
40
  issues = []
41
41
  content_lower = content.lower()
42
+ content_no_comments = re.sub('#.*', '', content_lower)
42
43
  versions = versions or {}
43
-
44
- # --- SITUATIONAL PLATFORM OPTIMIZATIONS ---
45
-
46
- v_ai = versions.get("google-cloud-aiplatform", "Not Installed")
47
- if "google.cloud.aiplatform" in content_lower or "vertexai" in content_lower:
48
- if v_ai == "Not Installed":
49
- issues.append(OptimizationIssue(
50
- "vertex_install", "Install Modern Vertex SDK", "HIGH", "90% cost savings",
51
- "You appear to be using Vertex AI logic but the SDK is not in your environment. Install v1.70.0+ to unlock context caching.",
52
- "+ # pip install google-cloud-aiplatform>=1.70.0",
53
- package="google-cloud-aiplatform"
54
- ))
55
- elif v_ai != "Unknown":
44
+ v_ai = versions.get('google-cloud-aiplatform', 'Not Installed')
45
+ if 'google.cloud.aiplatform' in content_lower or 'vertexai' in content_lower:
46
+ if v_ai == 'Not Installed':
47
+ issues.append(OptimizationIssue('vertex_install', 'Install Modern Vertex SDK', 'HIGH', '90% cost savings', 'You appear to be using Vertex AI logic but the SDK is not in your environment. Install v1.70.0+ to unlock context caching.', '+ # pip install google-cloud-aiplatform>=1.70.0', package='google-cloud-aiplatform'))
48
+ elif v_ai != 'Unknown':
56
49
  try:
57
- if version.parse(v_ai) < version.parse("1.70.0"):
58
- issues.append(OptimizationIssue(
59
- "vertex_legacy_opt", "Situational Performance (Legacy SDK)", "MEDIUM", "20% cost savings",
60
- f"Your SDK ({v_ai}) lacks native Context Caching. Optimize by using selective prompt pruning before execution.",
61
- "+ from agent_ops_cockpit.ops.cost_optimizer import situational_pruning\n+ pruned = situational_pruning(context)",
62
- package="google-cloud-aiplatform"
63
- ))
64
- issues.append(OptimizationIssue(
65
- "vertex_upgrade_path", "Modernization Path", "HIGH", "90% cost savings",
66
- "Upgrading to 1.70.0+ enables near-instant token reuse via CachingConfig.",
67
- "+ # Upgrade to >1.70.0",
68
- package="google-cloud-aiplatform"
69
- ))
70
- elif "cache" not in content_lower:
71
- issues.append(OptimizationIssue(
72
- "context_caching", "Enable Context Caching", "HIGH", "90% cost reduction",
73
- "Large model context detected. Use native CachingConfig.",
74
- "+ cache = vertexai.preview.CachingConfig(ttl=3600)",
75
- package="google-cloud-aiplatform"
76
- ))
50
+ if version.parse(v_ai) < version.parse('1.70.0'):
51
+ issues.append(OptimizationIssue('vertex_legacy_opt', 'Situational Performance (Legacy SDK)', 'MEDIUM', '20% cost savings', f'Your SDK ({v_ai}) lacks native Context Caching. Optimize by using selective prompt pruning before execution.', '+ from agent_ops_cockpit.ops.cost_optimizer import situational_pruning\n+ pruned = situational_pruning(context)', package='google-cloud-aiplatform'))
52
+ issues.append(OptimizationIssue('vertex_upgrade_path', 'Modernization Path', 'HIGH', '90% cost savings', 'Upgrading to 1.70.0+ enables near-instant token reuse via CachingConfig.', '+ # Upgrade to >1.70.0', package='google-cloud-aiplatform'))
53
+ elif 'cache' not in content_lower:
54
+ issues.append(OptimizationIssue('context_caching', 'Enable Context Caching', 'HIGH', '90% cost reduction', 'Large model context detected. Use native CachingConfig.', '+ cache = vertexai.preview.CachingConfig(ttl=3600)', package='google-cloud-aiplatform'))
77
55
  except Exception:
78
56
  pass
79
-
80
- # OpenAI
81
- openai_v = versions.get("openai", "Not Installed")
82
- if "openai" in content_lower:
83
- if openai_v != "Not Installed" and version.parse(openai_v) < version.parse("1.0.0"):
84
- issues.append(OptimizationIssue(
85
- "openai_legacy", "Found Legacy OpenAI SDK", "HIGH", "40% latency reduction",
86
- f"You are on {openai_v}. Transitioning to the v1.0.0+ Client pattern enables modern streaming and improved error handling.",
87
- "+ from openai import OpenAI\n+ client = OpenAI()",
88
- package="openai"
89
- ))
90
- elif "prompt_cache" not in content_lower:
91
- issues.append(OptimizationIssue(
92
- "openai_caching", "OpenAI Prompt Caching", "MEDIUM", "50% latency reduction",
93
- "OpenAI automatically caches repeated input prefixes. Ensure your system prompt is first.",
94
- "+ # Ensure system prompt is first\n+ messages = [{'role': 'system', ...}]",
95
- package="openai"
96
- ))
97
-
98
- # Anthropic
99
- if ("anthropic" in content_lower or "claude" in content_lower) and "orchestra" not in content_lower:
100
- issues.append(OptimizationIssue(
101
- "anthropic_orchestration", "Anthropic Orchestration Pattern", "HIGH", "30% reliability boost",
102
- "Claude performs best with an Orchestrator-Subagent pattern for complex tasks.",
103
- "+ # Use orchestrator to delegate sub-tasks",
104
- package="anthropic"
105
- ))
106
-
107
- # Microsoft
108
- if ("autogen" in content_lower or "microsoft" in content_lower) and "workflow" not in content_lower:
109
- issues.append(OptimizationIssue(
110
- "ms_workflows", "Microsoft Agent Workflows", "MEDIUM", "40% consistency boost",
111
- "Using graph-based repeatable workflows ensures enterprise reliability.",
112
- "+ # Define a repeatable graph-based flow",
113
- package="pyautogen"
114
- ))
115
-
116
- # AWS
117
- if ("bedrock" in content_lower or "boto3" in content_lower) and "actiongroup" not in content_lower:
118
- issues.append(OptimizationIssue(
119
- "aws_action_groups", "AWS Bedrock Action Groups", "HIGH", "50% tool reliability",
120
- "Standardize tool execution via Bedrock Action Group schemas.",
121
- "+ # Define Bedrock Action Group",
122
- package="aws-sdk"
123
- ))
124
-
125
- # CopilotKit
126
- if "copilotkit" in content_lower and "usecopilotstate" not in content_lower:
127
- issues.append(OptimizationIssue(
128
- "copilot_state", "CopilotKit Shared State", "MEDIUM", "60% UI responsiveness",
129
- "Ensure the Face remains aligned with the Engine via shared state sync.",
130
- "+ # Use shared state for UI alignment",
131
- package="@copilotkit/react-core"
132
- ))
133
-
134
- # Routing
135
- if "pro" in content_lower and "flash" not in content_lower:
136
- issues.append(OptimizationIssue(
137
- "model_routing", "Smart Model Routing", "HIGH", "70% cost savings",
138
- "Route simple queries to Flash models to minimize consumption.",
139
- "+ if is_simple(q): model = 'gemini-1.5-flash'",
140
- package="google-cloud-aiplatform"
141
- ))
142
-
143
- # Infrastructure (Cloud Run + GKE)
144
- if "cloud run" in content_lower and "cpu_boost" not in content_lower:
145
- issues.append(OptimizationIssue(
146
- "cr_startup_boost", "Cloud Run Startup Boost", "HIGH", "50% latency reduction",
147
- "Enable Startup CPU Boost to reduce cold-start latency for Python agents.",
148
- "+ startup_cpu_boost: true",
149
- package="google-cloud-run"
150
- ))
151
- if ("gke" in content_lower or "kubernetes" in content_lower) and "identity" not in content_lower:
152
- issues.append(OptimizationIssue(
153
- "gke_identity", "GKE Workload Identity", "HIGH", "100% security baseline",
154
- "Use Workload Identity for secure service-to-service communication.",
155
- "+ # Use Workload Identity",
156
- package="google-cloud-gke"
157
- ))
158
-
159
- # Language Specific (Go + Node)
160
- if file_path.endswith(".go") and "goroutine" not in content_lower:
161
- issues.append(OptimizationIssue(
162
- "go_concurrency", "Go Native Concurrency", "HIGH", "80% throughput boost",
163
- "Leveraging Goroutines for parallel tool execution is a Go best practice.",
164
- "+ go func() { tool.execute() }()",
165
- package="golang"
166
- ))
167
- if (file_path.endswith(".ts") or file_path.endswith(".js") or "axios" in content_lower) and "fetch" not in content_lower:
168
- issues.append(OptimizationIssue(
169
- "node_native_fetch", "Native Fetch API", "MEDIUM", "20% bundle reduction",
170
- "Node 20+ supports native fetch, reducing dependency on heavy libraries like axios.",
171
- "+ const res = await fetch(url);",
172
- package="nodejs"
173
- ))
174
-
175
- lg_v = versions.get("langgraph", "Not Installed")
176
- if "langgraph" in content_lower:
177
- if lg_v != "Not Installed" and lg_v != "Unknown":
57
+ openai_v = versions.get('openai', 'Not Installed')
58
+ if 'openai' in content_lower:
59
+ if openai_v != 'Not Installed' and version.parse(openai_v) < version.parse('1.0.0'):
60
+ issues.append(OptimizationIssue('openai_legacy', 'Found Legacy OpenAI SDK', 'HIGH', '40% latency reduction', f'You are on {openai_v}. Transitioning to the v1.0.0+ Client pattern enables modern streaming and improved error handling.', '+ from openai import OpenAI\n+ client = OpenAI()', package='openai'))
61
+ elif 'prompt_cache' not in content_lower:
62
+ issues.append(OptimizationIssue('openai_caching', 'OpenAI Prompt Caching', 'MEDIUM', '50% latency reduction', 'OpenAI automatically caches repeated input prefixes. Ensure your system prompt is first.', "+ # Ensure system prompt is first\n+ messages = [{'role': 'system', ...}]", package='openai'))
63
+ if ('anthropic' in content_lower or 'claude' in content_lower) and 'orchestra' not in content_lower:
64
+ issues.append(OptimizationIssue('anthropic_orchestration', 'Anthropic Orchestration Pattern', 'HIGH', '30% reliability boost', 'Claude performs best with an Orchestrator-Subagent pattern for complex tasks.', '+ # Use orchestrator to delegate sub-tasks', package='anthropic'))
65
+ if ('autogen' in content_lower or 'microsoft' in content_lower) and 'workflow' not in content_lower:
66
+ issues.append(OptimizationIssue('ms_workflows', 'Microsoft Agent Workflows', 'MEDIUM', '40% consistency boost', 'Using graph-based repeatable workflows ensures enterprise reliability.', '+ # Define a repeatable graph-based flow', package='pyautogen'))
67
+ if ('bedrock' in content_lower or 'boto3' in content_lower) and 'actiongroup' not in content_lower:
68
+ issues.append(OptimizationIssue('aws_action_groups', 'AWS Bedrock Action Groups', 'HIGH', '50% tool reliability', 'Standardize tool execution via Bedrock Action Group schemas.', '+ # Define Bedrock Action Group', package='aws-sdk'))
69
+ if 'copilotkit' in content_lower and 'usecopilotstate' not in content_lower:
70
+ issues.append(OptimizationIssue('copilot_state', 'CopilotKit Shared State', 'MEDIUM', '60% UI responsiveness', 'Ensure the Face remains aligned with the Engine via shared state sync.', '+ # Use shared state for UI alignment', package='@copilotkit/react-core'))
71
+ if 'pro' in content_lower and 'flash' not in content_lower:
72
+ issues.append(OptimizationIssue('model_routing', 'Smart Model Routing', 'HIGH', '70% cost savings', 'Route simple queries to Flash models to minimize consumption.', "+ if is_simple(q): model = 'gemini-1.5-flash'", package='google-cloud-aiplatform'))
73
+ if 'cloud run' in content_lower and 'cpu_boost' not in content_lower:
74
+ issues.append(OptimizationIssue('cr_startup_boost', 'Cloud Run Startup Boost', 'HIGH', '50% latency reduction', 'Enable Startup CPU Boost to reduce cold-start latency for Python agents.', '+ startup_cpu_boost: true', package='google-cloud-run'))
75
+ if ('gke' in content_lower or 'kubernetes' in content_lower) and 'identity' not in content_lower:
76
+ issues.append(OptimizationIssue('gke_identity', 'GKE Workload Identity', 'HIGH', '100% security baseline', 'Use Workload Identity for secure service-to-service communication.', '+ # Use Workload Identity', package='google-cloud-gke'))
77
+ if file_path.endswith('.go') and 'goroutine' not in content_lower:
78
+ issues.append(OptimizationIssue('go_concurrency', 'Go Native Concurrency', 'HIGH', '80% throughput boost', 'Leveraging Goroutines for parallel tool execution is a Go best practice.', '+ go func() { tool.execute() }()', package='golang'))
79
+ if (file_path.endswith('.ts') or file_path.endswith('.js') or 'axios' in content_lower) and 'fetch' not in content_lower:
80
+ issues.append(OptimizationIssue('node_native_fetch', 'Native Fetch API', 'MEDIUM', '20% bundle reduction', 'Node 20+ supports native fetch, reducing dependency on heavy libraries like axios.', '+ const res = await fetch(url);', package='nodejs'))
81
+ lg_v = versions.get('langgraph', 'Not Installed')
82
+ if 'langgraph' in content_lower:
83
+ if lg_v != 'Not Installed' and lg_v != 'Unknown':
178
84
  try:
179
- if version.parse(lg_v) < version.parse("0.1.0"):
180
- issues.append(OptimizationIssue(
181
- "langgraph_legacy", "Situational Stability (Legacy LangGraph)", "HIGH", "Stability Boost",
182
- f"You are on {lg_v}. Older versions lack the hardened StateGraph compilation. Upgrade is recommended.",
183
- "+ # Consider upgrading for better persistence",
184
- package="langgraph"
185
- ))
85
+ if version.parse(lg_v) < version.parse('0.1.0'):
86
+ issues.append(OptimizationIssue('langgraph_legacy', 'Situational Stability (Legacy LangGraph)', 'HIGH', 'Stability Boost', f'You are on {lg_v}. Older versions lack the hardened StateGraph compilation. Upgrade is recommended.', '+ # Consider upgrading for better persistence', package='langgraph'))
186
87
  except Exception:
187
88
  pass
188
-
189
- if "persistence" not in content_lower and "checkpointer" not in content_lower:
190
- issues.append(OptimizationIssue(
191
- "langgraph_persistence", "LangGraph Persistence", "HIGH", "100% state recovery",
192
- "A checkpointer is mandatory for reliable long-running agents.",
193
- "+ graph.compile(checkpointer=checkpointer)",
194
- package="langgraph"
195
- ))
196
- if "recursion" not in content_lower:
197
- issues.append(OptimizationIssue(
198
- "langgraph_recursion", "Recursion Limits", "MEDIUM", "Safety Guardrail",
199
- "Set recursion limits to prevent expensive infinite loops in cyclic graphs.",
200
- "+ graph.invoke(..., config={'recursion_limit': 50})",
201
- package="langgraph"
202
- ))
203
-
204
- # --- ARCHITECTURAL OPTIMIZATIONS ---
205
-
206
- # Large system instructions
207
- large_string_pattern = re.compile(r'"""[\s\S]{200,}"""|\'\'\'[\s\S]{200,}\'\'\'')
208
- if large_string_pattern.search(content) and "cache" not in content_lower:
209
- issues.append(OptimizationIssue(
210
- "context_caching", "Enable Context Caching", "HIGH", "90% cost reduction",
211
- "Large static system instructions detected. Use context caching.",
212
- "+ cache = vertexai.preview.CachingConfig(ttl=3600)",
213
- package="google-cloud-aiplatform"
214
- ))
215
-
216
- # Missing semantic cache
217
- if "hive_mind" not in content_lower and "cache" not in content_lower:
218
- issues.append(OptimizationIssue(
219
- "semantic_caching", "Implement Semantic Caching", "HIGH", "40-60% savings",
220
- "No caching layer detected. Adding a semantic cache reduces LLM costs.",
221
- "+ @hive_mind(cache=global_cache)",
222
- package="google-adk"
223
- ))
224
-
225
- # --- BEST PRACTICE OPTIMIZATIONS ---
226
-
227
- # Prompt Externalization
228
- if large_string_pattern.search(content):
229
- issues.append(OptimizationIssue(
230
- "external_prompts", "Externalize System Prompts", "MEDIUM", "Architectural Debt Reduction",
231
- "Keeping large system prompts in code makes them hard to version and test. Move them to 'system_prompt.md' and load dynamically.",
232
- "+ with open('system_prompt.md', 'r') as f:\n+ SYSTEM_PROMPT = f.read()"
233
- ))
234
-
235
- # Resiliency / Retries
236
- if "retry" not in content_lower and "tenacity" not in content_lower:
237
- issues.append(OptimizationIssue(
238
- "resiliency_retries", "Implement Exponential Backoff", "HIGH", "99.9% Reliability",
239
- "Your agent calls external APIs/DBs but has no retry logic. Use 'tenacity' to handle transient failures.",
240
- "+ @retry(wait=wait_exponential(multiplier=1, min=4, max=10), stop=stop_after_attempt(3))",
241
- package="tenacity"
242
- ))
243
-
244
- # Session Management
245
- if "session" not in content_lower and "conversation_id" not in content_lower:
246
- issues.append(OptimizationIssue(
247
- "session_management", "Add Session Tracking", "MEDIUM", "User Continuity",
248
- "No session tracking detected. Agents in production need a 'conversation_id' to maintain multi-turn context.",
249
- "+ def chat(q: str, conversation_id: str = None):"
250
- ))
251
-
252
- # Pinecone Optimization
253
- if "pinecone" in content_lower:
254
- if "grpc" not in content_lower:
255
- issues.append(OptimizationIssue(
256
- "pinecone_grpc", "Pinecone High-Perf (gRPC)", "MEDIUM", "40% latency reduction",
257
- "You are using the standard Pinecone client. Switching to pinecone[grpc] enables low-latency streaming for large vector retrievals.",
258
- "+ from pinecone.grpc import PineconeGRPC as Pinecone\n+ pc = Pinecone(api_key='...')"
259
- ))
260
- if "namespace" not in content_lower:
261
- issues.append(OptimizationIssue(
262
- "pinecone_isolation", "Pinecone Namespace Isolation", "MEDIUM", "RAG Accuracy Boost",
263
- "No namespaces detected. Use namespaces to isolate user data or document segments for more accurate retrieval.",
264
- "+ index.query(..., namespace='customer-a')"
265
- ))
266
-
267
- # Google Cloud Database Optimizations
89
+ if 'persistence' not in content_lower and 'checkpointer' not in content_lower:
90
+ issues.append(OptimizationIssue('langgraph_persistence', 'LangGraph Persistence', 'HIGH', '100% state recovery', 'A checkpointer is mandatory for reliable long-running agents.', '+ graph.compile(checkpointer=checkpointer)', package='langgraph'))
91
+ if 'recursion' not in content_lower:
92
+ issues.append(OptimizationIssue('langgraph_recursion', 'Recursion Limits', 'MEDIUM', 'Safety Guardrail', 'Set recursion limits to prevent expensive infinite loops in cyclic graphs.', "+ graph.invoke(..., config={'recursion_limit': 50})", package='langgraph'))
93
+ docstrings = re.findall('"""([\\s\\S]*?)"""|\\\'\\\'\\\'([\\s\\S]*?)\\\'\\\'\\\'', content)
94
+ has_large_prompt = any((len(d[0] or d[1]) > 200 for d in docstrings))
95
+ if has_large_prompt and 'cache' not in content_lower:
96
+ issues.append(OptimizationIssue('context_caching', 'Enable Context Caching', 'HIGH', '90% cost reduction', 'Large static system instructions detected. Use context caching.', '+ cache = vertexai.preview.CachingConfig(ttl=3600)', package='google-cloud-aiplatform'))
97
+ if 'hive_mind' not in content_lower and 'cache' not in content_lower:
98
+ issues.append(OptimizationIssue('semantic_caching', 'Implement Semantic Caching', 'HIGH', '40-60% savings', 'No caching layer detected. Adding a semantic cache reduces LLM costs.', '+ @hive_mind(cache=global_cache)', package='google-adk'))
99
+ if has_large_prompt:
100
+ issues.append(OptimizationIssue('external_prompts', 'Externalize System Prompts', 'MEDIUM', 'Architectural Debt Reduction', "Keeping large system prompts in code makes them hard to version and test. Move them to 'system_prompt.md' and load dynamically.", "+ with open('system_prompt.md', 'r') as f:\n+ SYSTEM_PROMPT = f.read()"))
101
+ if 'retry' not in content_lower and 'tenacity' not in content_lower:
102
+ issues.append(OptimizationIssue('resiliency_retries', 'Implement Exponential Backoff', 'HIGH', '99.9% Reliability', "Your agent calls external APIs/DBs but has no retry logic. Use 'tenacity' to handle transient failures.", '+ @retry(wait=wait_exponential(multiplier=1, min=4, max=10), stop=stop_after_attempt(3))', package='tenacity'))
103
+ if 'session' not in content_lower and 'conversation_id' not in content_lower:
104
+ issues.append(OptimizationIssue('session_management', 'Add Session Tracking', 'MEDIUM', 'User Continuity', "No session tracking detected. Agents in production need a 'conversation_id' to maintain multi-turn context.", '+ def chat(q: str, conversation_id: str = None):'))
105
+ if 'pinecone' in content_lower:
106
+ if 'grpc' not in content_lower:
107
+ issues.append(OptimizationIssue('pinecone_grpc', 'Pinecone High-Perf (gRPC)', 'MEDIUM', '40% latency reduction', 'You are using the standard Pinecone client. Switching to pinecone[grpc] enables low-latency streaming for large vector retrievals.', "+ from pinecone.grpc import PineconeGRPC as Pinecone\n+ pc = Pinecone(api_key='...')"))
108
+ if 'namespace' not in content_lower:
109
+ issues.append(OptimizationIssue('pinecone_isolation', 'Pinecone Namespace Isolation', 'MEDIUM', 'RAG Accuracy Boost', 'No namespaces detected. Use namespaces to isolate user data or document segments for more accurate retrieval.', "+ index.query(..., namespace='customer-a')"))
110
+ if 'alloydb' in content_no_comments:
111
+ if 'columnar' not in content_no_comments:
112
+ issues.append(OptimizationIssue('alloydb_columnar', 'AlloyDB Columnar Engine', 'HIGH', '100x Query Speedup', 'AlloyDB detected. Enable the Columnar Engine for analytical and AI-driven vector queries.', '+ # Enable AlloyDB Columnar Engine for vector scaling'))
113
+ if 'bigquery' in content_no_comments or 'bq' in content_no_comments:
114
+ if 'vector_search' not in content_no_comments:
115
+ issues.append(OptimizationIssue('bq_vector_search', 'BigQuery Vector Search', 'HIGH', 'FinOps: Serverless RAG', 'BigQuery detected. Use BQ Vector Search for cost-effective RAG over massive datasets without moving data to a separate DB.', '+ SELECT * FROM VECTOR_SEARCH(TABLE my_dataset.embeddings, ...)'))
116
+ if 'cloudsql' in content_lower or 'psycopg2' in content_lower or 'sqlalchemy' in content_lower:
117
+ if 'cloud-sql-connector' not in content_lower:
118
+ issues.append(OptimizationIssue('cloudsql_connector', 'Cloud SQL Python Connector', 'MEDIUM', '100% Secure Auth', 'Using raw drivers detected. Use the official Cloud SQL Python Connector for IAM-based authentication and automatic encryption.', '+ from google.cloud.sql.connector import Connector\n+ connector = Connector()'))
119
+ if 'firestore' in content_lower:
120
+ if 'vector' not in content_lower:
121
+ issues.append(OptimizationIssue('firestore_vector', 'Firestore Vector Search (Native)', 'HIGH', 'Real-time RAG', 'Firestore detected. Use native Vector Search and KNN queries for high-concurrency mobile/web agent retrieval.', "+ collection.find_nearest(vector_field='embedding', ...)"))
122
+ if 'oci' in content_lower or 'oracle' in content_lower:
123
+ if 'resource_principal' not in content_lower:
124
+ issues.append(OptimizationIssue('oci_auth', 'OCI Resource Principals', 'HIGH', '100% Secure Auth', 'Using static config/keys detected on OCI. Use Resource Principals for secure, credential-less access from OCI compute.', '+ auth = oci.auth.signers.get_resource_principals_signer()'))
125
+ if 'crewai' in content_lower or 'crew(' in content_lower:
126
+ if 'manager_agent' not in content_lower and 'hierarchical' not in content_lower:
127
+ issues.append(OptimizationIssue('crewai_manager', 'Use Hierarchical Manager', 'MEDIUM', '30% Coordination Boost', 'Your crew uses sequential execution. For complex tasks, a Manager Agent improves task handoffs and reasoning.', '+ crew = Crew(..., process=Process.hierarchical, manager_agent=manager)'))
268
128
 
269
- # AlloyDB
270
- if "alloydb" in content_lower:
271
- if "columnar" not in content_lower:
272
- issues.append(OptimizationIssue(
273
- "alloydb_columnar", "AlloyDB Columnar Engine", "HIGH", "100x Query Speedup",
274
- "AlloyDB detected. Enable the Columnar Engine for analytical and AI-driven vector queries.",
275
- "+ # Enable AlloyDB Columnar Engine for vector scaling"
276
- ))
129
+ # v1.2 Principal SME Extras
130
+ if 'rag' in content_lower or 'retriev' in content_lower:
131
+ if 'chunk' not in content_lower and 'atomic' not in content_lower:
132
+ issues.append(OptimizationIssue('atomic_rag', 'Implement Atomic RAG', 'HIGH', '30% Token Savings', "You appear to be using RAG but no 'chunking' or 'atomic retrieval' logic was detected. Sending full documents kills margins.", "+ docs = vector_db.search(query, chunk_limit=5)"))
277
133
 
278
- # BigQuery
279
- if "bigquery" in content_lower or "bq" in content_lower:
280
- if "vector_search" not in content_lower:
281
- issues.append(OptimizationIssue(
282
- "bq_vector_search", "BigQuery Vector Search", "HIGH", "FinOps: Serverless RAG",
283
- "BigQuery detected. Use BQ Vector Search for cost-effective RAG over massive datasets without moving data to a separate DB.",
284
- "+ SELECT * FROM VECTOR_SEARCH(TABLE my_dataset.embeddings, ...)"
285
- ))
134
+ if 'model' in content_lower and 'router' not in content_lower and 'is_simple' not in content_lower:
135
+ issues.append(OptimizationIssue('tiered_orchestration', 'Implement Tiered Orchestration', 'HIGH', '70% Cost Savings', "No model routing detected. Use a 'Router Agent' to decide if a query needs a Pro model or a Flash model.", "+ if is_simple(query): model = 'gemini-1.5-flash'"))
286
136
 
287
- # Cloud SQL
288
- if "cloudsql" in content_lower or "psycopg2" in content_lower or "sqlalchemy" in content_lower:
289
- if "cloud-sql-connector" not in content_lower:
290
- issues.append(OptimizationIssue(
291
- "cloudsql_connector", "Cloud SQL Python Connector", "MEDIUM", "100% Secure Auth",
292
- "Using raw drivers detected. Use the official Cloud SQL Python Connector for IAM-based authentication and automatic encryption.",
293
- "+ from google.cloud.sql.connector import Connector\n+ connector = Connector()"
294
- ))
137
+ if any(phrase in content_lower for phrase in ["you are a helpful assistant", "very good at", "please help me"]):
138
+ issues.append(OptimizationIssue('prompt_compression', 'Token Density: Redundant English', 'MEDIUM', '15% Token Savings', "Identified 'filler' tokens in system instructions. Compressing 'You are a helpful assistant who is very good at coding' to 'Expert coder' reduces baseline cost.", "- You are a helpful assistant...\n+ Expert coder"))
295
139
 
296
- # Firestore
297
- if "firestore" in content_lower:
298
- if "vector" not in content_lower:
299
- issues.append(OptimizationIssue(
300
- "firestore_vector", "Firestore Vector Search (Native)", "HIGH", "Real-time RAG",
301
- "Firestore detected. Use native Vector Search and KNN queries for high-concurrency mobile/web agent retrieval.",
302
- "+ collection.find_nearest(vector_field='embedding', ...)"
303
- ))
304
-
305
- # Oracle OCI Optimizations
306
- if "oci" in content_lower or "oracle" in content_lower:
307
- if "resource_principal" not in content_lower:
308
- issues.append(OptimizationIssue(
309
- "oci_auth", "OCI Resource Principals", "HIGH", "100% Secure Auth",
310
- "Using static config/keys detected on OCI. Use Resource Principals for secure, credential-less access from OCI compute.",
311
- "+ auth = oci.auth.signers.get_resource_principals_signer()"
312
- ))
313
-
314
- # CrewAI Optimizations
315
- if "crewai" in content_lower or "crew(" in content_lower:
316
- if "manager_agent" not in content_lower and "hierarchical" not in content_lower:
317
- issues.append(OptimizationIssue(
318
- "crewai_manager", "Use Hierarchical Manager", "MEDIUM", "30% Coordination Boost",
319
- "Your crew uses sequential execution. For complex tasks, a Manager Agent improves task handoffs and reasoning.",
320
- "+ crew = Crew(..., process=Process.hierarchical, manager_agent=manager)"
321
- ))
140
+ if 'model' in content_lower and 'retry' not in content_lower and 'tenacity' not in content_lower:
141
+ issues.append(OptimizationIssue('quota_management', 'Quota Management: Missing Backoff', 'HIGH', 'Resiliency & ROI', "High-volume model calls detected without Exponential Backoff. Failed requests due to rate-limiting represent wasted compute and broken ROI.", "+ @retry(wait=wait_exponential(multiplier=1, max=10))"))
322
142
 
323
143
  return issues
324
144
 
325
145
  def estimate_savings(token_count: int, issues: List[OptimizationIssue]) -> Dict[str, Any]:
326
146
  baseline_cost_per_m = 10.0
327
- monthly_requests = 10000
328
- current_cost = (token_count / 1_000_000) * baseline_cost_per_m * monthly_requests
329
-
147
+ monthly_requests = 10000
148
+ current_cost = token_count / 1000000 * baseline_cost_per_m * monthly_requests
330
149
  total_savings_pct = 0.0
331
150
  for issue in issues:
332
- if "90%" in issue.savings:
333
- total_savings_pct += 0.45 # Context Caching / Modern SDK
334
- elif "70%" in issue.savings:
335
- total_savings_pct += 0.35 # Smart Routing (Pro -> Flash)
336
- elif "50%" in issue.savings:
337
- total_savings_pct += 0.20 # Infrastructure / Startup Boost
338
- elif "40-60%" in issue.savings:
339
- total_savings_pct += 0.25 # Semantic Caching (Hive Mind)
151
+ if '90%' in issue.savings:
152
+ total_savings_pct += 0.45
153
+ elif '70%' in issue.savings:
154
+ total_savings_pct += 0.35
155
+ elif '50%' in issue.savings:
156
+ total_savings_pct += 0.2
157
+ elif '40-60%' in issue.savings:
158
+ total_savings_pct += 0.25
340
159
  else:
341
- total_savings_pct += 0.05 # Standard Best Practices
342
-
160
+ total_savings_pct += 0.05
343
161
  projected_savings = current_cost * min(total_savings_pct, 0.85)
344
-
345
- return {
346
- "current_monthly": current_cost,
347
- "projected_savings": projected_savings,
348
- "new_monthly": current_cost - projected_savings
349
- }
162
+ return {'current_monthly': current_cost, 'projected_savings': projected_savings, 'new_monthly': current_cost - projected_savings}
350
163
 
351
164
  @app.command()
352
- def audit(
353
- file_path: str = typer.Argument("agent.py", help="Path to the agent code to audit"),
354
- interactive: bool = typer.Option(True, "--interactive/--no-interactive", "-i", help="Run in interactive mode"),
355
- apply_fix: bool = typer.Option(False, "--apply", "--fix", help="Automatically apply recommended fixes"),
356
- quick: bool = typer.Option(False, "--quick", "-q", help="Skip live evidence fetching for faster execution")
357
- ):
358
- console.print(Panel.fit("🔍 [bold blue]GCP AGENT OPS: OPTIMIZER AUDIT[/bold blue]", border_style="blue"))
359
- if quick:
360
- console.print("[dim]⚡ Running in Quick Mode (skipping live evidence fetches)[/dim]")
361
- console.print(f"Target: [yellow]{file_path}[/yellow]")
362
-
165
+ def audit(file_path: str=typer.Argument('agent.py', help='Path to the agent code to audit'), interactive: bool=typer.Option(True, '--interactive/--no-interactive', '-i', help='Run in interactive mode'), apply_fix: bool=typer.Option(False, '--apply', '--fix', help='Automatically apply recommended fixes'), quick: bool=typer.Option(False, '--quick', '-q', help='Skip live evidence fetching for faster execution')):
166
+ console.print(Panel.fit('🔍 [bold blue]GCP AGENT OPS: OPTIMIZER AUDIT[/bold blue]', border_style='blue'))
363
167
  if not os.path.exists(file_path):
364
- console.print(f"❌ [red]Error: File {file_path} not found.[/red]")
168
+ console.print(f'❌ [red]Error: Path {file_path} not found.[/red]')
365
169
  raise typer.Exit(1)
366
-
170
+ if os.path.isdir(file_path):
171
+ from agent_ops_cockpit.ops.discovery import DiscoveryEngine
172
+ discovery = DiscoveryEngine(file_path)
173
+ file_path = discovery.find_agent_brain()
174
+
175
+ if not os.path.exists(file_path):
176
+ console.print(f'❌ [red]Error: No python entry point found in {discovery.root_path}[/red]')
177
+ raise typer.Exit(1)
178
+ console.print(f'Target: [yellow]{file_path}[/yellow]')
367
179
  with open(file_path, 'r') as f:
368
180
  content = f.read()
369
-
370
- # Heuristic: Find all imported packages
371
- imports = re.findall(r"(?:from|import)\s+([\w\.-]+)", content)
372
-
181
+ imports = re.findall('(?:from|import)\\s+([\\w\\.-]+)', content)
373
182
  from agent_ops_cockpit.ops.evidence_bridge import get_installed_version
374
- package_versions = { pkg: get_installed_version(pkg) for pkg in ["google-cloud-aiplatform", "openai", "anthropic", "langgraph", "crewai"] }
375
-
376
- token_estimate = len(content.split()) * 1.5
377
- console.print(f"📊 Token Metrics: ~[bold]{token_estimate:.0f}[/bold] prompt tokens detected.")
378
-
183
+ package_versions = {pkg: get_installed_version(pkg) for pkg in ['google-cloud-aiplatform', 'openai', 'anthropic', 'langgraph', 'crewai']}
184
+ token_estimate = len(content.split()) * 1.5
185
+ console.print(f'📊 Token Metrics: ~[bold]{token_estimate:.0f}[/bold] prompt tokens detected.')
379
186
  issues = analyze_code(content, file_path, versions=package_versions)
380
- # Inject live evidence (skip in quick mode)
381
187
  if not quick:
382
188
  for issue in issues:
383
189
  if issue.package:
384
190
  issue.evidence = get_package_evidence(issue.package)
385
-
386
- # --- CROSS-PACKAGE VALIDATION ---
387
191
  comp_reports = get_compatibility_report(imports)
388
-
389
192
  if comp_reports:
390
- console.print("\n[bold yellow]🧩 Cross-Package Validation:[/bold yellow]")
193
+ console.print('\n[bold yellow]🧩 Cross-Package Validation:[/bold yellow]')
391
194
  for report in comp_reports:
392
- if report["type"] == "INCOMPATIBLE":
195
+ if report['type'] == 'INCOMPATIBLE':
393
196
  console.print(f"❌ [bold red]Conflict Detected:[/bold red] {report['component']} + {report['conflict_with']}")
394
197
  console.print(f" [dim]{report['reason']}[/dim]")
395
- elif report["type"] == "SYNERGY":
198
+ elif report['type'] == 'SYNERGY':
396
199
  console.print(f"✅ [bold green]Synergy Verified:[/bold green] {report['component']} is optimally paired.")
397
-
398
200
  if not issues:
399
- console.print("\n[bold green]✅ No immediate code-level optimizations found. Your agent is lean![/bold green]")
201
+ console.print('\n[bold green]✅ No immediate code-level optimizations found. Your agent is lean![/bold green]')
400
202
  if not comp_reports:
401
- return
203
+ return
402
204
  else:
403
- raise typer.Exit(0)
404
-
205
+ raise typer.Exit(0)
405
206
  savings = estimate_savings(token_estimate, issues)
406
- finops_panel = Panel(
407
- f"💰 [bold]FinOps Projection (Est. 10k req/mo)[/bold]\n"
408
- f"Current Monthly Spend: [red]${savings['current_monthly']:.2f}[/red]\n"
409
- f"Projected Savings: [green]${savings['projected_savings']:.2f}[/green]\n"
410
- f"New Monthly Spend: [blue]${savings['new_monthly']:.2f}[/blue]",
411
- title="[bold yellow]Financial Optimization[/bold yellow]",
412
- border_style="yellow"
413
- )
207
+ finops_panel = Panel(f"💰 [bold]FinOps Projection (Est. 10k req/mo)[/bold]\nCurrent Monthly Spend: [red]${savings['current_monthly']:.2f}[/red]\nProjected Savings: [green]${savings['projected_savings']:.2f}[/green]\nNew Monthly Spend: [blue]${savings['new_monthly']:.2f}[/blue]", title='[bold yellow]Financial Optimization[/bold yellow]', border_style='yellow')
414
208
  console.print(finops_panel)
415
-
416
209
  applied = 0
417
210
  rejected = 0
418
211
  fixed_content = content
419
-
420
212
  for opt in issues:
421
- console.print(f"\n[bold white on blue] --- [{opt.impact} IMPACT] {opt.title} --- [/bold white on blue]")
422
- console.print(f"Benefit: [green]{opt.savings}[/green]")
423
- console.print(f"Reason: {opt.description}")
424
-
425
- if opt.evidence and "error" not in opt.evidence:
213
+ console.print(f'\n[bold white on blue] --- [{opt.impact} IMPACT] {opt.title} --- [/bold white on blue]')
214
+ console.print(f'Benefit: [green]{opt.savings}[/green]')
215
+ console.print(f'Reason: {opt.description}')
216
+ if opt.evidence and 'error' not in opt.evidence:
426
217
  ev = opt.evidence
427
- ev_title = "[dim]SDK Citation & Evidence[/dim]"
428
-
429
- # Highlight if an upgrade is required for maximum efficiency
430
- if ev.get("upgrade_required"):
431
- console.print("🚨 [bold yellow]URGENT UPGRADE RECOMMENDED[/bold yellow]")
218
+ ev_title = '[dim]SDK Citation & Evidence[/dim]'
219
+ if ev.get('upgrade_required'):
220
+ console.print('🚨 [bold yellow]URGENT UPGRADE RECOMMENDED[/bold yellow]')
432
221
  console.print(f" Current: {ev['installed_version']} | Required for optimization: >={ev['min_optimized_version']}")
433
- ev_title = "[bold red]UPGRADE REQUIRED Evidence[/bold red]"
434
-
435
- ev_panel = Panel(
436
- f"🔗 [bold]Source[/bold]: {ev['source_url']}\n"
437
- f"📅 [bold]Latest Release[/bold]: {ev['release_date'][:10]}\n"
438
- f"📝 [bold]Note[/bold]: {ev['best_practice_context']}",
439
- title=ev_title,
440
- border_style="red" if ev.get("upgrade_required") else "dim"
441
- )
222
+ ev_title = '[bold red]UPGRADE REQUIRED Evidence[/bold red]'
223
+ ev_panel = Panel(f"🔗 [bold]Source[/bold]: {ev['source_url']}\n📅 [bold]Latest Release[/bold]: {ev['release_date'][:10]}\n📝 [bold]Note[/bold]: {ev['best_practice_context']}", title=ev_title, border_style='red' if ev.get('upgrade_required') else 'dim')
442
224
  console.print(ev_panel)
443
- # Orchestrator parsing
444
225
  console.print(f"SOURCE: {opt.title} | {ev['source_url']} | {ev['best_practice_context'].replace('\\n', ' ')}")
445
-
446
- syntax = Syntax(opt.diff, "python", theme="monokai", line_numbers=False)
226
+ syntax = Syntax(opt.diff, 'python', theme='monokai', line_numbers=False)
447
227
  console.print(syntax)
448
-
449
- # Output ACTION: for report generation
450
- console.print(f"ACTION: {file_path}:1 | Optimization: {opt.title} | {opt.description} (Est. {opt.savings})")
451
-
228
+ console.print(f'ACTION: {file_path}:1 | Optimization: {opt.title} | {opt.description} (Est. {opt.savings})')
452
229
  do_apply = False
453
230
  if apply_fix:
454
231
  do_apply = True
455
232
  elif interactive:
456
- do_apply = typer.confirm("\nDo you want to apply this code-level optimization?", default=True)
457
-
233
+ do_apply = typer.confirm('\nDo you want to apply this code-level optimization?', default=True)
458
234
  if do_apply:
459
- console.print("✅ [APPROVED] applying fix...")
235
+ console.print('✅ [APPROVED] applying fix...')
460
236
  if opt.fix_pattern:
461
237
  fixed_content = opt.fix_pattern + fixed_content
462
238
  applied += 1
463
239
  else:
464
- console.print("❌ [REJECTED] skipping optimization.")
240
+ console.print('❌ [REJECTED] skipping optimization.')
465
241
  rejected += 1
466
-
467
242
  if applied > 0:
468
243
  with open(file_path, 'w') as f:
469
244
  f.write(fixed_content)
470
- console.print(f"\n✨ [bold green]Applied {applied} optimizations to {file_path}![/bold green]")
471
-
472
- summary_table = Table(title="🎯 AUDIT SUMMARY")
473
- summary_table.add_column("Category", style="cyan")
474
- summary_table.add_column("Count", style="magenta")
475
- summary_table.add_row("Optimizations Applied", str(applied))
476
- summary_table.add_row("Optimizations Rejected", str(rejected))
245
+ console.print(f'\n✨ [bold green]Applied {applied} optimizations to {file_path}![/bold green]')
246
+ summary_table = Table(title='🎯 AUDIT SUMMARY')
247
+ summary_table.add_column('Category', style='cyan')
248
+ summary_table.add_column('Count', style='magenta')
249
+ summary_table.add_row('Optimizations Applied', str(applied))
250
+ summary_table.add_row('Optimizations Rejected', str(rejected))
477
251
  console.print(summary_table)
478
-
479
- # CI/CD Enforcement: Fail if high-impact issues remain in non-interactive mode
480
- if not interactive and any(opt.impact == "HIGH" for opt in issues):
481
- console.print("\n[bold red]❌ HIGH IMPACT issues detected. Optimization required for production.[/bold red]")
252
+ if not interactive and any((opt.impact == 'HIGH' for opt in issues)):
253
+ console.print('\n[bold red]❌ HIGH IMPACT issues detected. Optimization required for production.[/bold red]')
482
254
  raise typer.Exit(code=1)
483
255
 
484
- if __name__ == "__main__":
256
+ @app.command()
257
+ def version():
258
+ """Show the version of the Optimizer module."""
259
+ console.print('[bold cyan]v1.3.0[/bold cyan]')
260
+
261
+ if __name__ == '__main__':
485
262
  app()