solace-agent-mesh 1.5.1__py3-none-any.whl → 1.6.1__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.

Potentially problematic release.


This version of solace-agent-mesh might be problematic. Click here for more details.

Files changed (184) hide show
  1. solace_agent_mesh/agent/adk/callbacks.py +0 -5
  2. solace_agent_mesh/agent/adk/models/lite_llm.py +123 -8
  3. solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +245 -0
  4. solace_agent_mesh/agent/protocol/event_handlers.py +213 -31
  5. solace_agent_mesh/agent/proxies/__init__.py +0 -0
  6. solace_agent_mesh/agent/proxies/a2a/__init__.py +3 -0
  7. solace_agent_mesh/agent/proxies/a2a/app.py +55 -0
  8. solace_agent_mesh/agent/proxies/a2a/component.py +1115 -0
  9. solace_agent_mesh/agent/proxies/a2a/config.py +140 -0
  10. solace_agent_mesh/agent/proxies/a2a/oauth_token_cache.py +104 -0
  11. solace_agent_mesh/agent/proxies/base/__init__.py +3 -0
  12. solace_agent_mesh/agent/proxies/base/app.py +99 -0
  13. solace_agent_mesh/agent/proxies/base/component.py +650 -0
  14. solace_agent_mesh/agent/proxies/base/config.py +85 -0
  15. solace_agent_mesh/agent/proxies/base/proxy_task_context.py +17 -0
  16. solace_agent_mesh/agent/sac/app.py +58 -5
  17. solace_agent_mesh/agent/sac/component.py +238 -75
  18. solace_agent_mesh/agent/sac/task_execution_context.py +46 -0
  19. solace_agent_mesh/agent/tools/audio_tools.py +125 -8
  20. solace_agent_mesh/agent/tools/web_tools.py +10 -5
  21. solace_agent_mesh/agent/utils/artifact_helpers.py +141 -3
  22. solace_agent_mesh/assets/docs/404.html +3 -3
  23. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.eda4bcb2.js +1 -0
  24. solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.f4b15f3b.js +1 -0
  25. solace_agent_mesh/assets/docs/assets/js/71da7b71.38583438.js +1 -0
  26. solace_agent_mesh/assets/docs/assets/js/77cf947d.48cb18a2.js +1 -0
  27. solace_agent_mesh/assets/docs/assets/js/924ffdeb.8095e148.js +1 -0
  28. solace_agent_mesh/assets/docs/assets/js/9e9d0a82.570c057b.js +1 -0
  29. solace_agent_mesh/assets/docs/assets/js/{ad71b5ed.60668e9e.js → ad71b5ed.af3ecfd1.js} +1 -1
  30. solace_agent_mesh/assets/docs/assets/js/ceb2a7a6.5d92d7d0.js +1 -0
  31. solace_agent_mesh/assets/docs/assets/js/{da0b5bad.9d369087.js → da0b5bad.d08a9466.js} +1 -1
  32. solace_agent_mesh/assets/docs/assets/js/db924877.e98d12a1.js +1 -0
  33. solace_agent_mesh/assets/docs/assets/js/de915948.27d6b065.js +1 -0
  34. solace_agent_mesh/assets/docs/assets/js/{e3d9abda.2b916f9e.js → e3d9abda.6b9493d0.js} +1 -1
  35. solace_agent_mesh/assets/docs/assets/js/e6f9706b.e74a984d.js +1 -0
  36. solace_agent_mesh/assets/docs/assets/js/f284c35a.42f59cdd.js +1 -0
  37. solace_agent_mesh/assets/docs/assets/js/ff4d71f2.15b02f97.js +1 -0
  38. solace_agent_mesh/assets/docs/assets/js/{main.bd3c34f3.js → main.b12eac43.js} +2 -2
  39. solace_agent_mesh/assets/docs/assets/js/runtime~main.e268214e.js +1 -0
  40. solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +15 -4
  41. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +4 -4
  42. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +4 -4
  43. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +4 -4
  44. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +4 -4
  45. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +4 -4
  46. solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +4 -4
  47. solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +4 -4
  48. solace_agent_mesh/assets/docs/docs/documentation/components/index.html +4 -4
  49. solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +4 -4
  50. solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +4 -4
  51. solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +262 -0
  52. solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +3 -3
  53. solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +31 -3
  54. solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +3 -3
  55. solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +3 -3
  56. solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +4 -4
  57. solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +5 -5
  58. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +4 -4
  59. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +4 -4
  60. solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +135 -0
  61. solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +6 -4
  62. solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +4 -4
  63. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +4 -4
  64. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +4 -4
  65. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +5 -5
  66. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +4 -4
  67. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +4 -4
  68. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +4 -4
  69. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +4 -4
  70. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +4 -4
  71. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +4 -4
  72. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +3 -3
  73. solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +3 -3
  74. solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +3 -3
  75. solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +3 -3
  76. solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +3 -3
  77. solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +3 -3
  78. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +3 -3
  79. solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +3 -3
  80. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +6 -5
  81. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +3 -3
  82. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +3 -3
  83. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +100 -3
  84. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +3 -3
  85. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +3 -3
  86. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +3 -3
  87. solace_agent_mesh/assets/docs/lunr-index-1761248203150.json +1 -0
  88. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  89. solace_agent_mesh/assets/docs/search-doc-1761248203150.json +1 -0
  90. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  91. solace_agent_mesh/assets/docs/sitemap.xml +1 -1
  92. solace_agent_mesh/cli/__init__.py +1 -1
  93. solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +2 -69
  94. solace_agent_mesh/cli/commands/eval_cmd.py +11 -49
  95. solace_agent_mesh/cli/commands/init_cmd/__init__.py +0 -5
  96. solace_agent_mesh/cli/commands/init_cmd/env_step.py +10 -12
  97. solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +9 -61
  98. solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +9 -49
  99. solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +1 -2
  100. solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-DwrxZE0E.js → authCallback-BTf6dqwp.js} +1 -1
  101. solace_agent_mesh/client/webui/frontend/static/assets/{client-DarGQzyw.js → client-CaY59VuC.js} +1 -1
  102. solace_agent_mesh/client/webui/frontend/static/assets/main-B32noGmR.js +342 -0
  103. solace_agent_mesh/client/webui/frontend/static/assets/main-DHJKSW1S.css +1 -0
  104. solace_agent_mesh/client/webui/frontend/static/assets/{vendor-BKIeiHj_.js → vendor-BEmvJSYz.js} +1 -1
  105. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
  106. solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
  107. solace_agent_mesh/common/a2a/__init__.py +24 -0
  108. solace_agent_mesh/common/a2a/artifact.py +39 -0
  109. solace_agent_mesh/common/a2a/events.py +29 -0
  110. solace_agent_mesh/common/a2a/message.py +68 -0
  111. solace_agent_mesh/common/a2a/protocol.py +151 -1
  112. solace_agent_mesh/common/agent_registry.py +83 -3
  113. solace_agent_mesh/common/constants.py +3 -1
  114. solace_agent_mesh/common/sac/sam_component_base.py +383 -4
  115. solace_agent_mesh/common/utils/pydantic_utils.py +12 -0
  116. solace_agent_mesh/config_portal/backend/common.py +1 -1
  117. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ByU1X1HD.js +98 -0
  118. solace_agent_mesh/config_portal/frontend/static/client/assets/{manifest-44d62be6.js → manifest-61038fc6.js} +1 -1
  119. solace_agent_mesh/config_portal/frontend/static/client/index.html +1 -1
  120. solace_agent_mesh/evaluation/evaluator.py +128 -104
  121. solace_agent_mesh/evaluation/message_organizer.py +116 -110
  122. solace_agent_mesh/evaluation/report_data_processor.py +84 -86
  123. solace_agent_mesh/evaluation/report_generator.py +73 -79
  124. solace_agent_mesh/evaluation/run.py +421 -235
  125. solace_agent_mesh/evaluation/shared/__init__.py +92 -0
  126. solace_agent_mesh/evaluation/shared/constants.py +47 -0
  127. solace_agent_mesh/evaluation/shared/exceptions.py +50 -0
  128. solace_agent_mesh/evaluation/shared/helpers.py +35 -0
  129. solace_agent_mesh/evaluation/shared/test_case_loader.py +167 -0
  130. solace_agent_mesh/evaluation/shared/test_suite_loader.py +280 -0
  131. solace_agent_mesh/evaluation/subscriber.py +111 -232
  132. solace_agent_mesh/evaluation/summary_builder.py +227 -117
  133. solace_agent_mesh/gateway/base/app.py +16 -1
  134. solace_agent_mesh/gateway/base/component.py +112 -39
  135. solace_agent_mesh/gateway/http_sse/alembic/versions/20251015_add_session_performance_indexes.py +70 -0
  136. solace_agent_mesh/gateway/http_sse/component.py +99 -3
  137. solace_agent_mesh/gateway/http_sse/dependencies.py +4 -4
  138. solace_agent_mesh/gateway/http_sse/main.py +1 -0
  139. solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +12 -13
  140. solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +15 -18
  141. solace_agent_mesh/gateway/http_sse/repository/interfaces.py +25 -18
  142. solace_agent_mesh/gateway/http_sse/repository/session_repository.py +30 -26
  143. solace_agent_mesh/gateway/http_sse/repository/task_repository.py +35 -44
  144. solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +4 -3
  145. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +95 -203
  146. solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +4 -3
  147. solace_agent_mesh/gateway/http_sse/routers/sessions.py +2 -2
  148. solace_agent_mesh/gateway/http_sse/routers/tasks.py +33 -41
  149. solace_agent_mesh/gateway/http_sse/routers/users.py +47 -1
  150. solace_agent_mesh/gateway/http_sse/routers/visualization.py +17 -11
  151. solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +4 -4
  152. solace_agent_mesh/gateway/http_sse/services/feedback_service.py +51 -43
  153. solace_agent_mesh/gateway/http_sse/services/session_service.py +20 -20
  154. solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +8 -8
  155. solace_agent_mesh/gateway/http_sse/shared/base_repository.py +45 -71
  156. solace_agent_mesh/gateway/http_sse/shared/types.py +0 -18
  157. solace_agent_mesh/templates/gateway_config_template.yaml +0 -5
  158. solace_agent_mesh/templates/logging_config_template.ini +10 -6
  159. solace_agent_mesh/templates/plugin_gateway_config_template.yaml +0 -3
  160. solace_agent_mesh/templates/shared_config.yaml +40 -0
  161. {solace_agent_mesh-1.5.1.dist-info → solace_agent_mesh-1.6.1.dist-info}/METADATA +47 -21
  162. {solace_agent_mesh-1.5.1.dist-info → solace_agent_mesh-1.6.1.dist-info}/RECORD +166 -145
  163. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.e49689dd.js +0 -1
  164. solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.39d5851d.js +0 -1
  165. solace_agent_mesh/assets/docs/assets/js/71da7b71.804d6567.js +0 -1
  166. solace_agent_mesh/assets/docs/assets/js/77cf947d.64c9bd6c.js +0 -1
  167. solace_agent_mesh/assets/docs/assets/js/9e9d0a82.dd810042.js +0 -1
  168. solace_agent_mesh/assets/docs/assets/js/db924877.cbc66f02.js +0 -1
  169. solace_agent_mesh/assets/docs/assets/js/de915948.139b4b9c.js +0 -1
  170. solace_agent_mesh/assets/docs/assets/js/e6f9706b.582a78ca.js +0 -1
  171. solace_agent_mesh/assets/docs/assets/js/f284c35a.5766a13d.js +0 -1
  172. solace_agent_mesh/assets/docs/assets/js/ff4d71f2.9c0297a6.js +0 -1
  173. solace_agent_mesh/assets/docs/assets/js/runtime~main.18dc45dd.js +0 -1
  174. solace_agent_mesh/assets/docs/lunr-index-1760121512891.json +0 -1
  175. solace_agent_mesh/assets/docs/search-doc-1760121512891.json +0 -1
  176. solace_agent_mesh/client/webui/frontend/static/assets/main-2nd1gbaH.js +0 -339
  177. solace_agent_mesh/client/webui/frontend/static/assets/main-DoKXctCM.css +0 -1
  178. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-BNuqpWDc.js +0 -98
  179. solace_agent_mesh/evaluation/config_loader.py +0 -657
  180. solace_agent_mesh/evaluation/test_case_loader.py +0 -714
  181. /solace_agent_mesh/assets/docs/assets/js/{main.bd3c34f3.js.LICENSE.txt → main.b12eac43.js.LICENSE.txt} +0 -0
  182. {solace_agent_mesh-1.5.1.dist-info → solace_agent_mesh-1.6.1.dist-info}/WHEEL +0 -0
  183. {solace_agent_mesh-1.5.1.dist-info → solace_agent_mesh-1.6.1.dist-info}/entry_points.txt +0 -0
  184. {solace_agent_mesh-1.5.1.dist-info → solace_agent_mesh-1.6.1.dist-info}/licenses/LICENSE +0 -0
@@ -5,27 +5,23 @@ This module generates HTML reports from evaluation results with a clean, modular
5
5
 
6
6
  import json
7
7
  import logging
8
- from datetime import datetime
9
8
  from dataclasses import dataclass, field
10
- from typing import Dict, Any
9
+ from datetime import datetime
11
10
  from pathlib import Path
12
11
 
13
- # Set up logging
14
- logging.basicConfig(level=logging.INFO)
15
- logger = logging.getLogger(__name__)
16
-
17
- # Import configuration and data services
18
- from .config_loader import ConfigLoader
19
12
  from .report_data_processor import ReportDataProcessor
13
+ from .shared import EvaluationConfigLoader, TestSuiteConfiguration
14
+
15
+ log = logging.getLogger(__name__)
20
16
 
21
17
 
22
18
  @dataclass
23
19
  class ReportConfig:
24
20
  """Centralized configuration for report generation."""
25
21
 
26
- def __init__(self, config_data: Dict[str, Any], results_dir: Path):
27
- self.config_data = config_data
28
- self.results_dir_name = config_data.get("results_dir_name", "tests")
22
+ def __init__(self, config: TestSuiteConfiguration, results_dir: Path):
23
+ self.config = config
24
+ self.results_dir_name = config.results_directory
29
25
 
30
26
  # Calculate paths
31
27
  self.script_dir = Path(__file__).parent
@@ -78,19 +74,19 @@ class ConfigurationService:
78
74
  """Handles configuration loading and validation."""
79
75
 
80
76
  def __init__(self, config_path: str):
81
- self.config_loader = ConfigLoader(config_path)
77
+ self.config_loader = EvaluationConfigLoader(config_path)
82
78
  self._config_cache = None
83
79
 
84
- def get_config(self) -> Dict[str, Any]:
80
+ def get_config(self) -> TestSuiteConfiguration:
85
81
  """Get the main configuration."""
86
82
  if self._config_cache is None:
87
- self._config_cache = self.config_loader.load_config()
83
+ self._config_cache = self.config_loader.load_configuration()
88
84
  return self._config_cache
89
85
 
90
86
  def create_report_config(self, results_dir: Path) -> ReportConfig:
91
87
  """Create a ReportConfig instance."""
92
- config_data = self.get_config()
93
- return ReportConfig(config_data, results_dir)
88
+ config = self.get_config()
89
+ return ReportConfig(config, results_dir)
94
90
 
95
91
 
96
92
  class FileService:
@@ -100,13 +96,12 @@ class FileService:
100
96
  def read_file(filepath: Path, encoding: str = "utf-8") -> str:
101
97
  """Read file content with error handling."""
102
98
  try:
103
- with open(filepath, "r", encoding=encoding) as f:
104
- return f.read()
99
+ return filepath.read_text(encoding=encoding)
105
100
  except FileNotFoundError:
106
- logger.error(f"File not found: {filepath}")
101
+ log.error(f"File not found: {filepath}")
107
102
  raise
108
103
  except Exception as e:
109
- logger.error(f"Error reading file {filepath}: {e}")
104
+ log.error(f"Error reading file {filepath}: {e}")
110
105
  raise
111
106
 
112
107
  @staticmethod
@@ -116,11 +111,10 @@ class FileService:
116
111
  # Ensure directory exists
117
112
  filepath.parent.mkdir(parents=True, exist_ok=True)
118
113
 
119
- with open(filepath, "w", encoding=encoding) as f:
120
- f.write(content)
121
- logger.info(f"File written successfully: {filepath}")
114
+ filepath.write_text(content, encoding=encoding)
115
+ log.info(f"File written successfully: {filepath}")
122
116
  except Exception as e:
123
- logger.error(f"Error writing file {filepath}: {e}")
117
+ log.error(f"Error writing file {filepath}: {e}")
124
118
  raise
125
119
 
126
120
  @staticmethod
@@ -138,20 +132,20 @@ class TemplateService:
138
132
  def load_template(self, template_path: Path) -> str:
139
133
  """Load a single template file."""
140
134
  if not self.file_service.file_exists(template_path):
141
- logger.warning(f"Template file not found: {template_path}")
135
+ log.warning(f"Template file not found: {template_path}")
142
136
  return ""
143
137
 
144
138
  try:
145
139
  content = self.file_service.read_file(template_path)
146
- logger.debug(f"Loaded template: {template_path}")
140
+ log.debug(f"Loaded template: {template_path}")
147
141
  return content
148
142
  except Exception as e:
149
- logger.error(f"Failed to load template {template_path}: {e}")
143
+ log.error(f"Failed to load template {template_path}: {e}")
150
144
  return ""
151
145
 
152
146
  def load_all_templates(self, config: ReportConfig) -> TemplateAssets:
153
147
  """Load all required templates including modal components."""
154
- logger.info("Loading HTML templates and modal components...")
148
+ log.info("Loading HTML templates and modal components...")
155
149
 
156
150
  assets = TemplateAssets()
157
151
 
@@ -170,7 +164,7 @@ class TemplateService:
170
164
  content = self.load_template(template_path)
171
165
  setattr(assets, template_name, content)
172
166
 
173
- logger.info(f"Loaded {len(template_files)} templates")
167
+ log.info(f"Loaded {len(template_files)} templates")
174
168
  return assets
175
169
 
176
170
 
@@ -185,38 +179,38 @@ class AssetService:
185
179
  css_path = report_dir / "performance_metrics_styles.css"
186
180
 
187
181
  if not self.file_service.file_exists(css_path):
188
- logger.warning(f"CSS file not found: {css_path}")
182
+ log.warning(f"CSS file not found: {css_path}")
189
183
  return ""
190
184
 
191
185
  try:
192
186
  content = self.file_service.read_file(css_path)
193
- logger.info(f"Loaded CSS content from: {css_path}")
187
+ log.info(f"Loaded CSS content from: {css_path}")
194
188
  return content
195
189
  except Exception as e:
196
- logger.error(f"Failed to load CSS content: {e}")
190
+ log.error(f"Failed to load CSS content: {e}")
197
191
  return ""
198
192
 
199
193
  def load_modal_assets(self, report_dir: Path, assets: TemplateAssets):
200
194
  """Load modal CSS and JavaScript files."""
201
- logger.info("Loading modal assets...")
195
+ log.info("Loading modal assets...")
202
196
 
203
197
  # Load modal CSS
204
198
  modal_css_path = report_dir / "modal_styles.css"
205
199
  if self.file_service.file_exists(modal_css_path):
206
200
  try:
207
201
  assets.modal_css = self.file_service.read_file(modal_css_path)
208
- logger.info("Loaded modal CSS")
202
+ log.info("Loaded modal CSS")
209
203
  except Exception as e:
210
- logger.error(f"Failed to load modal CSS: {e}")
204
+ log.error(f"Failed to load modal CSS: {e}")
211
205
 
212
206
  # Load modal JavaScript files
213
207
  modal_script_path = report_dir / "modal_script.js"
214
208
  if self.file_service.file_exists(modal_script_path):
215
209
  try:
216
210
  assets.modal_script_js = self.file_service.read_file(modal_script_path)
217
- logger.info("Loaded modal script JS")
211
+ log.info("Loaded modal script JS")
218
212
  except Exception as e:
219
- logger.error(f"Failed to load modal script JS: {e}")
213
+ log.error(f"Failed to load modal script JS: {e}")
220
214
 
221
215
  modal_chart_functions_path = report_dir / "modal_chart_functions.js"
222
216
  if self.file_service.file_exists(modal_chart_functions_path):
@@ -224,18 +218,18 @@ class AssetService:
224
218
  assets.modal_chart_functions_js = self.file_service.read_file(
225
219
  modal_chart_functions_path
226
220
  )
227
- logger.info("Loaded modal chart functions JS")
221
+ log.info("Loaded modal chart functions JS")
228
222
  except Exception as e:
229
- logger.error(f"Failed to load modal chart functions JS: {e}")
223
+ log.error(f"Failed to load modal chart functions JS: {e}")
230
224
 
231
- logger.info("Modal assets loaded successfully")
225
+ log.info("Modal assets loaded successfully")
232
226
 
233
227
 
234
228
  class TemplateProcessor:
235
229
  """Handles template rendering and placeholder replacement."""
236
230
 
237
231
  @staticmethod
238
- def replace_placeholders(template_content: str, data: Dict[str, Any]) -> str:
232
+ def replace_placeholders(template_content: str, data: dict[str, any]) -> str:
239
233
  """Replace placeholders in template with actual data."""
240
234
  try:
241
235
  # Convert all values to strings for replacement
@@ -264,15 +258,15 @@ class TemplateProcessor:
264
258
  return processed_content
265
259
 
266
260
  except Exception as e:
267
- logger.error(f"Error replacing placeholders: {e}")
261
+ log.error(f"Error replacing placeholders: {e}")
268
262
  return template_content
269
263
 
270
264
  def process_template_with_data(
271
- self, template_content: str, data: Dict[str, Any]
265
+ self, template_content: str, data: dict[str, any]
272
266
  ) -> str:
273
267
  """Process a template with evaluation data."""
274
268
  if not template_content:
275
- logger.warning("Empty template content provided")
269
+ log.warning("Empty template content provided")
276
270
  return ""
277
271
 
278
272
  return self.replace_placeholders(template_content, data)
@@ -295,11 +289,11 @@ class CSSProcessor:
295
289
  inline_css_block = f"<style>\n{css_content}\n</style>"
296
290
 
297
291
  processed_html = html_content.replace(css_link_pattern, inline_css_block)
298
- logger.debug("CSS content inlined successfully")
292
+ log.debug("CSS content inlined successfully")
299
293
  return processed_html
300
294
 
301
295
  except Exception as e:
302
- logger.error(f"Error inlining CSS: {e}")
296
+ log.error(f"Error inlining CSS: {e}")
303
297
  return html_content
304
298
 
305
299
  @staticmethod
@@ -380,11 +374,11 @@ class CSSProcessor:
380
374
  # Fallback: append to end
381
375
  processed_html += modal_content
382
376
 
383
- logger.debug("Modal assets inlined successfully")
377
+ log.debug("Modal assets inlined successfully")
384
378
  return processed_html
385
379
 
386
380
  except Exception as e:
387
- logger.error(f"Error inlining modal assets: {e}")
381
+ log.error(f"Error inlining modal assets: {e}")
388
382
  return html_content
389
383
 
390
384
 
@@ -400,11 +394,11 @@ class HTMLAssembler:
400
394
  def assemble_report(
401
395
  self,
402
396
  assets: TemplateAssets,
403
- evaluation_data: Dict[str, Any],
404
- detailed_data: Dict[str, Any],
397
+ evaluation_data: dict[str, any],
398
+ detailed_data: dict[str, any],
405
399
  ) -> str:
406
400
  """Assemble the complete HTML report with modal functionality."""
407
- logger.info("Assembling HTML report with modal functionality...")
401
+ log.info("Assembling HTML report with modal functionality...")
408
402
 
409
403
  try:
410
404
  # Process each template with appropriate data
@@ -447,11 +441,11 @@ class HTMLAssembler:
447
441
  # Inline CSS and modal assets into the complete HTML
448
442
  final_html = self.css_processor.inline_modal_assets(final_html, assets)
449
443
 
450
- logger.info("HTML report with modal functionality assembled successfully")
444
+ log.info("HTML report with modal functionality assembled successfully")
451
445
  return final_html
452
446
 
453
447
  except Exception as e:
454
- logger.error(f"Error assembling HTML report: {e}")
448
+ log.error(f"Error assembling HTML report: {e}")
455
449
  raise
456
450
 
457
451
 
@@ -460,8 +454,8 @@ class ReportSummaryService:
460
454
 
461
455
  @staticmethod
462
456
  def generate_summary(
463
- evaluation_data: Dict[str, Any], output_path: Path
464
- ) -> Dict[str, str]:
457
+ evaluation_data: dict[str, any], output_path: Path
458
+ ) -> dict[str, str]:
465
459
  """Generate summary information for logging."""
466
460
  models = evaluation_data.get("models", [])
467
461
  execution_time = evaluation_data.get(
@@ -496,7 +490,7 @@ class ReportGenerator:
496
490
 
497
491
  def generate_report(self, results_dir: Path):
498
492
  """Main entry point for report generation."""
499
- logger.info("--- Starting HTML report generation ---")
493
+ log.info("--- Starting HTML report generation ---")
500
494
 
501
495
  try:
502
496
  # Load configuration
@@ -519,22 +513,22 @@ class ReportGenerator:
519
513
  # Generate and log summary
520
514
  self._log_summary(evaluation_data, config.output_path)
521
515
 
522
- logger.info("--- HTML report generation completed successfully ---")
516
+ log.info("--- HTML report generation completed successfully ---")
523
517
 
524
518
  except Exception as e:
525
- logger.error(f"Report generation failed: {e}")
519
+ log.error(f"Report generation failed: {e}")
526
520
  raise
527
521
 
528
522
  def _load_configuration(self, results_dir: Path) -> ReportConfig:
529
523
  """Load and validate configuration."""
530
- logger.info("Loading configuration...")
524
+ log.info("Loading configuration...")
531
525
  config = self.config_service.create_report_config(results_dir)
532
- logger.info(f"Configuration loaded. Results directory: {config.results_dir}")
526
+ log.info(f"Configuration loaded. Results directory: {config.results_dir}")
533
527
  return config
534
528
 
535
529
  def _load_assets(self, config: ReportConfig) -> TemplateAssets:
536
530
  """Load all templates and assets including modal components."""
537
- logger.info("Loading templates and assets...")
531
+ log.info("Loading templates and assets...")
538
532
 
539
533
  # Load templates
540
534
  assets = self.template_service.load_all_templates(config)
@@ -545,53 +539,53 @@ class ReportGenerator:
545
539
  # Load modal assets
546
540
  self.asset_service.load_modal_assets(config.report_dir, assets)
547
541
 
548
- logger.info("Templates and assets loaded successfully")
542
+ log.info("Templates and assets loaded successfully")
549
543
  return assets
550
544
 
551
545
  def _get_evaluation_data(
552
546
  self, config: ReportConfig
553
- ) -> tuple[Dict[str, Any], Dict[str, Any]]:
547
+ ) -> tuple[dict[str, any], dict[str, any]]:
554
548
  """Get evaluation data from the data processor."""
555
- logger.info("Extracting evaluation data...")
549
+ log.info("Extracting evaluation data...")
556
550
 
557
551
  evaluation_data = self.data_processor.get_evaluation_data(config.results_dir)
558
552
  detailed_data = self.data_processor.get_detailed_evaluation_data(
559
553
  config.results_dir
560
554
  )
561
555
 
562
- logger.info("Evaluation data extracted successfully")
556
+ log.info("Evaluation data extracted successfully")
563
557
  return evaluation_data, detailed_data
564
558
 
565
559
  def _generate_html_content(
566
560
  self,
567
561
  assets: TemplateAssets,
568
- evaluation_data: Dict[str, Any],
569
- detailed_data: Dict[str, Any],
562
+ evaluation_data: dict[str, any],
563
+ detailed_data: dict[str, any],
570
564
  ) -> str:
571
565
  """Generate the complete HTML content."""
572
- logger.info("Generating HTML content...")
566
+ log.info("Generating HTML content...")
573
567
 
574
568
  html_content = self.html_assembler.assemble_report(
575
569
  assets, evaluation_data, detailed_data
576
570
  )
577
571
 
578
- logger.info("HTML content generated successfully")
572
+ log.info("HTML content generated successfully")
579
573
  return html_content
580
574
 
581
575
  def _write_report(self, html_content: str, output_path: Path):
582
576
  """Write the HTML report to file."""
583
- logger.info(f"Writing report to: {output_path}")
577
+ log.info(f"Writing report to: {output_path}")
584
578
  self.file_service.write_file(output_path, html_content)
585
579
 
586
- def _log_summary(self, evaluation_data: Dict[str, Any], output_path: Path):
580
+ def _log_summary(self, evaluation_data: dict[str, any], output_path: Path):
587
581
  """Log summary information about the generated report."""
588
582
  summary = self.summary_service.generate_summary(evaluation_data, output_path)
589
583
 
590
- logger.info("--- Report Generation Summary ---")
591
- logger.info(f"Report generated at: {summary['output_path']}")
592
- logger.info(f"Models evaluated: {summary['models_evaluated']}")
593
- logger.info(f"Total execution time: {summary['total_execution_time']}")
594
- logger.info(f"Generation completed at: {summary['generation_time']}")
584
+ log.info("--- Report Generation Summary ---")
585
+ log.info(f"Report generated at: {summary['output_path']}")
586
+ log.info(f"Models evaluated: {summary['models_evaluated']}")
587
+ log.info(f"Total execution time: {summary['total_execution_time']}")
588
+ log.info(f"Generation completed at: {summary['generation_time']}")
595
589
 
596
590
 
597
591
  def main(config_path: str = "evaluation/test_suite_config.json"):
@@ -599,13 +593,13 @@ def main(config_path: str = "evaluation/test_suite_config.json"):
599
593
  try:
600
594
  generator = ReportGenerator(config_path)
601
595
  # For standalone execution, calculate results_dir based on config
602
- config_data = generator.config_service.get_config()
603
- results_dir_name = config_data.get("results_dir_name", "tests")
596
+ config = generator.config_service.get_config()
597
+ results_dir_name = config.results_directory
604
598
  script_dir = Path(__file__).parent
605
599
  results_dir = script_dir / "results" / results_dir_name
606
600
  generator.generate_report(results_dir)
607
601
  except Exception as e:
608
- logger.error(f"Report generation failed: {e}")
602
+ log.error(f"Report generation failed: {e}")
609
603
  raise
610
604
 
611
605