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.
- solace_agent_mesh/agent/adk/adk_llm.txt +93 -0
- solace_agent_mesh/agent/adk/app_llm_agent.py +26 -0
- solace_agent_mesh/agent/adk/callbacks.py +1694 -0
- solace_agent_mesh/agent/adk/filesystem_artifact_service.py +381 -0
- solace_agent_mesh/agent/adk/invocation_monitor.py +295 -0
- solace_agent_mesh/agent/adk/models/lite_llm.py +872 -0
- solace_agent_mesh/agent/adk/models/models_llm.txt +94 -0
- solace_agent_mesh/agent/adk/runner.py +353 -0
- solace_agent_mesh/agent/adk/services.py +240 -0
- solace_agent_mesh/agent/adk/setup.py +751 -0
- solace_agent_mesh/agent/adk/stream_parser.py +214 -0
- solace_agent_mesh/agent/adk/tool_wrapper.py +139 -0
- solace_agent_mesh/agent/agent_llm.txt +41 -0
- solace_agent_mesh/agent/protocol/event_handlers.py +1469 -0
- solace_agent_mesh/agent/protocol/protocol_llm.txt +21 -0
- solace_agent_mesh/agent/sac/app.py +640 -0
- solace_agent_mesh/agent/sac/component.py +3388 -0
- solace_agent_mesh/agent/sac/patch_adk.py +111 -0
- solace_agent_mesh/agent/sac/sac_llm.txt +105 -0
- solace_agent_mesh/agent/sac/task_execution_context.py +176 -0
- solace_agent_mesh/agent/testing/__init__.py +3 -0
- solace_agent_mesh/agent/testing/debug_utils.py +135 -0
- solace_agent_mesh/agent/testing/testing_llm.txt +90 -0
- solace_agent_mesh/agent/tools/__init__.py +14 -0
- solace_agent_mesh/agent/tools/audio_tools.py +1622 -0
- solace_agent_mesh/agent/tools/builtin_artifact_tools.py +1954 -0
- solace_agent_mesh/agent/tools/builtin_data_analysis_tools.py +238 -0
- solace_agent_mesh/agent/tools/general_agent_tools.py +569 -0
- solace_agent_mesh/agent/tools/image_tools.py +1184 -0
- solace_agent_mesh/agent/tools/peer_agent_tool.py +289 -0
- solace_agent_mesh/agent/tools/registry.py +36 -0
- solace_agent_mesh/agent/tools/test_tools.py +135 -0
- solace_agent_mesh/agent/tools/tool_definition.py +45 -0
- solace_agent_mesh/agent/tools/tools_llm.txt +104 -0
- solace_agent_mesh/agent/tools/web_tools.py +381 -0
- solace_agent_mesh/agent/utils/artifact_helpers.py +927 -0
- solace_agent_mesh/agent/utils/config_parser.py +47 -0
- solace_agent_mesh/agent/utils/context_helpers.py +60 -0
- solace_agent_mesh/agent/utils/utils_llm.txt +153 -0
- solace_agent_mesh/assets/docs/404.html +16 -0
- solace_agent_mesh/assets/docs/assets/css/styles.906a1503.css +1 -0
- solace_agent_mesh/assets/docs/assets/images/Solace_AI_Framework_With_Broker-85f0a306a9bcdd20b390b7a949f6d862.png +0 -0
- solace_agent_mesh/assets/docs/assets/images/sac-flows-80d5b603c6aafd33e87945680ce0abf3.png +0 -0
- solace_agent_mesh/assets/docs/assets/images/sac_parts_of_a_component-cb3d0424b1d0c17734c5435cca6b4082.png +0 -0
- solace_agent_mesh/assets/docs/assets/js/04989206.674a8007.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/0e682baa.79f0ab22.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/1001.0182a8bd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/1023fc19.015679ca.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/1039.0bd46aa1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/149.b797a808.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/1523c6b4.91c7bc01.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/165.6a39807d.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/165.6a39807d.js.LICENSE.txt +9 -0
- solace_agent_mesh/assets/docs/assets/js/166ab619.7d97ccaf.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js.LICENSE.txt +7 -0
- solace_agent_mesh/assets/docs/assets/js/1c6e87d2.23bccffb.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2130.ab9fd314.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/21ceee5f.614fa8dd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2237.5e477fc6.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2334.622a6395.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2a9cab12.8909df92.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3219.adc1d663.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/332e10b5.7a103f42.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3624.b524e433.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/375.708d48db.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3834.b6cd790e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3d406171.f722eaf5.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4250.95455b28.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/42b3f8d8.36090198.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4356.d169ab5b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/442a8107.5ba94b65.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4458.518e66fa.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4488.c7cc3442.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4494.6ee23046.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4855.fc4444b6.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4866.22daefc0.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4950.ca4caeda.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4c2787c2.66ee00e9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5388.7a136447.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/55f47984.c484bf96.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5607.081356f8.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5864.b0d0e9de.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5b4258a4.bda20761.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5e95c892.558d5167.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6143.0a1464c9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6395.e9c73649.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6796.51d2c9b7.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6976.379be23b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6978.ee0b945c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/7040.cb436723.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/7195.412f418a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/7280.3fb73bdb.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/768e31b0.a12673db.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/7845.e33e7c4c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/7900.69516146.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8356.8a379c04.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/85387663.6bf41934.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8567.4732c6b7.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8573.cb04eda5.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8577.1d54e766.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8591.d7c16be6.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/8591.d7c16be6.js.LICENSE.txt +61 -0
- solace_agent_mesh/assets/docs/assets/js/8709.7ecd4047.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8731.49e930c2.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8908.f9d1b506.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9157.b4093d07.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9278.a4fd875d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/945fb41e.74d728aa.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9616.b75c2f6d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9793.c6d16376.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9eff14a2.1bf8f61c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/a3a92b25.26ca071f.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/a7bd4aaa.2204d2f7.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/a94703ab.0438dbc2.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/aba21aa0.c42a534c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/aba87c2f.d3e2dcc3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ae4415af.8e279b5d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/b7006a3a.40b10c9d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/bac0be12.f50d9bac.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/bb2ef573.207e6990.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/c2c06897.63b76e9e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/cc969b05.954186d4.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/cd3d4052.ca6eed8c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ced92a13.fb92e7ca.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/cee5d587.f5b73ca1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/f284c35a.ecc3d195.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/f897a61a.2c2e152c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/fbfa3e75.aca209c9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/main.7ed3319f.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/main.7ed3319f.js.LICENSE.txt +81 -0
- solace_agent_mesh/assets/docs/assets/js/runtime~main.d9520ae2.js +1 -0
- solace_agent_mesh/assets/docs/docs/documentation/concepts/agents/index.html +128 -0
- solace_agent_mesh/assets/docs/docs/documentation/concepts/architecture/index.html +91 -0
- solace_agent_mesh/assets/docs/docs/documentation/concepts/cli/index.html +201 -0
- solace_agent_mesh/assets/docs/docs/documentation/concepts/gateways/index.html +91 -0
- solace_agent_mesh/assets/docs/docs/documentation/concepts/orchestrator/index.html +55 -0
- solace_agent_mesh/assets/docs/docs/documentation/concepts/plugins/index.html +82 -0
- solace_agent_mesh/assets/docs/docs/documentation/deployment/debugging/index.html +60 -0
- solace_agent_mesh/assets/docs/docs/documentation/deployment/deploy/index.html +48 -0
- solace_agent_mesh/assets/docs/docs/documentation/deployment/observability/index.html +54 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +17 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/component-overview/index.html +45 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/installation/index.html +76 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +150 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/quick-start/index.html +54 -0
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/bedrock-agents/index.html +267 -0
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/custom-agent/index.html +136 -0
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/event-mesh-gateway/index.html +116 -0
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/mcp-integration/index.html +80 -0
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/mongodb-integration/index.html +164 -0
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/rest-gateway/index.html +57 -0
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/slack-integration/index.html +72 -0
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/sql-database/index.html +102 -0
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/artifact-management/index.html +99 -0
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/audio-tools/index.html +90 -0
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/data-analysis-tools/index.html +107 -0
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/embeds/index.html +152 -0
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/index.html +103 -0
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-agents/index.html +170 -0
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-gateways/index.html +200 -0
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/creating-service-providers/index.html +54 -0
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/solace-ai-connector/index.html +69 -0
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/structure/index.html +59 -0
- solace_agent_mesh/assets/docs/img/Solace_AI_Framework_README.png +0 -0
- solace_agent_mesh/assets/docs/img/Solace_AI_Framework_With_Broker.png +0 -0
- solace_agent_mesh/assets/docs/img/logo.png +0 -0
- solace_agent_mesh/assets/docs/img/sac-flows.png +0 -0
- solace_agent_mesh/assets/docs/img/sac_parts_of_a_component.png +0 -0
- solace_agent_mesh/assets/docs/img/solace-logo.png +0 -0
- solace_agent_mesh/assets/docs/lunr-index-1753813536522.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -0
- solace_agent_mesh/assets/docs/search-doc-1753813536522.json +1 -0
- solace_agent_mesh/assets/docs/search-doc.json +1 -0
- solace_agent_mesh/assets/docs/sitemap.xml +1 -0
- solace_agent_mesh/cli/__init__.py +1 -1
- solace_agent_mesh/cli/commands/add_cmd/__init__.py +15 -0
- solace_agent_mesh/cli/commands/add_cmd/add_cmd_llm.txt +250 -0
- solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +659 -0
- solace_agent_mesh/cli/commands/add_cmd/gateway_cmd.py +322 -0
- solace_agent_mesh/cli/commands/add_cmd/web_add_agent_step.py +93 -0
- solace_agent_mesh/cli/commands/add_cmd/web_add_gateway_step.py +118 -0
- solace_agent_mesh/cli/commands/docs_cmd.py +57 -0
- solace_agent_mesh/cli/commands/eval_cmd.py +64 -0
- solace_agent_mesh/cli/commands/init_cmd/__init__.py +404 -0
- solace_agent_mesh/cli/commands/init_cmd/broker_step.py +201 -0
- solace_agent_mesh/cli/commands/init_cmd/directory_step.py +28 -0
- solace_agent_mesh/cli/commands/init_cmd/env_step.py +197 -0
- solace_agent_mesh/cli/commands/init_cmd/init_cmd_llm.txt +365 -0
- solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +387 -0
- solace_agent_mesh/cli/commands/init_cmd/project_files_step.py +38 -0
- solace_agent_mesh/cli/commands/init_cmd/web_init_step.py +110 -0
- solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +183 -0
- solace_agent_mesh/cli/commands/plugin_cmd/__init__.py +18 -0
- solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +372 -0
- solace_agent_mesh/cli/commands/plugin_cmd/build_cmd.py +86 -0
- solace_agent_mesh/cli/commands/plugin_cmd/catalog_cmd.py +138 -0
- solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +309 -0
- solace_agent_mesh/cli/commands/plugin_cmd/official_registry.py +174 -0
- solace_agent_mesh/cli/commands/plugin_cmd/plugin_cmd_llm.txt +305 -0
- solace_agent_mesh/cli/commands/run_cmd.py +158 -0
- solace_agent_mesh/cli/main.py +17 -294
- solace_agent_mesh/cli/utils.py +135 -204
- solace_agent_mesh/client/webui/frontend/static/assets/authCallback-DvlO62me.js +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/client-bp6u3qVZ.js +49 -0
- solace_agent_mesh/client/webui/frontend/static/assets/favicon-BLgzUch9.ico +0 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-An0a5j5k.js +663 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-Bu5-4Bac.css +1 -0
- solace_agent_mesh/client/webui/frontend/static/auth-callback.html +14 -0
- solace_agent_mesh/client/webui/frontend/static/index.html +15 -0
- solace_agent_mesh/common/__init__.py +1 -0
- solace_agent_mesh/common/a2a_protocol.py +564 -0
- solace_agent_mesh/common/agent_registry.py +42 -0
- solace_agent_mesh/common/client/__init__.py +4 -0
- solace_agent_mesh/common/client/card_resolver.py +21 -0
- solace_agent_mesh/common/client/client.py +85 -0
- solace_agent_mesh/common/client/client_llm.txt +133 -0
- solace_agent_mesh/common/common_llm.txt +144 -0
- solace_agent_mesh/common/constants.py +1 -14
- solace_agent_mesh/common/middleware/__init__.py +12 -0
- solace_agent_mesh/common/middleware/config_resolver.py +130 -0
- solace_agent_mesh/common/middleware/middleware_llm.txt +174 -0
- solace_agent_mesh/common/middleware/registry.py +125 -0
- solace_agent_mesh/common/server/__init__.py +4 -0
- solace_agent_mesh/common/server/server.py +122 -0
- solace_agent_mesh/common/server/server_llm.txt +169 -0
- solace_agent_mesh/common/server/task_manager.py +291 -0
- solace_agent_mesh/common/server/utils.py +28 -0
- solace_agent_mesh/common/services/__init__.py +4 -0
- solace_agent_mesh/common/services/employee_service.py +162 -0
- solace_agent_mesh/common/services/identity_service.py +129 -0
- solace_agent_mesh/common/services/providers/__init__.py +4 -0
- solace_agent_mesh/common/services/providers/local_file_identity_service.py +148 -0
- solace_agent_mesh/common/services/providers/providers_llm.txt +113 -0
- solace_agent_mesh/common/services/services_llm.txt +132 -0
- solace_agent_mesh/common/types.py +411 -0
- solace_agent_mesh/common/utils/__init__.py +7 -0
- solace_agent_mesh/common/utils/asyncio_macos_fix.py +86 -0
- solace_agent_mesh/common/utils/embeds/__init__.py +33 -0
- solace_agent_mesh/common/utils/embeds/constants.py +55 -0
- solace_agent_mesh/common/utils/embeds/converter.py +452 -0
- solace_agent_mesh/common/utils/embeds/embeds_llm.txt +124 -0
- solace_agent_mesh/common/utils/embeds/evaluators.py +394 -0
- solace_agent_mesh/common/utils/embeds/modifiers.py +816 -0
- solace_agent_mesh/common/utils/embeds/resolver.py +865 -0
- solace_agent_mesh/common/utils/embeds/types.py +14 -0
- solace_agent_mesh/common/utils/in_memory_cache.py +108 -0
- solace_agent_mesh/common/utils/log_formatters.py +44 -0
- solace_agent_mesh/common/utils/mime_helpers.py +106 -0
- solace_agent_mesh/common/utils/push_notification_auth.py +134 -0
- solace_agent_mesh/common/utils/utils_llm.txt +67 -0
- solace_agent_mesh/config_portal/backend/common.py +66 -24
- solace_agent_mesh/config_portal/backend/plugin_catalog/constants.py +23 -0
- solace_agent_mesh/config_portal/backend/plugin_catalog/models.py +49 -0
- solace_agent_mesh/config_portal/backend/plugin_catalog/registry_manager.py +160 -0
- solace_agent_mesh/config_portal/backend/plugin_catalog/scraper.py +525 -0
- solace_agent_mesh/config_portal/backend/plugin_catalog_server.py +216 -0
- solace_agent_mesh/config_portal/backend/server.py +550 -140
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-DNxCwAGB.js +48 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/components-B7lKcHVY.js +140 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/{entry.client-DX1misIU.js → entry.client-CEumGClk.js} +3 -3
- solace_agent_mesh/config_portal/frontend/static/client/assets/index-DSo1AH_7.js +68 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-d2b54a97.js +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/{root-BApq5dPK.js → root-C4XmHinv.js} +2 -2
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-DxRwaWiE.css +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/index.html +3 -3
- solace_agent_mesh/core_a2a/__init__.py +1 -0
- solace_agent_mesh/core_a2a/core_a2a_llm.txt +88 -0
- solace_agent_mesh/core_a2a/service.py +331 -0
- solace_agent_mesh/evaluation/config_loader.py +657 -0
- solace_agent_mesh/evaluation/evaluator.py +667 -0
- solace_agent_mesh/evaluation/message_organizer.py +568 -0
- solace_agent_mesh/evaluation/report/benchmark_info.html +35 -0
- solace_agent_mesh/evaluation/report/chart_section.html +141 -0
- solace_agent_mesh/evaluation/report/detailed_breakdown.html +28 -0
- solace_agent_mesh/evaluation/report/modal.html +59 -0
- solace_agent_mesh/evaluation/report/modal_chart_functions.js +411 -0
- solace_agent_mesh/evaluation/report/modal_script.js +296 -0
- solace_agent_mesh/evaluation/report/modal_styles.css +340 -0
- solace_agent_mesh/evaluation/report/performance_metrics_styles.css +93 -0
- solace_agent_mesh/evaluation/report/templates/footer.html +2 -0
- solace_agent_mesh/evaluation/report/templates/header.html +340 -0
- solace_agent_mesh/evaluation/report_data_processor.py +972 -0
- solace_agent_mesh/evaluation/report_generator.py +613 -0
- solace_agent_mesh/evaluation/run.py +613 -0
- solace_agent_mesh/evaluation/subscriber.py +872 -0
- solace_agent_mesh/evaluation/summary_builder.py +775 -0
- solace_agent_mesh/evaluation/test_case_loader.py +714 -0
- solace_agent_mesh/gateway/base/__init__.py +1 -0
- solace_agent_mesh/gateway/base/app.py +266 -0
- solace_agent_mesh/gateway/base/base_llm.txt +119 -0
- solace_agent_mesh/gateway/base/component.py +1542 -0
- solace_agent_mesh/gateway/base/task_context.py +74 -0
- solace_agent_mesh/gateway/gateway_llm.txt +125 -0
- solace_agent_mesh/gateway/http_sse/app.py +190 -0
- solace_agent_mesh/gateway/http_sse/component.py +1602 -0
- solace_agent_mesh/gateway/http_sse/components/__init__.py +7 -0
- solace_agent_mesh/gateway/http_sse/components/components_llm.txt +65 -0
- solace_agent_mesh/gateway/http_sse/components/visualization_forwarder_component.py +108 -0
- solace_agent_mesh/gateway/http_sse/dependencies.py +316 -0
- solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +63 -0
- solace_agent_mesh/gateway/http_sse/main.py +442 -0
- solace_agent_mesh/gateway/http_sse/routers/__init__.py +4 -0
- solace_agent_mesh/gateway/http_sse/routers/agents.py +41 -0
- solace_agent_mesh/gateway/http_sse/routers/artifacts.py +821 -0
- solace_agent_mesh/gateway/http_sse/routers/auth.py +212 -0
- solace_agent_mesh/gateway/http_sse/routers/config.py +55 -0
- solace_agent_mesh/gateway/http_sse/routers/people.py +69 -0
- solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +37 -0
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +80 -0
- solace_agent_mesh/gateway/http_sse/routers/sse.py +138 -0
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +294 -0
- solace_agent_mesh/gateway/http_sse/routers/users.py +59 -0
- solace_agent_mesh/gateway/http_sse/routers/visualization.py +1131 -0
- solace_agent_mesh/gateway/http_sse/services/__init__.py +4 -0
- solace_agent_mesh/gateway/http_sse/services/agent_service.py +69 -0
- solace_agent_mesh/gateway/http_sse/services/people_service.py +158 -0
- solace_agent_mesh/gateway/http_sse/services/services_llm.txt +179 -0
- solace_agent_mesh/gateway/http_sse/services/task_service.py +121 -0
- solace_agent_mesh/gateway/http_sse/session_manager.py +187 -0
- solace_agent_mesh/gateway/http_sse/sse_manager.py +328 -0
- solace_agent_mesh/llm.txt +228 -0
- solace_agent_mesh/llm_detail.txt +2835 -0
- solace_agent_mesh/templates/agent_template.yaml +53 -0
- solace_agent_mesh/templates/eval_backend_template.yaml +54 -0
- solace_agent_mesh/templates/gateway_app_template.py +73 -0
- solace_agent_mesh/templates/gateway_component_template.py +400 -0
- solace_agent_mesh/templates/gateway_config_template.yaml +43 -0
- solace_agent_mesh/templates/main_orchestrator.yaml +55 -0
- solace_agent_mesh/templates/plugin_agent_config_template.yaml +122 -0
- solace_agent_mesh/templates/plugin_custom_config_template.yaml +27 -0
- solace_agent_mesh/templates/plugin_custom_template.py +10 -0
- solace_agent_mesh/templates/plugin_gateway_config_template.yaml +63 -0
- solace_agent_mesh/templates/plugin_pyproject_template.toml +33 -0
- solace_agent_mesh/templates/plugin_readme_template.md +34 -0
- solace_agent_mesh/templates/plugin_tools_template.py +224 -0
- solace_agent_mesh/templates/shared_config.yaml +66 -0
- solace_agent_mesh/templates/templates_llm.txt +147 -0
- solace_agent_mesh/templates/webui.yaml +53 -0
- solace_agent_mesh-1.0.1.dist-info/METADATA +432 -0
- solace_agent_mesh-1.0.1.dist-info/RECORD +359 -0
- solace_agent_mesh-1.0.1.dist-info/entry_points.txt +3 -0
- {solace_agent_mesh-0.2.3.dist-info → solace_agent_mesh-1.0.1.dist-info}/licenses/LICENSE +1 -1
- solace_agent_mesh/agents/base_agent_component.py +0 -226
- solace_agent_mesh/agents/global/actions/agent_state_change.py +0 -54
- solace_agent_mesh/agents/global/actions/clear_history.py +0 -32
- solace_agent_mesh/agents/global/actions/convert_file_to_markdown.py +0 -160
- solace_agent_mesh/agents/global/actions/create_file.py +0 -70
- solace_agent_mesh/agents/global/actions/error_action.py +0 -45
- solace_agent_mesh/agents/global/actions/plantuml_diagram.py +0 -163
- solace_agent_mesh/agents/global/actions/plotly_graph.py +0 -152
- solace_agent_mesh/agents/global/actions/retrieve_file.py +0 -51
- solace_agent_mesh/agents/global/global_agent_component.py +0 -38
- solace_agent_mesh/agents/image_processing/actions/create_image.py +0 -75
- solace_agent_mesh/agents/image_processing/actions/describe_image.py +0 -115
- solace_agent_mesh/agents/image_processing/image_processing_agent_component.py +0 -23
- solace_agent_mesh/agents/slack/__init__.py +0 -1
- solace_agent_mesh/agents/slack/actions/__init__.py +0 -1
- solace_agent_mesh/agents/slack/actions/post_message.py +0 -177
- solace_agent_mesh/agents/slack/slack_agent_component.py +0 -59
- solace_agent_mesh/agents/web_request/actions/do_image_search.py +0 -84
- solace_agent_mesh/agents/web_request/actions/do_news_search.py +0 -47
- solace_agent_mesh/agents/web_request/actions/do_suggestion_search.py +0 -34
- solace_agent_mesh/agents/web_request/actions/do_web_request.py +0 -135
- solace_agent_mesh/agents/web_request/actions/download_file.py +0 -69
- solace_agent_mesh/agents/web_request/web_request_agent_component.py +0 -33
- solace_agent_mesh/assets/web-visualizer/assets/index-D0qORgkg.css +0 -1
- solace_agent_mesh/assets/web-visualizer/assets/index-DnDr1pnu.js +0 -109
- solace_agent_mesh/assets/web-visualizer/index.html +0 -14
- solace_agent_mesh/assets/web-visualizer/vite.svg +0 -1
- solace_agent_mesh/cli/commands/add/__init__.py +0 -3
- solace_agent_mesh/cli/commands/add/add.py +0 -88
- solace_agent_mesh/cli/commands/add/agent.py +0 -110
- solace_agent_mesh/cli/commands/add/copy_from_plugin.py +0 -92
- solace_agent_mesh/cli/commands/add/gateway.py +0 -374
- solace_agent_mesh/cli/commands/build.py +0 -670
- solace_agent_mesh/cli/commands/chat/__init__.py +0 -3
- solace_agent_mesh/cli/commands/chat/chat.py +0 -361
- solace_agent_mesh/cli/commands/config.py +0 -29
- solace_agent_mesh/cli/commands/init/__init__.py +0 -3
- solace_agent_mesh/cli/commands/init/ai_provider_step.py +0 -93
- solace_agent_mesh/cli/commands/init/broker_step.py +0 -99
- solace_agent_mesh/cli/commands/init/builtin_agent_step.py +0 -83
- solace_agent_mesh/cli/commands/init/check_if_already_done.py +0 -13
- solace_agent_mesh/cli/commands/init/create_config_file_step.py +0 -65
- solace_agent_mesh/cli/commands/init/create_other_project_files_step.py +0 -147
- solace_agent_mesh/cli/commands/init/file_service_step.py +0 -73
- solace_agent_mesh/cli/commands/init/init.py +0 -92
- solace_agent_mesh/cli/commands/init/project_structure_step.py +0 -16
- solace_agent_mesh/cli/commands/init/web_init_step.py +0 -32
- solace_agent_mesh/cli/commands/plugin/__init__.py +0 -3
- solace_agent_mesh/cli/commands/plugin/add.py +0 -100
- solace_agent_mesh/cli/commands/plugin/build.py +0 -268
- solace_agent_mesh/cli/commands/plugin/create.py +0 -117
- solace_agent_mesh/cli/commands/plugin/plugin.py +0 -124
- solace_agent_mesh/cli/commands/plugin/remove.py +0 -73
- solace_agent_mesh/cli/commands/run.py +0 -68
- solace_agent_mesh/cli/commands/visualizer.py +0 -138
- solace_agent_mesh/cli/config.py +0 -85
- solace_agent_mesh/common/action.py +0 -91
- solace_agent_mesh/common/action_list.py +0 -37
- solace_agent_mesh/common/action_response.py +0 -340
- solace_agent_mesh/common/mysql_database.py +0 -40
- solace_agent_mesh/common/postgres_database.py +0 -85
- solace_agent_mesh/common/prompt_templates.py +0 -28
- solace_agent_mesh/common/stimulus_utils.py +0 -152
- solace_agent_mesh/common/time.py +0 -24
- solace_agent_mesh/common/utils.py +0 -712
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-DMmCawWe.js +0 -42
- solace_agent_mesh/config_portal/frontend/static/client/assets/components-ZIfdTbrV.js +0 -191
- solace_agent_mesh/config_portal/frontend/static/client/assets/index-BJHAE5s4.js +0 -17
- solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-dd988f05.js +0 -1
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-DX4gQ516.css +0 -1
- solace_agent_mesh/configs/agent_global.yaml +0 -74
- solace_agent_mesh/configs/agent_image_processing.yaml +0 -82
- solace_agent_mesh/configs/agent_slack.yaml +0 -64
- solace_agent_mesh/configs/agent_web_request.yaml +0 -75
- solace_agent_mesh/configs/conversation_to_file.yaml +0 -56
- solace_agent_mesh/configs/error_catcher.yaml +0 -56
- solace_agent_mesh/configs/monitor.yaml +0 -0
- solace_agent_mesh/configs/monitor_stim_and_errors_to_slack.yaml +0 -109
- solace_agent_mesh/configs/monitor_user_feedback.yaml +0 -58
- solace_agent_mesh/configs/orchestrator.yaml +0 -241
- solace_agent_mesh/configs/service_embedding.yaml +0 -81
- solace_agent_mesh/configs/service_llm.yaml +0 -265
- solace_agent_mesh/configs/visualize_websocket.yaml +0 -55
- solace_agent_mesh/gateway/components/gateway_base.py +0 -47
- solace_agent_mesh/gateway/components/gateway_input.py +0 -278
- solace_agent_mesh/gateway/components/gateway_output.py +0 -298
- solace_agent_mesh/gateway/identity/bamboohr_identity.py +0 -18
- solace_agent_mesh/gateway/identity/identity_base.py +0 -10
- solace_agent_mesh/gateway/identity/identity_provider.py +0 -60
- solace_agent_mesh/gateway/identity/no_identity.py +0 -9
- solace_agent_mesh/gateway/identity/passthru_identity.py +0 -9
- solace_agent_mesh/monitors/base_monitor_component.py +0 -26
- solace_agent_mesh/monitors/feedback/user_feedback_monitor.py +0 -75
- solace_agent_mesh/monitors/stim_and_errors/stim_and_error_monitor.py +0 -560
- solace_agent_mesh/orchestrator/__init__.py +0 -0
- solace_agent_mesh/orchestrator/action_manager.py +0 -237
- solace_agent_mesh/orchestrator/components/__init__.py +0 -0
- solace_agent_mesh/orchestrator/components/orchestrator_action_manager_timeout_component.py +0 -58
- solace_agent_mesh/orchestrator/components/orchestrator_action_response_component.py +0 -179
- solace_agent_mesh/orchestrator/components/orchestrator_register_component.py +0 -107
- solace_agent_mesh/orchestrator/components/orchestrator_stimulus_processor_component.py +0 -527
- solace_agent_mesh/orchestrator/components/orchestrator_streaming_output_component.py +0 -260
- solace_agent_mesh/orchestrator/orchestrator_main.py +0 -172
- solace_agent_mesh/orchestrator/orchestrator_prompt.py +0 -539
- solace_agent_mesh/services/__init__.py +0 -0
- solace_agent_mesh/services/authorization/providers/base_authorization_provider.py +0 -56
- solace_agent_mesh/services/bamboo_hr_service/__init__.py +0 -3
- solace_agent_mesh/services/bamboo_hr_service/bamboo_hr.py +0 -182
- solace_agent_mesh/services/common/__init__.py +0 -4
- solace_agent_mesh/services/common/auto_expiry.py +0 -45
- solace_agent_mesh/services/common/singleton.py +0 -18
- solace_agent_mesh/services/file_service/__init__.py +0 -14
- solace_agent_mesh/services/file_service/file_manager/__init__.py +0 -0
- solace_agent_mesh/services/file_service/file_manager/bucket_file_manager.py +0 -149
- solace_agent_mesh/services/file_service/file_manager/file_manager_base.py +0 -162
- solace_agent_mesh/services/file_service/file_manager/memory_file_manager.py +0 -64
- solace_agent_mesh/services/file_service/file_manager/volume_file_manager.py +0 -106
- solace_agent_mesh/services/file_service/file_service.py +0 -437
- solace_agent_mesh/services/file_service/file_service_constants.py +0 -54
- solace_agent_mesh/services/file_service/file_transformations.py +0 -141
- solace_agent_mesh/services/file_service/file_utils.py +0 -324
- solace_agent_mesh/services/file_service/transformers/__init__.py +0 -5
- solace_agent_mesh/services/history_service/__init__.py +0 -3
- solace_agent_mesh/services/history_service/history_providers/__init__.py +0 -0
- solace_agent_mesh/services/history_service/history_providers/base_history_provider.py +0 -54
- solace_agent_mesh/services/history_service/history_providers/file_history_provider.py +0 -74
- solace_agent_mesh/services/history_service/history_providers/index.py +0 -40
- solace_agent_mesh/services/history_service/history_providers/memory_history_provider.py +0 -33
- solace_agent_mesh/services/history_service/history_providers/mongodb_history_provider.py +0 -66
- solace_agent_mesh/services/history_service/history_providers/redis_history_provider.py +0 -66
- solace_agent_mesh/services/history_service/history_providers/sql_history_provider.py +0 -93
- solace_agent_mesh/services/history_service/history_service.py +0 -413
- solace_agent_mesh/services/history_service/long_term_memory/__init__.py +0 -0
- solace_agent_mesh/services/history_service/long_term_memory/long_term_memory.py +0 -399
- solace_agent_mesh/services/llm_service/components/llm_request_component.py +0 -340
- solace_agent_mesh/services/llm_service/components/llm_service_component_base.py +0 -152
- solace_agent_mesh/services/middleware_service/__init__.py +0 -0
- solace_agent_mesh/services/middleware_service/middleware_service.py +0 -20
- solace_agent_mesh/templates/action.py +0 -38
- solace_agent_mesh/templates/agent.py +0 -29
- solace_agent_mesh/templates/agent.yaml +0 -70
- solace_agent_mesh/templates/gateway-config-template.yaml +0 -6
- solace_agent_mesh/templates/gateway-default-config.yaml +0 -28
- solace_agent_mesh/templates/gateway-flows.yaml +0 -78
- solace_agent_mesh/templates/gateway-header.yaml +0 -16
- solace_agent_mesh/templates/gateway_base.py +0 -15
- solace_agent_mesh/templates/gateway_input.py +0 -98
- solace_agent_mesh/templates/gateway_output.py +0 -71
- solace_agent_mesh/templates/plugin-gateway-default-config.yaml +0 -29
- solace_agent_mesh/templates/plugin-pyproject.toml +0 -30
- solace_agent_mesh/templates/rest-api-default-config.yaml +0 -31
- solace_agent_mesh/templates/rest-api-flows.yaml +0 -81
- solace_agent_mesh/templates/slack-default-config.yaml +0 -16
- solace_agent_mesh/templates/slack-flows.yaml +0 -81
- solace_agent_mesh/templates/solace-agent-mesh-default.yaml +0 -86
- solace_agent_mesh/templates/solace-agent-mesh-plugin-default.yaml +0 -8
- solace_agent_mesh/templates/web-default-config.yaml +0 -10
- solace_agent_mesh/templates/web-flows.yaml +0 -76
- solace_agent_mesh/tools/__init__.py +0 -0
- solace_agent_mesh/tools/components/__init__.py +0 -0
- solace_agent_mesh/tools/components/conversation_formatter.py +0 -111
- solace_agent_mesh/tools/components/file_resolver_component.py +0 -58
- solace_agent_mesh/tools/config/runtime_config.py +0 -26
- solace_agent_mesh-0.2.3.dist-info/METADATA +0 -172
- solace_agent_mesh-0.2.3.dist-info/RECORD +0 -193
- solace_agent_mesh-0.2.3.dist-info/entry_points.txt +0 -3
- /solace_agent_mesh/{agents → agent}/__init__.py +0 -0
- /solace_agent_mesh/{agents/global → agent/adk}/__init__.py +0 -0
- /solace_agent_mesh/{agents/global/actions → agent/protocol}/__init__.py +0 -0
- /solace_agent_mesh/{agents/image_processing → agent/sac}/__init__.py +0 -0
- /solace_agent_mesh/{agents/image_processing/actions → agent/utils}/__init__.py +0 -0
- /solace_agent_mesh/{agents/web_request → config_portal/backend/plugin_catalog}/__init__.py +0 -0
- /solace_agent_mesh/{agents/web_request/actions → evaluation}/__init__.py +0 -0
- /solace_agent_mesh/gateway/{components → http_sse}/__init__.py +0 -0
- {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()
|