mcp-souschef 2.8.0__py3-none-any.whl → 3.2.0__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 (36) hide show
  1. {mcp_souschef-2.8.0.dist-info → mcp_souschef-3.2.0.dist-info}/METADATA +159 -384
  2. mcp_souschef-3.2.0.dist-info/RECORD +47 -0
  3. {mcp_souschef-2.8.0.dist-info → mcp_souschef-3.2.0.dist-info}/WHEEL +1 -1
  4. souschef/__init__.py +31 -7
  5. souschef/assessment.py +1451 -105
  6. souschef/ci/common.py +126 -0
  7. souschef/ci/github_actions.py +3 -92
  8. souschef/ci/gitlab_ci.py +2 -52
  9. souschef/ci/jenkins_pipeline.py +2 -59
  10. souschef/cli.py +149 -16
  11. souschef/converters/playbook.py +378 -138
  12. souschef/converters/resource.py +12 -11
  13. souschef/converters/template.py +177 -0
  14. souschef/core/__init__.py +6 -1
  15. souschef/core/metrics.py +313 -0
  16. souschef/core/path_utils.py +233 -19
  17. souschef/core/validation.py +53 -0
  18. souschef/deployment.py +71 -12
  19. souschef/generators/__init__.py +13 -0
  20. souschef/generators/repo.py +695 -0
  21. souschef/parsers/attributes.py +1 -1
  22. souschef/parsers/habitat.py +1 -1
  23. souschef/parsers/inspec.py +25 -2
  24. souschef/parsers/metadata.py +5 -3
  25. souschef/parsers/recipe.py +1 -1
  26. souschef/parsers/resource.py +1 -1
  27. souschef/parsers/template.py +1 -1
  28. souschef/server.py +1039 -121
  29. souschef/ui/app.py +486 -374
  30. souschef/ui/pages/ai_settings.py +74 -8
  31. souschef/ui/pages/cookbook_analysis.py +3216 -373
  32. souschef/ui/pages/validation_reports.py +274 -0
  33. mcp_souschef-2.8.0.dist-info/RECORD +0 -42
  34. souschef/converters/cookbook_specific.py.backup +0 -109
  35. {mcp_souschef-2.8.0.dist-info → mcp_souschef-3.2.0.dist-info}/entry_points.txt +0 -0
  36. {mcp_souschef-2.8.0.dist-info → mcp_souschef-3.2.0.dist-info}/licenses/LICENSE +0 -0
@@ -5,7 +5,9 @@ Configure and validate AI provider settings for the SousChef MCP server.
5
5
  """
6
6
 
7
7
  import json
8
+ import os
8
9
  from pathlib import Path
10
+ from typing import Any
9
11
  from urllib.parse import urlparse, urlunparse
10
12
 
11
13
  import streamlit as st
@@ -171,10 +173,15 @@ def _render_validation_section(
171
173
  st.subheader("Configuration Validation")
172
174
  col1, col2 = st.columns([1, 1])
173
175
  with col1:
174
- if st.button("Validate Configuration", type="primary", width="stretch"):
176
+ if st.button(
177
+ "Validate Configuration",
178
+ type="primary",
179
+ width="stretch",
180
+ key="validate_ai_config",
181
+ ):
175
182
  validate_ai_configuration(provider, api_key, model, base_url, project_id)
176
183
  with col2:
177
- if st.button("Save Settings", width="stretch"):
184
+ if st.button("Save Settings", width="stretch", key="save_ai_settings"):
178
185
  save_ai_settings(
179
186
  provider, api_key, model, base_url, temperature, max_tokens, project_id
180
187
  )
@@ -182,6 +189,17 @@ def _render_validation_section(
182
189
 
183
190
  def show_ai_settings_page():
184
191
  """Show the AI settings configuration page."""
192
+ # Add back to dashboard button
193
+ col1, col2 = st.columns([1, 4])
194
+ with col1:
195
+ if st.button(
196
+ "← Back to Dashboard",
197
+ help="Return to main dashboard",
198
+ key="back_to_dashboard_from_ai",
199
+ ):
200
+ st.session_state.current_page = "Dashboard"
201
+ st.rerun()
202
+
185
203
  st.markdown("""
186
204
  Configure your AI provider settings for the SousChef MCP server.
187
205
  These settings determine which AI model will be used for Chef to Ansible
@@ -481,17 +499,65 @@ def display_current_settings():
481
499
  st.info("No AI configuration found. Please configure your settings above.")
482
500
 
483
501
 
484
- def load_ai_settings():
502
+ def load_ai_settings() -> dict[str, Any]:
503
+ """Load AI settings from file, session state, or environment variables."""
504
+ file_config = _load_ai_settings_from_file()
505
+ if file_config:
506
+ return file_config
507
+
508
+ session_config = st.session_state.get("ai_config", {})
509
+ if isinstance(session_config, dict) and session_config:
510
+ return session_config
511
+
512
+ env_config = _load_ai_settings_from_env()
513
+ if env_config:
514
+ return env_config
515
+
516
+ return {}
517
+
518
+
519
+ def _load_ai_settings_from_env() -> dict[str, str | float | int]:
520
+ """Load AI settings from environment variables."""
521
+ from contextlib import suppress
522
+
523
+ env_config: dict[str, str | float | int] = {}
524
+ env_mappings = {
525
+ "SOUSCHEF_AI_PROVIDER": "provider",
526
+ "SOUSCHEF_AI_MODEL": "model",
527
+ "SOUSCHEF_AI_API_KEY": "api_key",
528
+ "SOUSCHEF_AI_BASE_URL": "base_url",
529
+ "SOUSCHEF_AI_PROJECT_ID": "project_id",
530
+ }
531
+
532
+ # Handle string values
533
+ for env_var, config_key in env_mappings.items():
534
+ env_value = os.environ.get(env_var)
535
+ if env_value:
536
+ env_config[config_key] = env_value
537
+
538
+ # Handle numeric values with error suppression
539
+ temp_value = os.environ.get("SOUSCHEF_AI_TEMPERATURE")
540
+ if temp_value:
541
+ with suppress(ValueError):
542
+ env_config["temperature"] = float(temp_value)
543
+
544
+ tokens_value = os.environ.get("SOUSCHEF_AI_MAX_TOKENS")
545
+ if tokens_value:
546
+ with suppress(ValueError):
547
+ env_config["max_tokens"] = int(tokens_value)
548
+
549
+ return env_config
550
+
551
+
552
+ def _load_ai_settings_from_file() -> dict[str, Any]:
485
553
  """Load AI settings from configuration file."""
486
554
  try:
487
- # Use /tmp/.souschef for container compatibility (tmpfs is writable)
488
555
  config_file = Path("/tmp/.souschef/ai_config.json")
489
556
  if config_file.exists():
490
557
  with config_file.open() as f:
491
- return json.load(f)
558
+ result = json.load(f)
559
+ return result if isinstance(result, dict) else {}
492
560
  except Exception as e:
493
- # Failed to load config from file; fall back to session state/defaults
494
561
  st.warning(f"Unable to load saved AI settings: {e}")
495
562
 
496
- # Fallback to session state or return empty dict
497
- return st.session_state.get("ai_config", {})
563
+ return {}