solace-agent-mesh 0.2.3__py3-none-any.whl → 1.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (518) hide show
  1. solace_agent_mesh/agent/adk/adk_llm.txt +93 -0
  2. solace_agent_mesh/agent/adk/app_llm_agent.py +26 -0
  3. solace_agent_mesh/agent/adk/callbacks.py +1694 -0
  4. solace_agent_mesh/agent/adk/filesystem_artifact_service.py +381 -0
  5. solace_agent_mesh/agent/adk/invocation_monitor.py +295 -0
  6. solace_agent_mesh/agent/adk/models/lite_llm.py +872 -0
  7. solace_agent_mesh/agent/adk/models/models_llm.txt +94 -0
  8. solace_agent_mesh/agent/adk/runner.py +353 -0
  9. solace_agent_mesh/agent/adk/services.py +240 -0
  10. solace_agent_mesh/agent/adk/setup.py +751 -0
  11. solace_agent_mesh/agent/adk/stream_parser.py +214 -0
  12. solace_agent_mesh/agent/adk/tool_wrapper.py +139 -0
  13. solace_agent_mesh/agent/agent_llm.txt +41 -0
  14. solace_agent_mesh/agent/protocol/event_handlers.py +1469 -0
  15. solace_agent_mesh/agent/protocol/protocol_llm.txt +21 -0
  16. solace_agent_mesh/agent/sac/app.py +640 -0
  17. solace_agent_mesh/agent/sac/component.py +3388 -0
  18. solace_agent_mesh/agent/sac/patch_adk.py +111 -0
  19. solace_agent_mesh/agent/sac/sac_llm.txt +105 -0
  20. solace_agent_mesh/agent/sac/task_execution_context.py +176 -0
  21. solace_agent_mesh/agent/testing/__init__.py +3 -0
  22. solace_agent_mesh/agent/testing/debug_utils.py +135 -0
  23. solace_agent_mesh/agent/testing/testing_llm.txt +90 -0
  24. solace_agent_mesh/agent/tools/__init__.py +14 -0
  25. solace_agent_mesh/agent/tools/audio_tools.py +1622 -0
  26. solace_agent_mesh/agent/tools/builtin_artifact_tools.py +1954 -0
  27. solace_agent_mesh/agent/tools/builtin_data_analysis_tools.py +238 -0
  28. solace_agent_mesh/agent/tools/general_agent_tools.py +569 -0
  29. solace_agent_mesh/agent/tools/image_tools.py +1184 -0
  30. solace_agent_mesh/agent/tools/peer_agent_tool.py +289 -0
  31. solace_agent_mesh/agent/tools/registry.py +36 -0
  32. solace_agent_mesh/agent/tools/test_tools.py +135 -0
  33. solace_agent_mesh/agent/tools/tool_definition.py +45 -0
  34. solace_agent_mesh/agent/tools/tools_llm.txt +104 -0
  35. solace_agent_mesh/agent/tools/web_tools.py +381 -0
  36. solace_agent_mesh/agent/utils/artifact_helpers.py +927 -0
  37. solace_agent_mesh/agent/utils/config_parser.py +47 -0
  38. solace_agent_mesh/agent/utils/context_helpers.py +60 -0
  39. solace_agent_mesh/agent/utils/utils_llm.txt +153 -0
  40. solace_agent_mesh/assets/docs/404.html +16 -0
  41. solace_agent_mesh/assets/docs/assets/css/styles.906a1503.css +1 -0
  42. solace_agent_mesh/assets/docs/assets/images/Solace_AI_Framework_With_Broker-85f0a306a9bcdd20b390b7a949f6d862.png +0 -0
  43. solace_agent_mesh/assets/docs/assets/images/sac-flows-80d5b603c6aafd33e87945680ce0abf3.png +0 -0
  44. solace_agent_mesh/assets/docs/assets/images/sac_parts_of_a_component-cb3d0424b1d0c17734c5435cca6b4082.png +0 -0
  45. solace_agent_mesh/assets/docs/assets/js/04989206.674a8007.js +1 -0
  46. solace_agent_mesh/assets/docs/assets/js/0e682baa.79f0ab22.js +1 -0
  47. solace_agent_mesh/assets/docs/assets/js/1001.0182a8bd.js +1 -0
  48. solace_agent_mesh/assets/docs/assets/js/1023fc19.015679ca.js +1 -0
  49. solace_agent_mesh/assets/docs/assets/js/1039.0bd46aa1.js +1 -0
  50. solace_agent_mesh/assets/docs/assets/js/149.b797a808.js +1 -0
  51. solace_agent_mesh/assets/docs/assets/js/1523c6b4.91c7bc01.js +1 -0
  52. solace_agent_mesh/assets/docs/assets/js/165.6a39807d.js +2 -0
  53. solace_agent_mesh/assets/docs/assets/js/165.6a39807d.js.LICENSE.txt +9 -0
  54. solace_agent_mesh/assets/docs/assets/js/166ab619.7d97ccaf.js +1 -0
  55. solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js +2 -0
  56. solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js.LICENSE.txt +7 -0
  57. solace_agent_mesh/assets/docs/assets/js/1c6e87d2.23bccffb.js +1 -0
  58. solace_agent_mesh/assets/docs/assets/js/2130.ab9fd314.js +1 -0
  59. solace_agent_mesh/assets/docs/assets/js/21ceee5f.614fa8dd.js +1 -0
  60. solace_agent_mesh/assets/docs/assets/js/2237.5e477fc6.js +1 -0
  61. solace_agent_mesh/assets/docs/assets/js/2334.622a6395.js +1 -0
  62. solace_agent_mesh/assets/docs/assets/js/2a9cab12.8909df92.js +1 -0
  63. solace_agent_mesh/assets/docs/assets/js/3219.adc1d663.js +1 -0
  64. solace_agent_mesh/assets/docs/assets/js/332e10b5.7a103f42.js +1 -0
  65. solace_agent_mesh/assets/docs/assets/js/3624.b524e433.js +1 -0
  66. solace_agent_mesh/assets/docs/assets/js/375.708d48db.js +1 -0
  67. solace_agent_mesh/assets/docs/assets/js/3834.b6cd790e.js +1 -0
  68. solace_agent_mesh/assets/docs/assets/js/3d406171.f722eaf5.js +1 -0
  69. solace_agent_mesh/assets/docs/assets/js/4250.95455b28.js +1 -0
  70. solace_agent_mesh/assets/docs/assets/js/42b3f8d8.36090198.js +1 -0
  71. solace_agent_mesh/assets/docs/assets/js/4356.d169ab5b.js +1 -0
  72. solace_agent_mesh/assets/docs/assets/js/442a8107.5ba94b65.js +1 -0
  73. solace_agent_mesh/assets/docs/assets/js/4458.518e66fa.js +1 -0
  74. solace_agent_mesh/assets/docs/assets/js/4488.c7cc3442.js +1 -0
  75. solace_agent_mesh/assets/docs/assets/js/4494.6ee23046.js +1 -0
  76. solace_agent_mesh/assets/docs/assets/js/4855.fc4444b6.js +1 -0
  77. solace_agent_mesh/assets/docs/assets/js/4866.22daefc0.js +1 -0
  78. solace_agent_mesh/assets/docs/assets/js/4950.ca4caeda.js +1 -0
  79. solace_agent_mesh/assets/docs/assets/js/4c2787c2.66ee00e9.js +1 -0
  80. solace_agent_mesh/assets/docs/assets/js/5388.7a136447.js +1 -0
  81. solace_agent_mesh/assets/docs/assets/js/55f47984.c484bf96.js +1 -0
  82. solace_agent_mesh/assets/docs/assets/js/5607.081356f8.js +1 -0
  83. solace_agent_mesh/assets/docs/assets/js/5864.b0d0e9de.js +1 -0
  84. solace_agent_mesh/assets/docs/assets/js/5b4258a4.bda20761.js +1 -0
  85. solace_agent_mesh/assets/docs/assets/js/5e95c892.558d5167.js +1 -0
  86. solace_agent_mesh/assets/docs/assets/js/6143.0a1464c9.js +1 -0
  87. solace_agent_mesh/assets/docs/assets/js/6395.e9c73649.js +1 -0
  88. solace_agent_mesh/assets/docs/assets/js/6796.51d2c9b7.js +1 -0
  89. solace_agent_mesh/assets/docs/assets/js/6976.379be23b.js +1 -0
  90. solace_agent_mesh/assets/docs/assets/js/6978.ee0b945c.js +1 -0
  91. solace_agent_mesh/assets/docs/assets/js/7040.cb436723.js +1 -0
  92. solace_agent_mesh/assets/docs/assets/js/7195.412f418a.js +1 -0
  93. solace_agent_mesh/assets/docs/assets/js/7280.3fb73bdb.js +1 -0
  94. solace_agent_mesh/assets/docs/assets/js/768e31b0.a12673db.js +1 -0
  95. solace_agent_mesh/assets/docs/assets/js/7845.e33e7c4c.js +1 -0
  96. solace_agent_mesh/assets/docs/assets/js/7900.69516146.js +1 -0
  97. solace_agent_mesh/assets/docs/assets/js/8356.8a379c04.js +1 -0
  98. solace_agent_mesh/assets/docs/assets/js/85387663.6bf41934.js +1 -0
  99. solace_agent_mesh/assets/docs/assets/js/8567.4732c6b7.js +1 -0
  100. solace_agent_mesh/assets/docs/assets/js/8573.cb04eda5.js +1 -0
  101. solace_agent_mesh/assets/docs/assets/js/8577.1d54e766.js +1 -0
  102. solace_agent_mesh/assets/docs/assets/js/8591.d7c16be6.js +2 -0
  103. solace_agent_mesh/assets/docs/assets/js/8591.d7c16be6.js.LICENSE.txt +61 -0
  104. solace_agent_mesh/assets/docs/assets/js/8709.7ecd4047.js +1 -0
  105. solace_agent_mesh/assets/docs/assets/js/8731.49e930c2.js +1 -0
  106. solace_agent_mesh/assets/docs/assets/js/8908.f9d1b506.js +1 -0
  107. solace_agent_mesh/assets/docs/assets/js/9157.b4093d07.js +1 -0
  108. solace_agent_mesh/assets/docs/assets/js/9278.a4fd875d.js +1 -0
  109. solace_agent_mesh/assets/docs/assets/js/945fb41e.74d728aa.js +1 -0
  110. solace_agent_mesh/assets/docs/assets/js/9616.b75c2f6d.js +1 -0
  111. solace_agent_mesh/assets/docs/assets/js/9793.c6d16376.js +1 -0
  112. solace_agent_mesh/assets/docs/assets/js/9eff14a2.1bf8f61c.js +1 -0
  113. solace_agent_mesh/assets/docs/assets/js/a3a92b25.26ca071f.js +1 -0
  114. solace_agent_mesh/assets/docs/assets/js/a7bd4aaa.2204d2f7.js +1 -0
  115. solace_agent_mesh/assets/docs/assets/js/a94703ab.0438dbc2.js +1 -0
  116. solace_agent_mesh/assets/docs/assets/js/aba21aa0.c42a534c.js +1 -0
  117. solace_agent_mesh/assets/docs/assets/js/aba87c2f.d3e2dcc3.js +1 -0
  118. solace_agent_mesh/assets/docs/assets/js/ae4415af.8e279b5d.js +1 -0
  119. solace_agent_mesh/assets/docs/assets/js/b7006a3a.40b10c9d.js +1 -0
  120. solace_agent_mesh/assets/docs/assets/js/bac0be12.f50d9bac.js +1 -0
  121. solace_agent_mesh/assets/docs/assets/js/bb2ef573.207e6990.js +1 -0
  122. solace_agent_mesh/assets/docs/assets/js/c2c06897.63b76e9e.js +1 -0
  123. solace_agent_mesh/assets/docs/assets/js/cc969b05.954186d4.js +1 -0
  124. solace_agent_mesh/assets/docs/assets/js/cd3d4052.ca6eed8c.js +1 -0
  125. solace_agent_mesh/assets/docs/assets/js/ced92a13.fb92e7ca.js +1 -0
  126. solace_agent_mesh/assets/docs/assets/js/cee5d587.f5b73ca1.js +1 -0
  127. solace_agent_mesh/assets/docs/assets/js/f284c35a.ecc3d195.js +1 -0
  128. solace_agent_mesh/assets/docs/assets/js/f897a61a.2c2e152c.js +1 -0
  129. solace_agent_mesh/assets/docs/assets/js/fbfa3e75.aca209c9.js +1 -0
  130. solace_agent_mesh/assets/docs/assets/js/main.7ed3319f.js +2 -0
  131. solace_agent_mesh/assets/docs/assets/js/main.7ed3319f.js.LICENSE.txt +81 -0
  132. solace_agent_mesh/assets/docs/assets/js/runtime~main.d9520ae2.js +1 -0
  133. solace_agent_mesh/assets/docs/docs/documentation/concepts/agents/index.html +128 -0
  134. solace_agent_mesh/assets/docs/docs/documentation/concepts/architecture/index.html +91 -0
  135. solace_agent_mesh/assets/docs/docs/documentation/concepts/cli/index.html +201 -0
  136. solace_agent_mesh/assets/docs/docs/documentation/concepts/gateways/index.html +91 -0
  137. solace_agent_mesh/assets/docs/docs/documentation/concepts/orchestrator/index.html +55 -0
  138. solace_agent_mesh/assets/docs/docs/documentation/concepts/plugins/index.html +82 -0
  139. solace_agent_mesh/assets/docs/docs/documentation/deployment/debugging/index.html +60 -0
  140. solace_agent_mesh/assets/docs/docs/documentation/deployment/deploy/index.html +48 -0
  141. solace_agent_mesh/assets/docs/docs/documentation/deployment/observability/index.html +54 -0
  142. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +17 -0
  143. solace_agent_mesh/assets/docs/docs/documentation/getting-started/component-overview/index.html +45 -0
  144. solace_agent_mesh/assets/docs/docs/documentation/getting-started/installation/index.html +76 -0
  145. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +150 -0
  146. solace_agent_mesh/assets/docs/docs/documentation/getting-started/quick-start/index.html +54 -0
  147. solace_agent_mesh/assets/docs/docs/documentation/tutorials/bedrock-agents/index.html +267 -0
  148. solace_agent_mesh/assets/docs/docs/documentation/tutorials/custom-agent/index.html +136 -0
  149. solace_agent_mesh/assets/docs/docs/documentation/tutorials/event-mesh-gateway/index.html +116 -0
  150. solace_agent_mesh/assets/docs/docs/documentation/tutorials/mcp-integration/index.html +80 -0
  151. solace_agent_mesh/assets/docs/docs/documentation/tutorials/mongodb-integration/index.html +164 -0
  152. solace_agent_mesh/assets/docs/docs/documentation/tutorials/rest-gateway/index.html +57 -0
  153. solace_agent_mesh/assets/docs/docs/documentation/tutorials/slack-integration/index.html +72 -0
  154. solace_agent_mesh/assets/docs/docs/documentation/tutorials/sql-database/index.html +102 -0
  155. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/artifact-management/index.html +99 -0
  156. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/audio-tools/index.html +90 -0
  157. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/data-analysis-tools/index.html +107 -0
  158. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/embeds/index.html +152 -0
  159. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/index.html +103 -0
  160. solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-agents/index.html +170 -0
  161. solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-gateways/index.html +200 -0
  162. solace_agent_mesh/assets/docs/docs/documentation/user-guide/creating-service-providers/index.html +54 -0
  163. solace_agent_mesh/assets/docs/docs/documentation/user-guide/solace-ai-connector/index.html +69 -0
  164. solace_agent_mesh/assets/docs/docs/documentation/user-guide/structure/index.html +59 -0
  165. solace_agent_mesh/assets/docs/img/Solace_AI_Framework_README.png +0 -0
  166. solace_agent_mesh/assets/docs/img/Solace_AI_Framework_With_Broker.png +0 -0
  167. solace_agent_mesh/assets/docs/img/logo.png +0 -0
  168. solace_agent_mesh/assets/docs/img/sac-flows.png +0 -0
  169. solace_agent_mesh/assets/docs/img/sac_parts_of_a_component.png +0 -0
  170. solace_agent_mesh/assets/docs/img/solace-logo.png +0 -0
  171. solace_agent_mesh/assets/docs/lunr-index-1753813536522.json +1 -0
  172. solace_agent_mesh/assets/docs/lunr-index.json +1 -0
  173. solace_agent_mesh/assets/docs/search-doc-1753813536522.json +1 -0
  174. solace_agent_mesh/assets/docs/search-doc.json +1 -0
  175. solace_agent_mesh/assets/docs/sitemap.xml +1 -0
  176. solace_agent_mesh/cli/__init__.py +1 -1
  177. solace_agent_mesh/cli/commands/add_cmd/__init__.py +15 -0
  178. solace_agent_mesh/cli/commands/add_cmd/add_cmd_llm.txt +250 -0
  179. solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +659 -0
  180. solace_agent_mesh/cli/commands/add_cmd/gateway_cmd.py +322 -0
  181. solace_agent_mesh/cli/commands/add_cmd/web_add_agent_step.py +93 -0
  182. solace_agent_mesh/cli/commands/add_cmd/web_add_gateway_step.py +118 -0
  183. solace_agent_mesh/cli/commands/docs_cmd.py +57 -0
  184. solace_agent_mesh/cli/commands/eval_cmd.py +64 -0
  185. solace_agent_mesh/cli/commands/init_cmd/__init__.py +404 -0
  186. solace_agent_mesh/cli/commands/init_cmd/broker_step.py +201 -0
  187. solace_agent_mesh/cli/commands/init_cmd/directory_step.py +28 -0
  188. solace_agent_mesh/cli/commands/init_cmd/env_step.py +197 -0
  189. solace_agent_mesh/cli/commands/init_cmd/init_cmd_llm.txt +365 -0
  190. solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +387 -0
  191. solace_agent_mesh/cli/commands/init_cmd/project_files_step.py +38 -0
  192. solace_agent_mesh/cli/commands/init_cmd/web_init_step.py +110 -0
  193. solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +183 -0
  194. solace_agent_mesh/cli/commands/plugin_cmd/__init__.py +18 -0
  195. solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +372 -0
  196. solace_agent_mesh/cli/commands/plugin_cmd/build_cmd.py +86 -0
  197. solace_agent_mesh/cli/commands/plugin_cmd/catalog_cmd.py +138 -0
  198. solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +309 -0
  199. solace_agent_mesh/cli/commands/plugin_cmd/official_registry.py +174 -0
  200. solace_agent_mesh/cli/commands/plugin_cmd/plugin_cmd_llm.txt +305 -0
  201. solace_agent_mesh/cli/commands/run_cmd.py +158 -0
  202. solace_agent_mesh/cli/main.py +17 -294
  203. solace_agent_mesh/cli/utils.py +135 -204
  204. solace_agent_mesh/client/webui/frontend/static/assets/authCallback-DvlO62me.js +1 -0
  205. solace_agent_mesh/client/webui/frontend/static/assets/client-bp6u3qVZ.js +49 -0
  206. solace_agent_mesh/client/webui/frontend/static/assets/favicon-BLgzUch9.ico +0 -0
  207. solace_agent_mesh/client/webui/frontend/static/assets/main-An0a5j5k.js +663 -0
  208. solace_agent_mesh/client/webui/frontend/static/assets/main-Bu5-4Bac.css +1 -0
  209. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +14 -0
  210. solace_agent_mesh/client/webui/frontend/static/index.html +15 -0
  211. solace_agent_mesh/common/__init__.py +1 -0
  212. solace_agent_mesh/common/a2a_protocol.py +564 -0
  213. solace_agent_mesh/common/agent_registry.py +42 -0
  214. solace_agent_mesh/common/client/__init__.py +4 -0
  215. solace_agent_mesh/common/client/card_resolver.py +21 -0
  216. solace_agent_mesh/common/client/client.py +85 -0
  217. solace_agent_mesh/common/client/client_llm.txt +133 -0
  218. solace_agent_mesh/common/common_llm.txt +144 -0
  219. solace_agent_mesh/common/constants.py +1 -14
  220. solace_agent_mesh/common/middleware/__init__.py +12 -0
  221. solace_agent_mesh/common/middleware/config_resolver.py +130 -0
  222. solace_agent_mesh/common/middleware/middleware_llm.txt +174 -0
  223. solace_agent_mesh/common/middleware/registry.py +125 -0
  224. solace_agent_mesh/common/server/__init__.py +4 -0
  225. solace_agent_mesh/common/server/server.py +122 -0
  226. solace_agent_mesh/common/server/server_llm.txt +169 -0
  227. solace_agent_mesh/common/server/task_manager.py +291 -0
  228. solace_agent_mesh/common/server/utils.py +28 -0
  229. solace_agent_mesh/common/services/__init__.py +4 -0
  230. solace_agent_mesh/common/services/employee_service.py +162 -0
  231. solace_agent_mesh/common/services/identity_service.py +129 -0
  232. solace_agent_mesh/common/services/providers/__init__.py +4 -0
  233. solace_agent_mesh/common/services/providers/local_file_identity_service.py +148 -0
  234. solace_agent_mesh/common/services/providers/providers_llm.txt +113 -0
  235. solace_agent_mesh/common/services/services_llm.txt +132 -0
  236. solace_agent_mesh/common/types.py +411 -0
  237. solace_agent_mesh/common/utils/__init__.py +7 -0
  238. solace_agent_mesh/common/utils/asyncio_macos_fix.py +86 -0
  239. solace_agent_mesh/common/utils/embeds/__init__.py +33 -0
  240. solace_agent_mesh/common/utils/embeds/constants.py +55 -0
  241. solace_agent_mesh/common/utils/embeds/converter.py +452 -0
  242. solace_agent_mesh/common/utils/embeds/embeds_llm.txt +124 -0
  243. solace_agent_mesh/common/utils/embeds/evaluators.py +394 -0
  244. solace_agent_mesh/common/utils/embeds/modifiers.py +816 -0
  245. solace_agent_mesh/common/utils/embeds/resolver.py +865 -0
  246. solace_agent_mesh/common/utils/embeds/types.py +14 -0
  247. solace_agent_mesh/common/utils/in_memory_cache.py +108 -0
  248. solace_agent_mesh/common/utils/log_formatters.py +44 -0
  249. solace_agent_mesh/common/utils/mime_helpers.py +106 -0
  250. solace_agent_mesh/common/utils/push_notification_auth.py +134 -0
  251. solace_agent_mesh/common/utils/utils_llm.txt +67 -0
  252. solace_agent_mesh/config_portal/backend/common.py +66 -24
  253. solace_agent_mesh/config_portal/backend/plugin_catalog/constants.py +23 -0
  254. solace_agent_mesh/config_portal/backend/plugin_catalog/models.py +49 -0
  255. solace_agent_mesh/config_portal/backend/plugin_catalog/registry_manager.py +160 -0
  256. solace_agent_mesh/config_portal/backend/plugin_catalog/scraper.py +525 -0
  257. solace_agent_mesh/config_portal/backend/plugin_catalog_server.py +216 -0
  258. solace_agent_mesh/config_portal/backend/server.py +550 -140
  259. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-DNxCwAGB.js +48 -0
  260. solace_agent_mesh/config_portal/frontend/static/client/assets/components-B7lKcHVY.js +140 -0
  261. solace_agent_mesh/config_portal/frontend/static/client/assets/{entry.client-DX1misIU.js → entry.client-CEumGClk.js} +3 -3
  262. solace_agent_mesh/config_portal/frontend/static/client/assets/index-DSo1AH_7.js +68 -0
  263. solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-d2b54a97.js +1 -0
  264. solace_agent_mesh/config_portal/frontend/static/client/assets/{root-BApq5dPK.js → root-C4XmHinv.js} +2 -2
  265. solace_agent_mesh/config_portal/frontend/static/client/assets/root-DxRwaWiE.css +1 -0
  266. solace_agent_mesh/config_portal/frontend/static/client/index.html +3 -3
  267. solace_agent_mesh/core_a2a/__init__.py +1 -0
  268. solace_agent_mesh/core_a2a/core_a2a_llm.txt +88 -0
  269. solace_agent_mesh/core_a2a/service.py +331 -0
  270. solace_agent_mesh/evaluation/config_loader.py +657 -0
  271. solace_agent_mesh/evaluation/evaluator.py +667 -0
  272. solace_agent_mesh/evaluation/message_organizer.py +568 -0
  273. solace_agent_mesh/evaluation/report/benchmark_info.html +35 -0
  274. solace_agent_mesh/evaluation/report/chart_section.html +141 -0
  275. solace_agent_mesh/evaluation/report/detailed_breakdown.html +28 -0
  276. solace_agent_mesh/evaluation/report/modal.html +59 -0
  277. solace_agent_mesh/evaluation/report/modal_chart_functions.js +411 -0
  278. solace_agent_mesh/evaluation/report/modal_script.js +296 -0
  279. solace_agent_mesh/evaluation/report/modal_styles.css +340 -0
  280. solace_agent_mesh/evaluation/report/performance_metrics_styles.css +93 -0
  281. solace_agent_mesh/evaluation/report/templates/footer.html +2 -0
  282. solace_agent_mesh/evaluation/report/templates/header.html +340 -0
  283. solace_agent_mesh/evaluation/report_data_processor.py +972 -0
  284. solace_agent_mesh/evaluation/report_generator.py +613 -0
  285. solace_agent_mesh/evaluation/run.py +613 -0
  286. solace_agent_mesh/evaluation/subscriber.py +872 -0
  287. solace_agent_mesh/evaluation/summary_builder.py +775 -0
  288. solace_agent_mesh/evaluation/test_case_loader.py +714 -0
  289. solace_agent_mesh/gateway/base/__init__.py +1 -0
  290. solace_agent_mesh/gateway/base/app.py +266 -0
  291. solace_agent_mesh/gateway/base/base_llm.txt +119 -0
  292. solace_agent_mesh/gateway/base/component.py +1542 -0
  293. solace_agent_mesh/gateway/base/task_context.py +74 -0
  294. solace_agent_mesh/gateway/gateway_llm.txt +125 -0
  295. solace_agent_mesh/gateway/http_sse/app.py +190 -0
  296. solace_agent_mesh/gateway/http_sse/component.py +1602 -0
  297. solace_agent_mesh/gateway/http_sse/components/__init__.py +7 -0
  298. solace_agent_mesh/gateway/http_sse/components/components_llm.txt +65 -0
  299. solace_agent_mesh/gateway/http_sse/components/visualization_forwarder_component.py +108 -0
  300. solace_agent_mesh/gateway/http_sse/dependencies.py +316 -0
  301. solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +63 -0
  302. solace_agent_mesh/gateway/http_sse/main.py +442 -0
  303. solace_agent_mesh/gateway/http_sse/routers/__init__.py +4 -0
  304. solace_agent_mesh/gateway/http_sse/routers/agents.py +41 -0
  305. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +821 -0
  306. solace_agent_mesh/gateway/http_sse/routers/auth.py +212 -0
  307. solace_agent_mesh/gateway/http_sse/routers/config.py +55 -0
  308. solace_agent_mesh/gateway/http_sse/routers/people.py +69 -0
  309. solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +37 -0
  310. solace_agent_mesh/gateway/http_sse/routers/sessions.py +80 -0
  311. solace_agent_mesh/gateway/http_sse/routers/sse.py +138 -0
  312. solace_agent_mesh/gateway/http_sse/routers/tasks.py +294 -0
  313. solace_agent_mesh/gateway/http_sse/routers/users.py +59 -0
  314. solace_agent_mesh/gateway/http_sse/routers/visualization.py +1131 -0
  315. solace_agent_mesh/gateway/http_sse/services/__init__.py +4 -0
  316. solace_agent_mesh/gateway/http_sse/services/agent_service.py +69 -0
  317. solace_agent_mesh/gateway/http_sse/services/people_service.py +158 -0
  318. solace_agent_mesh/gateway/http_sse/services/services_llm.txt +179 -0
  319. solace_agent_mesh/gateway/http_sse/services/task_service.py +121 -0
  320. solace_agent_mesh/gateway/http_sse/session_manager.py +187 -0
  321. solace_agent_mesh/gateway/http_sse/sse_manager.py +328 -0
  322. solace_agent_mesh/llm.txt +228 -0
  323. solace_agent_mesh/llm_detail.txt +2835 -0
  324. solace_agent_mesh/templates/agent_template.yaml +53 -0
  325. solace_agent_mesh/templates/eval_backend_template.yaml +54 -0
  326. solace_agent_mesh/templates/gateway_app_template.py +73 -0
  327. solace_agent_mesh/templates/gateway_component_template.py +400 -0
  328. solace_agent_mesh/templates/gateway_config_template.yaml +43 -0
  329. solace_agent_mesh/templates/main_orchestrator.yaml +55 -0
  330. solace_agent_mesh/templates/plugin_agent_config_template.yaml +122 -0
  331. solace_agent_mesh/templates/plugin_custom_config_template.yaml +27 -0
  332. solace_agent_mesh/templates/plugin_custom_template.py +10 -0
  333. solace_agent_mesh/templates/plugin_gateway_config_template.yaml +63 -0
  334. solace_agent_mesh/templates/plugin_pyproject_template.toml +33 -0
  335. solace_agent_mesh/templates/plugin_readme_template.md +34 -0
  336. solace_agent_mesh/templates/plugin_tools_template.py +224 -0
  337. solace_agent_mesh/templates/shared_config.yaml +66 -0
  338. solace_agent_mesh/templates/templates_llm.txt +147 -0
  339. solace_agent_mesh/templates/webui.yaml +53 -0
  340. solace_agent_mesh-1.0.1.dist-info/METADATA +432 -0
  341. solace_agent_mesh-1.0.1.dist-info/RECORD +359 -0
  342. solace_agent_mesh-1.0.1.dist-info/entry_points.txt +3 -0
  343. {solace_agent_mesh-0.2.3.dist-info → solace_agent_mesh-1.0.1.dist-info}/licenses/LICENSE +1 -1
  344. solace_agent_mesh/agents/base_agent_component.py +0 -226
  345. solace_agent_mesh/agents/global/actions/agent_state_change.py +0 -54
  346. solace_agent_mesh/agents/global/actions/clear_history.py +0 -32
  347. solace_agent_mesh/agents/global/actions/convert_file_to_markdown.py +0 -160
  348. solace_agent_mesh/agents/global/actions/create_file.py +0 -70
  349. solace_agent_mesh/agents/global/actions/error_action.py +0 -45
  350. solace_agent_mesh/agents/global/actions/plantuml_diagram.py +0 -163
  351. solace_agent_mesh/agents/global/actions/plotly_graph.py +0 -152
  352. solace_agent_mesh/agents/global/actions/retrieve_file.py +0 -51
  353. solace_agent_mesh/agents/global/global_agent_component.py +0 -38
  354. solace_agent_mesh/agents/image_processing/actions/create_image.py +0 -75
  355. solace_agent_mesh/agents/image_processing/actions/describe_image.py +0 -115
  356. solace_agent_mesh/agents/image_processing/image_processing_agent_component.py +0 -23
  357. solace_agent_mesh/agents/slack/__init__.py +0 -1
  358. solace_agent_mesh/agents/slack/actions/__init__.py +0 -1
  359. solace_agent_mesh/agents/slack/actions/post_message.py +0 -177
  360. solace_agent_mesh/agents/slack/slack_agent_component.py +0 -59
  361. solace_agent_mesh/agents/web_request/actions/do_image_search.py +0 -84
  362. solace_agent_mesh/agents/web_request/actions/do_news_search.py +0 -47
  363. solace_agent_mesh/agents/web_request/actions/do_suggestion_search.py +0 -34
  364. solace_agent_mesh/agents/web_request/actions/do_web_request.py +0 -135
  365. solace_agent_mesh/agents/web_request/actions/download_file.py +0 -69
  366. solace_agent_mesh/agents/web_request/web_request_agent_component.py +0 -33
  367. solace_agent_mesh/assets/web-visualizer/assets/index-D0qORgkg.css +0 -1
  368. solace_agent_mesh/assets/web-visualizer/assets/index-DnDr1pnu.js +0 -109
  369. solace_agent_mesh/assets/web-visualizer/index.html +0 -14
  370. solace_agent_mesh/assets/web-visualizer/vite.svg +0 -1
  371. solace_agent_mesh/cli/commands/add/__init__.py +0 -3
  372. solace_agent_mesh/cli/commands/add/add.py +0 -88
  373. solace_agent_mesh/cli/commands/add/agent.py +0 -110
  374. solace_agent_mesh/cli/commands/add/copy_from_plugin.py +0 -92
  375. solace_agent_mesh/cli/commands/add/gateway.py +0 -374
  376. solace_agent_mesh/cli/commands/build.py +0 -670
  377. solace_agent_mesh/cli/commands/chat/__init__.py +0 -3
  378. solace_agent_mesh/cli/commands/chat/chat.py +0 -361
  379. solace_agent_mesh/cli/commands/config.py +0 -29
  380. solace_agent_mesh/cli/commands/init/__init__.py +0 -3
  381. solace_agent_mesh/cli/commands/init/ai_provider_step.py +0 -93
  382. solace_agent_mesh/cli/commands/init/broker_step.py +0 -99
  383. solace_agent_mesh/cli/commands/init/builtin_agent_step.py +0 -83
  384. solace_agent_mesh/cli/commands/init/check_if_already_done.py +0 -13
  385. solace_agent_mesh/cli/commands/init/create_config_file_step.py +0 -65
  386. solace_agent_mesh/cli/commands/init/create_other_project_files_step.py +0 -147
  387. solace_agent_mesh/cli/commands/init/file_service_step.py +0 -73
  388. solace_agent_mesh/cli/commands/init/init.py +0 -92
  389. solace_agent_mesh/cli/commands/init/project_structure_step.py +0 -16
  390. solace_agent_mesh/cli/commands/init/web_init_step.py +0 -32
  391. solace_agent_mesh/cli/commands/plugin/__init__.py +0 -3
  392. solace_agent_mesh/cli/commands/plugin/add.py +0 -100
  393. solace_agent_mesh/cli/commands/plugin/build.py +0 -268
  394. solace_agent_mesh/cli/commands/plugin/create.py +0 -117
  395. solace_agent_mesh/cli/commands/plugin/plugin.py +0 -124
  396. solace_agent_mesh/cli/commands/plugin/remove.py +0 -73
  397. solace_agent_mesh/cli/commands/run.py +0 -68
  398. solace_agent_mesh/cli/commands/visualizer.py +0 -138
  399. solace_agent_mesh/cli/config.py +0 -85
  400. solace_agent_mesh/common/action.py +0 -91
  401. solace_agent_mesh/common/action_list.py +0 -37
  402. solace_agent_mesh/common/action_response.py +0 -340
  403. solace_agent_mesh/common/mysql_database.py +0 -40
  404. solace_agent_mesh/common/postgres_database.py +0 -85
  405. solace_agent_mesh/common/prompt_templates.py +0 -28
  406. solace_agent_mesh/common/stimulus_utils.py +0 -152
  407. solace_agent_mesh/common/time.py +0 -24
  408. solace_agent_mesh/common/utils.py +0 -712
  409. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-DMmCawWe.js +0 -42
  410. solace_agent_mesh/config_portal/frontend/static/client/assets/components-ZIfdTbrV.js +0 -191
  411. solace_agent_mesh/config_portal/frontend/static/client/assets/index-BJHAE5s4.js +0 -17
  412. solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-dd988f05.js +0 -1
  413. solace_agent_mesh/config_portal/frontend/static/client/assets/root-DX4gQ516.css +0 -1
  414. solace_agent_mesh/configs/agent_global.yaml +0 -74
  415. solace_agent_mesh/configs/agent_image_processing.yaml +0 -82
  416. solace_agent_mesh/configs/agent_slack.yaml +0 -64
  417. solace_agent_mesh/configs/agent_web_request.yaml +0 -75
  418. solace_agent_mesh/configs/conversation_to_file.yaml +0 -56
  419. solace_agent_mesh/configs/error_catcher.yaml +0 -56
  420. solace_agent_mesh/configs/monitor.yaml +0 -0
  421. solace_agent_mesh/configs/monitor_stim_and_errors_to_slack.yaml +0 -109
  422. solace_agent_mesh/configs/monitor_user_feedback.yaml +0 -58
  423. solace_agent_mesh/configs/orchestrator.yaml +0 -241
  424. solace_agent_mesh/configs/service_embedding.yaml +0 -81
  425. solace_agent_mesh/configs/service_llm.yaml +0 -265
  426. solace_agent_mesh/configs/visualize_websocket.yaml +0 -55
  427. solace_agent_mesh/gateway/components/gateway_base.py +0 -47
  428. solace_agent_mesh/gateway/components/gateway_input.py +0 -278
  429. solace_agent_mesh/gateway/components/gateway_output.py +0 -298
  430. solace_agent_mesh/gateway/identity/bamboohr_identity.py +0 -18
  431. solace_agent_mesh/gateway/identity/identity_base.py +0 -10
  432. solace_agent_mesh/gateway/identity/identity_provider.py +0 -60
  433. solace_agent_mesh/gateway/identity/no_identity.py +0 -9
  434. solace_agent_mesh/gateway/identity/passthru_identity.py +0 -9
  435. solace_agent_mesh/monitors/base_monitor_component.py +0 -26
  436. solace_agent_mesh/monitors/feedback/user_feedback_monitor.py +0 -75
  437. solace_agent_mesh/monitors/stim_and_errors/stim_and_error_monitor.py +0 -560
  438. solace_agent_mesh/orchestrator/__init__.py +0 -0
  439. solace_agent_mesh/orchestrator/action_manager.py +0 -237
  440. solace_agent_mesh/orchestrator/components/__init__.py +0 -0
  441. solace_agent_mesh/orchestrator/components/orchestrator_action_manager_timeout_component.py +0 -58
  442. solace_agent_mesh/orchestrator/components/orchestrator_action_response_component.py +0 -179
  443. solace_agent_mesh/orchestrator/components/orchestrator_register_component.py +0 -107
  444. solace_agent_mesh/orchestrator/components/orchestrator_stimulus_processor_component.py +0 -527
  445. solace_agent_mesh/orchestrator/components/orchestrator_streaming_output_component.py +0 -260
  446. solace_agent_mesh/orchestrator/orchestrator_main.py +0 -172
  447. solace_agent_mesh/orchestrator/orchestrator_prompt.py +0 -539
  448. solace_agent_mesh/services/__init__.py +0 -0
  449. solace_agent_mesh/services/authorization/providers/base_authorization_provider.py +0 -56
  450. solace_agent_mesh/services/bamboo_hr_service/__init__.py +0 -3
  451. solace_agent_mesh/services/bamboo_hr_service/bamboo_hr.py +0 -182
  452. solace_agent_mesh/services/common/__init__.py +0 -4
  453. solace_agent_mesh/services/common/auto_expiry.py +0 -45
  454. solace_agent_mesh/services/common/singleton.py +0 -18
  455. solace_agent_mesh/services/file_service/__init__.py +0 -14
  456. solace_agent_mesh/services/file_service/file_manager/__init__.py +0 -0
  457. solace_agent_mesh/services/file_service/file_manager/bucket_file_manager.py +0 -149
  458. solace_agent_mesh/services/file_service/file_manager/file_manager_base.py +0 -162
  459. solace_agent_mesh/services/file_service/file_manager/memory_file_manager.py +0 -64
  460. solace_agent_mesh/services/file_service/file_manager/volume_file_manager.py +0 -106
  461. solace_agent_mesh/services/file_service/file_service.py +0 -437
  462. solace_agent_mesh/services/file_service/file_service_constants.py +0 -54
  463. solace_agent_mesh/services/file_service/file_transformations.py +0 -141
  464. solace_agent_mesh/services/file_service/file_utils.py +0 -324
  465. solace_agent_mesh/services/file_service/transformers/__init__.py +0 -5
  466. solace_agent_mesh/services/history_service/__init__.py +0 -3
  467. solace_agent_mesh/services/history_service/history_providers/__init__.py +0 -0
  468. solace_agent_mesh/services/history_service/history_providers/base_history_provider.py +0 -54
  469. solace_agent_mesh/services/history_service/history_providers/file_history_provider.py +0 -74
  470. solace_agent_mesh/services/history_service/history_providers/index.py +0 -40
  471. solace_agent_mesh/services/history_service/history_providers/memory_history_provider.py +0 -33
  472. solace_agent_mesh/services/history_service/history_providers/mongodb_history_provider.py +0 -66
  473. solace_agent_mesh/services/history_service/history_providers/redis_history_provider.py +0 -66
  474. solace_agent_mesh/services/history_service/history_providers/sql_history_provider.py +0 -93
  475. solace_agent_mesh/services/history_service/history_service.py +0 -413
  476. solace_agent_mesh/services/history_service/long_term_memory/__init__.py +0 -0
  477. solace_agent_mesh/services/history_service/long_term_memory/long_term_memory.py +0 -399
  478. solace_agent_mesh/services/llm_service/components/llm_request_component.py +0 -340
  479. solace_agent_mesh/services/llm_service/components/llm_service_component_base.py +0 -152
  480. solace_agent_mesh/services/middleware_service/__init__.py +0 -0
  481. solace_agent_mesh/services/middleware_service/middleware_service.py +0 -20
  482. solace_agent_mesh/templates/action.py +0 -38
  483. solace_agent_mesh/templates/agent.py +0 -29
  484. solace_agent_mesh/templates/agent.yaml +0 -70
  485. solace_agent_mesh/templates/gateway-config-template.yaml +0 -6
  486. solace_agent_mesh/templates/gateway-default-config.yaml +0 -28
  487. solace_agent_mesh/templates/gateway-flows.yaml +0 -78
  488. solace_agent_mesh/templates/gateway-header.yaml +0 -16
  489. solace_agent_mesh/templates/gateway_base.py +0 -15
  490. solace_agent_mesh/templates/gateway_input.py +0 -98
  491. solace_agent_mesh/templates/gateway_output.py +0 -71
  492. solace_agent_mesh/templates/plugin-gateway-default-config.yaml +0 -29
  493. solace_agent_mesh/templates/plugin-pyproject.toml +0 -30
  494. solace_agent_mesh/templates/rest-api-default-config.yaml +0 -31
  495. solace_agent_mesh/templates/rest-api-flows.yaml +0 -81
  496. solace_agent_mesh/templates/slack-default-config.yaml +0 -16
  497. solace_agent_mesh/templates/slack-flows.yaml +0 -81
  498. solace_agent_mesh/templates/solace-agent-mesh-default.yaml +0 -86
  499. solace_agent_mesh/templates/solace-agent-mesh-plugin-default.yaml +0 -8
  500. solace_agent_mesh/templates/web-default-config.yaml +0 -10
  501. solace_agent_mesh/templates/web-flows.yaml +0 -76
  502. solace_agent_mesh/tools/__init__.py +0 -0
  503. solace_agent_mesh/tools/components/__init__.py +0 -0
  504. solace_agent_mesh/tools/components/conversation_formatter.py +0 -111
  505. solace_agent_mesh/tools/components/file_resolver_component.py +0 -58
  506. solace_agent_mesh/tools/config/runtime_config.py +0 -26
  507. solace_agent_mesh-0.2.3.dist-info/METADATA +0 -172
  508. solace_agent_mesh-0.2.3.dist-info/RECORD +0 -193
  509. solace_agent_mesh-0.2.3.dist-info/entry_points.txt +0 -3
  510. /solace_agent_mesh/{agents → agent}/__init__.py +0 -0
  511. /solace_agent_mesh/{agents/global → agent/adk}/__init__.py +0 -0
  512. /solace_agent_mesh/{agents/global/actions → agent/protocol}/__init__.py +0 -0
  513. /solace_agent_mesh/{agents/image_processing → agent/sac}/__init__.py +0 -0
  514. /solace_agent_mesh/{agents/image_processing/actions → agent/utils}/__init__.py +0 -0
  515. /solace_agent_mesh/{agents/web_request → config_portal/backend/plugin_catalog}/__init__.py +0 -0
  516. /solace_agent_mesh/{agents/web_request/actions → evaluation}/__init__.py +0 -0
  517. /solace_agent_mesh/gateway/{components → http_sse}/__init__.py +0 -0
  518. {solace_agent_mesh-0.2.3.dist-info → solace_agent_mesh-1.0.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,927 @@
1
+ """
2
+ Helper functions for artifact management, including metadata handling and schema inference.
3
+ """
4
+
5
+ import base64
6
+ import binascii
7
+ import json
8
+ import csv
9
+ import io
10
+ import inspect
11
+ import datetime
12
+ import os
13
+ from typing import Any, Dict, Optional, Tuple, List, Union, TYPE_CHECKING
14
+ from datetime import timezone
15
+ from google.adk.artifacts import BaseArtifactService
16
+ from google.genai import types as adk_types
17
+ from solace_ai_connector.common.log import log
18
+ from ...common.utils.mime_helpers import is_text_based_mime_type, is_text_based_file
19
+
20
+ if TYPE_CHECKING:
21
+ from google.adk.tools import ToolContext
22
+
23
+ METADATA_SUFFIX = ".metadata.json"
24
+ DEFAULT_SCHEMA_MAX_KEYS = 20
25
+
26
+
27
+ def is_filename_safe(filename: str) -> bool:
28
+ """
29
+ Checks if a filename is safe for artifact creation.
30
+ - Must not be empty or just whitespace.
31
+ - Must not contain path traversal sequences ('..').
32
+ - Must not contain path separators ('/' or '\\').
33
+ - Must not be a reserved name like '.' or '..'.
34
+
35
+ Args:
36
+ filename: The filename to validate.
37
+
38
+ Returns:
39
+ True if the filename is safe, False otherwise.
40
+ """
41
+ if not filename or not filename.strip():
42
+ return False
43
+
44
+ # Check for path traversal
45
+ if ".." in filename:
46
+ return False
47
+
48
+ # Check for path separators
49
+ if "/" in filename or "\\" in filename:
50
+ return False
51
+
52
+ # Check for reserved names
53
+ if filename.strip() in [".", ".."]:
54
+ return False
55
+
56
+ return True
57
+
58
+
59
+ def ensure_correct_extension(filename_from_llm: str, desired_extension: str) -> str:
60
+ """
61
+ Ensures a filename has the correct extension, handling cases where the LLM
62
+ might provide a filename with or without an extension, or with the wrong one.
63
+
64
+ Args:
65
+ filename_from_llm: The filename string provided by the LLM.
66
+ desired_extension: The correct extension for the file (e.g., 'png', 'md').
67
+ Should be provided without a leading dot.
68
+
69
+ Returns:
70
+ A string with the correctly formatted filename.
71
+ """
72
+ if not filename_from_llm:
73
+ return f"unnamed.{desired_extension.lower()}"
74
+ filename_stripped = filename_from_llm.strip()
75
+ desired_ext_clean = desired_extension.lower().strip().lstrip(".")
76
+ base_name, current_ext = os.path.splitext(filename_stripped)
77
+ current_ext_clean = current_ext.lower().lstrip(".")
78
+ if current_ext_clean == desired_ext_clean:
79
+ return filename_stripped
80
+ else:
81
+ return f"{base_name}.{desired_ext_clean}"
82
+
83
+
84
+ def _inspect_structure(
85
+ data: Any, max_depth: int, max_keys: int, current_depth: int = 0
86
+ ) -> Any:
87
+ """
88
+ Recursively inspects data structure up to max_depth and max_keys for dictionaries.
89
+ """
90
+ if current_depth >= max_depth:
91
+ return type(data).__name__
92
+ if isinstance(data, dict):
93
+ if not data:
94
+ return {}
95
+ inspected_dict = {}
96
+ keys = list(data.keys())
97
+ keys_to_inspect = keys[:max_keys]
98
+ for key in keys_to_inspect:
99
+ inspected_dict[key] = _inspect_structure(
100
+ data[key], max_depth, max_keys, current_depth + 1
101
+ )
102
+ if len(keys) > max_keys:
103
+ inspected_dict["..."] = f"{len(keys) - max_keys} more keys"
104
+ return inspected_dict
105
+ elif isinstance(data, list):
106
+ if not data:
107
+ return []
108
+ return [_inspect_structure(data[0], max_depth, max_keys, current_depth + 1)]
109
+ else:
110
+ return type(data).__name__
111
+
112
+
113
+ def _infer_schema(
114
+ content_bytes: bytes,
115
+ mime_type: str,
116
+ depth: int = 3,
117
+ max_keys: int = DEFAULT_SCHEMA_MAX_KEYS,
118
+ ) -> Dict[str, Any]:
119
+ """
120
+ Infers basic schema information for common text-based types.
121
+ Args:
122
+ content_bytes: The raw byte content.
123
+ mime_type: The MIME type.
124
+ depth: Maximum recursion depth for nested structures.
125
+ max_keys: Maximum number of dictionary keys to inspect at each level.
126
+ Returns:
127
+ A dictionary representing the inferred schema, including an 'inferred' flag
128
+ and potential 'error' field.
129
+ """
130
+ schema_info = {"type": mime_type, "inferred": False, "error": None}
131
+ normalized_mime_type = mime_type.lower() if mime_type else ""
132
+ try:
133
+ if normalized_mime_type == "text/csv":
134
+ try:
135
+ text_content = io.TextIOWrapper(
136
+ io.BytesIO(content_bytes), encoding="utf-8"
137
+ )
138
+ reader = csv.reader(text_content)
139
+ header = next(reader)
140
+ schema_info["columns"] = header
141
+ schema_info["inferred"] = True
142
+ except (StopIteration, csv.Error, UnicodeDecodeError) as e:
143
+ schema_info["error"] = f"CSV header inference failed: {e}"
144
+ elif normalized_mime_type in ["application/json", "text/json"]:
145
+ try:
146
+ data = json.loads(content_bytes.decode("utf-8"))
147
+ schema_info["structure"] = _inspect_structure(data, depth, max_keys)
148
+ schema_info["inferred"] = True
149
+ except (json.JSONDecodeError, UnicodeDecodeError) as e:
150
+ schema_info["error"] = f"JSON structure inference failed: {e}"
151
+ elif normalized_mime_type in [
152
+ "application/yaml",
153
+ "text/yaml",
154
+ "application/x-yaml",
155
+ "text/x-yaml",
156
+ ]:
157
+ try:
158
+ import yaml
159
+
160
+ data = yaml.safe_load(content_bytes)
161
+ schema_info["structure"] = _inspect_structure(data, depth, max_keys)
162
+ schema_info["inferred"] = True
163
+ except ImportError:
164
+ schema_info["error"] = "YAML inference skipped: PyYAML not installed."
165
+ except (yaml.YAMLError, UnicodeDecodeError) as e:
166
+ schema_info["error"] = f"YAML structure inference failed: {e}"
167
+ except Exception as e:
168
+ schema_info["error"] = f"Unexpected error during schema inference: {e}"
169
+ if schema_info["error"]:
170
+ log.warning(
171
+ "Schema inference for mime_type '%s' encountered error: %s",
172
+ mime_type,
173
+ schema_info["error"],
174
+ )
175
+ elif not schema_info["inferred"]:
176
+ log.debug(
177
+ "No specific schema inference logic applied for mime_type '%s'.", mime_type
178
+ )
179
+ return schema_info
180
+
181
+
182
+ async def save_artifact_with_metadata(
183
+ artifact_service: BaseArtifactService,
184
+ app_name: str,
185
+ user_id: str,
186
+ session_id: str,
187
+ filename: str,
188
+ content_bytes: bytes,
189
+ mime_type: str,
190
+ metadata_dict: Dict[str, Any],
191
+ timestamp: datetime.datetime,
192
+ explicit_schema: Optional[Dict] = None,
193
+ schema_inference_depth: int = 2,
194
+ schema_max_keys: int = DEFAULT_SCHEMA_MAX_KEYS,
195
+ tool_context: Optional["ToolContext"] = None,
196
+ ) -> Dict[str, Any]:
197
+ """
198
+ Saves a data artifact and its corresponding metadata artifact using BaseArtifactService.
199
+ """
200
+ log_identifier = f"[ArtifactHelper:save:{filename}]"
201
+ log.debug("%s Saving artifact and metadata (async)...", log_identifier)
202
+ data_version = None
203
+ metadata_version = None
204
+ metadata_filename = f"{filename}{METADATA_SUFFIX}"
205
+ status = "error"
206
+ status_message = "Initialization error"
207
+ try:
208
+ data_artifact_part = adk_types.Part.from_bytes(
209
+ data=content_bytes, mime_type=mime_type
210
+ )
211
+ log.debug(
212
+ f"{log_identifier} artifact_service object type: {type(artifact_service)}"
213
+ )
214
+ log.debug(
215
+ f"{log_identifier} artifact_service object dir: {dir(artifact_service)}"
216
+ )
217
+ if hasattr(artifact_service, "save_artifact"):
218
+ save_artifact_method = getattr(artifact_service, "save_artifact")
219
+ log.debug(
220
+ f"{log_identifier} type of artifact_service.save_artifact: {type(save_artifact_method)}"
221
+ )
222
+ log.debug(
223
+ f"{log_identifier} Is save_artifact a coroutine function? {inspect.iscoroutinefunction(save_artifact_method)}"
224
+ )
225
+ log.debug(
226
+ f"{log_identifier} Is save_artifact an async generator function? {inspect.isasyncgenfunction(save_artifact_method)}"
227
+ )
228
+ if callable(save_artifact_method):
229
+ try:
230
+ sig = inspect.signature(save_artifact_method)
231
+ log.debug(f"{log_identifier} Signature of save_artifact: {sig}")
232
+ except Exception as e_inspect:
233
+ log.debug(
234
+ f"{log_identifier} Could not get signature of save_artifact: {e_inspect}"
235
+ )
236
+ save_data_method = getattr(artifact_service, "save_artifact")
237
+ data_version = await save_data_method(
238
+ app_name=app_name,
239
+ user_id=user_id,
240
+ session_id=session_id,
241
+ filename=filename,
242
+ artifact=data_artifact_part,
243
+ )
244
+ log.info(
245
+ "%s Saved data artifact '%s' as version %s.",
246
+ log_identifier,
247
+ filename,
248
+ data_version,
249
+ )
250
+
251
+ # Populate artifact_delta for ADK callbacks if tool_context is provided
252
+ if (
253
+ tool_context
254
+ and hasattr(tool_context, "actions")
255
+ and hasattr(tool_context.actions, "artifact_delta")
256
+ ):
257
+ tool_context.actions.artifact_delta[filename] = data_version
258
+ log.debug(
259
+ "%s Populated artifact_delta for ADK callbacks: %s -> %s",
260
+ log_identifier,
261
+ filename,
262
+ data_version,
263
+ )
264
+
265
+ final_metadata = {
266
+ "filename": filename,
267
+ "mime_type": mime_type,
268
+ "size_bytes": len(content_bytes),
269
+ "timestamp_utc": (
270
+ timestamp
271
+ if isinstance(timestamp, (int, float))
272
+ else timestamp.timestamp()
273
+ ),
274
+ **(metadata_dict or {}),
275
+ }
276
+ if explicit_schema:
277
+ final_metadata["schema"] = {
278
+ "type": mime_type,
279
+ "inferred": False,
280
+ **explicit_schema,
281
+ }
282
+ log.debug("%s Using explicit schema provided by caller.", log_identifier)
283
+ else:
284
+ inferred_schema = _infer_schema(
285
+ content_bytes, mime_type, schema_inference_depth, schema_max_keys
286
+ )
287
+ final_metadata["schema"] = inferred_schema
288
+ if inferred_schema.get("inferred"):
289
+ log.debug(
290
+ "%s Added inferred schema (max_keys=%d).",
291
+ log_identifier,
292
+ schema_max_keys,
293
+ )
294
+ elif inferred_schema.get("error"):
295
+ log.warning(
296
+ "%s Schema inference failed: %s",
297
+ log_identifier,
298
+ inferred_schema["error"],
299
+ )
300
+ try:
301
+ metadata_bytes = json.dumps(final_metadata, indent=2).encode("utf-8")
302
+ metadata_artifact_part = adk_types.Part.from_bytes(
303
+ data=metadata_bytes, mime_type="application/json"
304
+ )
305
+ save_metadata_method = getattr(artifact_service, "save_artifact")
306
+ metadata_version = await save_metadata_method(
307
+ app_name=app_name,
308
+ user_id=user_id,
309
+ session_id=session_id,
310
+ filename=metadata_filename,
311
+ artifact=metadata_artifact_part,
312
+ )
313
+ log.info(
314
+ "%s Saved metadata artifact '%s' as version %s.",
315
+ log_identifier,
316
+ metadata_filename,
317
+ metadata_version,
318
+ )
319
+ status = "success"
320
+ status_message = "Artifact and metadata saved successfully."
321
+ except Exception as meta_save_err:
322
+ log.exception(
323
+ "%s Failed to save metadata artifact '%s': %s",
324
+ log_identifier,
325
+ metadata_filename,
326
+ meta_save_err,
327
+ )
328
+ status = "partial_success"
329
+ status_message = f"Data artifact saved (v{data_version}), but failed to save metadata: {meta_save_err}"
330
+ except Exception as data_save_err:
331
+ log.exception(
332
+ "%s Failed to save data artifact '%s': %s",
333
+ log_identifier,
334
+ filename,
335
+ data_save_err,
336
+ )
337
+ status = "error"
338
+ status_message = f"Failed to save data artifact: {data_save_err}"
339
+ return {
340
+ "status": status,
341
+ "data_filename": filename,
342
+ "data_version": data_version,
343
+ "metadata_filename": metadata_filename,
344
+ "metadata_version": metadata_version,
345
+ "message": status_message,
346
+ }
347
+
348
+
349
+ def format_metadata_for_llm(metadata: Dict[str, Any]) -> str:
350
+ """Formats loaded metadata into an LLM-friendly text block."""
351
+ lines = []
352
+ filename = metadata.get("filename", "Unknown Filename")
353
+ version = metadata.get("version", "N/A")
354
+ lines.append(f"--- Metadata for artifact '{filename}' (v{version}) ---")
355
+ lines.append("**Artifact Metadata:**")
356
+ if "description" in metadata:
357
+ lines.append(f"* **Description:** {metadata['description']}")
358
+ if "source" in metadata:
359
+ lines.append(f"* **Source:** {metadata['source']}")
360
+ if "mime_type" in metadata:
361
+ lines.append(f"* **Type:** {metadata['mime_type']}")
362
+ if "size_bytes" in metadata:
363
+ lines.append(f"* **Size:** {metadata['size_bytes']} bytes")
364
+ schema = metadata.get("schema", {})
365
+ schema_type = schema.get("type", metadata.get("mime_type", "unknown"))
366
+ schema_details = []
367
+ if schema.get("inferred"):
368
+ schema_details.append("(Inferred)")
369
+ if "columns" in schema:
370
+ schema_details.append(f"Columns: {','.join(schema['columns'])}")
371
+ if "structure" in schema:
372
+ schema_details.append(f"Structure: {json.dumps(schema['structure'])}")
373
+ if schema.get("error"):
374
+ schema_details.append(f"Schema Error: {schema['error']}")
375
+ if schema_details:
376
+ lines.append(f"* **Schema:** {schema_type} {' '.join(schema_details)}")
377
+ elif schema_type != "unknown":
378
+ lines.append(f"* **Schema Type:** {schema_type}")
379
+ custom_fields = {
380
+ k: v
381
+ for k, v in metadata.items()
382
+ if k
383
+ not in [
384
+ "filename",
385
+ "mime_type",
386
+ "size_bytes",
387
+ "timestamp_utc",
388
+ "schema",
389
+ "version",
390
+ "description",
391
+ "source",
392
+ ]
393
+ }
394
+ if custom_fields:
395
+ lines.append("* **Other:**")
396
+ for k, v in custom_fields.items():
397
+ lines.append(f" * {k}: {v}")
398
+ lines.append("--- End Metadata ---")
399
+ return "\n".join(lines)
400
+
401
+
402
+ def decode_and_get_bytes(
403
+ content_str: str, mime_type: str, log_identifier: str
404
+ ) -> Tuple[bytes, str]:
405
+ """
406
+ Decodes content if necessary (based on mime_type) and returns bytes and final mime_type.
407
+ Args:
408
+ content_str: The input content string (potentially base64).
409
+ mime_type: The provided MIME type.
410
+ log_identifier: Identifier for logging.
411
+ Returns:
412
+ A tuple containing (content_bytes, final_mime_type).
413
+ """
414
+ file_bytes: bytes
415
+ final_mime_type = mime_type
416
+ normalized_mime_type = mime_type.lower() if mime_type else ""
417
+ if is_text_based_mime_type(normalized_mime_type):
418
+ file_bytes = content_str.encode("utf-8")
419
+ log.debug(
420
+ "%s Encoded text content for text mimeType '%s'.",
421
+ log_identifier,
422
+ mime_type,
423
+ )
424
+ else:
425
+ try:
426
+ file_bytes = base64.b64decode(content_str, validate=True)
427
+ log.debug(
428
+ "%s Decoded base64 content for non-text mimeType '%s'.",
429
+ log_identifier,
430
+ mime_type,
431
+ )
432
+ except (binascii.Error, ValueError) as decode_error:
433
+ log.warning(
434
+ "%s Failed to base64 decode content for mimeType '%s'. Treating as text/plain. Error: %s",
435
+ log_identifier,
436
+ mime_type,
437
+ decode_error,
438
+ )
439
+ file_bytes = content_str.encode("utf-8")
440
+ final_mime_type = "text/plain"
441
+ return file_bytes, final_mime_type
442
+
443
+
444
+ from google.adk.artifacts import BaseArtifactService
445
+ from datetime import datetime, timezone
446
+ import traceback
447
+ from ...common.types import ArtifactInfo
448
+
449
+
450
+ async def get_latest_artifact_version(
451
+ artifact_service: BaseArtifactService,
452
+ app_name: str,
453
+ user_id: str,
454
+ session_id: str,
455
+ filename: str,
456
+ ) -> Optional[int]:
457
+ """
458
+ Retrieves the latest version number for a given artifact.
459
+
460
+ Args:
461
+ artifact_service: The artifact service instance.
462
+ app_name: The application name.
463
+ user_id: The user ID.
464
+ session_id: The session ID.
465
+ filename: The name of the artifact.
466
+
467
+ Returns:
468
+ The latest version number as an integer, or None if no versions exist.
469
+ """
470
+ log_identifier = f"[ArtifactHelper:get_latest_version:{filename}]"
471
+ try:
472
+ if not hasattr(artifact_service, "list_versions"):
473
+ log.warning(
474
+ "%s Artifact service does not support 'list_versions'.", log_identifier
475
+ )
476
+ return None
477
+
478
+ versions = await artifact_service.list_versions(
479
+ app_name=app_name, user_id=user_id, session_id=session_id, filename=filename
480
+ )
481
+ if not versions:
482
+ log.debug("%s No versions found for artifact.", log_identifier)
483
+ return None
484
+
485
+ latest_version = max(versions)
486
+ log.debug("%s Resolved latest version to %d.", log_identifier, latest_version)
487
+ return latest_version
488
+ except Exception as e:
489
+ log.error("%s Error resolving latest version: %s", log_identifier, e)
490
+ return None
491
+
492
+
493
+ async def get_artifact_info_list(
494
+ artifact_service: BaseArtifactService,
495
+ app_name: str,
496
+ user_id: str,
497
+ session_id: str,
498
+ ) -> List[ArtifactInfo]:
499
+ """
500
+ Retrieves detailed information for all artifacts using the artifact service.
501
+
502
+ Args:
503
+ artifact_service: The artifact service instance.
504
+ app_name: The application name.
505
+ user_id: The user ID.
506
+ session_id: The session ID.
507
+
508
+ Returns:
509
+ A list of ArtifactInfo objects.
510
+ """
511
+ log_prefix = f"[ArtifactHelper:get_info_list] App={app_name}, User={user_id}, Session={session_id} -"
512
+ artifact_info_list: List[ArtifactInfo] = []
513
+
514
+ try:
515
+ list_keys_method = getattr(artifact_service, "list_artifact_keys")
516
+ keys = await list_keys_method(
517
+ app_name=app_name, user_id=user_id, session_id=session_id
518
+ )
519
+ log.info(
520
+ "%s Found %d artifact keys. Fetching details...", log_prefix, len(keys)
521
+ )
522
+
523
+ for filename in keys:
524
+ if filename.endswith(METADATA_SUFFIX):
525
+ continue
526
+
527
+ log_identifier_item = f"{log_prefix} [{filename}]"
528
+ try:
529
+
530
+ version_count: int = 0
531
+ latest_version_num: Optional[int] = await get_latest_artifact_version(
532
+ artifact_service, app_name, user_id, session_id, filename
533
+ )
534
+
535
+ if hasattr(artifact_service, "list_versions"):
536
+ try:
537
+ available_versions = await artifact_service.list_versions(
538
+ app_name=app_name,
539
+ user_id=user_id,
540
+ session_id=session_id,
541
+ filename=filename,
542
+ )
543
+ version_count = len(available_versions)
544
+ except Exception as list_ver_err:
545
+ log.error(
546
+ "%s Error listing versions for count: %s.",
547
+ log_identifier_item,
548
+ list_ver_err,
549
+ )
550
+
551
+ data = await load_artifact_content_or_metadata(
552
+ artifact_service=artifact_service,
553
+ app_name=app_name,
554
+ user_id=user_id,
555
+ session_id=session_id,
556
+ filename=filename,
557
+ version="latest",
558
+ load_metadata_only=True,
559
+ log_identifier_prefix=log_identifier_item,
560
+ )
561
+
562
+ metadata = data.get("metadata", {})
563
+ mime_type = metadata.get("mime_type", "application/data")
564
+ size = metadata.get("size_bytes", 0)
565
+ schema_definition = metadata.get("schema", {})
566
+ description = metadata.get("description", "No description provided")
567
+ loaded_version_num = data.get("version", latest_version_num)
568
+
569
+ last_modified_ts = metadata.get("timestamp_utc")
570
+ last_modified_ts = metadata.get("timestamp_utc")
571
+ last_modified_iso = (
572
+ datetime.fromtimestamp(
573
+ last_modified_ts, tz=timezone.utc
574
+ ).isoformat()
575
+ if last_modified_ts
576
+ else None
577
+ )
578
+
579
+ artifact_info_list.append(
580
+ ArtifactInfo(
581
+ filename=filename,
582
+ mime_type=mime_type,
583
+ size=size,
584
+ last_modified=last_modified_iso,
585
+ schema_definition=schema_definition,
586
+ description=description,
587
+ version=loaded_version_num,
588
+ version_count=version_count,
589
+ )
590
+ )
591
+ log.debug(
592
+ "%s Successfully processed artifact info.", log_identifier_item
593
+ )
594
+
595
+ except FileNotFoundError:
596
+ log.warning(
597
+ "%s Artifact file not found by service for key '%s'. Skipping.",
598
+ log_prefix,
599
+ filename,
600
+ )
601
+ except Exception as detail_e:
602
+ log.error(
603
+ "%s Error processing details for artifact '%s': %s\n%s",
604
+ log_prefix,
605
+ filename,
606
+ detail_e,
607
+ traceback.format_exc(),
608
+ )
609
+ artifact_info_list.append(
610
+ ArtifactInfo(
611
+ filename=filename,
612
+ size=0,
613
+ description=f"Error loading details: {detail_e}",
614
+ mime_type="application/octet-stream",
615
+ )
616
+ )
617
+
618
+ except Exception as e:
619
+ log.exception(
620
+ "%s Error listing artifact keys or processing list: %s", log_prefix, e
621
+ )
622
+ return []
623
+ return artifact_info_list
624
+
625
+
626
+ async def load_artifact_content_or_metadata(
627
+ artifact_service: BaseArtifactService,
628
+ app_name: str,
629
+ user_id: str,
630
+ session_id: str,
631
+ filename: str,
632
+ version: Union[int, str],
633
+ load_metadata_only: bool = False,
634
+ return_raw_bytes: bool = False,
635
+ max_content_length: Optional[int] = None,
636
+ component: Optional[Any] = None,
637
+ log_identifier_prefix: str = "[ArtifactHelper:load]",
638
+ encoding: str = "utf-8",
639
+ error_handling: str = "strict",
640
+ ) -> Dict[str, Any]:
641
+ """
642
+ Loads the content or metadata of a specific artifact version using the artifact service.
643
+ """
644
+ log_identifier_req = f"{log_identifier_prefix}:{filename}:{version}"
645
+ log.debug(
646
+ "%s Processing request (load_metadata_only=%s, return_raw_bytes=%s) (async).",
647
+ log_identifier_req,
648
+ load_metadata_only,
649
+ return_raw_bytes,
650
+ )
651
+
652
+ if max_content_length is None and component:
653
+ max_content_length = component.get_config(
654
+ "text_artifact_content_max_length", 1000
655
+ )
656
+ if max_content_length < 100:
657
+ log.warning(
658
+ "%s text_artifact_content_max_length too small (%d), using minimum: 100",
659
+ log_identifier_req,
660
+ max_content_length,
661
+ )
662
+ max_content_length = 100
663
+ elif max_content_length > 100000:
664
+ log.warning(
665
+ "%s text_artifact_content_max_length too large (%d), using maximum: 100000",
666
+ log_identifier_req,
667
+ max_content_length,
668
+ )
669
+ max_content_length = 100000
670
+ elif max_content_length is None:
671
+ max_content_length = 1000
672
+
673
+ log.debug(
674
+ "%s Using max_content_length: %d characters (from %s).",
675
+ log_identifier_req,
676
+ max_content_length,
677
+ "app config" if component else "default",
678
+ )
679
+
680
+ try:
681
+ actual_version: int
682
+ if isinstance(version, str) and version.lower() == "latest":
683
+ log.debug(
684
+ "%s Requested version is 'latest', resolving...", log_identifier_req
685
+ )
686
+ try:
687
+ list_versions_method = getattr(artifact_service, "list_versions")
688
+ available_versions = await list_versions_method(
689
+ app_name=app_name,
690
+ user_id=user_id,
691
+ session_id=session_id,
692
+ filename=filename,
693
+ )
694
+ if not available_versions:
695
+ raise FileNotFoundError(
696
+ f"Artifact '{filename}' has no versions available to determine 'latest'."
697
+ )
698
+ actual_version = max(available_versions)
699
+ log.info(
700
+ "%s Resolved 'latest' to version %d.",
701
+ log_identifier_req,
702
+ actual_version,
703
+ )
704
+ except Exception as list_err:
705
+ log.error(
706
+ "%s Failed to list versions for '%s' to resolve 'latest': %s",
707
+ log_identifier_req,
708
+ filename,
709
+ list_err,
710
+ )
711
+ raise FileNotFoundError(
712
+ f"Could not determine latest version for '{filename}': {list_err}"
713
+ ) from list_err
714
+ elif isinstance(version, int):
715
+ actual_version = version
716
+ elif isinstance(version, str):
717
+ try:
718
+ actual_version = int(version)
719
+ except ValueError:
720
+ raise ValueError(
721
+ f"Invalid version specified: '{version}'. Must be a positive integer string or 'latest'."
722
+ )
723
+ else:
724
+ raise ValueError(
725
+ f"Invalid version type: '{type(version).__name__}'. Must be an integer or 'latest'."
726
+ )
727
+
728
+ if actual_version < 0:
729
+ raise ValueError(
730
+ f"Version number must be a positive integer. Got: {actual_version}"
731
+ )
732
+
733
+ target_filename = (
734
+ f"{filename}{METADATA_SUFFIX}" if load_metadata_only else filename
735
+ )
736
+ version_to_load = actual_version
737
+
738
+ log_identifier = f"{log_identifier_prefix}:{filename}:{version_to_load}"
739
+
740
+ log.debug(
741
+ "%s Attempting to load '%s' v%d (async)",
742
+ log_identifier,
743
+ target_filename,
744
+ version_to_load,
745
+ )
746
+
747
+ load_artifact_method = getattr(artifact_service, "load_artifact")
748
+ artifact_part = await load_artifact_method(
749
+ app_name=app_name,
750
+ user_id=user_id,
751
+ session_id=session_id,
752
+ filename=target_filename,
753
+ version=version_to_load,
754
+ )
755
+
756
+ if not artifact_part or not artifact_part.inline_data:
757
+ raise FileNotFoundError(
758
+ f"Artifact '{target_filename}' version {version_to_load} not found or has no data."
759
+ )
760
+
761
+ mime_type = artifact_part.inline_data.mime_type
762
+ data_bytes = artifact_part.inline_data.data
763
+ size_bytes = len(data_bytes)
764
+
765
+ if load_metadata_only:
766
+ if mime_type != "application/json":
767
+ log.warning(
768
+ "%s Expected metadata file '%s' v%d to be application/json, but got '%s'. Attempting parse anyway.",
769
+ log_identifier,
770
+ target_filename,
771
+ version_to_load,
772
+ mime_type,
773
+ )
774
+ try:
775
+ metadata_dict = json.loads(data_bytes.decode("utf-8"))
776
+ log.info(
777
+ "%s Successfully loaded and parsed metadata for '%s' v%d.",
778
+ log_identifier,
779
+ filename,
780
+ version_to_load,
781
+ )
782
+ return {
783
+ "status": "success",
784
+ "filename": filename,
785
+ "version": version_to_load,
786
+ "metadata": metadata_dict,
787
+ }
788
+
789
+ except (json.JSONDecodeError, UnicodeDecodeError) as parse_err:
790
+ raise ValueError(
791
+ f"Failed to parse metadata file '{target_filename}' v{version_to_load}: {parse_err}"
792
+ ) from parse_err
793
+
794
+ else:
795
+ if return_raw_bytes:
796
+ log.info(
797
+ "%s Loaded artifact '%s' v%d (%d bytes, type: %s). Returning raw_bytes.",
798
+ log_identifier,
799
+ filename,
800
+ version_to_load,
801
+ size_bytes,
802
+ mime_type,
803
+ )
804
+ return {
805
+ "status": "success",
806
+ "filename": filename,
807
+ "version": version_to_load,
808
+ "mime_type": mime_type,
809
+ "raw_bytes": data_bytes,
810
+ "size_bytes": size_bytes,
811
+ }
812
+ else:
813
+ is_text = is_text_based_file(mime_type, data_bytes)
814
+
815
+ if is_text:
816
+ try:
817
+ content_str = data_bytes.decode(encoding, errors=error_handling)
818
+ if len(content_str) > max_content_length:
819
+ truncated_content = content_str[:max_content_length] + "..."
820
+ log.info(
821
+ "%s Loaded and decoded text artifact '%s' v%d. Returning truncated content (%d chars, limit: %d).",
822
+ log_identifier,
823
+ filename,
824
+ version_to_load,
825
+ len(truncated_content),
826
+ max_content_length,
827
+ )
828
+ else:
829
+ truncated_content = content_str
830
+ log.info(
831
+ "%s Loaded and decoded text artifact '%s' v%d. Returning full content (%d chars).",
832
+ log_identifier,
833
+ filename,
834
+ version_to_load,
835
+ len(content_str),
836
+ )
837
+ return {
838
+ "status": "success",
839
+ "filename": filename,
840
+ "version": version_to_load,
841
+ "mime_type": mime_type,
842
+ "content": truncated_content,
843
+ "size_bytes": size_bytes,
844
+ }
845
+ except UnicodeDecodeError as decode_err:
846
+ log.error(
847
+ "%s Failed to decode text artifact '%s' v%d with encoding '%s': %s",
848
+ log_identifier,
849
+ filename,
850
+ version_to_load,
851
+ mime_type,
852
+ decode_err,
853
+ )
854
+ raise ValueError(
855
+ f"Failed to decode artifact '{filename}' v{version_to_load} as {encoding}."
856
+ ) from decode_err
857
+ else:
858
+ log.info(
859
+ "%s Loaded binary/unknown artifact '%s' v%d. Returning metadata summary.",
860
+ log_identifier,
861
+ filename,
862
+ version_to_load,
863
+ )
864
+
865
+ metadata_for_binary = {}
866
+ if not filename.endswith(METADATA_SUFFIX):
867
+ try:
868
+ metadata_filename_for_binary = (
869
+ f"{filename}{METADATA_SUFFIX}"
870
+ )
871
+ log.debug(
872
+ "%s Attempting to load linked metadata file '%s' for binary artifact '%s' v%d.",
873
+ log_identifier,
874
+ metadata_filename_for_binary,
875
+ filename,
876
+ version_to_load,
877
+ )
878
+ metadata_data = await load_artifact_content_or_metadata(
879
+ artifact_service=artifact_service,
880
+ app_name=app_name,
881
+ user_id=user_id,
882
+ session_id=session_id,
883
+ filename=f"{filename}{METADATA_SUFFIX}",
884
+ version=version,
885
+ load_metadata_only=True,
886
+ log_identifier_prefix=f"{log_identifier}[meta_for_binary]",
887
+ )
888
+ if metadata_data.get("status") == "success":
889
+ metadata_for_binary = metadata_data.get("metadata", {})
890
+ except Exception as e_meta_bin:
891
+ log.warning(
892
+ f"{log_identifier} Could not load metadata for binary artifact {filename}: {e_meta_bin}"
893
+ )
894
+ metadata_for_binary = {
895
+ "error": f"Could not load metadata: {e_meta_bin}"
896
+ }
897
+
898
+ return {
899
+ "status": "success",
900
+ "filename": filename,
901
+ "version": version_to_load,
902
+ "mime_type": mime_type,
903
+ "size_bytes": size_bytes,
904
+ "metadata": metadata_for_binary,
905
+ "content": f"Binary data of type {mime_type}. Content not displayed.",
906
+ }
907
+
908
+ except FileNotFoundError as fnf_err:
909
+ log.warning("%s Artifact not found: %s", log_identifier_req, fnf_err)
910
+ return {"status": "not_found", "message": str(fnf_err)}
911
+ except ValueError as val_err:
912
+ log.error(
913
+ "%s Value error during artifact load: %s", log_identifier_req, val_err
914
+ )
915
+ return {"status": "error", "message": str(val_err)}
916
+ except Exception as e:
917
+ log.exception(
918
+ "%s Unexpected error loading artifact '%s' version '%s': %s",
919
+ log_identifier_req,
920
+ filename,
921
+ version,
922
+ e,
923
+ )
924
+ return {
925
+ "status": "error",
926
+ "message": f"Unexpected error loading artifact: {e}",
927
+ }