solace-agent-mesh 0.2.3__py3-none-any.whl → 1.0.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 (518) hide show
  1. solace_agent_mesh/agent/adk/adk_llm.txt +93 -0
  2. solace_agent_mesh/agent/adk/app_llm_agent.py +26 -0
  3. solace_agent_mesh/agent/adk/callbacks.py +1694 -0
  4. solace_agent_mesh/agent/adk/filesystem_artifact_service.py +381 -0
  5. solace_agent_mesh/agent/adk/invocation_monitor.py +295 -0
  6. solace_agent_mesh/agent/adk/models/lite_llm.py +872 -0
  7. solace_agent_mesh/agent/adk/models/models_llm.txt +94 -0
  8. solace_agent_mesh/agent/adk/runner.py +353 -0
  9. solace_agent_mesh/agent/adk/services.py +240 -0
  10. solace_agent_mesh/agent/adk/setup.py +751 -0
  11. solace_agent_mesh/agent/adk/stream_parser.py +214 -0
  12. solace_agent_mesh/agent/adk/tool_wrapper.py +139 -0
  13. solace_agent_mesh/agent/agent_llm.txt +41 -0
  14. solace_agent_mesh/agent/protocol/event_handlers.py +1469 -0
  15. solace_agent_mesh/agent/protocol/protocol_llm.txt +21 -0
  16. solace_agent_mesh/agent/sac/app.py +640 -0
  17. solace_agent_mesh/agent/sac/component.py +3388 -0
  18. solace_agent_mesh/agent/sac/patch_adk.py +111 -0
  19. solace_agent_mesh/agent/sac/sac_llm.txt +105 -0
  20. solace_agent_mesh/agent/sac/task_execution_context.py +176 -0
  21. solace_agent_mesh/agent/testing/__init__.py +3 -0
  22. solace_agent_mesh/agent/testing/debug_utils.py +135 -0
  23. solace_agent_mesh/agent/testing/testing_llm.txt +90 -0
  24. solace_agent_mesh/agent/tools/__init__.py +14 -0
  25. solace_agent_mesh/agent/tools/audio_tools.py +1622 -0
  26. solace_agent_mesh/agent/tools/builtin_artifact_tools.py +1954 -0
  27. solace_agent_mesh/agent/tools/builtin_data_analysis_tools.py +238 -0
  28. solace_agent_mesh/agent/tools/general_agent_tools.py +569 -0
  29. solace_agent_mesh/agent/tools/image_tools.py +1184 -0
  30. solace_agent_mesh/agent/tools/peer_agent_tool.py +289 -0
  31. solace_agent_mesh/agent/tools/registry.py +36 -0
  32. solace_agent_mesh/agent/tools/test_tools.py +135 -0
  33. solace_agent_mesh/agent/tools/tool_definition.py +45 -0
  34. solace_agent_mesh/agent/tools/tools_llm.txt +104 -0
  35. solace_agent_mesh/agent/tools/web_tools.py +381 -0
  36. solace_agent_mesh/agent/utils/artifact_helpers.py +927 -0
  37. solace_agent_mesh/agent/utils/config_parser.py +47 -0
  38. solace_agent_mesh/agent/utils/context_helpers.py +60 -0
  39. solace_agent_mesh/agent/utils/utils_llm.txt +153 -0
  40. solace_agent_mesh/assets/docs/404.html +16 -0
  41. solace_agent_mesh/assets/docs/assets/css/styles.906a1503.css +1 -0
  42. solace_agent_mesh/assets/docs/assets/images/Solace_AI_Framework_With_Broker-85f0a306a9bcdd20b390b7a949f6d862.png +0 -0
  43. solace_agent_mesh/assets/docs/assets/images/sac-flows-80d5b603c6aafd33e87945680ce0abf3.png +0 -0
  44. solace_agent_mesh/assets/docs/assets/images/sac_parts_of_a_component-cb3d0424b1d0c17734c5435cca6b4082.png +0 -0
  45. solace_agent_mesh/assets/docs/assets/js/04989206.674a8007.js +1 -0
  46. solace_agent_mesh/assets/docs/assets/js/0e682baa.79f0ab22.js +1 -0
  47. solace_agent_mesh/assets/docs/assets/js/1001.0182a8bd.js +1 -0
  48. solace_agent_mesh/assets/docs/assets/js/1023fc19.015679ca.js +1 -0
  49. solace_agent_mesh/assets/docs/assets/js/1039.0bd46aa1.js +1 -0
  50. solace_agent_mesh/assets/docs/assets/js/149.b797a808.js +1 -0
  51. solace_agent_mesh/assets/docs/assets/js/1523c6b4.91c7bc01.js +1 -0
  52. solace_agent_mesh/assets/docs/assets/js/165.6a39807d.js +2 -0
  53. solace_agent_mesh/assets/docs/assets/js/165.6a39807d.js.LICENSE.txt +9 -0
  54. solace_agent_mesh/assets/docs/assets/js/166ab619.7d97ccaf.js +1 -0
  55. solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js +2 -0
  56. solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js.LICENSE.txt +7 -0
  57. solace_agent_mesh/assets/docs/assets/js/1c6e87d2.23bccffb.js +1 -0
  58. solace_agent_mesh/assets/docs/assets/js/2130.ab9fd314.js +1 -0
  59. solace_agent_mesh/assets/docs/assets/js/21ceee5f.614fa8dd.js +1 -0
  60. solace_agent_mesh/assets/docs/assets/js/2237.5e477fc6.js +1 -0
  61. solace_agent_mesh/assets/docs/assets/js/2334.622a6395.js +1 -0
  62. solace_agent_mesh/assets/docs/assets/js/2a9cab12.8909df92.js +1 -0
  63. solace_agent_mesh/assets/docs/assets/js/3219.adc1d663.js +1 -0
  64. solace_agent_mesh/assets/docs/assets/js/332e10b5.7a103f42.js +1 -0
  65. solace_agent_mesh/assets/docs/assets/js/3624.b524e433.js +1 -0
  66. solace_agent_mesh/assets/docs/assets/js/375.708d48db.js +1 -0
  67. solace_agent_mesh/assets/docs/assets/js/3834.b6cd790e.js +1 -0
  68. solace_agent_mesh/assets/docs/assets/js/3d406171.f722eaf5.js +1 -0
  69. solace_agent_mesh/assets/docs/assets/js/4250.95455b28.js +1 -0
  70. solace_agent_mesh/assets/docs/assets/js/42b3f8d8.36090198.js +1 -0
  71. solace_agent_mesh/assets/docs/assets/js/4356.d169ab5b.js +1 -0
  72. solace_agent_mesh/assets/docs/assets/js/442a8107.5ba94b65.js +1 -0
  73. solace_agent_mesh/assets/docs/assets/js/4458.518e66fa.js +1 -0
  74. solace_agent_mesh/assets/docs/assets/js/4488.c7cc3442.js +1 -0
  75. solace_agent_mesh/assets/docs/assets/js/4494.6ee23046.js +1 -0
  76. solace_agent_mesh/assets/docs/assets/js/4855.fc4444b6.js +1 -0
  77. solace_agent_mesh/assets/docs/assets/js/4866.22daefc0.js +1 -0
  78. solace_agent_mesh/assets/docs/assets/js/4950.ca4caeda.js +1 -0
  79. solace_agent_mesh/assets/docs/assets/js/4c2787c2.66ee00e9.js +1 -0
  80. solace_agent_mesh/assets/docs/assets/js/5388.7a136447.js +1 -0
  81. solace_agent_mesh/assets/docs/assets/js/55f47984.c484bf96.js +1 -0
  82. solace_agent_mesh/assets/docs/assets/js/5607.081356f8.js +1 -0
  83. solace_agent_mesh/assets/docs/assets/js/5864.b0d0e9de.js +1 -0
  84. solace_agent_mesh/assets/docs/assets/js/5b4258a4.bda20761.js +1 -0
  85. solace_agent_mesh/assets/docs/assets/js/5e95c892.558d5167.js +1 -0
  86. solace_agent_mesh/assets/docs/assets/js/6143.0a1464c9.js +1 -0
  87. solace_agent_mesh/assets/docs/assets/js/6395.e9c73649.js +1 -0
  88. solace_agent_mesh/assets/docs/assets/js/6796.51d2c9b7.js +1 -0
  89. solace_agent_mesh/assets/docs/assets/js/6976.379be23b.js +1 -0
  90. solace_agent_mesh/assets/docs/assets/js/6978.ee0b945c.js +1 -0
  91. solace_agent_mesh/assets/docs/assets/js/7040.cb436723.js +1 -0
  92. solace_agent_mesh/assets/docs/assets/js/7195.412f418a.js +1 -0
  93. solace_agent_mesh/assets/docs/assets/js/7280.3fb73bdb.js +1 -0
  94. solace_agent_mesh/assets/docs/assets/js/768e31b0.a12673db.js +1 -0
  95. solace_agent_mesh/assets/docs/assets/js/7845.e33e7c4c.js +1 -0
  96. solace_agent_mesh/assets/docs/assets/js/7900.69516146.js +1 -0
  97. solace_agent_mesh/assets/docs/assets/js/8356.8a379c04.js +1 -0
  98. solace_agent_mesh/assets/docs/assets/js/85387663.6bf41934.js +1 -0
  99. solace_agent_mesh/assets/docs/assets/js/8567.4732c6b7.js +1 -0
  100. solace_agent_mesh/assets/docs/assets/js/8573.cb04eda5.js +1 -0
  101. solace_agent_mesh/assets/docs/assets/js/8577.1d54e766.js +1 -0
  102. solace_agent_mesh/assets/docs/assets/js/8591.d7c16be6.js +2 -0
  103. solace_agent_mesh/assets/docs/assets/js/8591.d7c16be6.js.LICENSE.txt +61 -0
  104. solace_agent_mesh/assets/docs/assets/js/8709.7ecd4047.js +1 -0
  105. solace_agent_mesh/assets/docs/assets/js/8731.49e930c2.js +1 -0
  106. solace_agent_mesh/assets/docs/assets/js/8908.f9d1b506.js +1 -0
  107. solace_agent_mesh/assets/docs/assets/js/9157.b4093d07.js +1 -0
  108. solace_agent_mesh/assets/docs/assets/js/9278.a4fd875d.js +1 -0
  109. solace_agent_mesh/assets/docs/assets/js/945fb41e.74d728aa.js +1 -0
  110. solace_agent_mesh/assets/docs/assets/js/9616.b75c2f6d.js +1 -0
  111. solace_agent_mesh/assets/docs/assets/js/9793.c6d16376.js +1 -0
  112. solace_agent_mesh/assets/docs/assets/js/9eff14a2.1bf8f61c.js +1 -0
  113. solace_agent_mesh/assets/docs/assets/js/a3a92b25.26ca071f.js +1 -0
  114. solace_agent_mesh/assets/docs/assets/js/a7bd4aaa.2204d2f7.js +1 -0
  115. solace_agent_mesh/assets/docs/assets/js/a94703ab.0438dbc2.js +1 -0
  116. solace_agent_mesh/assets/docs/assets/js/aba21aa0.c42a534c.js +1 -0
  117. solace_agent_mesh/assets/docs/assets/js/aba87c2f.d3e2dcc3.js +1 -0
  118. solace_agent_mesh/assets/docs/assets/js/ae4415af.8e279b5d.js +1 -0
  119. solace_agent_mesh/assets/docs/assets/js/b7006a3a.40b10c9d.js +1 -0
  120. solace_agent_mesh/assets/docs/assets/js/bac0be12.f50d9bac.js +1 -0
  121. solace_agent_mesh/assets/docs/assets/js/bb2ef573.207e6990.js +1 -0
  122. solace_agent_mesh/assets/docs/assets/js/c2c06897.63b76e9e.js +1 -0
  123. solace_agent_mesh/assets/docs/assets/js/cc969b05.954186d4.js +1 -0
  124. solace_agent_mesh/assets/docs/assets/js/cd3d4052.ca6eed8c.js +1 -0
  125. solace_agent_mesh/assets/docs/assets/js/ced92a13.fb92e7ca.js +1 -0
  126. solace_agent_mesh/assets/docs/assets/js/cee5d587.f5b73ca1.js +1 -0
  127. solace_agent_mesh/assets/docs/assets/js/f284c35a.ecc3d195.js +1 -0
  128. solace_agent_mesh/assets/docs/assets/js/f897a61a.2c2e152c.js +1 -0
  129. solace_agent_mesh/assets/docs/assets/js/fbfa3e75.aca209c9.js +1 -0
  130. solace_agent_mesh/assets/docs/assets/js/main.7ed3319f.js +2 -0
  131. solace_agent_mesh/assets/docs/assets/js/main.7ed3319f.js.LICENSE.txt +81 -0
  132. solace_agent_mesh/assets/docs/assets/js/runtime~main.d9520ae2.js +1 -0
  133. solace_agent_mesh/assets/docs/docs/documentation/concepts/agents/index.html +128 -0
  134. solace_agent_mesh/assets/docs/docs/documentation/concepts/architecture/index.html +91 -0
  135. solace_agent_mesh/assets/docs/docs/documentation/concepts/cli/index.html +201 -0
  136. solace_agent_mesh/assets/docs/docs/documentation/concepts/gateways/index.html +91 -0
  137. solace_agent_mesh/assets/docs/docs/documentation/concepts/orchestrator/index.html +55 -0
  138. solace_agent_mesh/assets/docs/docs/documentation/concepts/plugins/index.html +82 -0
  139. solace_agent_mesh/assets/docs/docs/documentation/deployment/debugging/index.html +60 -0
  140. solace_agent_mesh/assets/docs/docs/documentation/deployment/deploy/index.html +48 -0
  141. solace_agent_mesh/assets/docs/docs/documentation/deployment/observability/index.html +54 -0
  142. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +17 -0
  143. solace_agent_mesh/assets/docs/docs/documentation/getting-started/component-overview/index.html +45 -0
  144. solace_agent_mesh/assets/docs/docs/documentation/getting-started/installation/index.html +76 -0
  145. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +150 -0
  146. solace_agent_mesh/assets/docs/docs/documentation/getting-started/quick-start/index.html +54 -0
  147. solace_agent_mesh/assets/docs/docs/documentation/tutorials/bedrock-agents/index.html +267 -0
  148. solace_agent_mesh/assets/docs/docs/documentation/tutorials/custom-agent/index.html +136 -0
  149. solace_agent_mesh/assets/docs/docs/documentation/tutorials/event-mesh-gateway/index.html +116 -0
  150. solace_agent_mesh/assets/docs/docs/documentation/tutorials/mcp-integration/index.html +80 -0
  151. solace_agent_mesh/assets/docs/docs/documentation/tutorials/mongodb-integration/index.html +164 -0
  152. solace_agent_mesh/assets/docs/docs/documentation/tutorials/rest-gateway/index.html +57 -0
  153. solace_agent_mesh/assets/docs/docs/documentation/tutorials/slack-integration/index.html +72 -0
  154. solace_agent_mesh/assets/docs/docs/documentation/tutorials/sql-database/index.html +102 -0
  155. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/artifact-management/index.html +99 -0
  156. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/audio-tools/index.html +90 -0
  157. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/data-analysis-tools/index.html +107 -0
  158. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/embeds/index.html +152 -0
  159. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/index.html +103 -0
  160. solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-agents/index.html +170 -0
  161. solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-gateways/index.html +200 -0
  162. solace_agent_mesh/assets/docs/docs/documentation/user-guide/creating-service-providers/index.html +54 -0
  163. solace_agent_mesh/assets/docs/docs/documentation/user-guide/solace-ai-connector/index.html +69 -0
  164. solace_agent_mesh/assets/docs/docs/documentation/user-guide/structure/index.html +59 -0
  165. solace_agent_mesh/assets/docs/img/Solace_AI_Framework_README.png +0 -0
  166. solace_agent_mesh/assets/docs/img/Solace_AI_Framework_With_Broker.png +0 -0
  167. solace_agent_mesh/assets/docs/img/logo.png +0 -0
  168. solace_agent_mesh/assets/docs/img/sac-flows.png +0 -0
  169. solace_agent_mesh/assets/docs/img/sac_parts_of_a_component.png +0 -0
  170. solace_agent_mesh/assets/docs/img/solace-logo.png +0 -0
  171. solace_agent_mesh/assets/docs/lunr-index-1753813536522.json +1 -0
  172. solace_agent_mesh/assets/docs/lunr-index.json +1 -0
  173. solace_agent_mesh/assets/docs/search-doc-1753813536522.json +1 -0
  174. solace_agent_mesh/assets/docs/search-doc.json +1 -0
  175. solace_agent_mesh/assets/docs/sitemap.xml +1 -0
  176. solace_agent_mesh/cli/__init__.py +1 -1
  177. solace_agent_mesh/cli/commands/add_cmd/__init__.py +15 -0
  178. solace_agent_mesh/cli/commands/add_cmd/add_cmd_llm.txt +250 -0
  179. solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +659 -0
  180. solace_agent_mesh/cli/commands/add_cmd/gateway_cmd.py +322 -0
  181. solace_agent_mesh/cli/commands/add_cmd/web_add_agent_step.py +93 -0
  182. solace_agent_mesh/cli/commands/add_cmd/web_add_gateway_step.py +118 -0
  183. solace_agent_mesh/cli/commands/docs_cmd.py +57 -0
  184. solace_agent_mesh/cli/commands/eval_cmd.py +64 -0
  185. solace_agent_mesh/cli/commands/init_cmd/__init__.py +404 -0
  186. solace_agent_mesh/cli/commands/init_cmd/broker_step.py +201 -0
  187. solace_agent_mesh/cli/commands/init_cmd/directory_step.py +28 -0
  188. solace_agent_mesh/cli/commands/init_cmd/env_step.py +197 -0
  189. solace_agent_mesh/cli/commands/init_cmd/init_cmd_llm.txt +365 -0
  190. solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +387 -0
  191. solace_agent_mesh/cli/commands/init_cmd/project_files_step.py +38 -0
  192. solace_agent_mesh/cli/commands/init_cmd/web_init_step.py +110 -0
  193. solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +183 -0
  194. solace_agent_mesh/cli/commands/plugin_cmd/__init__.py +18 -0
  195. solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +372 -0
  196. solace_agent_mesh/cli/commands/plugin_cmd/build_cmd.py +86 -0
  197. solace_agent_mesh/cli/commands/plugin_cmd/catalog_cmd.py +138 -0
  198. solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +309 -0
  199. solace_agent_mesh/cli/commands/plugin_cmd/official_registry.py +174 -0
  200. solace_agent_mesh/cli/commands/plugin_cmd/plugin_cmd_llm.txt +305 -0
  201. solace_agent_mesh/cli/commands/run_cmd.py +158 -0
  202. solace_agent_mesh/cli/main.py +17 -294
  203. solace_agent_mesh/cli/utils.py +135 -204
  204. solace_agent_mesh/client/webui/frontend/static/assets/authCallback-DvlO62me.js +1 -0
  205. solace_agent_mesh/client/webui/frontend/static/assets/client-bp6u3qVZ.js +49 -0
  206. solace_agent_mesh/client/webui/frontend/static/assets/favicon-BLgzUch9.ico +0 -0
  207. solace_agent_mesh/client/webui/frontend/static/assets/main-An0a5j5k.js +663 -0
  208. solace_agent_mesh/client/webui/frontend/static/assets/main-Bu5-4Bac.css +1 -0
  209. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +14 -0
  210. solace_agent_mesh/client/webui/frontend/static/index.html +15 -0
  211. solace_agent_mesh/common/__init__.py +1 -0
  212. solace_agent_mesh/common/a2a_protocol.py +564 -0
  213. solace_agent_mesh/common/agent_registry.py +42 -0
  214. solace_agent_mesh/common/client/__init__.py +4 -0
  215. solace_agent_mesh/common/client/card_resolver.py +21 -0
  216. solace_agent_mesh/common/client/client.py +85 -0
  217. solace_agent_mesh/common/client/client_llm.txt +133 -0
  218. solace_agent_mesh/common/common_llm.txt +144 -0
  219. solace_agent_mesh/common/constants.py +1 -14
  220. solace_agent_mesh/common/middleware/__init__.py +12 -0
  221. solace_agent_mesh/common/middleware/config_resolver.py +130 -0
  222. solace_agent_mesh/common/middleware/middleware_llm.txt +174 -0
  223. solace_agent_mesh/common/middleware/registry.py +125 -0
  224. solace_agent_mesh/common/server/__init__.py +4 -0
  225. solace_agent_mesh/common/server/server.py +122 -0
  226. solace_agent_mesh/common/server/server_llm.txt +169 -0
  227. solace_agent_mesh/common/server/task_manager.py +291 -0
  228. solace_agent_mesh/common/server/utils.py +28 -0
  229. solace_agent_mesh/common/services/__init__.py +4 -0
  230. solace_agent_mesh/common/services/employee_service.py +162 -0
  231. solace_agent_mesh/common/services/identity_service.py +129 -0
  232. solace_agent_mesh/common/services/providers/__init__.py +4 -0
  233. solace_agent_mesh/common/services/providers/local_file_identity_service.py +148 -0
  234. solace_agent_mesh/common/services/providers/providers_llm.txt +113 -0
  235. solace_agent_mesh/common/services/services_llm.txt +132 -0
  236. solace_agent_mesh/common/types.py +411 -0
  237. solace_agent_mesh/common/utils/__init__.py +7 -0
  238. solace_agent_mesh/common/utils/asyncio_macos_fix.py +86 -0
  239. solace_agent_mesh/common/utils/embeds/__init__.py +33 -0
  240. solace_agent_mesh/common/utils/embeds/constants.py +55 -0
  241. solace_agent_mesh/common/utils/embeds/converter.py +452 -0
  242. solace_agent_mesh/common/utils/embeds/embeds_llm.txt +124 -0
  243. solace_agent_mesh/common/utils/embeds/evaluators.py +394 -0
  244. solace_agent_mesh/common/utils/embeds/modifiers.py +816 -0
  245. solace_agent_mesh/common/utils/embeds/resolver.py +865 -0
  246. solace_agent_mesh/common/utils/embeds/types.py +14 -0
  247. solace_agent_mesh/common/utils/in_memory_cache.py +108 -0
  248. solace_agent_mesh/common/utils/log_formatters.py +44 -0
  249. solace_agent_mesh/common/utils/mime_helpers.py +106 -0
  250. solace_agent_mesh/common/utils/push_notification_auth.py +134 -0
  251. solace_agent_mesh/common/utils/utils_llm.txt +67 -0
  252. solace_agent_mesh/config_portal/backend/common.py +66 -24
  253. solace_agent_mesh/config_portal/backend/plugin_catalog/constants.py +23 -0
  254. solace_agent_mesh/config_portal/backend/plugin_catalog/models.py +49 -0
  255. solace_agent_mesh/config_portal/backend/plugin_catalog/registry_manager.py +160 -0
  256. solace_agent_mesh/config_portal/backend/plugin_catalog/scraper.py +525 -0
  257. solace_agent_mesh/config_portal/backend/plugin_catalog_server.py +216 -0
  258. solace_agent_mesh/config_portal/backend/server.py +550 -140
  259. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-DNxCwAGB.js +48 -0
  260. solace_agent_mesh/config_portal/frontend/static/client/assets/components-B7lKcHVY.js +140 -0
  261. solace_agent_mesh/config_portal/frontend/static/client/assets/{entry.client-DX1misIU.js → entry.client-CEumGClk.js} +3 -3
  262. solace_agent_mesh/config_portal/frontend/static/client/assets/index-DSo1AH_7.js +68 -0
  263. solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-d2b54a97.js +1 -0
  264. solace_agent_mesh/config_portal/frontend/static/client/assets/{root-BApq5dPK.js → root-C4XmHinv.js} +2 -2
  265. solace_agent_mesh/config_portal/frontend/static/client/assets/root-DxRwaWiE.css +1 -0
  266. solace_agent_mesh/config_portal/frontend/static/client/index.html +3 -3
  267. solace_agent_mesh/core_a2a/__init__.py +1 -0
  268. solace_agent_mesh/core_a2a/core_a2a_llm.txt +88 -0
  269. solace_agent_mesh/core_a2a/service.py +331 -0
  270. solace_agent_mesh/evaluation/config_loader.py +657 -0
  271. solace_agent_mesh/evaluation/evaluator.py +667 -0
  272. solace_agent_mesh/evaluation/message_organizer.py +568 -0
  273. solace_agent_mesh/evaluation/report/benchmark_info.html +35 -0
  274. solace_agent_mesh/evaluation/report/chart_section.html +141 -0
  275. solace_agent_mesh/evaluation/report/detailed_breakdown.html +28 -0
  276. solace_agent_mesh/evaluation/report/modal.html +59 -0
  277. solace_agent_mesh/evaluation/report/modal_chart_functions.js +411 -0
  278. solace_agent_mesh/evaluation/report/modal_script.js +296 -0
  279. solace_agent_mesh/evaluation/report/modal_styles.css +340 -0
  280. solace_agent_mesh/evaluation/report/performance_metrics_styles.css +93 -0
  281. solace_agent_mesh/evaluation/report/templates/footer.html +2 -0
  282. solace_agent_mesh/evaluation/report/templates/header.html +340 -0
  283. solace_agent_mesh/evaluation/report_data_processor.py +972 -0
  284. solace_agent_mesh/evaluation/report_generator.py +613 -0
  285. solace_agent_mesh/evaluation/run.py +613 -0
  286. solace_agent_mesh/evaluation/subscriber.py +872 -0
  287. solace_agent_mesh/evaluation/summary_builder.py +775 -0
  288. solace_agent_mesh/evaluation/test_case_loader.py +714 -0
  289. solace_agent_mesh/gateway/base/__init__.py +1 -0
  290. solace_agent_mesh/gateway/base/app.py +266 -0
  291. solace_agent_mesh/gateway/base/base_llm.txt +119 -0
  292. solace_agent_mesh/gateway/base/component.py +1542 -0
  293. solace_agent_mesh/gateway/base/task_context.py +74 -0
  294. solace_agent_mesh/gateway/gateway_llm.txt +125 -0
  295. solace_agent_mesh/gateway/http_sse/app.py +190 -0
  296. solace_agent_mesh/gateway/http_sse/component.py +1602 -0
  297. solace_agent_mesh/gateway/http_sse/components/__init__.py +7 -0
  298. solace_agent_mesh/gateway/http_sse/components/components_llm.txt +65 -0
  299. solace_agent_mesh/gateway/http_sse/components/visualization_forwarder_component.py +108 -0
  300. solace_agent_mesh/gateway/http_sse/dependencies.py +316 -0
  301. solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +63 -0
  302. solace_agent_mesh/gateway/http_sse/main.py +442 -0
  303. solace_agent_mesh/gateway/http_sse/routers/__init__.py +4 -0
  304. solace_agent_mesh/gateway/http_sse/routers/agents.py +41 -0
  305. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +821 -0
  306. solace_agent_mesh/gateway/http_sse/routers/auth.py +212 -0
  307. solace_agent_mesh/gateway/http_sse/routers/config.py +55 -0
  308. solace_agent_mesh/gateway/http_sse/routers/people.py +69 -0
  309. solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +37 -0
  310. solace_agent_mesh/gateway/http_sse/routers/sessions.py +80 -0
  311. solace_agent_mesh/gateway/http_sse/routers/sse.py +138 -0
  312. solace_agent_mesh/gateway/http_sse/routers/tasks.py +294 -0
  313. solace_agent_mesh/gateway/http_sse/routers/users.py +59 -0
  314. solace_agent_mesh/gateway/http_sse/routers/visualization.py +1131 -0
  315. solace_agent_mesh/gateway/http_sse/services/__init__.py +4 -0
  316. solace_agent_mesh/gateway/http_sse/services/agent_service.py +69 -0
  317. solace_agent_mesh/gateway/http_sse/services/people_service.py +158 -0
  318. solace_agent_mesh/gateway/http_sse/services/services_llm.txt +179 -0
  319. solace_agent_mesh/gateway/http_sse/services/task_service.py +121 -0
  320. solace_agent_mesh/gateway/http_sse/session_manager.py +187 -0
  321. solace_agent_mesh/gateway/http_sse/sse_manager.py +328 -0
  322. solace_agent_mesh/llm.txt +228 -0
  323. solace_agent_mesh/llm_detail.txt +2835 -0
  324. solace_agent_mesh/templates/agent_template.yaml +53 -0
  325. solace_agent_mesh/templates/eval_backend_template.yaml +54 -0
  326. solace_agent_mesh/templates/gateway_app_template.py +73 -0
  327. solace_agent_mesh/templates/gateway_component_template.py +400 -0
  328. solace_agent_mesh/templates/gateway_config_template.yaml +43 -0
  329. solace_agent_mesh/templates/main_orchestrator.yaml +55 -0
  330. solace_agent_mesh/templates/plugin_agent_config_template.yaml +122 -0
  331. solace_agent_mesh/templates/plugin_custom_config_template.yaml +27 -0
  332. solace_agent_mesh/templates/plugin_custom_template.py +10 -0
  333. solace_agent_mesh/templates/plugin_gateway_config_template.yaml +63 -0
  334. solace_agent_mesh/templates/plugin_pyproject_template.toml +33 -0
  335. solace_agent_mesh/templates/plugin_readme_template.md +34 -0
  336. solace_agent_mesh/templates/plugin_tools_template.py +224 -0
  337. solace_agent_mesh/templates/shared_config.yaml +66 -0
  338. solace_agent_mesh/templates/templates_llm.txt +147 -0
  339. solace_agent_mesh/templates/webui.yaml +53 -0
  340. solace_agent_mesh-1.0.1.dist-info/METADATA +432 -0
  341. solace_agent_mesh-1.0.1.dist-info/RECORD +359 -0
  342. solace_agent_mesh-1.0.1.dist-info/entry_points.txt +3 -0
  343. {solace_agent_mesh-0.2.3.dist-info → solace_agent_mesh-1.0.1.dist-info}/licenses/LICENSE +1 -1
  344. solace_agent_mesh/agents/base_agent_component.py +0 -226
  345. solace_agent_mesh/agents/global/actions/agent_state_change.py +0 -54
  346. solace_agent_mesh/agents/global/actions/clear_history.py +0 -32
  347. solace_agent_mesh/agents/global/actions/convert_file_to_markdown.py +0 -160
  348. solace_agent_mesh/agents/global/actions/create_file.py +0 -70
  349. solace_agent_mesh/agents/global/actions/error_action.py +0 -45
  350. solace_agent_mesh/agents/global/actions/plantuml_diagram.py +0 -163
  351. solace_agent_mesh/agents/global/actions/plotly_graph.py +0 -152
  352. solace_agent_mesh/agents/global/actions/retrieve_file.py +0 -51
  353. solace_agent_mesh/agents/global/global_agent_component.py +0 -38
  354. solace_agent_mesh/agents/image_processing/actions/create_image.py +0 -75
  355. solace_agent_mesh/agents/image_processing/actions/describe_image.py +0 -115
  356. solace_agent_mesh/agents/image_processing/image_processing_agent_component.py +0 -23
  357. solace_agent_mesh/agents/slack/__init__.py +0 -1
  358. solace_agent_mesh/agents/slack/actions/__init__.py +0 -1
  359. solace_agent_mesh/agents/slack/actions/post_message.py +0 -177
  360. solace_agent_mesh/agents/slack/slack_agent_component.py +0 -59
  361. solace_agent_mesh/agents/web_request/actions/do_image_search.py +0 -84
  362. solace_agent_mesh/agents/web_request/actions/do_news_search.py +0 -47
  363. solace_agent_mesh/agents/web_request/actions/do_suggestion_search.py +0 -34
  364. solace_agent_mesh/agents/web_request/actions/do_web_request.py +0 -135
  365. solace_agent_mesh/agents/web_request/actions/download_file.py +0 -69
  366. solace_agent_mesh/agents/web_request/web_request_agent_component.py +0 -33
  367. solace_agent_mesh/assets/web-visualizer/assets/index-D0qORgkg.css +0 -1
  368. solace_agent_mesh/assets/web-visualizer/assets/index-DnDr1pnu.js +0 -109
  369. solace_agent_mesh/assets/web-visualizer/index.html +0 -14
  370. solace_agent_mesh/assets/web-visualizer/vite.svg +0 -1
  371. solace_agent_mesh/cli/commands/add/__init__.py +0 -3
  372. solace_agent_mesh/cli/commands/add/add.py +0 -88
  373. solace_agent_mesh/cli/commands/add/agent.py +0 -110
  374. solace_agent_mesh/cli/commands/add/copy_from_plugin.py +0 -92
  375. solace_agent_mesh/cli/commands/add/gateway.py +0 -374
  376. solace_agent_mesh/cli/commands/build.py +0 -670
  377. solace_agent_mesh/cli/commands/chat/__init__.py +0 -3
  378. solace_agent_mesh/cli/commands/chat/chat.py +0 -361
  379. solace_agent_mesh/cli/commands/config.py +0 -29
  380. solace_agent_mesh/cli/commands/init/__init__.py +0 -3
  381. solace_agent_mesh/cli/commands/init/ai_provider_step.py +0 -93
  382. solace_agent_mesh/cli/commands/init/broker_step.py +0 -99
  383. solace_agent_mesh/cli/commands/init/builtin_agent_step.py +0 -83
  384. solace_agent_mesh/cli/commands/init/check_if_already_done.py +0 -13
  385. solace_agent_mesh/cli/commands/init/create_config_file_step.py +0 -65
  386. solace_agent_mesh/cli/commands/init/create_other_project_files_step.py +0 -147
  387. solace_agent_mesh/cli/commands/init/file_service_step.py +0 -73
  388. solace_agent_mesh/cli/commands/init/init.py +0 -92
  389. solace_agent_mesh/cli/commands/init/project_structure_step.py +0 -16
  390. solace_agent_mesh/cli/commands/init/web_init_step.py +0 -32
  391. solace_agent_mesh/cli/commands/plugin/__init__.py +0 -3
  392. solace_agent_mesh/cli/commands/plugin/add.py +0 -100
  393. solace_agent_mesh/cli/commands/plugin/build.py +0 -268
  394. solace_agent_mesh/cli/commands/plugin/create.py +0 -117
  395. solace_agent_mesh/cli/commands/plugin/plugin.py +0 -124
  396. solace_agent_mesh/cli/commands/plugin/remove.py +0 -73
  397. solace_agent_mesh/cli/commands/run.py +0 -68
  398. solace_agent_mesh/cli/commands/visualizer.py +0 -138
  399. solace_agent_mesh/cli/config.py +0 -85
  400. solace_agent_mesh/common/action.py +0 -91
  401. solace_agent_mesh/common/action_list.py +0 -37
  402. solace_agent_mesh/common/action_response.py +0 -340
  403. solace_agent_mesh/common/mysql_database.py +0 -40
  404. solace_agent_mesh/common/postgres_database.py +0 -85
  405. solace_agent_mesh/common/prompt_templates.py +0 -28
  406. solace_agent_mesh/common/stimulus_utils.py +0 -152
  407. solace_agent_mesh/common/time.py +0 -24
  408. solace_agent_mesh/common/utils.py +0 -712
  409. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-DMmCawWe.js +0 -42
  410. solace_agent_mesh/config_portal/frontend/static/client/assets/components-ZIfdTbrV.js +0 -191
  411. solace_agent_mesh/config_portal/frontend/static/client/assets/index-BJHAE5s4.js +0 -17
  412. solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-dd988f05.js +0 -1
  413. solace_agent_mesh/config_portal/frontend/static/client/assets/root-DX4gQ516.css +0 -1
  414. solace_agent_mesh/configs/agent_global.yaml +0 -74
  415. solace_agent_mesh/configs/agent_image_processing.yaml +0 -82
  416. solace_agent_mesh/configs/agent_slack.yaml +0 -64
  417. solace_agent_mesh/configs/agent_web_request.yaml +0 -75
  418. solace_agent_mesh/configs/conversation_to_file.yaml +0 -56
  419. solace_agent_mesh/configs/error_catcher.yaml +0 -56
  420. solace_agent_mesh/configs/monitor.yaml +0 -0
  421. solace_agent_mesh/configs/monitor_stim_and_errors_to_slack.yaml +0 -109
  422. solace_agent_mesh/configs/monitor_user_feedback.yaml +0 -58
  423. solace_agent_mesh/configs/orchestrator.yaml +0 -241
  424. solace_agent_mesh/configs/service_embedding.yaml +0 -81
  425. solace_agent_mesh/configs/service_llm.yaml +0 -265
  426. solace_agent_mesh/configs/visualize_websocket.yaml +0 -55
  427. solace_agent_mesh/gateway/components/gateway_base.py +0 -47
  428. solace_agent_mesh/gateway/components/gateway_input.py +0 -278
  429. solace_agent_mesh/gateway/components/gateway_output.py +0 -298
  430. solace_agent_mesh/gateway/identity/bamboohr_identity.py +0 -18
  431. solace_agent_mesh/gateway/identity/identity_base.py +0 -10
  432. solace_agent_mesh/gateway/identity/identity_provider.py +0 -60
  433. solace_agent_mesh/gateway/identity/no_identity.py +0 -9
  434. solace_agent_mesh/gateway/identity/passthru_identity.py +0 -9
  435. solace_agent_mesh/monitors/base_monitor_component.py +0 -26
  436. solace_agent_mesh/monitors/feedback/user_feedback_monitor.py +0 -75
  437. solace_agent_mesh/monitors/stim_and_errors/stim_and_error_monitor.py +0 -560
  438. solace_agent_mesh/orchestrator/__init__.py +0 -0
  439. solace_agent_mesh/orchestrator/action_manager.py +0 -237
  440. solace_agent_mesh/orchestrator/components/__init__.py +0 -0
  441. solace_agent_mesh/orchestrator/components/orchestrator_action_manager_timeout_component.py +0 -58
  442. solace_agent_mesh/orchestrator/components/orchestrator_action_response_component.py +0 -179
  443. solace_agent_mesh/orchestrator/components/orchestrator_register_component.py +0 -107
  444. solace_agent_mesh/orchestrator/components/orchestrator_stimulus_processor_component.py +0 -527
  445. solace_agent_mesh/orchestrator/components/orchestrator_streaming_output_component.py +0 -260
  446. solace_agent_mesh/orchestrator/orchestrator_main.py +0 -172
  447. solace_agent_mesh/orchestrator/orchestrator_prompt.py +0 -539
  448. solace_agent_mesh/services/__init__.py +0 -0
  449. solace_agent_mesh/services/authorization/providers/base_authorization_provider.py +0 -56
  450. solace_agent_mesh/services/bamboo_hr_service/__init__.py +0 -3
  451. solace_agent_mesh/services/bamboo_hr_service/bamboo_hr.py +0 -182
  452. solace_agent_mesh/services/common/__init__.py +0 -4
  453. solace_agent_mesh/services/common/auto_expiry.py +0 -45
  454. solace_agent_mesh/services/common/singleton.py +0 -18
  455. solace_agent_mesh/services/file_service/__init__.py +0 -14
  456. solace_agent_mesh/services/file_service/file_manager/__init__.py +0 -0
  457. solace_agent_mesh/services/file_service/file_manager/bucket_file_manager.py +0 -149
  458. solace_agent_mesh/services/file_service/file_manager/file_manager_base.py +0 -162
  459. solace_agent_mesh/services/file_service/file_manager/memory_file_manager.py +0 -64
  460. solace_agent_mesh/services/file_service/file_manager/volume_file_manager.py +0 -106
  461. solace_agent_mesh/services/file_service/file_service.py +0 -437
  462. solace_agent_mesh/services/file_service/file_service_constants.py +0 -54
  463. solace_agent_mesh/services/file_service/file_transformations.py +0 -141
  464. solace_agent_mesh/services/file_service/file_utils.py +0 -324
  465. solace_agent_mesh/services/file_service/transformers/__init__.py +0 -5
  466. solace_agent_mesh/services/history_service/__init__.py +0 -3
  467. solace_agent_mesh/services/history_service/history_providers/__init__.py +0 -0
  468. solace_agent_mesh/services/history_service/history_providers/base_history_provider.py +0 -54
  469. solace_agent_mesh/services/history_service/history_providers/file_history_provider.py +0 -74
  470. solace_agent_mesh/services/history_service/history_providers/index.py +0 -40
  471. solace_agent_mesh/services/history_service/history_providers/memory_history_provider.py +0 -33
  472. solace_agent_mesh/services/history_service/history_providers/mongodb_history_provider.py +0 -66
  473. solace_agent_mesh/services/history_service/history_providers/redis_history_provider.py +0 -66
  474. solace_agent_mesh/services/history_service/history_providers/sql_history_provider.py +0 -93
  475. solace_agent_mesh/services/history_service/history_service.py +0 -413
  476. solace_agent_mesh/services/history_service/long_term_memory/__init__.py +0 -0
  477. solace_agent_mesh/services/history_service/long_term_memory/long_term_memory.py +0 -399
  478. solace_agent_mesh/services/llm_service/components/llm_request_component.py +0 -340
  479. solace_agent_mesh/services/llm_service/components/llm_service_component_base.py +0 -152
  480. solace_agent_mesh/services/middleware_service/__init__.py +0 -0
  481. solace_agent_mesh/services/middleware_service/middleware_service.py +0 -20
  482. solace_agent_mesh/templates/action.py +0 -38
  483. solace_agent_mesh/templates/agent.py +0 -29
  484. solace_agent_mesh/templates/agent.yaml +0 -70
  485. solace_agent_mesh/templates/gateway-config-template.yaml +0 -6
  486. solace_agent_mesh/templates/gateway-default-config.yaml +0 -28
  487. solace_agent_mesh/templates/gateway-flows.yaml +0 -78
  488. solace_agent_mesh/templates/gateway-header.yaml +0 -16
  489. solace_agent_mesh/templates/gateway_base.py +0 -15
  490. solace_agent_mesh/templates/gateway_input.py +0 -98
  491. solace_agent_mesh/templates/gateway_output.py +0 -71
  492. solace_agent_mesh/templates/plugin-gateway-default-config.yaml +0 -29
  493. solace_agent_mesh/templates/plugin-pyproject.toml +0 -30
  494. solace_agent_mesh/templates/rest-api-default-config.yaml +0 -31
  495. solace_agent_mesh/templates/rest-api-flows.yaml +0 -81
  496. solace_agent_mesh/templates/slack-default-config.yaml +0 -16
  497. solace_agent_mesh/templates/slack-flows.yaml +0 -81
  498. solace_agent_mesh/templates/solace-agent-mesh-default.yaml +0 -86
  499. solace_agent_mesh/templates/solace-agent-mesh-plugin-default.yaml +0 -8
  500. solace_agent_mesh/templates/web-default-config.yaml +0 -10
  501. solace_agent_mesh/templates/web-flows.yaml +0 -76
  502. solace_agent_mesh/tools/__init__.py +0 -0
  503. solace_agent_mesh/tools/components/__init__.py +0 -0
  504. solace_agent_mesh/tools/components/conversation_formatter.py +0 -111
  505. solace_agent_mesh/tools/components/file_resolver_component.py +0 -58
  506. solace_agent_mesh/tools/config/runtime_config.py +0 -26
  507. solace_agent_mesh-0.2.3.dist-info/METADATA +0 -172
  508. solace_agent_mesh-0.2.3.dist-info/RECORD +0 -193
  509. solace_agent_mesh-0.2.3.dist-info/entry_points.txt +0 -3
  510. /solace_agent_mesh/{agents → agent}/__init__.py +0 -0
  511. /solace_agent_mesh/{agents/global → agent/adk}/__init__.py +0 -0
  512. /solace_agent_mesh/{agents/global/actions → agent/protocol}/__init__.py +0 -0
  513. /solace_agent_mesh/{agents/image_processing → agent/sac}/__init__.py +0 -0
  514. /solace_agent_mesh/{agents/image_processing/actions → agent/utils}/__init__.py +0 -0
  515. /solace_agent_mesh/{agents/web_request → config_portal/backend/plugin_catalog}/__init__.py +0 -0
  516. /solace_agent_mesh/{agents/web_request/actions → evaluation}/__init__.py +0 -0
  517. /solace_agent_mesh/gateway/{components → http_sse}/__init__.py +0 -0
  518. {solace_agent_mesh-0.2.3.dist-info → solace_agent_mesh-1.0.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,775 @@
1
+ """
2
+ Refactored summarization module with improved structure and readability.
3
+ This module processes test run messages and generates comprehensive summaries.
4
+ """
5
+
6
+ import json
7
+ import os
8
+ import re
9
+ import yaml
10
+
11
+ from datetime import datetime
12
+ from typing import Dict, List, Optional, Any, Tuple, Set
13
+ from dataclasses import dataclass, field
14
+ from .test_case_loader import load_test_case
15
+
16
+
17
+ @dataclass
18
+ class ToolCall:
19
+ """Structured representation of a tool call."""
20
+
21
+ call_id: str
22
+ agent: str
23
+ tool_name: str
24
+ arguments: Dict[str, Any]
25
+ timestamp: str
26
+
27
+
28
+ @dataclass
29
+ class ArtifactInfo:
30
+ """Comprehensive artifact information with categorization."""
31
+
32
+ artifact_name: str
33
+ directory: str
34
+ versions: List[Dict[str, Any]]
35
+ artifact_type: Optional[str] = None
36
+ source_path: Optional[str] = None
37
+ created_by_tool: Optional[str] = None
38
+ created_by_call_id: Optional[str] = None
39
+ creation_timestamp: Optional[str] = None
40
+
41
+
42
+ @dataclass
43
+ class TimeMetrics:
44
+ """Time-related metrics for a test run."""
45
+
46
+ start_time: Optional[str] = None
47
+ end_time: Optional[str] = None
48
+ duration_seconds: Optional[float] = None
49
+
50
+
51
+ @dataclass
52
+ class RunSummary:
53
+ """Complete summary of a test run with all metrics and metadata."""
54
+
55
+ test_case_id: str
56
+ run_id: str
57
+ query: str = ""
58
+ target_agent: str = ""
59
+ namespace: str = ""
60
+ session_id: str = ""
61
+ final_status: str = ""
62
+ final_message: str = ""
63
+ time_metrics: TimeMetrics = field(default_factory=TimeMetrics)
64
+ tool_calls: List[ToolCall] = field(default_factory=list)
65
+ input_artifacts: List[ArtifactInfo] = field(default_factory=list)
66
+ output_artifacts: List[ArtifactInfo] = field(default_factory=list)
67
+ errors: List[str] = field(default_factory=list)
68
+
69
+ def to_dict(self) -> Dict[str, Any]:
70
+ """Convert summary to dictionary format for JSON serialization."""
71
+ return {
72
+ "test_case_id": self.test_case_id,
73
+ "run_id": self.run_id,
74
+ "query": self.query,
75
+ "target_agent": self.target_agent,
76
+ "namespace": self.namespace,
77
+ "session_id": self.session_id,
78
+ "final_status": self.final_status,
79
+ "final_message": self.final_message,
80
+ "start_time": self.time_metrics.start_time,
81
+ "end_time": self.time_metrics.end_time,
82
+ "duration_seconds": self.time_metrics.duration_seconds,
83
+ "tool_calls": [
84
+ {
85
+ "call_id": tc.call_id,
86
+ "agent": tc.agent,
87
+ "tool_name": tc.tool_name,
88
+ "arguments": tc.arguments,
89
+ "timestamp": tc.timestamp,
90
+ }
91
+ for tc in self.tool_calls
92
+ ],
93
+ "input_artifacts": [
94
+ {
95
+ "artifact_name": art.artifact_name,
96
+ "directory": art.directory,
97
+ "versions": art.versions,
98
+ "type": art.artifact_type,
99
+ "source_path": art.source_path,
100
+ }
101
+ for art in self.input_artifacts
102
+ ],
103
+ "output_artifacts": [
104
+ {
105
+ "artifact_name": art.artifact_name,
106
+ "directory": art.directory,
107
+ "versions": art.versions,
108
+ "created_by_tool": art.created_by_tool,
109
+ "created_by_call_id": art.created_by_call_id,
110
+ "creation_timestamp": art.creation_timestamp,
111
+ }
112
+ for art in self.output_artifacts
113
+ ],
114
+ "errors": self.errors,
115
+ }
116
+
117
+
118
+ class ConfigService:
119
+ """Handles configuration loading and YAML processing."""
120
+
121
+ _config_cache: Dict[str, Any] = {}
122
+
123
+ @classmethod
124
+ def load_yaml_with_includes(cls, file_path: str) -> Dict[str, Any]:
125
+ """Load YAML file with !include directive processing and caching."""
126
+ if file_path in cls._config_cache:
127
+ return cls._config_cache[file_path]
128
+
129
+ try:
130
+ with open(file_path, "r") as f:
131
+ content = f.read()
132
+
133
+ content = cls._process_includes(content, file_path)
134
+ config = yaml.safe_load(content)
135
+ cls._config_cache[file_path] = config
136
+ return config
137
+
138
+ except (FileNotFoundError, yaml.YAMLError) as e:
139
+ raise ValueError(f"Failed to load YAML config from {file_path}: {e}")
140
+
141
+ @staticmethod
142
+ def _process_includes(content: str, base_file_path: str) -> str:
143
+ """Process !include directives in YAML content."""
144
+ include_pattern = re.compile(r"^\s*!include\s+(.*)$", re.MULTILINE)
145
+
146
+ def replacer(match):
147
+ include_path = match.group(1).strip()
148
+ include_path = os.path.join(os.path.dirname(base_file_path), include_path)
149
+ with open(include_path, "r") as inc_f:
150
+ return inc_f.read()
151
+
152
+ # Repeatedly replace includes until none are left
153
+ while include_pattern.search(content):
154
+ content = include_pattern.sub(replacer, content)
155
+
156
+ return content
157
+
158
+ @classmethod
159
+ def get_artifact_config(cls) -> Tuple[str, str]:
160
+ """Get artifact service configuration from eval backend config."""
161
+ try:
162
+ webui_config = cls.load_yaml_with_includes("configs/eval_backend.yaml")
163
+
164
+ # Find the correct app_config
165
+ for app in webui_config.get("apps", []):
166
+ if app.get("name") == "a2a_eval_backend_app":
167
+ app_config = app.get("app_config", {})
168
+ base_path = app_config.get("artifact_service", {}).get("base_path")
169
+ user_identity = app_config.get("default_user_identity")
170
+
171
+ if base_path and user_identity:
172
+ return base_path, user_identity
173
+
174
+ raise ValueError("Could not find 'a2a_eval_backend_app' config")
175
+
176
+ except Exception as e:
177
+ raise ValueError(f"Failed to load artifact configuration: {e}")
178
+
179
+
180
+ class FileService:
181
+ """Handles file operations and path management."""
182
+
183
+ @staticmethod
184
+ def load_json(filepath: str) -> Any:
185
+ """Load JSON data from file."""
186
+ try:
187
+ with open(filepath, "r") as f:
188
+ return json.load(f)
189
+ except (FileNotFoundError, json.JSONDecodeError) as e:
190
+ raise ValueError(f"Failed to load JSON from {filepath}: {e}")
191
+
192
+ @staticmethod
193
+ def save_json(data: Any, filepath: str):
194
+ """Save data as JSON to file."""
195
+ try:
196
+ with open(filepath, "w") as f:
197
+ json.dump(data, f, indent=2)
198
+ except Exception as e:
199
+ raise ValueError(f"Failed to save JSON to {filepath}: {e}")
200
+
201
+
202
+ class TestCaseService:
203
+ """Handles test case loading and validation."""
204
+
205
+ @staticmethod
206
+ def load_test_case(test_case_id: str) -> Optional[Dict[str, Any]]:
207
+ """Load test case definition with error handling."""
208
+ try:
209
+ return load_test_case(test_case_id)
210
+ except Exception:
211
+ return None
212
+
213
+ @staticmethod
214
+ def extract_input_artifact_names(test_case: Dict[str, Any]) -> Set[str]:
215
+ """Extract input artifact names from test case definition."""
216
+ input_artifact_names = set()
217
+ test_case_artifacts = test_case.get("artifacts", [])
218
+
219
+ for tc_artifact in test_case_artifacts:
220
+ if tc_artifact.get("type") == "file" and "path" in tc_artifact:
221
+ # Extract filename from path (e.g., "artifacts/sample.csv" -> "sample.csv")
222
+ artifact_name = os.path.basename(tc_artifact["path"])
223
+ input_artifact_names.add(artifact_name)
224
+
225
+ return input_artifact_names
226
+
227
+
228
+ class TimeProcessor:
229
+ """Handles timestamp parsing and duration calculations."""
230
+
231
+ @staticmethod
232
+ def extract_start_time(first_message: Dict[str, Any]) -> Optional[str]:
233
+ """Extract start time from the first message."""
234
+ try:
235
+ payload = first_message.get("payload", {})
236
+ params = payload.get("params", {})
237
+ message = params.get("message", {})
238
+ parts = message.get("parts", [])
239
+
240
+ for part in parts:
241
+ if "text" in part and "Request received by gateway at:" in part["text"]:
242
+ time_str = (
243
+ part["text"]
244
+ .split("Request received by gateway at: ")[1]
245
+ .strip()
246
+ )
247
+ # Validate timestamp format
248
+ datetime.fromisoformat(time_str)
249
+ return time_str
250
+ except (KeyError, ValueError, IndexError):
251
+ pass
252
+
253
+ return None
254
+
255
+ @staticmethod
256
+ def extract_end_time(last_message: Dict[str, Any]) -> Optional[str]:
257
+ """Extract end time from the last message."""
258
+ try:
259
+ payload = last_message.get("payload", {})
260
+ result = payload.get("result", {})
261
+ status = result.get("status", {})
262
+ return status.get("timestamp")
263
+ except KeyError:
264
+ return None
265
+
266
+ @staticmethod
267
+ def calculate_duration(
268
+ start_time_str: str, end_time_str: str
269
+ ) -> Tuple[Optional[float], Optional[str]]:
270
+ """Calculate duration and return normalized start time."""
271
+ try:
272
+ start_time = datetime.fromisoformat(start_time_str)
273
+ end_time = datetime.fromisoformat(end_time_str)
274
+
275
+ # Handle timezone differences
276
+ if (start_time.tzinfo is not None) and (end_time.tzinfo is None):
277
+ start_time = start_time.astimezone().replace(tzinfo=None)
278
+ elif (end_time.tzinfo is not None) and (start_time.tzinfo is None):
279
+ end_time = end_time.astimezone().replace(tzinfo=None)
280
+
281
+ duration = end_time - start_time
282
+
283
+ # Normalize start time for output
284
+ s_time = datetime.fromisoformat(start_time_str)
285
+ if s_time.tzinfo is not None:
286
+ s_time = s_time.astimezone().replace(tzinfo=None)
287
+
288
+ return duration.total_seconds(), s_time.isoformat()
289
+
290
+ except ValueError:
291
+ return None, None
292
+
293
+
294
+ class MessageProcessor:
295
+ """Processes messages to extract tool calls and metadata."""
296
+
297
+ @staticmethod
298
+ def extract_namespace_and_agent(
299
+ first_message: Dict[str, Any],
300
+ ) -> Tuple[Optional[str], Optional[str]]:
301
+ """Extract namespace and target agent from the first message topic."""
302
+ try:
303
+ topic = first_message.get("topic", "")
304
+ # Regex to match the topic format and capture the namespace and target_agent
305
+ match = re.match(r"^([^/]+)/a2a/v1/agent/request/([^/]+)$", topic)
306
+ if match:
307
+ return match.group(1), match.group(2)
308
+ except Exception:
309
+ pass
310
+
311
+ return None, None
312
+
313
+ @staticmethod
314
+ def extract_session_id(first_message: Dict[str, Any]) -> Optional[str]:
315
+ """Extract session ID from the first message."""
316
+ try:
317
+ payload = first_message.get("payload", {})
318
+ params = payload.get("params", {})
319
+ return params.get("sessionId")
320
+ except KeyError:
321
+ return None
322
+
323
+ @staticmethod
324
+ def extract_final_status_info(
325
+ last_message: Dict[str, Any],
326
+ ) -> Tuple[Optional[str], Optional[str]]:
327
+ """Extract final status and message from the last message."""
328
+ try:
329
+ payload = last_message.get("payload", {})
330
+ result = payload.get("result", {})
331
+ status_info = result.get("status", {})
332
+
333
+ final_status = status_info.get("state")
334
+ final_message = None
335
+
336
+ message = status_info.get("message", {})
337
+ parts = message.get("parts", [])
338
+ for part in parts:
339
+ if "text" in part:
340
+ final_message = part["text"]
341
+ break
342
+
343
+ return final_status, final_message
344
+
345
+ except KeyError:
346
+ return None, None
347
+
348
+ @staticmethod
349
+ def extract_tool_calls(messages: List[Dict[str, Any]]) -> List[ToolCall]:
350
+ """Extract all tool calls from messages."""
351
+ tool_calls = []
352
+ processed_tool_calls = set()
353
+
354
+ for message in messages:
355
+ try:
356
+ payload = message.get("payload", {})
357
+ result = payload.get("result", {})
358
+ status = result.get("status", {})
359
+ message_data = status.get("message", {})
360
+ metadata = message_data.get("metadata", {})
361
+ data = metadata.get("data", {})
362
+ content = data.get("content", {})
363
+ parts = content.get("parts", [])
364
+
365
+ if parts:
366
+ function_call = parts[0].get("function_call", {})
367
+ call_id = function_call.get("id")
368
+
369
+ if call_id and call_id not in processed_tool_calls:
370
+ tool_call = ToolCall(
371
+ call_id=call_id,
372
+ agent=result.get("metadata", {}).get("agent_name", ""),
373
+ tool_name=function_call.get("name", ""),
374
+ arguments=function_call.get("args", {}),
375
+ timestamp=status.get("timestamp", ""),
376
+ )
377
+ tool_calls.append(tool_call)
378
+ processed_tool_calls.add(call_id)
379
+
380
+ except (KeyError, IndexError):
381
+ continue
382
+
383
+ return tool_calls
384
+
385
+
386
+ class ArtifactService:
387
+ """Manages artifact discovery, categorization, and metadata."""
388
+
389
+ def __init__(self, base_path: str, user_identity: str):
390
+ self.base_path = base_path
391
+ self.user_identity = user_identity
392
+
393
+ def get_artifact_info(self, namespace: str, session_id: str) -> List[ArtifactInfo]:
394
+ """Retrieve information about artifacts from the session directory."""
395
+ artifact_info = []
396
+ session_dir = os.path.join(
397
+ self.base_path, namespace, self.user_identity, session_id
398
+ )
399
+
400
+ if not os.path.isdir(session_dir):
401
+ return artifact_info
402
+
403
+ for item in os.listdir(session_dir):
404
+ item_path = os.path.join(session_dir, item)
405
+ if os.path.isdir(item_path) and not item.endswith(".metadata.json"):
406
+ artifact_info.append(
407
+ self._process_artifact_directory(session_dir, item, item_path)
408
+ )
409
+
410
+ return artifact_info
411
+
412
+ def _process_artifact_directory(
413
+ self, session_dir: str, artifact_name: str, item_path: str
414
+ ) -> ArtifactInfo:
415
+ """Process a single artifact directory and extract metadata."""
416
+ metadata_dir = os.path.join(session_dir, f"{artifact_name}.metadata.json")
417
+ versions = []
418
+
419
+ if os.path.isdir(metadata_dir):
420
+ for version_file in os.listdir(item_path):
421
+ if not version_file.endswith(".meta"):
422
+ version_metadata_path = os.path.join(metadata_dir, version_file)
423
+ if os.path.exists(version_metadata_path):
424
+ try:
425
+ with open(version_metadata_path, "r") as f:
426
+ metadata = json.load(f)
427
+ versions.append(
428
+ {"version": version_file, "metadata": metadata}
429
+ )
430
+ except (json.JSONDecodeError, FileNotFoundError):
431
+ continue
432
+
433
+ return ArtifactInfo(
434
+ artifact_name=artifact_name, directory=item_path, versions=versions
435
+ )
436
+
437
+ def categorize_artifacts(
438
+ self,
439
+ artifacts: List[ArtifactInfo],
440
+ test_case: Dict[str, Any],
441
+ tool_calls: List[ToolCall],
442
+ ) -> Tuple[List[ArtifactInfo], List[ArtifactInfo]]:
443
+ """Categorize artifacts into input and output based on test case and tool calls."""
444
+ input_artifacts = []
445
+ output_artifacts = []
446
+
447
+ # Get input artifact names from test case
448
+ input_artifact_names = TestCaseService.extract_input_artifact_names(test_case)
449
+
450
+ # Create mapping of output artifacts to creating tools
451
+ tool_output_mapping = self._create_tool_output_mapping(tool_calls)
452
+
453
+ # Categorize each artifact
454
+ for artifact in artifacts:
455
+ artifact_name = artifact.artifact_name
456
+
457
+ # Check if this is an input artifact
458
+ if artifact_name in input_artifact_names:
459
+ input_artifact = self._enhance_input_artifact(artifact, test_case)
460
+ input_artifacts.append(input_artifact)
461
+
462
+ # All artifacts also go to output (including input ones that exist in session)
463
+ output_artifact = self._enhance_output_artifact(
464
+ artifact, tool_output_mapping
465
+ )
466
+ output_artifacts.append(output_artifact)
467
+
468
+ return input_artifacts, output_artifacts
469
+
470
+ def _create_tool_output_mapping(
471
+ self, tool_calls: List[ToolCall]
472
+ ) -> Dict[str, ToolCall]:
473
+ """Create mapping of output filenames to the tools that created them."""
474
+ tool_output_mapping = {}
475
+
476
+ for tool_call in tool_calls:
477
+ args = tool_call.arguments
478
+
479
+ # Look for output filename in tool arguments
480
+ output_filename = None
481
+ if "output_filename" in args:
482
+ output_filename = args["output_filename"]
483
+ elif "filename" in args:
484
+ output_filename = args["filename"]
485
+
486
+ if output_filename:
487
+ tool_output_mapping[output_filename] = tool_call
488
+
489
+ return tool_output_mapping
490
+
491
+ def _enhance_input_artifact(
492
+ self, artifact: ArtifactInfo, test_case: Dict[str, Any]
493
+ ) -> ArtifactInfo:
494
+ """Enhance input artifact with test case information."""
495
+ enhanced_artifact = ArtifactInfo(
496
+ artifact_name=artifact.artifact_name,
497
+ directory=artifact.directory,
498
+ versions=artifact.versions,
499
+ artifact_type=None,
500
+ source_path=None,
501
+ )
502
+
503
+ # Add test case information
504
+ test_case_artifacts = test_case.get("artifacts", [])
505
+ for tc_artifact in test_case_artifacts:
506
+ if (
507
+ tc_artifact.get("type") == "file"
508
+ and os.path.basename(tc_artifact["path"]) == artifact.artifact_name
509
+ ):
510
+ enhanced_artifact.artifact_type = tc_artifact["type"]
511
+ enhanced_artifact.source_path = tc_artifact["path"]
512
+ break
513
+
514
+ return enhanced_artifact
515
+
516
+ def _enhance_output_artifact(
517
+ self, artifact: ArtifactInfo, tool_output_mapping: Dict[str, ToolCall]
518
+ ) -> ArtifactInfo:
519
+ """Enhance output artifact with tool creation information."""
520
+ enhanced_artifact = ArtifactInfo(
521
+ artifact_name=artifact.artifact_name,
522
+ directory=artifact.directory,
523
+ versions=artifact.versions,
524
+ )
525
+
526
+ # Add tool creation information if available
527
+ if artifact.artifact_name in tool_output_mapping:
528
+ creating_tool = tool_output_mapping[artifact.artifact_name]
529
+ enhanced_artifact.created_by_tool = creating_tool.tool_name
530
+ enhanced_artifact.created_by_call_id = creating_tool.call_id
531
+ enhanced_artifact.creation_timestamp = creating_tool.timestamp
532
+
533
+ return enhanced_artifact
534
+
535
+
536
+ class SummaryBuilder:
537
+ """Main orchestrator for summary creation."""
538
+
539
+ def __init__(self):
540
+ self.file_service = FileService()
541
+ self.test_case_service = TestCaseService()
542
+ self.time_processor = TimeProcessor()
543
+ self.message_processor = MessageProcessor()
544
+ self.artifact_service: Optional[ArtifactService] = None
545
+
546
+ def summarize_run(self, messages_file_path: str) -> Dict[str, Any]:
547
+ """
548
+ Create a comprehensive summary of a test run from messages.json file.
549
+
550
+ Args:
551
+ messages_file_path: Path to the messages.json file
552
+
553
+ Returns:
554
+ Dictionary containing the summarized metrics
555
+ """
556
+ try:
557
+ # Load and validate messages
558
+ messages = self._load_and_validate_messages(messages_file_path)
559
+ if not messages:
560
+ return {}
561
+
562
+ run_path = os.path.dirname(messages_file_path)
563
+ test_case_info_path = os.path.join(run_path, "test_case_info.json")
564
+ test_case_info = self.file_service.load_json(test_case_info_path)
565
+ test_case_path = test_case_info["path"]
566
+
567
+ # Initialize summary with basic info
568
+ summary = self._initialize_summary(messages_file_path, test_case_path)
569
+
570
+ # Load test case
571
+ test_case = self._load_test_case(summary, test_case_path)
572
+
573
+ # Process messages to extract data
574
+ self._process_messages(messages, summary, test_case)
575
+
576
+ # Add artifact information if possible
577
+ self._add_artifact_information(summary, test_case)
578
+
579
+ return summary.to_dict()
580
+
581
+ except Exception as e:
582
+ # Return minimal summary with error information
583
+ run_path = os.path.dirname(messages_file_path)
584
+ return {
585
+ "test_case_id": os.path.basename(os.path.dirname(run_path)),
586
+ "run_id": os.path.basename(run_path),
587
+ "errors": [f"Failed to process summary: {str(e)}"],
588
+ }
589
+
590
+ def _load_and_validate_messages(
591
+ self, messages_file_path: str
592
+ ) -> List[Dict[str, Any]]:
593
+ """Load and validate messages from file."""
594
+ try:
595
+ messages = self.file_service.load_json(messages_file_path)
596
+ return messages if isinstance(messages, list) else []
597
+ except Exception:
598
+ return []
599
+
600
+ def _initialize_summary(
601
+ self, messages_file_path: str, test_case_path: str
602
+ ) -> RunSummary:
603
+ """Initialize summary with basic path-derived information."""
604
+ run_path = os.path.dirname(messages_file_path)
605
+ run_id = os.path.basename(run_path)
606
+ test_case_id = os.path.splitext(os.path.basename(test_case_path))[0].replace(
607
+ ".test", ""
608
+ )
609
+
610
+ return RunSummary(test_case_id=test_case_id, run_id=run_id)
611
+
612
+ def _load_test_case(
613
+ self, summary: RunSummary, test_case_path: str
614
+ ) -> Dict[str, Any]:
615
+ """Load test case and update summary with test case info."""
616
+ test_case = self.test_case_service.load_test_case(test_case_path)
617
+
618
+ if test_case:
619
+ summary.query = test_case.get("query", "")
620
+ summary.target_agent = test_case.get("target_agent", "")
621
+ else:
622
+ summary.errors.append(f"Could not load test case: {summary.test_case_id}")
623
+ test_case = {"artifacts": []} # Fallback
624
+
625
+ return test_case
626
+
627
+ def _process_messages(
628
+ self,
629
+ messages: List[Dict[str, Any]],
630
+ summary: RunSummary,
631
+ test_case: Dict[str, Any],
632
+ ):
633
+ """Process all messages to extract relevant information."""
634
+ if not messages:
635
+ return
636
+
637
+ first_message = messages[0]
638
+ last_message = messages[-1]
639
+
640
+ # Extract basic metadata
641
+ namespace, target_agent = self.message_processor.extract_namespace_and_agent(
642
+ first_message
643
+ )
644
+ if namespace:
645
+ summary.namespace = namespace
646
+ if target_agent:
647
+ summary.target_agent = target_agent
648
+ else:
649
+ summary.errors.append(
650
+ "Could not find target agent and namespace in the first message."
651
+ )
652
+
653
+ session_id = self.message_processor.extract_session_id(first_message)
654
+ if session_id:
655
+ summary.session_id = session_id
656
+
657
+ # Extract final status information
658
+ final_status, final_message = self.message_processor.extract_final_status_info(
659
+ last_message
660
+ )
661
+ if final_status:
662
+ summary.final_status = final_status
663
+ if final_message:
664
+ summary.final_message = final_message
665
+
666
+ # Extract time metrics
667
+ self._process_time_metrics(first_message, last_message, summary)
668
+
669
+ # Extract tool calls
670
+ summary.tool_calls = self.message_processor.extract_tool_calls(messages)
671
+
672
+ def _process_time_metrics(
673
+ self,
674
+ first_message: Dict[str, Any],
675
+ last_message: Dict[str, Any],
676
+ summary: RunSummary,
677
+ ):
678
+ """Process and calculate time metrics."""
679
+ start_time = self.time_processor.extract_start_time(first_message)
680
+ end_time = self.time_processor.extract_end_time(last_message)
681
+
682
+ summary.time_metrics.start_time = start_time
683
+ summary.time_metrics.end_time = end_time
684
+
685
+ if start_time and end_time:
686
+ duration, normalized_start = self.time_processor.calculate_duration(
687
+ start_time, end_time
688
+ )
689
+ if duration is not None:
690
+ summary.time_metrics.duration_seconds = duration
691
+ if normalized_start:
692
+ summary.time_metrics.start_time = normalized_start
693
+ else:
694
+ summary.errors.append(
695
+ "Could not parse start or end time to calculate duration."
696
+ )
697
+
698
+ def _add_artifact_information(self, summary: RunSummary, test_case: Dict[str, Any]):
699
+ """Add artifact information if configuration is available."""
700
+ if not summary.namespace or not summary.session_id:
701
+ return
702
+
703
+ try:
704
+ # Initialize artifact service if not already done
705
+ if not self.artifact_service:
706
+ base_path, user_identity = ConfigService.get_artifact_config()
707
+ self.artifact_service = ArtifactService(base_path, user_identity)
708
+
709
+ # Get and categorize artifacts
710
+ all_artifacts = self.artifact_service.get_artifact_info(
711
+ summary.namespace, summary.session_id
712
+ )
713
+
714
+ input_artifacts, output_artifacts = (
715
+ self.artifact_service.categorize_artifacts(
716
+ all_artifacts, test_case, summary.tool_calls
717
+ )
718
+ )
719
+
720
+ summary.input_artifacts = input_artifacts
721
+ summary.output_artifacts = output_artifacts
722
+
723
+ except Exception as e:
724
+ summary.errors.append(f"Could not add artifact info: {str(e)}")
725
+
726
+
727
+ def summarize_run(messages_file_path: str) -> Dict[str, Any]:
728
+ """
729
+ Main entry point for summarizing a test run.
730
+
731
+ This function maintains compatibility with the original API while using
732
+ the refactored implementation.
733
+
734
+ Args:
735
+ messages_file_path: Path to the messages.json file
736
+
737
+ Returns:
738
+ Dictionary containing the summarized metrics
739
+ """
740
+ builder = SummaryBuilder()
741
+ return builder.summarize_run(messages_file_path)
742
+
743
+
744
+ def main():
745
+ """Main entry point for command-line usage."""
746
+ import sys
747
+
748
+ if len(sys.argv) != 2:
749
+ print("Usage: python summarize_refactored.py <messages_file_path>")
750
+ sys.exit(1)
751
+
752
+ messages_file_path = sys.argv[1]
753
+
754
+ if not os.path.exists(messages_file_path):
755
+ print(f"Error: Messages file not found at: {messages_file_path}")
756
+ sys.exit(1)
757
+
758
+ try:
759
+ # Generate summary
760
+ summary_data = summarize_run(messages_file_path)
761
+
762
+ # Save summary file
763
+ output_dir = os.path.dirname(messages_file_path)
764
+ summary_file_path = os.path.join(output_dir, "summary.json")
765
+
766
+ FileService.save_json(summary_data, summary_file_path)
767
+ print(f"Summary file created at: {summary_file_path}")
768
+
769
+ except Exception as e:
770
+ print(f"Error generating summary: {e}")
771
+ sys.exit(1)
772
+
773
+
774
+ if __name__ == "__main__":
775
+ main()