solace-agent-mesh 1.11.2__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.
- solace_agent_mesh/__init__.py +0 -0
- solace_agent_mesh/agent/__init__.py +0 -0
- solace_agent_mesh/agent/adk/__init__.py +0 -0
- solace_agent_mesh/agent/adk/adk_llm.txt +226 -0
- solace_agent_mesh/agent/adk/adk_llm_detail.txt +566 -0
- solace_agent_mesh/agent/adk/alembic/README +74 -0
- solace_agent_mesh/agent/adk/alembic/env.py +77 -0
- solace_agent_mesh/agent/adk/alembic/script.py.mako +28 -0
- solace_agent_mesh/agent/adk/alembic/versions/e2902798564d_adk_session_db_upgrade.py +52 -0
- solace_agent_mesh/agent/adk/alembic.ini +112 -0
- solace_agent_mesh/agent/adk/app_llm_agent.py +52 -0
- solace_agent_mesh/agent/adk/artifacts/__init__.py +1 -0
- solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +171 -0
- solace_agent_mesh/agent/adk/artifacts/filesystem_artifact_service.py +545 -0
- solace_agent_mesh/agent/adk/artifacts/s3_artifact_service.py +609 -0
- solace_agent_mesh/agent/adk/callbacks.py +2318 -0
- solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +406 -0
- solace_agent_mesh/agent/adk/intelligent_mcp_callbacks.py +415 -0
- solace_agent_mesh/agent/adk/mcp_content_processor.py +666 -0
- solace_agent_mesh/agent/adk/models/lite_llm.py +1026 -0
- solace_agent_mesh/agent/adk/models/models_llm.txt +189 -0
- solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +132 -0
- solace_agent_mesh/agent/adk/runner.py +390 -0
- solace_agent_mesh/agent/adk/schema_migration.py +88 -0
- solace_agent_mesh/agent/adk/services.py +468 -0
- solace_agent_mesh/agent/adk/setup.py +1325 -0
- solace_agent_mesh/agent/adk/stream_parser.py +415 -0
- solace_agent_mesh/agent/adk/tool_wrapper.py +165 -0
- solace_agent_mesh/agent/agent_llm.txt +369 -0
- solace_agent_mesh/agent/agent_llm_detail.txt +1702 -0
- solace_agent_mesh/agent/protocol/__init__.py +0 -0
- solace_agent_mesh/agent/protocol/event_handlers.py +2041 -0
- solace_agent_mesh/agent/protocol/protocol_llm.txt +81 -0
- solace_agent_mesh/agent/protocol/protocol_llm_detail.txt +92 -0
- solace_agent_mesh/agent/proxies/__init__.py +0 -0
- solace_agent_mesh/agent/proxies/a2a/__init__.py +3 -0
- solace_agent_mesh/agent/proxies/a2a/a2a_llm.txt +190 -0
- solace_agent_mesh/agent/proxies/a2a/app.py +56 -0
- solace_agent_mesh/agent/proxies/a2a/component.py +1585 -0
- solace_agent_mesh/agent/proxies/a2a/config.py +216 -0
- solace_agent_mesh/agent/proxies/a2a/oauth_token_cache.py +104 -0
- solace_agent_mesh/agent/proxies/base/__init__.py +3 -0
- solace_agent_mesh/agent/proxies/base/app.py +100 -0
- solace_agent_mesh/agent/proxies/base/base_llm.txt +148 -0
- solace_agent_mesh/agent/proxies/base/component.py +816 -0
- solace_agent_mesh/agent/proxies/base/config.py +85 -0
- solace_agent_mesh/agent/proxies/base/proxy_task_context.py +19 -0
- solace_agent_mesh/agent/proxies/proxies_llm.txt +283 -0
- solace_agent_mesh/agent/sac/__init__.py +0 -0
- solace_agent_mesh/agent/sac/app.py +595 -0
- solace_agent_mesh/agent/sac/component.py +3668 -0
- solace_agent_mesh/agent/sac/patch_adk.py +103 -0
- solace_agent_mesh/agent/sac/sac_llm.txt +189 -0
- solace_agent_mesh/agent/sac/sac_llm_detail.txt +200 -0
- solace_agent_mesh/agent/sac/task_execution_context.py +415 -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 +58 -0
- solace_agent_mesh/agent/testing/testing_llm_detail.txt +68 -0
- solace_agent_mesh/agent/tools/__init__.py +16 -0
- solace_agent_mesh/agent/tools/audio_tools.py +1740 -0
- solace_agent_mesh/agent/tools/builtin_artifact_tools.py +2500 -0
- solace_agent_mesh/agent/tools/builtin_data_analysis_tools.py +244 -0
- solace_agent_mesh/agent/tools/dynamic_tool.py +396 -0
- solace_agent_mesh/agent/tools/general_agent_tools.py +572 -0
- solace_agent_mesh/agent/tools/image_tools.py +1185 -0
- solace_agent_mesh/agent/tools/peer_agent_tool.py +363 -0
- solace_agent_mesh/agent/tools/registry.py +38 -0
- solace_agent_mesh/agent/tools/test_tools.py +136 -0
- solace_agent_mesh/agent/tools/time_tools.py +126 -0
- solace_agent_mesh/agent/tools/tool_config_types.py +93 -0
- solace_agent_mesh/agent/tools/tool_definition.py +53 -0
- solace_agent_mesh/agent/tools/tools_llm.txt +276 -0
- solace_agent_mesh/agent/tools/tools_llm_detail.txt +275 -0
- solace_agent_mesh/agent/tools/web_tools.py +392 -0
- solace_agent_mesh/agent/utils/__init__.py +0 -0
- solace_agent_mesh/agent/utils/artifact_helpers.py +1353 -0
- solace_agent_mesh/agent/utils/config_parser.py +49 -0
- solace_agent_mesh/agent/utils/context_helpers.py +77 -0
- solace_agent_mesh/agent/utils/utils_llm.txt +152 -0
- solace_agent_mesh/agent/utils/utils_llm_detail.txt +149 -0
- solace_agent_mesh/assets/docs/404.html +16 -0
- solace_agent_mesh/assets/docs/assets/css/styles.8162edfb.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/sam-enterprise-credentials-b269f095349473118b2b33bdfcc40122.png +0 -0
- solace_agent_mesh/assets/docs/assets/js/032c2d61.f3d37824.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/05749d90.19ac4f35.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/0bcf40b7.c019ad46.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/1001.0182a8bd.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/15ba94aa.92fea363.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/15e40e79.434bb30f.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/17896441.e612dfb4.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2130.ab9fd314.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2131ec11.5c7a1f6e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2237.5e477fc6.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2279.550aa580.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/2279.550aa580.js.LICENSE.txt +13 -0
- solace_agent_mesh/assets/docs/assets/js/2334.1cf50a20.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/240a0364.9ad94d1b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2987107d.a80604f9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2e32b5e0.33f5d75b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3219.adc1d663.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/341393d4.0fac2613.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3624.0eaa1fd0.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/3a6c6137.f5940cfa.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ac1795d.28b7c67b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.2ddc75c0.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/41adc471.48b12a4e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4250.95455b28.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4356.d169ab5b.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/509e993c.a1fbf45a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5388.7a136447.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/547e15cc.2f7790c1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/55b7b518.29d6e75d.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/5c2bd65f.90a87880.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5e95c892.558d5167.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6063ff4c.ef84f702.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/60702c0e.a8bdd79b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6143.0a1464c9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/631738c7.fa471607.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6395.e9c73649.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/64195356.c498c4d0.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/66d4869e.b77431fc.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/6a520c9d.b6e3f2ce.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6aaedf65.7253541d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.a5b36a60.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.fd23ba4a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6fdfefc7.99de744e.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/71da7b71.374b9d54.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/722f809d.965da774.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/7280.3fb73bdb.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/742f027b.46c07808.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/77cf947d.48cb18a2.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/8024126c.fa0e7186.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/81a99df0.2484b8d9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/82fbfb93.161823a5.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8356.8a379c04.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.5d015485.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/8591.5d015485.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.6c1dbf0c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8908.f9d1b506.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8b032486.91a91afc.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9157.b4093d07.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/924ffdeb.975e428a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9278.a4fd875d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/945fb41e.6f4cdffd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/94e8668d.16083b3f.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/9bb13469.b2333011.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9e9d0a82.570c057b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/a7bd4aaa.2204d2f7.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/a94703ab.3e5fbcb3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ab9708a8.245ae0ef.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/aba21aa0.c42a534c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ad71b5ed.af3ecfd1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ad87452a.9d73dad6.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/c198a0dc.8f31f867.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/c93cbaa0.0e0d8baf.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/cab03b5b.6a073091.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.07e170dd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ceb2a7a6.5d92d7d0.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/da0b5bad.b62f7b08.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/db5d6442.3daf1696.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/db924877.e98d12a1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/dd817ffc.c37a755e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/dd81e2b8.b682e9c2.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/de5f4c65.e8241890.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/de915948.44a432bc.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e04b235d.52cb25ed.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e1b6eeb4.b1068f9b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e3d9abda.1476f570.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.4488e34c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e92d0134.3bda61dd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/f284c35a.250993bf.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ff4d71f2.74710fc1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/main.7acf7ace.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/main.7acf7ace.js.LICENSE.txt +81 -0
- solace_agent_mesh/assets/docs/assets/js/runtime~main.9e0813a2.js +1 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +154 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +99 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +90 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +107 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +166 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +101 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +219 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +92 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/index.html +29 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +55 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +110 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/projects/index.html +182 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/prompts/index.html +147 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +345 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/speech/index.html +52 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +83 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +84 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +25 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes-deployment/index.html +47 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +85 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +60 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/proxy_configuration/index.html +49 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +144 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +191 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +128 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +54 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +135 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +34 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +55 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +267 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +142 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +116 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +86 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +164 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +140 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +57 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +72 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +102 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/teams-integration/index.html +115 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/agent-builder/index.html +86 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +67 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +37 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +86 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/openapi-tools/index.html +324 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +247 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +440 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +184 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +62 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +75 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +54 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +85 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +41 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/artifact-storage/index.html +290 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +78 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +25 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +78 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +160 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +142 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/session-storage/index.html +251 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +88 -0
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +100 -0
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +52 -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/sam-enterprise-credentials.png +0 -0
- solace_agent_mesh/assets/docs/img/solace-logo-text.svg +18 -0
- solace_agent_mesh/assets/docs/img/solace-logo.png +0 -0
- solace_agent_mesh/assets/docs/lunr-index-1765810064709.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -0
- solace_agent_mesh/assets/docs/search-doc-1765810064709.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 -0
- solace_agent_mesh/cli/commands/__init__.py +0 -0
- 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 +729 -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 +102 -0
- solace_agent_mesh/cli/commands/add_cmd/web_add_gateway_step.py +114 -0
- solace_agent_mesh/cli/commands/docs_cmd.py +60 -0
- solace_agent_mesh/cli/commands/eval_cmd.py +46 -0
- solace_agent_mesh/cli/commands/init_cmd/__init__.py +439 -0
- solace_agent_mesh/cli/commands/init_cmd/broker_step.py +201 -0
- solace_agent_mesh/cli/commands/init_cmd/database_step.py +91 -0
- solace_agent_mesh/cli/commands/init_cmd/directory_step.py +28 -0
- solace_agent_mesh/cli/commands/init_cmd/env_step.py +238 -0
- solace_agent_mesh/cli/commands/init_cmd/init_cmd_llm.txt +365 -0
- solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +464 -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 +119 -0
- solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +215 -0
- solace_agent_mesh/cli/commands/plugin_cmd/__init__.py +20 -0
- solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +137 -0
- solace_agent_mesh/cli/commands/plugin_cmd/build_cmd.py +86 -0
- solace_agent_mesh/cli/commands/plugin_cmd/catalog_cmd.py +144 -0
- solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +306 -0
- solace_agent_mesh/cli/commands/plugin_cmd/install_cmd.py +283 -0
- solace_agent_mesh/cli/commands/plugin_cmd/official_registry.py +175 -0
- solace_agent_mesh/cli/commands/plugin_cmd/plugin_cmd_llm.txt +305 -0
- solace_agent_mesh/cli/commands/run_cmd.py +215 -0
- solace_agent_mesh/cli/main.py +52 -0
- solace_agent_mesh/cli/utils.py +262 -0
- solace_agent_mesh/client/webui/frontend/static/assets/authCallback-Dj3JtK42.js +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/client-ZKk9kEJ5.js +25 -0
- solace_agent_mesh/client/webui/frontend/static/assets/favicon-BLgzUch9.ico +0 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-BcUaNZ-Q.css +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-vjch4RYc.js +435 -0
- solace_agent_mesh/client/webui/frontend/static/assets/vendor-BNV4kZN0.js +535 -0
- solace_agent_mesh/client/webui/frontend/static/auth-callback.html +15 -0
- solace_agent_mesh/client/webui/frontend/static/index.html +16 -0
- solace_agent_mesh/client/webui/frontend/static/mockServiceWorker.js +336 -0
- solace_agent_mesh/client/webui/frontend/static/ui-version.json +6 -0
- solace_agent_mesh/common/__init__.py +1 -0
- solace_agent_mesh/common/a2a/__init__.py +241 -0
- solace_agent_mesh/common/a2a/a2a_llm.txt +175 -0
- solace_agent_mesh/common/a2a/a2a_llm_detail.txt +193 -0
- solace_agent_mesh/common/a2a/artifact.py +368 -0
- solace_agent_mesh/common/a2a/events.py +213 -0
- solace_agent_mesh/common/a2a/message.py +375 -0
- solace_agent_mesh/common/a2a/protocol.py +689 -0
- solace_agent_mesh/common/a2a/task.py +127 -0
- solace_agent_mesh/common/a2a/translation.py +655 -0
- solace_agent_mesh/common/a2a/types.py +55 -0
- solace_agent_mesh/common/a2a_spec/a2a.json +2576 -0
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +445 -0
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm_detail.txt +736 -0
- solace_agent_mesh/common/a2a_spec/schemas/agent_progress_update.json +18 -0
- solace_agent_mesh/common/a2a_spec/schemas/artifact_creation_progress.json +48 -0
- solace_agent_mesh/common/a2a_spec/schemas/feedback_event.json +51 -0
- solace_agent_mesh/common/a2a_spec/schemas/llm_invocation.json +41 -0
- solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +330 -0
- solace_agent_mesh/common/a2a_spec/schemas/tool_invocation_start.json +26 -0
- solace_agent_mesh/common/a2a_spec/schemas/tool_result.json +48 -0
- solace_agent_mesh/common/agent_registry.py +122 -0
- solace_agent_mesh/common/common_llm.txt +230 -0
- solace_agent_mesh/common/common_llm_detail.txt +2562 -0
- solace_agent_mesh/common/constants.py +6 -0
- solace_agent_mesh/common/data_parts.py +150 -0
- solace_agent_mesh/common/exceptions.py +49 -0
- solace_agent_mesh/common/middleware/__init__.py +12 -0
- solace_agent_mesh/common/middleware/config_resolver.py +132 -0
- solace_agent_mesh/common/middleware/middleware_llm.txt +174 -0
- solace_agent_mesh/common/middleware/middleware_llm_detail.txt +185 -0
- solace_agent_mesh/common/middleware/registry.py +127 -0
- solace_agent_mesh/common/oauth/__init__.py +17 -0
- solace_agent_mesh/common/oauth/oauth_client.py +408 -0
- solace_agent_mesh/common/oauth/utils.py +50 -0
- solace_agent_mesh/common/sac/__init__.py +0 -0
- solace_agent_mesh/common/sac/sac_llm.txt +71 -0
- solace_agent_mesh/common/sac/sac_llm_detail.txt +82 -0
- solace_agent_mesh/common/sac/sam_component_base.py +730 -0
- solace_agent_mesh/common/sam_events/__init__.py +9 -0
- solace_agent_mesh/common/sam_events/event_service.py +208 -0
- solace_agent_mesh/common/sam_events/sam_events_llm.txt +104 -0
- solace_agent_mesh/common/sam_events/sam_events_llm_detail.txt +115 -0
- solace_agent_mesh/common/services/__init__.py +4 -0
- solace_agent_mesh/common/services/employee_service.py +164 -0
- solace_agent_mesh/common/services/identity_service.py +134 -0
- solace_agent_mesh/common/services/providers/__init__.py +4 -0
- solace_agent_mesh/common/services/providers/local_file_identity_service.py +151 -0
- solace_agent_mesh/common/services/providers/providers_llm.txt +81 -0
- solace_agent_mesh/common/services/services_llm.txt +368 -0
- solace_agent_mesh/common/services/services_llm_detail.txt +459 -0
- solace_agent_mesh/common/utils/__init__.py +7 -0
- solace_agent_mesh/common/utils/artifact_utils.py +31 -0
- solace_agent_mesh/common/utils/asyncio_macos_fix.py +88 -0
- solace_agent_mesh/common/utils/embeds/__init__.py +33 -0
- solace_agent_mesh/common/utils/embeds/constants.py +56 -0
- solace_agent_mesh/common/utils/embeds/converter.py +447 -0
- solace_agent_mesh/common/utils/embeds/embeds_llm.txt +220 -0
- solace_agent_mesh/common/utils/embeds/evaluators.py +395 -0
- solace_agent_mesh/common/utils/embeds/modifiers.py +793 -0
- solace_agent_mesh/common/utils/embeds/resolver.py +967 -0
- solace_agent_mesh/common/utils/embeds/types.py +23 -0
- solace_agent_mesh/common/utils/in_memory_cache.py +108 -0
- solace_agent_mesh/common/utils/initializer.py +52 -0
- solace_agent_mesh/common/utils/log_formatters.py +64 -0
- solace_agent_mesh/common/utils/message_utils.py +80 -0
- solace_agent_mesh/common/utils/mime_helpers.py +172 -0
- solace_agent_mesh/common/utils/push_notification_auth.py +135 -0
- solace_agent_mesh/common/utils/pydantic_utils.py +159 -0
- solace_agent_mesh/common/utils/rbac_utils.py +69 -0
- solace_agent_mesh/common/utils/templates/__init__.py +8 -0
- solace_agent_mesh/common/utils/templates/liquid_renderer.py +210 -0
- solace_agent_mesh/common/utils/templates/template_resolver.py +161 -0
- solace_agent_mesh/common/utils/type_utils.py +28 -0
- solace_agent_mesh/common/utils/utils_llm.txt +335 -0
- solace_agent_mesh/common/utils/utils_llm_detail.txt +572 -0
- solace_agent_mesh/config_portal/__init__.py +0 -0
- solace_agent_mesh/config_portal/backend/__init__.py +0 -0
- solace_agent_mesh/config_portal/backend/common.py +77 -0
- solace_agent_mesh/config_portal/backend/plugin_catalog/__init__.py +0 -0
- solace_agent_mesh/config_portal/backend/plugin_catalog/constants.py +24 -0
- solace_agent_mesh/config_portal/backend/plugin_catalog/models.py +49 -0
- solace_agent_mesh/config_portal/backend/plugin_catalog/registry_manager.py +166 -0
- solace_agent_mesh/config_portal/backend/plugin_catalog/scraper.py +521 -0
- solace_agent_mesh/config_portal/backend/plugin_catalog_server.py +217 -0
- solace_agent_mesh/config_portal/backend/server.py +644 -0
- solace_agent_mesh/config_portal/frontend/static/client/Solace_community_logo.png +0 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-DiOiAjzL.js +103 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/components-Rk0n-9cK.js +140 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/entry.client-mvZjNKiz.js +19 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/index-DzNKzXrc.js +68 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-ba77705e.js +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-B17tZKK7.css +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-V2BeTIUc.js +10 -0
- solace_agent_mesh/config_portal/frontend/static/client/favicon.ico +0 -0
- solace_agent_mesh/config_portal/frontend/static/client/index.html +7 -0
- solace_agent_mesh/core_a2a/__init__.py +1 -0
- solace_agent_mesh/core_a2a/core_a2a_llm.txt +90 -0
- solace_agent_mesh/core_a2a/core_a2a_llm_detail.txt +101 -0
- solace_agent_mesh/core_a2a/service.py +307 -0
- solace_agent_mesh/evaluation/__init__.py +0 -0
- solace_agent_mesh/evaluation/evaluator.py +691 -0
- solace_agent_mesh/evaluation/message_organizer.py +553 -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 +970 -0
- solace_agent_mesh/evaluation/report_generator.py +607 -0
- solace_agent_mesh/evaluation/run.py +954 -0
- solace_agent_mesh/evaluation/shared/__init__.py +92 -0
- solace_agent_mesh/evaluation/shared/constants.py +47 -0
- solace_agent_mesh/evaluation/shared/exceptions.py +50 -0
- solace_agent_mesh/evaluation/shared/helpers.py +35 -0
- solace_agent_mesh/evaluation/shared/test_case_loader.py +167 -0
- solace_agent_mesh/evaluation/shared/test_suite_loader.py +280 -0
- solace_agent_mesh/evaluation/subscriber.py +776 -0
- solace_agent_mesh/evaluation/summary_builder.py +880 -0
- solace_agent_mesh/gateway/__init__.py +0 -0
- solace_agent_mesh/gateway/adapter/__init__.py +1 -0
- solace_agent_mesh/gateway/adapter/base.py +143 -0
- solace_agent_mesh/gateway/adapter/types.py +221 -0
- solace_agent_mesh/gateway/base/__init__.py +1 -0
- solace_agent_mesh/gateway/base/app.py +345 -0
- solace_agent_mesh/gateway/base/base_llm.txt +226 -0
- solace_agent_mesh/gateway/base/base_llm_detail.txt +235 -0
- solace_agent_mesh/gateway/base/component.py +2030 -0
- solace_agent_mesh/gateway/base/task_context.py +75 -0
- solace_agent_mesh/gateway/gateway_llm.txt +369 -0
- solace_agent_mesh/gateway/gateway_llm_detail.txt +3885 -0
- solace_agent_mesh/gateway/generic/__init__.py +1 -0
- solace_agent_mesh/gateway/generic/app.py +50 -0
- solace_agent_mesh/gateway/generic/component.py +727 -0
- solace_agent_mesh/gateway/http_sse/__init__.py +0 -0
- solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +345 -0
- solace_agent_mesh/gateway/http_sse/alembic/env.py +87 -0
- solace_agent_mesh/gateway/http_sse/alembic/script.py.mako +28 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20250910_d5b3f8f2e9a0_create_initial_database.py +58 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20250911_b1c2d3e4f5g6_add_database_indexes.py +83 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20250916_f6e7d8c9b0a1_convert_timestamps_to_epoch_and_align_columns.py +412 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251006_98882922fa59_add_tasks_events_feedback_chat_tasks.py +190 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251015_add_session_performance_indexes.py +70 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_project_users_table.py +72 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_soft_delete_and_search.py +109 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_default_agent_to_projects.py +26 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_projects_table.py +135 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251108_create_prompt_tables_with_sharing.py +154 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251115_add_parent_task_id.py +32 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251126_add_background_task_fields.py +47 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251202_add_versioned_fields_to_prompts.py +52 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +161 -0
- solace_agent_mesh/gateway/http_sse/alembic.ini +109 -0
- solace_agent_mesh/gateway/http_sse/app.py +351 -0
- solace_agent_mesh/gateway/http_sse/component.py +2360 -0
- solace_agent_mesh/gateway/http_sse/components/__init__.py +7 -0
- solace_agent_mesh/gateway/http_sse/components/components_llm.txt +105 -0
- solace_agent_mesh/gateway/http_sse/components/task_logger_forwarder.py +109 -0
- solace_agent_mesh/gateway/http_sse/components/visualization_forwarder_component.py +110 -0
- solace_agent_mesh/gateway/http_sse/dependencies.py +653 -0
- solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +299 -0
- solace_agent_mesh/gateway/http_sse/http_sse_llm_detail.txt +3278 -0
- solace_agent_mesh/gateway/http_sse/main.py +789 -0
- solace_agent_mesh/gateway/http_sse/repository/__init__.py +46 -0
- solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +102 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/__init__.py +11 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/chat_task.py +75 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/entities_llm.txt +221 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/feedback.py +20 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/project.py +81 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/project_user.py +47 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/session.py +66 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/session_history.py +0 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/task.py +32 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/task_event.py +21 -0
- solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +125 -0
- solace_agent_mesh/gateway/http_sse/repository/interfaces.py +239 -0
- solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +34 -0
- solace_agent_mesh/gateway/http_sse/repository/models/base.py +7 -0
- solace_agent_mesh/gateway/http_sse/repository/models/chat_task_model.py +31 -0
- solace_agent_mesh/gateway/http_sse/repository/models/feedback_model.py +21 -0
- solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +257 -0
- solace_agent_mesh/gateway/http_sse/repository/models/project_model.py +51 -0
- solace_agent_mesh/gateway/http_sse/repository/models/project_user_model.py +75 -0
- solace_agent_mesh/gateway/http_sse/repository/models/prompt_model.py +159 -0
- solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +53 -0
- solace_agent_mesh/gateway/http_sse/repository/models/task_event_model.py +25 -0
- solace_agent_mesh/gateway/http_sse/repository/models/task_model.py +39 -0
- solace_agent_mesh/gateway/http_sse/repository/project_repository.py +172 -0
- solace_agent_mesh/gateway/http_sse/repository/project_user_repository.py +186 -0
- solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +308 -0
- solace_agent_mesh/gateway/http_sse/repository/session_repository.py +268 -0
- solace_agent_mesh/gateway/http_sse/repository/task_repository.py +248 -0
- solace_agent_mesh/gateway/http_sse/routers/__init__.py +4 -0
- solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +74 -0
- solace_agent_mesh/gateway/http_sse/routers/artifacts.py +1137 -0
- solace_agent_mesh/gateway/http_sse/routers/auth.py +311 -0
- solace_agent_mesh/gateway/http_sse/routers/config.py +371 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/__init__.py +10 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +450 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/project_dto.py +69 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/prompt_dto.py +255 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/__init__.py +15 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/project_requests.py +48 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +133 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +33 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/task_requests.py +58 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/__init__.py +18 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/base_responses.py +42 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/project_responses.py +31 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +123 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +33 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/task_responses.py +30 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/version_responses.py +31 -0
- solace_agent_mesh/gateway/http_sse/routers/feedback.py +168 -0
- solace_agent_mesh/gateway/http_sse/routers/people.py +38 -0
- solace_agent_mesh/gateway/http_sse/routers/projects.py +767 -0
- solace_agent_mesh/gateway/http_sse/routers/prompts.py +1415 -0
- solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +312 -0
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +634 -0
- solace_agent_mesh/gateway/http_sse/routers/speech.py +355 -0
- solace_agent_mesh/gateway/http_sse/routers/sse.py +230 -0
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +1089 -0
- solace_agent_mesh/gateway/http_sse/routers/users.py +83 -0
- solace_agent_mesh/gateway/http_sse/routers/version.py +343 -0
- solace_agent_mesh/gateway/http_sse/routers/visualization.py +1220 -0
- solace_agent_mesh/gateway/http_sse/services/__init__.py +4 -0
- solace_agent_mesh/gateway/http_sse/services/agent_card_service.py +71 -0
- solace_agent_mesh/gateway/http_sse/services/audio_service.py +1227 -0
- solace_agent_mesh/gateway/http_sse/services/background_task_monitor.py +186 -0
- solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +273 -0
- solace_agent_mesh/gateway/http_sse/services/feedback_service.py +250 -0
- solace_agent_mesh/gateway/http_sse/services/people_service.py +78 -0
- solace_agent_mesh/gateway/http_sse/services/project_service.py +930 -0
- solace_agent_mesh/gateway/http_sse/services/prompt_builder_assistant.py +303 -0
- solace_agent_mesh/gateway/http_sse/services/services_llm.txt +303 -0
- solace_agent_mesh/gateway/http_sse/services/session_service.py +702 -0
- solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +593 -0
- solace_agent_mesh/gateway/http_sse/services/task_service.py +119 -0
- solace_agent_mesh/gateway/http_sse/session_manager.py +219 -0
- solace_agent_mesh/gateway/http_sse/shared/__init__.py +146 -0
- solace_agent_mesh/gateway/http_sse/shared/auth_utils.py +29 -0
- solace_agent_mesh/gateway/http_sse/shared/base_repository.py +252 -0
- solace_agent_mesh/gateway/http_sse/shared/database_exceptions.py +274 -0
- solace_agent_mesh/gateway/http_sse/shared/database_helpers.py +43 -0
- solace_agent_mesh/gateway/http_sse/shared/enums.py +40 -0
- solace_agent_mesh/gateway/http_sse/shared/error_dto.py +107 -0
- solace_agent_mesh/gateway/http_sse/shared/exception_handlers.py +217 -0
- solace_agent_mesh/gateway/http_sse/shared/exceptions.py +192 -0
- solace_agent_mesh/gateway/http_sse/shared/pagination.py +138 -0
- solace_agent_mesh/gateway/http_sse/shared/response_utils.py +134 -0
- solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +319 -0
- solace_agent_mesh/gateway/http_sse/shared/timestamp_utils.py +97 -0
- solace_agent_mesh/gateway/http_sse/shared/types.py +50 -0
- solace_agent_mesh/gateway/http_sse/shared/utils.py +22 -0
- solace_agent_mesh/gateway/http_sse/sse_event_buffer.py +88 -0
- solace_agent_mesh/gateway/http_sse/sse_manager.py +491 -0
- solace_agent_mesh/gateway/http_sse/utils/__init__.py +1 -0
- solace_agent_mesh/gateway/http_sse/utils/artifact_copy_utils.py +370 -0
- solace_agent_mesh/gateway/http_sse/utils/stim_utils.py +72 -0
- solace_agent_mesh/gateway/http_sse/utils/utils_llm.txt +47 -0
- solace_agent_mesh/llm.txt +228 -0
- solace_agent_mesh/llm_detail.txt +2835 -0
- solace_agent_mesh/services/__init__.py +0 -0
- solace_agent_mesh/services/platform/__init__.py +18 -0
- solace_agent_mesh/services/platform/alembic/env.py +85 -0
- solace_agent_mesh/services/platform/alembic/script.py.mako +28 -0
- solace_agent_mesh/services/platform/alembic.ini +109 -0
- solace_agent_mesh/services/platform/api/__init__.py +3 -0
- solace_agent_mesh/services/platform/api/dependencies.py +147 -0
- solace_agent_mesh/services/platform/api/main.py +280 -0
- solace_agent_mesh/services/platform/api/middleware.py +51 -0
- solace_agent_mesh/services/platform/api/routers/__init__.py +24 -0
- solace_agent_mesh/services/platform/app.py +114 -0
- solace_agent_mesh/services/platform/component.py +235 -0
- solace_agent_mesh/solace_agent_mesh_llm.txt +362 -0
- solace_agent_mesh/solace_agent_mesh_llm_detail.txt +8599 -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 +75 -0
- solace_agent_mesh/templates/gateway_component_template.py +484 -0
- solace_agent_mesh/templates/gateway_config_template.yaml +38 -0
- solace_agent_mesh/templates/logging_config_template.yaml +48 -0
- solace_agent_mesh/templates/main_orchestrator.yaml +66 -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 +60 -0
- solace_agent_mesh/templates/plugin_pyproject_template.toml +32 -0
- solace_agent_mesh/templates/plugin_readme_template.md +12 -0
- solace_agent_mesh/templates/plugin_tool_config_template.yaml +109 -0
- solace_agent_mesh/templates/plugin_tools_template.py +224 -0
- solace_agent_mesh/templates/shared_config.yaml +112 -0
- solace_agent_mesh/templates/templates_llm.txt +147 -0
- solace_agent_mesh/templates/webui.yaml +177 -0
- solace_agent_mesh-1.11.2.dist-info/METADATA +504 -0
- solace_agent_mesh-1.11.2.dist-info/RECORD +624 -0
- solace_agent_mesh-1.11.2.dist-info/WHEEL +4 -0
- solace_agent_mesh-1.11.2.dist-info/entry_points.txt +3 -0
- solace_agent_mesh-1.11.2.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,880 @@
|
|
|
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 logging
|
|
8
|
+
import re
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
import requests
|
|
14
|
+
import yaml
|
|
15
|
+
|
|
16
|
+
from .shared import TestSuiteConfiguration, load_test_case
|
|
17
|
+
|
|
18
|
+
log = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class ToolCall:
|
|
23
|
+
"""Structured representation of a tool call."""
|
|
24
|
+
|
|
25
|
+
call_id: str
|
|
26
|
+
agent: str
|
|
27
|
+
tool_name: str
|
|
28
|
+
arguments: dict[str, any]
|
|
29
|
+
timestamp: str
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class ArtifactInfo:
|
|
34
|
+
"""Comprehensive artifact information with categorization."""
|
|
35
|
+
|
|
36
|
+
artifact_name: str
|
|
37
|
+
directory: str
|
|
38
|
+
versions: list[dict[str, any]]
|
|
39
|
+
artifact_type: str | None = None
|
|
40
|
+
source_path: str | None = None
|
|
41
|
+
created_by_tool: str | None = None
|
|
42
|
+
created_by_call_id: str | None = None
|
|
43
|
+
creation_timestamp: str | None = None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class TimeMetrics:
|
|
48
|
+
"""Time-related metrics for a test run."""
|
|
49
|
+
|
|
50
|
+
start_time: str | None = None
|
|
51
|
+
end_time: str | None = None
|
|
52
|
+
duration_seconds: float | None = None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass
|
|
56
|
+
class RunSummary:
|
|
57
|
+
"""Complete summary of a test run with all metrics and metadata."""
|
|
58
|
+
|
|
59
|
+
test_case_id: str
|
|
60
|
+
run_id: str
|
|
61
|
+
query: str = ""
|
|
62
|
+
target_agent: str = ""
|
|
63
|
+
namespace: str = ""
|
|
64
|
+
context_id: str = ""
|
|
65
|
+
final_status: str = ""
|
|
66
|
+
final_message: str = ""
|
|
67
|
+
time_metrics: TimeMetrics = field(default_factory=TimeMetrics)
|
|
68
|
+
tool_calls: list[ToolCall] = field(default_factory=list)
|
|
69
|
+
input_artifacts: list[ArtifactInfo] = field(default_factory=list)
|
|
70
|
+
output_artifacts: list[ArtifactInfo] = field(default_factory=list)
|
|
71
|
+
errors: list[str] = field(default_factory=list)
|
|
72
|
+
|
|
73
|
+
def to_dict(self) -> dict[str, any]:
|
|
74
|
+
"""Convert summary to dictionary format for JSON serialization."""
|
|
75
|
+
return {
|
|
76
|
+
"test_case_id": self.test_case_id,
|
|
77
|
+
"run_id": self.run_id,
|
|
78
|
+
"query": self.query,
|
|
79
|
+
"target_agent": self.target_agent,
|
|
80
|
+
"namespace": self.namespace,
|
|
81
|
+
"context_id": self.context_id,
|
|
82
|
+
"final_status": self.final_status,
|
|
83
|
+
"final_message": self.final_message,
|
|
84
|
+
"start_time": self.time_metrics.start_time,
|
|
85
|
+
"end_time": self.time_metrics.end_time,
|
|
86
|
+
"duration_seconds": self.time_metrics.duration_seconds,
|
|
87
|
+
"tool_calls": [
|
|
88
|
+
{
|
|
89
|
+
"call_id": tc.call_id,
|
|
90
|
+
"agent": tc.agent,
|
|
91
|
+
"tool_name": tc.tool_name,
|
|
92
|
+
"arguments": tc.arguments,
|
|
93
|
+
"timestamp": tc.timestamp,
|
|
94
|
+
}
|
|
95
|
+
for tc in self.tool_calls
|
|
96
|
+
],
|
|
97
|
+
"input_artifacts": [
|
|
98
|
+
{
|
|
99
|
+
"artifact_name": art.artifact_name,
|
|
100
|
+
"directory": art.directory,
|
|
101
|
+
"versions": art.versions,
|
|
102
|
+
"type": art.artifact_type,
|
|
103
|
+
"source_path": art.source_path,
|
|
104
|
+
}
|
|
105
|
+
for art in self.input_artifacts
|
|
106
|
+
],
|
|
107
|
+
"output_artifacts": [
|
|
108
|
+
{
|
|
109
|
+
"artifact_name": art.artifact_name,
|
|
110
|
+
"directory": art.directory,
|
|
111
|
+
"versions": art.versions,
|
|
112
|
+
}
|
|
113
|
+
for art in self.output_artifacts
|
|
114
|
+
],
|
|
115
|
+
"errors": self.errors,
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class ConfigService:
|
|
120
|
+
"""Handles configuration loading and YAML processing."""
|
|
121
|
+
|
|
122
|
+
_config_cache: dict[str, any] = {}
|
|
123
|
+
|
|
124
|
+
@classmethod
|
|
125
|
+
def load_yaml_with_includes(cls, file_path: str) -> dict[str, any]:
|
|
126
|
+
"""Load YAML file with !include directive processing and caching."""
|
|
127
|
+
if file_path in cls._config_cache:
|
|
128
|
+
return cls._config_cache[file_path]
|
|
129
|
+
|
|
130
|
+
try:
|
|
131
|
+
with open(file_path) as f:
|
|
132
|
+
content = f.read()
|
|
133
|
+
|
|
134
|
+
content = cls._process_includes(content, file_path)
|
|
135
|
+
config = yaml.safe_load(content)
|
|
136
|
+
cls._config_cache[file_path] = config
|
|
137
|
+
return config
|
|
138
|
+
|
|
139
|
+
except (FileNotFoundError, yaml.YAMLError) as e:
|
|
140
|
+
raise ValueError(f"Failed to load YAML config from {file_path}: {e}") from e
|
|
141
|
+
|
|
142
|
+
@staticmethod
|
|
143
|
+
def _process_includes(content: str, base_file_path: str) -> str:
|
|
144
|
+
"""Process !include directives in YAML content."""
|
|
145
|
+
include_pattern = re.compile(r"^\s*!include\s+(.*)$", re.MULTILINE)
|
|
146
|
+
base_dir = Path(base_file_path).parent
|
|
147
|
+
|
|
148
|
+
def replacer(match):
|
|
149
|
+
include_path_str = match.group(1).strip()
|
|
150
|
+
include_path = base_dir / include_path_str
|
|
151
|
+
with include_path.open() as inc_f:
|
|
152
|
+
return inc_f.read()
|
|
153
|
+
|
|
154
|
+
# Repeatedly replace includes until none are left
|
|
155
|
+
while include_pattern.search(content):
|
|
156
|
+
content = include_pattern.sub(replacer, content)
|
|
157
|
+
|
|
158
|
+
return content
|
|
159
|
+
|
|
160
|
+
@classmethod
|
|
161
|
+
def get_local_artifact_config(cls) -> tuple[str, str]:
|
|
162
|
+
"""Get artifact service configuration from eval backend config."""
|
|
163
|
+
try:
|
|
164
|
+
webui_config = cls.load_yaml_with_includes("configs/eval_backend.yaml")
|
|
165
|
+
|
|
166
|
+
# Find the correct app_config
|
|
167
|
+
for app in webui_config.get("apps", []):
|
|
168
|
+
if app.get("name") == "a2a_eval_backend_app":
|
|
169
|
+
app_config = app.get("app_config", {})
|
|
170
|
+
base_path = app_config.get("artifact_service", {}).get("base_path")
|
|
171
|
+
user_identity = app_config.get("default_user_identity")
|
|
172
|
+
|
|
173
|
+
if base_path and user_identity:
|
|
174
|
+
return base_path, user_identity
|
|
175
|
+
|
|
176
|
+
raise ValueError("Could not find 'a2a_eval_backend_app' config")
|
|
177
|
+
|
|
178
|
+
except Exception as e:
|
|
179
|
+
raise ValueError(f"Failed to load artifact configuration: {e}") from e
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class FileService:
|
|
183
|
+
"""Handles file operations and path management."""
|
|
184
|
+
|
|
185
|
+
@staticmethod
|
|
186
|
+
def load_json(filepath: Path) -> any:
|
|
187
|
+
"""Load JSON data from file."""
|
|
188
|
+
try:
|
|
189
|
+
with filepath.open() as f:
|
|
190
|
+
return json.load(f)
|
|
191
|
+
except (FileNotFoundError, json.JSONDecodeError) as e:
|
|
192
|
+
raise ValueError(f"Failed to load JSON from {filepath}: {e}") from e
|
|
193
|
+
|
|
194
|
+
@staticmethod
|
|
195
|
+
def save_json(data: any, filepath: Path):
|
|
196
|
+
"""Save data as JSON to file."""
|
|
197
|
+
try:
|
|
198
|
+
filepath.parent.mkdir(parents=True, exist_ok=True)
|
|
199
|
+
with filepath.open("w") as f:
|
|
200
|
+
json.dump(data, f, indent=2)
|
|
201
|
+
except Exception as e:
|
|
202
|
+
raise ValueError(f"Failed to save JSON to {filepath}: {e}") from e
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class TestCaseService:
|
|
206
|
+
"""Handles test case loading and validation."""
|
|
207
|
+
|
|
208
|
+
@staticmethod
|
|
209
|
+
def load_test_case(test_case_id: str) -> dict[str, any] | None:
|
|
210
|
+
"""Load test case definition with error handling."""
|
|
211
|
+
try:
|
|
212
|
+
return load_test_case(test_case_id)
|
|
213
|
+
except Exception:
|
|
214
|
+
return None
|
|
215
|
+
|
|
216
|
+
@staticmethod
|
|
217
|
+
def extract_input_artifact_names(test_case: dict[str, any]) -> set[str]:
|
|
218
|
+
"""Extract input artifact names from test case definition."""
|
|
219
|
+
input_artifact_names = set()
|
|
220
|
+
test_case_artifacts = test_case.get("artifacts", [])
|
|
221
|
+
|
|
222
|
+
for tc_artifact in test_case_artifacts:
|
|
223
|
+
if tc_artifact.get("type") == "file" and "path" in tc_artifact:
|
|
224
|
+
# Extract filename from path (e.g., "artifacts/sample.csv" -> "sample.csv")
|
|
225
|
+
artifact_name = Path(tc_artifact["path"]).name
|
|
226
|
+
input_artifact_names.add(artifact_name)
|
|
227
|
+
|
|
228
|
+
return input_artifact_names
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
class TimeProcessor:
|
|
232
|
+
"""Handles timestamp parsing and duration calculations."""
|
|
233
|
+
|
|
234
|
+
@staticmethod
|
|
235
|
+
def extract_start_time(first_message: dict[str, any]) -> str | None:
|
|
236
|
+
"""Extract start time from the first message."""
|
|
237
|
+
try:
|
|
238
|
+
payload = first_message.get("payload", {})
|
|
239
|
+
params = payload.get("params", {})
|
|
240
|
+
message = params.get("message", {})
|
|
241
|
+
parts = message.get("parts", [])
|
|
242
|
+
|
|
243
|
+
for part in parts:
|
|
244
|
+
if "text" in part and "Request received by gateway at:" in part["text"]:
|
|
245
|
+
time_str = (
|
|
246
|
+
part["text"]
|
|
247
|
+
.split("Request received by gateway at: ")[1]
|
|
248
|
+
.strip()
|
|
249
|
+
)
|
|
250
|
+
# Validate timestamp format
|
|
251
|
+
datetime.fromisoformat(time_str)
|
|
252
|
+
return time_str
|
|
253
|
+
except (KeyError, ValueError, IndexError):
|
|
254
|
+
pass
|
|
255
|
+
|
|
256
|
+
return None
|
|
257
|
+
|
|
258
|
+
@staticmethod
|
|
259
|
+
def extract_end_time(last_message: dict[str, any]) -> str | None:
|
|
260
|
+
"""Extract end time from the last message."""
|
|
261
|
+
try:
|
|
262
|
+
payload = last_message.get("payload", {})
|
|
263
|
+
result = payload.get("result", {})
|
|
264
|
+
status = result.get("status", {})
|
|
265
|
+
return status.get("timestamp")
|
|
266
|
+
except KeyError:
|
|
267
|
+
return None
|
|
268
|
+
|
|
269
|
+
@staticmethod
|
|
270
|
+
def calculate_duration(
|
|
271
|
+
start_time_str: str, end_time_str: str
|
|
272
|
+
) -> tuple[float | None, str | None]:
|
|
273
|
+
"""Calculate duration and return normalized start time."""
|
|
274
|
+
try:
|
|
275
|
+
start_time = datetime.fromisoformat(start_time_str)
|
|
276
|
+
end_time = datetime.fromisoformat(end_time_str)
|
|
277
|
+
|
|
278
|
+
# Handle timezone differences
|
|
279
|
+
if (start_time.tzinfo is not None) and (end_time.tzinfo is None):
|
|
280
|
+
start_time = start_time.astimezone().replace(tzinfo=None)
|
|
281
|
+
elif (end_time.tzinfo is not None) and (start_time.tzinfo is None):
|
|
282
|
+
end_time = end_time.astimezone().replace(tzinfo=None)
|
|
283
|
+
|
|
284
|
+
duration = end_time - start_time
|
|
285
|
+
|
|
286
|
+
# Normalize start time for output
|
|
287
|
+
s_time = datetime.fromisoformat(start_time_str)
|
|
288
|
+
if s_time.tzinfo is not None:
|
|
289
|
+
s_time = s_time.astimezone().replace(tzinfo=None)
|
|
290
|
+
|
|
291
|
+
return duration.total_seconds(), s_time.isoformat()
|
|
292
|
+
|
|
293
|
+
except ValueError:
|
|
294
|
+
return None, None
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class MessageProcessor:
|
|
298
|
+
"""Processes messages to extract tool calls and metadata."""
|
|
299
|
+
|
|
300
|
+
@staticmethod
|
|
301
|
+
def extract_namespace_and_agent(
|
|
302
|
+
first_message: dict[str, any],
|
|
303
|
+
) -> tuple[str | None, str | None]:
|
|
304
|
+
"""Extract namespace and target agent from the first message topic."""
|
|
305
|
+
try:
|
|
306
|
+
topic = first_message.get("topic", "")
|
|
307
|
+
# Regex to match the topic format and capture the namespace and target_agent
|
|
308
|
+
match = re.match(r"^([^/]+)/a2a/v1/agent/request/([^/]+)$", topic)
|
|
309
|
+
if match:
|
|
310
|
+
return match.group(1), match.group(2)
|
|
311
|
+
except Exception:
|
|
312
|
+
pass
|
|
313
|
+
|
|
314
|
+
return None, None
|
|
315
|
+
|
|
316
|
+
@staticmethod
|
|
317
|
+
def extract_context_id(first_message: dict[str, any]) -> str | None:
|
|
318
|
+
"""Extract context ID from the first message."""
|
|
319
|
+
try:
|
|
320
|
+
payload = first_message.get("payload", {})
|
|
321
|
+
params = payload.get("params", {})
|
|
322
|
+
message = params.get("message", {})
|
|
323
|
+
return message.get("contextId")
|
|
324
|
+
except KeyError:
|
|
325
|
+
return None
|
|
326
|
+
|
|
327
|
+
@staticmethod
|
|
328
|
+
def extract_final_status_info(
|
|
329
|
+
last_message: dict[str, any],
|
|
330
|
+
) -> tuple[str | None, str | None]:
|
|
331
|
+
"""Extract final status and message from the last message."""
|
|
332
|
+
try:
|
|
333
|
+
payload = last_message.get("payload", {})
|
|
334
|
+
result = payload.get("result", {})
|
|
335
|
+
status_info = result.get("status", {})
|
|
336
|
+
|
|
337
|
+
final_status = status_info.get("state")
|
|
338
|
+
final_message = None
|
|
339
|
+
|
|
340
|
+
message = status_info.get("message", {})
|
|
341
|
+
parts = message.get("parts", [])
|
|
342
|
+
for part in parts:
|
|
343
|
+
if "text" in part:
|
|
344
|
+
final_message = part["text"]
|
|
345
|
+
break
|
|
346
|
+
|
|
347
|
+
return final_status, final_message
|
|
348
|
+
|
|
349
|
+
except KeyError:
|
|
350
|
+
return None, None
|
|
351
|
+
|
|
352
|
+
@staticmethod
|
|
353
|
+
def extract_tool_calls(messages: list[dict[str, any]]) -> list[ToolCall]:
|
|
354
|
+
"""Extract all tool calls from messages."""
|
|
355
|
+
tool_calls = []
|
|
356
|
+
processed_tool_calls = set()
|
|
357
|
+
|
|
358
|
+
for message in messages:
|
|
359
|
+
try:
|
|
360
|
+
payload = message.get("payload", {})
|
|
361
|
+
result = payload.get("result", {})
|
|
362
|
+
status = result.get("status", {})
|
|
363
|
+
message_data = status.get("message", {})
|
|
364
|
+
parts = message_data.get("parts", [])
|
|
365
|
+
|
|
366
|
+
for part in parts:
|
|
367
|
+
data = part.get("data", {})
|
|
368
|
+
if data.get("type") == "tool_invocation_start":
|
|
369
|
+
call_id = data.get("function_call_id")
|
|
370
|
+
if call_id and call_id not in processed_tool_calls:
|
|
371
|
+
tool_call = ToolCall(
|
|
372
|
+
call_id=call_id,
|
|
373
|
+
agent=result.get("metadata", {}).get("agent_name", ""),
|
|
374
|
+
tool_name=data.get("tool_name", ""),
|
|
375
|
+
arguments=data.get("tool_args", {}),
|
|
376
|
+
timestamp=status.get("timestamp", ""),
|
|
377
|
+
)
|
|
378
|
+
tool_calls.append(tool_call)
|
|
379
|
+
processed_tool_calls.add(call_id)
|
|
380
|
+
|
|
381
|
+
except (KeyError, IndexError):
|
|
382
|
+
continue
|
|
383
|
+
|
|
384
|
+
return tool_calls
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
class ArtifactService:
|
|
388
|
+
"""Manages artifact discovery, categorization, and metadata."""
|
|
389
|
+
|
|
390
|
+
def __init__(self, config: TestSuiteConfiguration):
|
|
391
|
+
self.config = config
|
|
392
|
+
self.is_remote = config.remote is not None
|
|
393
|
+
if self.is_remote:
|
|
394
|
+
self.base_url = config.remote.environment.get("EVAL_REMOTE_URL")
|
|
395
|
+
self.auth_token = config.remote.environment.get("EVAL_AUTH_TOKEN")
|
|
396
|
+
else:
|
|
397
|
+
self.base_path, self.user_identity = (
|
|
398
|
+
ConfigService.get_local_artifact_config()
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
def get_artifacts(
|
|
402
|
+
self, namespace: str, context_id: str
|
|
403
|
+
) -> list[ArtifactInfo]:
|
|
404
|
+
"""Retrieve artifact information, either locally or from a remote API."""
|
|
405
|
+
if self.is_remote:
|
|
406
|
+
return self._get_remote_artifacts(context_id)
|
|
407
|
+
else:
|
|
408
|
+
return self._get_local_artifacts(namespace, context_id)
|
|
409
|
+
|
|
410
|
+
def _get_remote_artifacts(self, context_id: str) -> list[ArtifactInfo]:
|
|
411
|
+
"""Fetch artifacts from the remote API."""
|
|
412
|
+
if not self.base_url:
|
|
413
|
+
return []
|
|
414
|
+
|
|
415
|
+
url = f"{self.base_url}/api/v2/artifacts"
|
|
416
|
+
params = {"session_id": context_id}
|
|
417
|
+
|
|
418
|
+
headers = {"Content-Type": "application/json"}
|
|
419
|
+
if self.auth_token:
|
|
420
|
+
headers["Authorization"] = f"Bearer {self.auth_token}"
|
|
421
|
+
log.info("Auth token found and added to headers.")
|
|
422
|
+
else:
|
|
423
|
+
log.warning("No auth token found for remote artifact request.")
|
|
424
|
+
|
|
425
|
+
log.info(f"Fetching remote artifacts from URL: {url} with params: {params}")
|
|
426
|
+
|
|
427
|
+
try:
|
|
428
|
+
with requests.Session() as session:
|
|
429
|
+
session.headers.update(headers)
|
|
430
|
+
response = session.get(url, params=params, allow_redirects=False)
|
|
431
|
+
|
|
432
|
+
log.info(f"Initial response status: {response.status_code}")
|
|
433
|
+
|
|
434
|
+
# Handle 307 Temporary Redirect manually
|
|
435
|
+
if response.status_code == 307:
|
|
436
|
+
redirect_url = response.headers.get("Location")
|
|
437
|
+
if not redirect_url:
|
|
438
|
+
log.error(
|
|
439
|
+
f"Server sent 307 redirect without a Location header. Full headers: {response.headers}"
|
|
440
|
+
)
|
|
441
|
+
response.raise_for_status() # Re-raise the error to halt execution
|
|
442
|
+
|
|
443
|
+
log.info(f"Handling 307 redirect to: {redirect_url}")
|
|
444
|
+
with requests.Session() as redirect_session:
|
|
445
|
+
redirect_session.headers.update(headers)
|
|
446
|
+
# The redirected URL from the server should be complete, so no params needed.
|
|
447
|
+
response = redirect_session.get(redirect_url)
|
|
448
|
+
|
|
449
|
+
response.raise_for_status()
|
|
450
|
+
|
|
451
|
+
# Handle empty response body after potential redirect
|
|
452
|
+
if not response.text:
|
|
453
|
+
log.info("Received empty response from artifact API, assuming no artifacts.")
|
|
454
|
+
return []
|
|
455
|
+
|
|
456
|
+
artifacts_data = response.json()
|
|
457
|
+
|
|
458
|
+
artifact_infos = []
|
|
459
|
+
for data in artifacts_data:
|
|
460
|
+
# The API returns a flat list of latest versions, so we reconstruct
|
|
461
|
+
# the version list to match the structure ArtifactInfo expects.
|
|
462
|
+
version_info = {
|
|
463
|
+
"version": data.get("version", 0),
|
|
464
|
+
"metadata": {
|
|
465
|
+
"mime_type": data.get("mime_type"),
|
|
466
|
+
"size": data.get("size"),
|
|
467
|
+
"last_modified": data.get("last_modified"),
|
|
468
|
+
"description": data.get("description"),
|
|
469
|
+
"schema": data.get("schema"),
|
|
470
|
+
},
|
|
471
|
+
}
|
|
472
|
+
info = ArtifactInfo(
|
|
473
|
+
artifact_name=data.get("filename"),
|
|
474
|
+
directory="", # Not applicable for remote
|
|
475
|
+
versions=[version_info],
|
|
476
|
+
)
|
|
477
|
+
artifact_infos.append(info)
|
|
478
|
+
return artifact_infos
|
|
479
|
+
|
|
480
|
+
except requests.RequestException as e:
|
|
481
|
+
log.error(f"Failed to fetch remote artifacts: {e}")
|
|
482
|
+
return []
|
|
483
|
+
except json.JSONDecodeError:
|
|
484
|
+
log.error("Failed to decode JSON response from artifact API")
|
|
485
|
+
return []
|
|
486
|
+
|
|
487
|
+
def _get_local_artifacts(
|
|
488
|
+
self, namespace: str, context_id: str
|
|
489
|
+
) -> list[ArtifactInfo]:
|
|
490
|
+
"""Retrieve information about artifacts from the local session directory."""
|
|
491
|
+
artifact_info = []
|
|
492
|
+
session_dir = (
|
|
493
|
+
Path(self.base_path) / namespace / self.user_identity / context_id
|
|
494
|
+
)
|
|
495
|
+
|
|
496
|
+
if not session_dir.is_dir():
|
|
497
|
+
return artifact_info
|
|
498
|
+
|
|
499
|
+
for item_path in session_dir.iterdir():
|
|
500
|
+
if item_path.is_dir() and not item_path.name.endswith(".metadata.json"):
|
|
501
|
+
artifact_info.append(
|
|
502
|
+
self._process_artifact_directory(
|
|
503
|
+
session_dir, item_path.name, item_path
|
|
504
|
+
)
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
return artifact_info
|
|
508
|
+
|
|
509
|
+
def _process_artifact_directory(
|
|
510
|
+
self, session_dir: Path, artifact_name: str, item_path: Path
|
|
511
|
+
) -> ArtifactInfo:
|
|
512
|
+
"""Process a single artifact directory and extract metadata."""
|
|
513
|
+
metadata_dir = session_dir / f"{artifact_name}.metadata.json"
|
|
514
|
+
versions = []
|
|
515
|
+
|
|
516
|
+
if metadata_dir.is_dir():
|
|
517
|
+
for version_path in item_path.iterdir():
|
|
518
|
+
if not version_path.name.endswith(".meta"):
|
|
519
|
+
version_metadata_path = metadata_dir / version_path.name
|
|
520
|
+
if version_metadata_path.exists():
|
|
521
|
+
try:
|
|
522
|
+
with version_metadata_path.open() as f:
|
|
523
|
+
metadata = json.load(f)
|
|
524
|
+
versions.append(
|
|
525
|
+
{"version": version_path.name, "metadata": metadata}
|
|
526
|
+
)
|
|
527
|
+
except (json.JSONDecodeError, FileNotFoundError):
|
|
528
|
+
continue
|
|
529
|
+
|
|
530
|
+
return ArtifactInfo(
|
|
531
|
+
artifact_name=artifact_name, directory=str(item_path), versions=versions
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
def categorize_artifacts(
|
|
535
|
+
self,
|
|
536
|
+
artifacts: list[ArtifactInfo],
|
|
537
|
+
test_case: dict[str, any],
|
|
538
|
+
tool_calls: list[ToolCall],
|
|
539
|
+
) -> tuple[list[ArtifactInfo], list[ArtifactInfo]]:
|
|
540
|
+
"""Categorize artifacts into input and output based on test case and tool calls."""
|
|
541
|
+
input_artifacts = []
|
|
542
|
+
output_artifacts = []
|
|
543
|
+
|
|
544
|
+
# Get input artifact names from test case
|
|
545
|
+
input_artifact_names = TestCaseService.extract_input_artifact_names(test_case)
|
|
546
|
+
|
|
547
|
+
# Create mapping of output artifacts to creating tools
|
|
548
|
+
tool_output_mapping = self._create_tool_output_mapping(tool_calls)
|
|
549
|
+
|
|
550
|
+
# Categorize each artifact
|
|
551
|
+
for artifact in artifacts:
|
|
552
|
+
artifact_name = artifact.artifact_name
|
|
553
|
+
|
|
554
|
+
# Check if this is an input artifact
|
|
555
|
+
if artifact_name in input_artifact_names:
|
|
556
|
+
input_artifact = self._enhance_input_artifact(artifact, test_case)
|
|
557
|
+
input_artifacts.append(input_artifact)
|
|
558
|
+
|
|
559
|
+
# All artifacts also go to output (including input ones that exist in session)
|
|
560
|
+
output_artifact = self._enhance_output_artifact(
|
|
561
|
+
artifact, tool_output_mapping
|
|
562
|
+
)
|
|
563
|
+
output_artifacts.append(output_artifact)
|
|
564
|
+
|
|
565
|
+
return input_artifacts, output_artifacts
|
|
566
|
+
|
|
567
|
+
def _create_tool_output_mapping(
|
|
568
|
+
self, tool_calls: list[ToolCall]
|
|
569
|
+
) -> dict[str, ToolCall]:
|
|
570
|
+
"""Create mapping of output filenames to the tools that created them."""
|
|
571
|
+
tool_output_mapping = {}
|
|
572
|
+
|
|
573
|
+
for tool_call in tool_calls:
|
|
574
|
+
args = tool_call.arguments
|
|
575
|
+
|
|
576
|
+
# Look for output filename in tool arguments
|
|
577
|
+
output_filename = None
|
|
578
|
+
if "output_filename" in args:
|
|
579
|
+
output_filename = args["output_filename"]
|
|
580
|
+
elif "filename" in args:
|
|
581
|
+
output_filename = args["filename"]
|
|
582
|
+
|
|
583
|
+
if output_filename:
|
|
584
|
+
tool_output_mapping[output_filename] = tool_call
|
|
585
|
+
|
|
586
|
+
return tool_output_mapping
|
|
587
|
+
|
|
588
|
+
def _enhance_input_artifact(
|
|
589
|
+
self, artifact: ArtifactInfo, test_case: dict[str, any]
|
|
590
|
+
) -> ArtifactInfo:
|
|
591
|
+
"""Enhance input artifact with test case information."""
|
|
592
|
+
enhanced_artifact = ArtifactInfo(
|
|
593
|
+
artifact_name=artifact.artifact_name,
|
|
594
|
+
directory=artifact.directory,
|
|
595
|
+
versions=artifact.versions,
|
|
596
|
+
artifact_type=None,
|
|
597
|
+
source_path=None,
|
|
598
|
+
)
|
|
599
|
+
|
|
600
|
+
# Add test case information
|
|
601
|
+
test_case_artifacts = test_case.get("artifacts", [])
|
|
602
|
+
for tc_artifact in test_case_artifacts:
|
|
603
|
+
if (
|
|
604
|
+
tc_artifact.get("type") == "file"
|
|
605
|
+
and Path(tc_artifact["path"]).name == artifact.artifact_name
|
|
606
|
+
):
|
|
607
|
+
enhanced_artifact.artifact_type = tc_artifact["type"]
|
|
608
|
+
enhanced_artifact.source_path = tc_artifact["path"]
|
|
609
|
+
break
|
|
610
|
+
|
|
611
|
+
return enhanced_artifact
|
|
612
|
+
|
|
613
|
+
def _enhance_output_artifact(
|
|
614
|
+
self, artifact: ArtifactInfo, tool_output_mapping: dict[str, ToolCall]
|
|
615
|
+
) -> ArtifactInfo:
|
|
616
|
+
"""Enhance output artifact with tool creation information."""
|
|
617
|
+
enhanced_artifact = ArtifactInfo(
|
|
618
|
+
artifact_name=artifact.artifact_name,
|
|
619
|
+
directory=artifact.directory,
|
|
620
|
+
versions=artifact.versions,
|
|
621
|
+
)
|
|
622
|
+
|
|
623
|
+
# Add tool creation information if available
|
|
624
|
+
if artifact.artifact_name in tool_output_mapping:
|
|
625
|
+
creating_tool = tool_output_mapping[artifact.artifact_name]
|
|
626
|
+
enhanced_artifact.created_by_tool = creating_tool.tool_name
|
|
627
|
+
enhanced_artifact.created_by_call_id = creating_tool.call_id
|
|
628
|
+
enhanced_artifact.creation_timestamp = creating_tool.timestamp
|
|
629
|
+
|
|
630
|
+
return enhanced_artifact
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
class SummaryBuilder:
|
|
634
|
+
"""Main orchestrator for summary creation."""
|
|
635
|
+
|
|
636
|
+
def __init__(self, config: TestSuiteConfiguration):
|
|
637
|
+
self.config = config
|
|
638
|
+
self.file_service = FileService()
|
|
639
|
+
self.test_case_service = TestCaseService()
|
|
640
|
+
self.time_processor = TimeProcessor()
|
|
641
|
+
self.message_processor = MessageProcessor()
|
|
642
|
+
self.artifact_service = ArtifactService(self.config)
|
|
643
|
+
|
|
644
|
+
def summarize_run(self, messages_file_path: str) -> dict[str, any]:
|
|
645
|
+
"""
|
|
646
|
+
Create a comprehensive summary of a test run from messages.json file.
|
|
647
|
+
|
|
648
|
+
Args:
|
|
649
|
+
messages_file_path: Path to the messages.json file
|
|
650
|
+
|
|
651
|
+
Returns:
|
|
652
|
+
Dictionary containing the summarized metrics
|
|
653
|
+
"""
|
|
654
|
+
try:
|
|
655
|
+
# Load and validate messages
|
|
656
|
+
messages = self._load_and_validate_messages(messages_file_path)
|
|
657
|
+
if not messages:
|
|
658
|
+
return {}
|
|
659
|
+
|
|
660
|
+
run_path = Path(messages_file_path).parent
|
|
661
|
+
test_case_info_path = run_path / "test_case_info.json"
|
|
662
|
+
test_case_info = self.file_service.load_json(test_case_info_path)
|
|
663
|
+
test_case_path = test_case_info["path"]
|
|
664
|
+
|
|
665
|
+
# Initialize summary with basic info
|
|
666
|
+
summary = self._initialize_summary(messages_file_path, test_case_path)
|
|
667
|
+
|
|
668
|
+
# Load test case
|
|
669
|
+
test_case = self._load_test_case(summary, test_case_path)
|
|
670
|
+
|
|
671
|
+
# Process messages to extract data
|
|
672
|
+
self._process_messages(messages, summary, test_case)
|
|
673
|
+
|
|
674
|
+
# Add artifact information if possible
|
|
675
|
+
self._add_artifact_information(summary, test_case)
|
|
676
|
+
|
|
677
|
+
return summary.to_dict()
|
|
678
|
+
|
|
679
|
+
except Exception as e:
|
|
680
|
+
# Return minimal summary with error information
|
|
681
|
+
run_path = Path(messages_file_path).parent
|
|
682
|
+
return {
|
|
683
|
+
"test_case_id": run_path.parent.name,
|
|
684
|
+
"run_id": run_path.name,
|
|
685
|
+
"errors": [f"Failed to process summary: {str(e)}"],
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
def _load_and_validate_messages(
|
|
689
|
+
self, messages_file_path: str
|
|
690
|
+
) -> list[dict[str, any]]:
|
|
691
|
+
"""Load and validate messages from file."""
|
|
692
|
+
try:
|
|
693
|
+
messages = self.file_service.load_json(Path(messages_file_path))
|
|
694
|
+
return messages if isinstance(messages, list) else []
|
|
695
|
+
except Exception:
|
|
696
|
+
return []
|
|
697
|
+
|
|
698
|
+
def _initialize_summary(
|
|
699
|
+
self, messages_file_path: str, test_case_path: str
|
|
700
|
+
) -> RunSummary:
|
|
701
|
+
"""Initialize summary with basic path-derived information."""
|
|
702
|
+
run_path = Path(messages_file_path).parent
|
|
703
|
+
run_id = run_path.name
|
|
704
|
+
test_case_id = Path(test_case_path).stem.replace(".test", "")
|
|
705
|
+
|
|
706
|
+
return RunSummary(test_case_id=test_case_id, run_id=run_id)
|
|
707
|
+
|
|
708
|
+
def _load_test_case(
|
|
709
|
+
self, summary: RunSummary, test_case_path: str
|
|
710
|
+
) -> dict[str, any]:
|
|
711
|
+
"""Load test case and update summary with test case info."""
|
|
712
|
+
test_case = self.test_case_service.load_test_case(test_case_path)
|
|
713
|
+
|
|
714
|
+
if test_case:
|
|
715
|
+
summary.query = test_case.get("query", "")
|
|
716
|
+
summary.target_agent = test_case.get("target_agent", "")
|
|
717
|
+
else:
|
|
718
|
+
summary.errors.append(f"Could not load test case: {summary.test_case_id}")
|
|
719
|
+
test_case = {"artifacts": []} # Fallback
|
|
720
|
+
|
|
721
|
+
return test_case
|
|
722
|
+
|
|
723
|
+
def _process_messages(
|
|
724
|
+
self,
|
|
725
|
+
messages: list[dict[str, any]],
|
|
726
|
+
summary: RunSummary,
|
|
727
|
+
test_case: dict[str, any],
|
|
728
|
+
):
|
|
729
|
+
"""Process all messages to extract relevant information."""
|
|
730
|
+
if not messages:
|
|
731
|
+
return
|
|
732
|
+
|
|
733
|
+
first_message = messages[0]
|
|
734
|
+
last_message = messages[-1]
|
|
735
|
+
|
|
736
|
+
# Extract basic metadata
|
|
737
|
+
namespace, target_agent = self.message_processor.extract_namespace_and_agent(
|
|
738
|
+
first_message
|
|
739
|
+
)
|
|
740
|
+
if namespace:
|
|
741
|
+
summary.namespace = namespace
|
|
742
|
+
if target_agent:
|
|
743
|
+
summary.target_agent = target_agent
|
|
744
|
+
else:
|
|
745
|
+
summary.errors.append(
|
|
746
|
+
"Could not find target agent and namespace in the first message."
|
|
747
|
+
)
|
|
748
|
+
|
|
749
|
+
context_id = self.message_processor.extract_context_id(first_message)
|
|
750
|
+
if context_id:
|
|
751
|
+
summary.context_id = context_id
|
|
752
|
+
|
|
753
|
+
# Extract final status information
|
|
754
|
+
final_status, final_message = self.message_processor.extract_final_status_info(
|
|
755
|
+
last_message
|
|
756
|
+
)
|
|
757
|
+
if final_status:
|
|
758
|
+
summary.final_status = final_status
|
|
759
|
+
if final_message:
|
|
760
|
+
summary.final_message = final_message
|
|
761
|
+
|
|
762
|
+
# Extract time metrics
|
|
763
|
+
self._process_time_metrics(first_message, last_message, summary)
|
|
764
|
+
|
|
765
|
+
# Extract tool calls
|
|
766
|
+
summary.tool_calls = self.message_processor.extract_tool_calls(messages)
|
|
767
|
+
|
|
768
|
+
def _process_time_metrics(
|
|
769
|
+
self,
|
|
770
|
+
first_message: dict[str, any],
|
|
771
|
+
last_message: dict[str, any],
|
|
772
|
+
summary: RunSummary,
|
|
773
|
+
):
|
|
774
|
+
"""Process and calculate time metrics."""
|
|
775
|
+
start_time = self.time_processor.extract_start_time(first_message)
|
|
776
|
+
end_time = self.time_processor.extract_end_time(last_message)
|
|
777
|
+
|
|
778
|
+
summary.time_metrics.start_time = start_time
|
|
779
|
+
summary.time_metrics.end_time = end_time
|
|
780
|
+
|
|
781
|
+
if start_time and end_time:
|
|
782
|
+
duration, normalized_start = self.time_processor.calculate_duration(
|
|
783
|
+
start_time, end_time
|
|
784
|
+
)
|
|
785
|
+
if duration is not None:
|
|
786
|
+
summary.time_metrics.duration_seconds = duration
|
|
787
|
+
if normalized_start:
|
|
788
|
+
summary.time_metrics.start_time = normalized_start
|
|
789
|
+
else:
|
|
790
|
+
summary.errors.append(
|
|
791
|
+
"Could not parse start or end time to calculate duration."
|
|
792
|
+
)
|
|
793
|
+
|
|
794
|
+
def _add_artifact_information(self, summary: RunSummary, test_case: dict[str, any]):
|
|
795
|
+
"""Add artifact information if configuration is available."""
|
|
796
|
+
if not summary.context_id:
|
|
797
|
+
return
|
|
798
|
+
|
|
799
|
+
try:
|
|
800
|
+
# Get and categorize artifacts
|
|
801
|
+
all_artifacts = self.artifact_service.get_artifacts(
|
|
802
|
+
summary.namespace, summary.context_id
|
|
803
|
+
)
|
|
804
|
+
|
|
805
|
+
input_artifacts, output_artifacts = (
|
|
806
|
+
self.artifact_service.categorize_artifacts(
|
|
807
|
+
all_artifacts, test_case, summary.tool_calls
|
|
808
|
+
)
|
|
809
|
+
)
|
|
810
|
+
|
|
811
|
+
summary.input_artifacts = input_artifacts
|
|
812
|
+
summary.output_artifacts = output_artifacts
|
|
813
|
+
|
|
814
|
+
except Exception as e:
|
|
815
|
+
summary.errors.append(f"Could not add artifact info: {str(e)}")
|
|
816
|
+
|
|
817
|
+
|
|
818
|
+
def summarize_run(
|
|
819
|
+
messages_file_path: str, config: TestSuiteConfiguration
|
|
820
|
+
) -> dict[str, any]:
|
|
821
|
+
"""
|
|
822
|
+
Main entry point for summarizing a test run.
|
|
823
|
+
|
|
824
|
+
This function maintains compatibility with the original API while using
|
|
825
|
+
the refactored implementation.
|
|
826
|
+
|
|
827
|
+
Args:
|
|
828
|
+
messages_file_path: Path to the messages.json file
|
|
829
|
+
config: The test suite configuration.
|
|
830
|
+
|
|
831
|
+
Returns:
|
|
832
|
+
Dictionary containing the summarized metrics
|
|
833
|
+
"""
|
|
834
|
+
builder = SummaryBuilder(config)
|
|
835
|
+
return builder.summarize_run(messages_file_path)
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
def main():
|
|
839
|
+
"""Main entry point for command-line usage."""
|
|
840
|
+
import sys
|
|
841
|
+
|
|
842
|
+
from .shared import EvaluationConfigLoader
|
|
843
|
+
|
|
844
|
+
if len(sys.argv) != 2:
|
|
845
|
+
log.info("Usage: python summarize_refactored.py <messages_file_path>")
|
|
846
|
+
sys.exit(1)
|
|
847
|
+
|
|
848
|
+
messages_file_path = Path(sys.argv[1])
|
|
849
|
+
|
|
850
|
+
if not messages_file_path.exists():
|
|
851
|
+
log.info(f"Error: Messages file not found at: {messages_file_path}")
|
|
852
|
+
sys.exit(1)
|
|
853
|
+
|
|
854
|
+
try:
|
|
855
|
+
# This main function is for standalone testing. It needs a config.
|
|
856
|
+
# We'll assume a default config for this purpose.
|
|
857
|
+
config_path = Path.cwd() / "tests" / "evaluation" / "config.json"
|
|
858
|
+
if not config_path.exists():
|
|
859
|
+
log.error(f"Default test config not found at {config_path}")
|
|
860
|
+
return
|
|
861
|
+
config_loader = EvaluationConfigLoader(str(config_path))
|
|
862
|
+
config = config_loader.load_configuration()
|
|
863
|
+
|
|
864
|
+
# Generate summary
|
|
865
|
+
summary_data = summarize_run(str(messages_file_path), config)
|
|
866
|
+
|
|
867
|
+
# Save summary file
|
|
868
|
+
output_dir = messages_file_path.parent
|
|
869
|
+
summary_file_path = output_dir / "summary.json"
|
|
870
|
+
|
|
871
|
+
FileService.save_json(summary_data, summary_file_path)
|
|
872
|
+
log.info(f"Summary file created at: {summary_file_path}")
|
|
873
|
+
|
|
874
|
+
except Exception as e:
|
|
875
|
+
log.error(f"Error generating summary: {e}")
|
|
876
|
+
sys.exit(1)
|
|
877
|
+
|
|
878
|
+
|
|
879
|
+
if __name__ == "__main__":
|
|
880
|
+
main()
|