solace-agent-mesh 0.2.4__py3-none-any.whl → 1.0.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.

Potentially problematic release.


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

Files changed (521) hide show
  1. solace_agent_mesh/__init__.py +5 -0
  2. solace_agent_mesh/agent/adk/adk_llm.txt +93 -0
  3. solace_agent_mesh/agent/adk/app_llm_agent.py +26 -0
  4. solace_agent_mesh/agent/adk/callbacks.py +1716 -0
  5. solace_agent_mesh/agent/adk/filesystem_artifact_service.py +381 -0
  6. solace_agent_mesh/agent/adk/invocation_monitor.py +295 -0
  7. solace_agent_mesh/agent/adk/models/lite_llm.py +872 -0
  8. solace_agent_mesh/agent/adk/models/models_llm.txt +94 -0
  9. solace_agent_mesh/agent/adk/runner.py +357 -0
  10. solace_agent_mesh/agent/adk/services.py +240 -0
  11. solace_agent_mesh/agent/adk/setup.py +751 -0
  12. solace_agent_mesh/agent/adk/stream_parser.py +214 -0
  13. solace_agent_mesh/agent/adk/tool_wrapper.py +139 -0
  14. solace_agent_mesh/agent/agent_llm.txt +41 -0
  15. solace_agent_mesh/agent/protocol/event_handlers.py +1444 -0
  16. solace_agent_mesh/agent/protocol/protocol_llm.txt +21 -0
  17. solace_agent_mesh/agent/sac/app.py +640 -0
  18. solace_agent_mesh/agent/sac/component.py +3496 -0
  19. solace_agent_mesh/agent/sac/patch_adk.py +111 -0
  20. solace_agent_mesh/agent/sac/sac_llm.txt +105 -0
  21. solace_agent_mesh/agent/sac/task_execution_context.py +185 -0
  22. solace_agent_mesh/agent/testing/__init__.py +3 -0
  23. solace_agent_mesh/agent/testing/debug_utils.py +135 -0
  24. solace_agent_mesh/agent/testing/testing_llm.txt +90 -0
  25. solace_agent_mesh/agent/tools/__init__.py +14 -0
  26. solace_agent_mesh/agent/tools/audio_tools.py +1622 -0
  27. solace_agent_mesh/agent/tools/builtin_artifact_tools.py +1954 -0
  28. solace_agent_mesh/agent/tools/builtin_data_analysis_tools.py +238 -0
  29. solace_agent_mesh/agent/tools/general_agent_tools.py +571 -0
  30. solace_agent_mesh/agent/tools/image_tools.py +1184 -0
  31. solace_agent_mesh/agent/tools/peer_agent_tool.py +290 -0
  32. solace_agent_mesh/agent/tools/registry.py +36 -0
  33. solace_agent_mesh/agent/tools/test_tools.py +135 -0
  34. solace_agent_mesh/agent/tools/tool_definition.py +45 -0
  35. solace_agent_mesh/agent/tools/tools_llm.txt +104 -0
  36. solace_agent_mesh/agent/tools/web_tools.py +381 -0
  37. solace_agent_mesh/agent/utils/artifact_helpers.py +927 -0
  38. solace_agent_mesh/agent/utils/config_parser.py +47 -0
  39. solace_agent_mesh/agent/utils/context_helpers.py +60 -0
  40. solace_agent_mesh/agent/utils/utils_llm.txt +153 -0
  41. solace_agent_mesh/assets/docs/404.html +16 -0
  42. solace_agent_mesh/assets/docs/assets/css/styles.906a1503.css +1 -0
  43. solace_agent_mesh/assets/docs/assets/images/Solace_AI_Framework_With_Broker-85f0a306a9bcdd20b390b7a949f6d862.png +0 -0
  44. solace_agent_mesh/assets/docs/assets/images/sac-flows-80d5b603c6aafd33e87945680ce0abf3.png +0 -0
  45. solace_agent_mesh/assets/docs/assets/images/sac_parts_of_a_component-cb3d0424b1d0c17734c5435cca6b4082.png +0 -0
  46. solace_agent_mesh/assets/docs/assets/js/04989206.674a8007.js +1 -0
  47. solace_agent_mesh/assets/docs/assets/js/0e682baa.79f0ab22.js +1 -0
  48. solace_agent_mesh/assets/docs/assets/js/1001.0182a8bd.js +1 -0
  49. solace_agent_mesh/assets/docs/assets/js/1023fc19.015679ca.js +1 -0
  50. solace_agent_mesh/assets/docs/assets/js/1039.0bd46aa1.js +1 -0
  51. solace_agent_mesh/assets/docs/assets/js/149.b797a808.js +1 -0
  52. solace_agent_mesh/assets/docs/assets/js/1523c6b4.91c7bc01.js +1 -0
  53. solace_agent_mesh/assets/docs/assets/js/165.6a39807d.js +2 -0
  54. solace_agent_mesh/assets/docs/assets/js/165.6a39807d.js.LICENSE.txt +9 -0
  55. solace_agent_mesh/assets/docs/assets/js/166ab619.7d97ccaf.js +1 -0
  56. solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js +2 -0
  57. solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js.LICENSE.txt +7 -0
  58. solace_agent_mesh/assets/docs/assets/js/1c6e87d2.a8c5ce5a.js +1 -0
  59. solace_agent_mesh/assets/docs/assets/js/2130.ab9fd314.js +1 -0
  60. solace_agent_mesh/assets/docs/assets/js/21ceee5f.614fa8dd.js +1 -0
  61. solace_agent_mesh/assets/docs/assets/js/2237.5e477fc6.js +1 -0
  62. solace_agent_mesh/assets/docs/assets/js/2334.622a6395.js +1 -0
  63. solace_agent_mesh/assets/docs/assets/js/2a9cab12.8909df92.js +1 -0
  64. solace_agent_mesh/assets/docs/assets/js/3219.adc1d663.js +1 -0
  65. solace_agent_mesh/assets/docs/assets/js/332e10b5.7a103f42.js +1 -0
  66. solace_agent_mesh/assets/docs/assets/js/3624.b524e433.js +1 -0
  67. solace_agent_mesh/assets/docs/assets/js/375.708d48db.js +1 -0
  68. solace_agent_mesh/assets/docs/assets/js/3834.b6cd790e.js +1 -0
  69. solace_agent_mesh/assets/docs/assets/js/3d406171.f722eaf5.js +1 -0
  70. solace_agent_mesh/assets/docs/assets/js/4250.95455b28.js +1 -0
  71. solace_agent_mesh/assets/docs/assets/js/42b3f8d8.36090198.js +1 -0
  72. solace_agent_mesh/assets/docs/assets/js/4356.d169ab5b.js +1 -0
  73. solace_agent_mesh/assets/docs/assets/js/442a8107.5ba94b65.js +1 -0
  74. solace_agent_mesh/assets/docs/assets/js/4458.518e66fa.js +1 -0
  75. solace_agent_mesh/assets/docs/assets/js/4488.c7cc3442.js +1 -0
  76. solace_agent_mesh/assets/docs/assets/js/4494.6ee23046.js +1 -0
  77. solace_agent_mesh/assets/docs/assets/js/4855.fc4444b6.js +1 -0
  78. solace_agent_mesh/assets/docs/assets/js/4866.22daefc0.js +1 -0
  79. solace_agent_mesh/assets/docs/assets/js/4950.ca4caeda.js +1 -0
  80. solace_agent_mesh/assets/docs/assets/js/4c2787c2.66ee00e9.js +1 -0
  81. solace_agent_mesh/assets/docs/assets/js/5388.7a136447.js +1 -0
  82. solace_agent_mesh/assets/docs/assets/js/55f47984.c484bf96.js +1 -0
  83. solace_agent_mesh/assets/docs/assets/js/5607.081356f8.js +1 -0
  84. solace_agent_mesh/assets/docs/assets/js/5864.b0d0e9de.js +1 -0
  85. solace_agent_mesh/assets/docs/assets/js/5b4258a4.bda20761.js +1 -0
  86. solace_agent_mesh/assets/docs/assets/js/5e95c892.558d5167.js +1 -0
  87. solace_agent_mesh/assets/docs/assets/js/6143.0a1464c9.js +1 -0
  88. solace_agent_mesh/assets/docs/assets/js/6395.e9c73649.js +1 -0
  89. solace_agent_mesh/assets/docs/assets/js/6796.51d2c9b7.js +1 -0
  90. solace_agent_mesh/assets/docs/assets/js/6976.379be23b.js +1 -0
  91. solace_agent_mesh/assets/docs/assets/js/6978.ee0b945c.js +1 -0
  92. solace_agent_mesh/assets/docs/assets/js/7040.cb436723.js +1 -0
  93. solace_agent_mesh/assets/docs/assets/js/7195.412f418a.js +1 -0
  94. solace_agent_mesh/assets/docs/assets/js/7280.3fb73bdb.js +1 -0
  95. solace_agent_mesh/assets/docs/assets/js/768e31b0.a12673db.js +1 -0
  96. solace_agent_mesh/assets/docs/assets/js/7845.e33e7c4c.js +1 -0
  97. solace_agent_mesh/assets/docs/assets/js/7900.69516146.js +1 -0
  98. solace_agent_mesh/assets/docs/assets/js/8356.8a379c04.js +1 -0
  99. solace_agent_mesh/assets/docs/assets/js/85387663.6bf41934.js +1 -0
  100. solace_agent_mesh/assets/docs/assets/js/8567.4732c6b7.js +1 -0
  101. solace_agent_mesh/assets/docs/assets/js/8573.cb04eda5.js +1 -0
  102. solace_agent_mesh/assets/docs/assets/js/8577.1d54e766.js +1 -0
  103. solace_agent_mesh/assets/docs/assets/js/8591.d7c16be6.js +2 -0
  104. solace_agent_mesh/assets/docs/assets/js/8591.d7c16be6.js.LICENSE.txt +61 -0
  105. solace_agent_mesh/assets/docs/assets/js/8709.7ecd4047.js +1 -0
  106. solace_agent_mesh/assets/docs/assets/js/8731.49e930c2.js +1 -0
  107. solace_agent_mesh/assets/docs/assets/js/8908.f9d1b506.js +1 -0
  108. solace_agent_mesh/assets/docs/assets/js/9157.b4093d07.js +1 -0
  109. solace_agent_mesh/assets/docs/assets/js/9278.a4fd875d.js +1 -0
  110. solace_agent_mesh/assets/docs/assets/js/945fb41e.74d728aa.js +1 -0
  111. solace_agent_mesh/assets/docs/assets/js/9616.b75c2f6d.js +1 -0
  112. solace_agent_mesh/assets/docs/assets/js/9793.c6d16376.js +1 -0
  113. solace_agent_mesh/assets/docs/assets/js/9eff14a2.1bf8f61c.js +1 -0
  114. solace_agent_mesh/assets/docs/assets/js/a3a92b25.26ca071f.js +1 -0
  115. solace_agent_mesh/assets/docs/assets/js/a7bd4aaa.2204d2f7.js +1 -0
  116. solace_agent_mesh/assets/docs/assets/js/a94703ab.0438dbc2.js +1 -0
  117. solace_agent_mesh/assets/docs/assets/js/aba21aa0.c42a534c.js +1 -0
  118. solace_agent_mesh/assets/docs/assets/js/aba87c2f.d3e2dcc3.js +1 -0
  119. solace_agent_mesh/assets/docs/assets/js/ae4415af.8e279b5d.js +1 -0
  120. solace_agent_mesh/assets/docs/assets/js/b7006a3a.40b10c9d.js +1 -0
  121. solace_agent_mesh/assets/docs/assets/js/bac0be12.f50d9bac.js +1 -0
  122. solace_agent_mesh/assets/docs/assets/js/bb2ef573.207e6990.js +1 -0
  123. solace_agent_mesh/assets/docs/assets/js/c2c06897.63b76e9e.js +1 -0
  124. solace_agent_mesh/assets/docs/assets/js/cc969b05.954186d4.js +1 -0
  125. solace_agent_mesh/assets/docs/assets/js/cd3d4052.ca6eed8c.js +1 -0
  126. solace_agent_mesh/assets/docs/assets/js/ced92a13.fb92e7ca.js +1 -0
  127. solace_agent_mesh/assets/docs/assets/js/cee5d587.f5b73ca1.js +1 -0
  128. solace_agent_mesh/assets/docs/assets/js/f284c35a.ecc3d195.js +1 -0
  129. solace_agent_mesh/assets/docs/assets/js/f897a61a.f8c53b0f.js +1 -0
  130. solace_agent_mesh/assets/docs/assets/js/fbfa3e75.aca209c9.js +1 -0
  131. solace_agent_mesh/assets/docs/assets/js/main.c6286d7c.js +2 -0
  132. solace_agent_mesh/assets/docs/assets/js/main.c6286d7c.js.LICENSE.txt +81 -0
  133. solace_agent_mesh/assets/docs/assets/js/runtime~main.d5133813.js +1 -0
  134. solace_agent_mesh/assets/docs/docs/documentation/concepts/agents/index.html +128 -0
  135. solace_agent_mesh/assets/docs/docs/documentation/concepts/architecture/index.html +91 -0
  136. solace_agent_mesh/assets/docs/docs/documentation/concepts/cli/index.html +201 -0
  137. solace_agent_mesh/assets/docs/docs/documentation/concepts/gateways/index.html +91 -0
  138. solace_agent_mesh/assets/docs/docs/documentation/concepts/orchestrator/index.html +55 -0
  139. solace_agent_mesh/assets/docs/docs/documentation/concepts/plugins/index.html +82 -0
  140. solace_agent_mesh/assets/docs/docs/documentation/deployment/debugging/index.html +77 -0
  141. solace_agent_mesh/assets/docs/docs/documentation/deployment/deploy/index.html +48 -0
  142. solace_agent_mesh/assets/docs/docs/documentation/deployment/observability/index.html +54 -0
  143. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +17 -0
  144. solace_agent_mesh/assets/docs/docs/documentation/getting-started/component-overview/index.html +45 -0
  145. solace_agent_mesh/assets/docs/docs/documentation/getting-started/installation/index.html +76 -0
  146. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +150 -0
  147. solace_agent_mesh/assets/docs/docs/documentation/getting-started/quick-start/index.html +54 -0
  148. solace_agent_mesh/assets/docs/docs/documentation/tutorials/bedrock-agents/index.html +267 -0
  149. solace_agent_mesh/assets/docs/docs/documentation/tutorials/custom-agent/index.html +136 -0
  150. solace_agent_mesh/assets/docs/docs/documentation/tutorials/event-mesh-gateway/index.html +116 -0
  151. solace_agent_mesh/assets/docs/docs/documentation/tutorials/mcp-integration/index.html +80 -0
  152. solace_agent_mesh/assets/docs/docs/documentation/tutorials/mongodb-integration/index.html +164 -0
  153. solace_agent_mesh/assets/docs/docs/documentation/tutorials/rest-gateway/index.html +57 -0
  154. solace_agent_mesh/assets/docs/docs/documentation/tutorials/slack-integration/index.html +72 -0
  155. solace_agent_mesh/assets/docs/docs/documentation/tutorials/sql-database/index.html +102 -0
  156. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/artifact-management/index.html +99 -0
  157. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/audio-tools/index.html +90 -0
  158. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/data-analysis-tools/index.html +107 -0
  159. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/embeds/index.html +152 -0
  160. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/index.html +103 -0
  161. solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-agents/index.html +170 -0
  162. solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-gateways/index.html +200 -0
  163. solace_agent_mesh/assets/docs/docs/documentation/user-guide/creating-service-providers/index.html +54 -0
  164. solace_agent_mesh/assets/docs/docs/documentation/user-guide/solace-ai-connector/index.html +69 -0
  165. solace_agent_mesh/assets/docs/docs/documentation/user-guide/structure/index.html +59 -0
  166. solace_agent_mesh/assets/docs/img/Solace_AI_Framework_README.png +0 -0
  167. solace_agent_mesh/assets/docs/img/Solace_AI_Framework_With_Broker.png +0 -0
  168. solace_agent_mesh/assets/docs/img/logo.png +0 -0
  169. solace_agent_mesh/assets/docs/img/sac-flows.png +0 -0
  170. solace_agent_mesh/assets/docs/img/sac_parts_of_a_component.png +0 -0
  171. solace_agent_mesh/assets/docs/img/solace-logo.png +0 -0
  172. solace_agent_mesh/assets/docs/lunr-index-1754075282978.json +1 -0
  173. solace_agent_mesh/assets/docs/lunr-index.json +1 -0
  174. solace_agent_mesh/assets/docs/search-doc-1754075282978.json +1 -0
  175. solace_agent_mesh/assets/docs/search-doc.json +1 -0
  176. solace_agent_mesh/assets/docs/sitemap.xml +1 -0
  177. solace_agent_mesh/cli/__init__.py +1 -1
  178. solace_agent_mesh/cli/commands/add_cmd/__init__.py +15 -0
  179. solace_agent_mesh/cli/commands/add_cmd/add_cmd_llm.txt +250 -0
  180. solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +659 -0
  181. solace_agent_mesh/cli/commands/add_cmd/gateway_cmd.py +322 -0
  182. solace_agent_mesh/cli/commands/add_cmd/web_add_agent_step.py +93 -0
  183. solace_agent_mesh/cli/commands/add_cmd/web_add_gateway_step.py +118 -0
  184. solace_agent_mesh/cli/commands/docs_cmd.py +57 -0
  185. solace_agent_mesh/cli/commands/eval_cmd.py +64 -0
  186. solace_agent_mesh/cli/commands/init_cmd/__init__.py +404 -0
  187. solace_agent_mesh/cli/commands/init_cmd/broker_step.py +201 -0
  188. solace_agent_mesh/cli/commands/init_cmd/directory_step.py +28 -0
  189. solace_agent_mesh/cli/commands/init_cmd/env_step.py +205 -0
  190. solace_agent_mesh/cli/commands/init_cmd/init_cmd_llm.txt +365 -0
  191. solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +407 -0
  192. solace_agent_mesh/cli/commands/init_cmd/project_files_step.py +38 -0
  193. solace_agent_mesh/cli/commands/init_cmd/web_init_step.py +110 -0
  194. solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +183 -0
  195. solace_agent_mesh/cli/commands/plugin_cmd/__init__.py +18 -0
  196. solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +372 -0
  197. solace_agent_mesh/cli/commands/plugin_cmd/build_cmd.py +86 -0
  198. solace_agent_mesh/cli/commands/plugin_cmd/catalog_cmd.py +139 -0
  199. solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +309 -0
  200. solace_agent_mesh/cli/commands/plugin_cmd/official_registry.py +175 -0
  201. solace_agent_mesh/cli/commands/plugin_cmd/plugin_cmd_llm.txt +305 -0
  202. solace_agent_mesh/cli/commands/run_cmd.py +158 -0
  203. solace_agent_mesh/cli/main.py +17 -294
  204. solace_agent_mesh/cli/utils.py +135 -204
  205. solace_agent_mesh/client/webui/frontend/static/assets/authCallback-DvlO62me.js +1 -0
  206. solace_agent_mesh/client/webui/frontend/static/assets/client-bp6u3qVZ.js +49 -0
  207. solace_agent_mesh/client/webui/frontend/static/assets/favicon-BLgzUch9.ico +0 -0
  208. solace_agent_mesh/client/webui/frontend/static/assets/main-D11Lmy9p.css +1 -0
  209. solace_agent_mesh/client/webui/frontend/static/assets/main-Gfk3BYn5.js +663 -0
  210. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +14 -0
  211. solace_agent_mesh/client/webui/frontend/static/index.html +15 -0
  212. solace_agent_mesh/common/__init__.py +1 -0
  213. solace_agent_mesh/common/a2a_protocol.py +564 -0
  214. solace_agent_mesh/common/agent_registry.py +42 -0
  215. solace_agent_mesh/common/client/__init__.py +4 -0
  216. solace_agent_mesh/common/client/card_resolver.py +21 -0
  217. solace_agent_mesh/common/client/client.py +85 -0
  218. solace_agent_mesh/common/client/client_llm.txt +133 -0
  219. solace_agent_mesh/common/common_llm.txt +144 -0
  220. solace_agent_mesh/common/constants.py +1 -14
  221. solace_agent_mesh/common/middleware/__init__.py +12 -0
  222. solace_agent_mesh/common/middleware/config_resolver.py +130 -0
  223. solace_agent_mesh/common/middleware/middleware_llm.txt +174 -0
  224. solace_agent_mesh/common/middleware/registry.py +125 -0
  225. solace_agent_mesh/common/server/__init__.py +4 -0
  226. solace_agent_mesh/common/server/server.py +122 -0
  227. solace_agent_mesh/common/server/server_llm.txt +169 -0
  228. solace_agent_mesh/common/server/task_manager.py +291 -0
  229. solace_agent_mesh/common/server/utils.py +28 -0
  230. solace_agent_mesh/common/services/__init__.py +4 -0
  231. solace_agent_mesh/common/services/employee_service.py +162 -0
  232. solace_agent_mesh/common/services/identity_service.py +129 -0
  233. solace_agent_mesh/common/services/providers/__init__.py +4 -0
  234. solace_agent_mesh/common/services/providers/local_file_identity_service.py +148 -0
  235. solace_agent_mesh/common/services/providers/providers_llm.txt +113 -0
  236. solace_agent_mesh/common/services/services_llm.txt +132 -0
  237. solace_agent_mesh/common/types.py +411 -0
  238. solace_agent_mesh/common/utils/__init__.py +7 -0
  239. solace_agent_mesh/common/utils/asyncio_macos_fix.py +86 -0
  240. solace_agent_mesh/common/utils/embeds/__init__.py +33 -0
  241. solace_agent_mesh/common/utils/embeds/constants.py +55 -0
  242. solace_agent_mesh/common/utils/embeds/converter.py +452 -0
  243. solace_agent_mesh/common/utils/embeds/embeds_llm.txt +124 -0
  244. solace_agent_mesh/common/utils/embeds/evaluators.py +394 -0
  245. solace_agent_mesh/common/utils/embeds/modifiers.py +816 -0
  246. solace_agent_mesh/common/utils/embeds/resolver.py +865 -0
  247. solace_agent_mesh/common/utils/embeds/types.py +14 -0
  248. solace_agent_mesh/common/utils/in_memory_cache.py +108 -0
  249. solace_agent_mesh/common/utils/initializer.py +51 -0
  250. solace_agent_mesh/common/utils/log_formatters.py +44 -0
  251. solace_agent_mesh/common/utils/mime_helpers.py +106 -0
  252. solace_agent_mesh/common/utils/push_notification_auth.py +134 -0
  253. solace_agent_mesh/common/utils/utils_llm.txt +67 -0
  254. solace_agent_mesh/config_portal/backend/common.py +66 -24
  255. solace_agent_mesh/config_portal/backend/plugin_catalog/constants.py +24 -0
  256. solace_agent_mesh/config_portal/backend/plugin_catalog/models.py +49 -0
  257. solace_agent_mesh/config_portal/backend/plugin_catalog/registry_manager.py +164 -0
  258. solace_agent_mesh/config_portal/backend/plugin_catalog/scraper.py +521 -0
  259. solace_agent_mesh/config_portal/backend/plugin_catalog_server.py +217 -0
  260. solace_agent_mesh/config_portal/backend/server.py +551 -181
  261. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-_7yox_eh.js +48 -0
  262. solace_agent_mesh/config_portal/frontend/static/client/assets/components-B7lKcHVY.js +140 -0
  263. solace_agent_mesh/config_portal/frontend/static/client/assets/{entry.client-DX1misIU.js → entry.client-CEumGClk.js} +3 -3
  264. solace_agent_mesh/config_portal/frontend/static/client/assets/index-DSo1AH_7.js +68 -0
  265. solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-e5c3acfe.js +1 -0
  266. solace_agent_mesh/config_portal/frontend/static/client/assets/{root-BApq5dPK.js → root-C4XmHinv.js} +2 -2
  267. solace_agent_mesh/config_portal/frontend/static/client/assets/root-DxRwaWiE.css +1 -0
  268. solace_agent_mesh/config_portal/frontend/static/client/index.html +3 -3
  269. solace_agent_mesh/core_a2a/__init__.py +1 -0
  270. solace_agent_mesh/core_a2a/core_a2a_llm.txt +88 -0
  271. solace_agent_mesh/core_a2a/service.py +331 -0
  272. solace_agent_mesh/evaluation/config_loader.py +657 -0
  273. solace_agent_mesh/evaluation/evaluator.py +667 -0
  274. solace_agent_mesh/evaluation/message_organizer.py +568 -0
  275. solace_agent_mesh/evaluation/report/benchmark_info.html +35 -0
  276. solace_agent_mesh/evaluation/report/chart_section.html +141 -0
  277. solace_agent_mesh/evaluation/report/detailed_breakdown.html +28 -0
  278. solace_agent_mesh/evaluation/report/modal.html +59 -0
  279. solace_agent_mesh/evaluation/report/modal_chart_functions.js +411 -0
  280. solace_agent_mesh/evaluation/report/modal_script.js +296 -0
  281. solace_agent_mesh/evaluation/report/modal_styles.css +340 -0
  282. solace_agent_mesh/evaluation/report/performance_metrics_styles.css +93 -0
  283. solace_agent_mesh/evaluation/report/templates/footer.html +2 -0
  284. solace_agent_mesh/evaluation/report/templates/header.html +340 -0
  285. solace_agent_mesh/evaluation/report_data_processor.py +972 -0
  286. solace_agent_mesh/evaluation/report_generator.py +613 -0
  287. solace_agent_mesh/evaluation/run.py +613 -0
  288. solace_agent_mesh/evaluation/subscriber.py +872 -0
  289. solace_agent_mesh/evaluation/summary_builder.py +775 -0
  290. solace_agent_mesh/evaluation/test_case_loader.py +714 -0
  291. solace_agent_mesh/gateway/base/__init__.py +1 -0
  292. solace_agent_mesh/gateway/base/app.py +266 -0
  293. solace_agent_mesh/gateway/base/base_llm.txt +119 -0
  294. solace_agent_mesh/gateway/base/component.py +1542 -0
  295. solace_agent_mesh/gateway/base/task_context.py +74 -0
  296. solace_agent_mesh/gateway/gateway_llm.txt +125 -0
  297. solace_agent_mesh/gateway/http_sse/app.py +190 -0
  298. solace_agent_mesh/gateway/http_sse/component.py +1602 -0
  299. solace_agent_mesh/gateway/http_sse/components/__init__.py +7 -0
  300. solace_agent_mesh/gateway/http_sse/components/components_llm.txt +65 -0
  301. solace_agent_mesh/gateway/http_sse/components/visualization_forwarder_component.py +108 -0
  302. solace_agent_mesh/gateway/http_sse/dependencies.py +316 -0
  303. solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +63 -0
  304. solace_agent_mesh/gateway/http_sse/main.py +442 -0
  305. solace_agent_mesh/gateway/http_sse/routers/__init__.py +4 -0
  306. solace_agent_mesh/gateway/http_sse/routers/agents.py +41 -0
  307. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +827 -0
  308. solace_agent_mesh/gateway/http_sse/routers/auth.py +212 -0
  309. solace_agent_mesh/gateway/http_sse/routers/config.py +55 -0
  310. solace_agent_mesh/gateway/http_sse/routers/people.py +69 -0
  311. solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +37 -0
  312. solace_agent_mesh/gateway/http_sse/routers/sessions.py +80 -0
  313. solace_agent_mesh/gateway/http_sse/routers/sse.py +138 -0
  314. solace_agent_mesh/gateway/http_sse/routers/tasks.py +294 -0
  315. solace_agent_mesh/gateway/http_sse/routers/users.py +59 -0
  316. solace_agent_mesh/gateway/http_sse/routers/visualization.py +1131 -0
  317. solace_agent_mesh/gateway/http_sse/services/__init__.py +4 -0
  318. solace_agent_mesh/gateway/http_sse/services/agent_service.py +69 -0
  319. solace_agent_mesh/gateway/http_sse/services/people_service.py +158 -0
  320. solace_agent_mesh/gateway/http_sse/services/services_llm.txt +179 -0
  321. solace_agent_mesh/gateway/http_sse/services/task_service.py +121 -0
  322. solace_agent_mesh/gateway/http_sse/session_manager.py +187 -0
  323. solace_agent_mesh/gateway/http_sse/sse_manager.py +328 -0
  324. solace_agent_mesh/llm.txt +228 -0
  325. solace_agent_mesh/llm_detail.txt +2835 -0
  326. solace_agent_mesh/templates/agent_template.yaml +53 -0
  327. solace_agent_mesh/templates/eval_backend_template.yaml +54 -0
  328. solace_agent_mesh/templates/gateway_app_template.py +73 -0
  329. solace_agent_mesh/templates/gateway_component_template.py +431 -0
  330. solace_agent_mesh/templates/gateway_config_template.yaml +43 -0
  331. solace_agent_mesh/templates/logging_config_template.ini +64 -0
  332. solace_agent_mesh/templates/main_orchestrator.yaml +55 -0
  333. solace_agent_mesh/templates/plugin_agent_config_template.yaml +122 -0
  334. solace_agent_mesh/templates/plugin_custom_config_template.yaml +27 -0
  335. solace_agent_mesh/templates/plugin_custom_template.py +10 -0
  336. solace_agent_mesh/templates/plugin_gateway_config_template.yaml +63 -0
  337. solace_agent_mesh/templates/plugin_pyproject_template.toml +33 -0
  338. solace_agent_mesh/templates/plugin_readme_template.md +34 -0
  339. solace_agent_mesh/templates/plugin_tools_template.py +224 -0
  340. solace_agent_mesh/templates/shared_config.yaml +66 -0
  341. solace_agent_mesh/templates/templates_llm.txt +147 -0
  342. solace_agent_mesh/templates/webui.yaml +53 -0
  343. solace_agent_mesh-1.0.2.dist-info/METADATA +432 -0
  344. solace_agent_mesh-1.0.2.dist-info/RECORD +361 -0
  345. solace_agent_mesh-1.0.2.dist-info/entry_points.txt +3 -0
  346. {solace_agent_mesh-0.2.4.dist-info → solace_agent_mesh-1.0.2.dist-info}/licenses/LICENSE +1 -1
  347. solace_agent_mesh/agents/base_agent_component.py +0 -256
  348. solace_agent_mesh/agents/global/actions/agent_state_change.py +0 -54
  349. solace_agent_mesh/agents/global/actions/clear_history.py +0 -32
  350. solace_agent_mesh/agents/global/actions/convert_file_to_markdown.py +0 -160
  351. solace_agent_mesh/agents/global/actions/create_file.py +0 -70
  352. solace_agent_mesh/agents/global/actions/error_action.py +0 -45
  353. solace_agent_mesh/agents/global/actions/plantuml_diagram.py +0 -163
  354. solace_agent_mesh/agents/global/actions/plotly_graph.py +0 -152
  355. solace_agent_mesh/agents/global/actions/retrieve_file.py +0 -51
  356. solace_agent_mesh/agents/global/global_agent_component.py +0 -38
  357. solace_agent_mesh/agents/image_processing/actions/create_image.py +0 -75
  358. solace_agent_mesh/agents/image_processing/actions/describe_image.py +0 -115
  359. solace_agent_mesh/agents/image_processing/image_processing_agent_component.py +0 -23
  360. solace_agent_mesh/agents/slack/__init__.py +0 -1
  361. solace_agent_mesh/agents/slack/actions/__init__.py +0 -1
  362. solace_agent_mesh/agents/slack/actions/post_message.py +0 -177
  363. solace_agent_mesh/agents/slack/slack_agent_component.py +0 -59
  364. solace_agent_mesh/agents/web_request/actions/do_image_search.py +0 -84
  365. solace_agent_mesh/agents/web_request/actions/do_news_search.py +0 -47
  366. solace_agent_mesh/agents/web_request/actions/do_suggestion_search.py +0 -34
  367. solace_agent_mesh/agents/web_request/actions/do_web_request.py +0 -135
  368. solace_agent_mesh/agents/web_request/actions/download_file.py +0 -69
  369. solace_agent_mesh/agents/web_request/web_request_agent_component.py +0 -33
  370. solace_agent_mesh/assets/web-visualizer/assets/index-D0qORgkg.css +0 -1
  371. solace_agent_mesh/assets/web-visualizer/assets/index-DnDr1pnu.js +0 -109
  372. solace_agent_mesh/assets/web-visualizer/index.html +0 -14
  373. solace_agent_mesh/assets/web-visualizer/vite.svg +0 -1
  374. solace_agent_mesh/cli/commands/add/__init__.py +0 -3
  375. solace_agent_mesh/cli/commands/add/add.py +0 -88
  376. solace_agent_mesh/cli/commands/add/agent.py +0 -110
  377. solace_agent_mesh/cli/commands/add/copy_from_plugin.py +0 -92
  378. solace_agent_mesh/cli/commands/add/gateway.py +0 -374
  379. solace_agent_mesh/cli/commands/build.py +0 -670
  380. solace_agent_mesh/cli/commands/chat/__init__.py +0 -3
  381. solace_agent_mesh/cli/commands/chat/chat.py +0 -361
  382. solace_agent_mesh/cli/commands/config.py +0 -29
  383. solace_agent_mesh/cli/commands/init/__init__.py +0 -3
  384. solace_agent_mesh/cli/commands/init/ai_provider_step.py +0 -93
  385. solace_agent_mesh/cli/commands/init/broker_step.py +0 -99
  386. solace_agent_mesh/cli/commands/init/builtin_agent_step.py +0 -83
  387. solace_agent_mesh/cli/commands/init/check_if_already_done.py +0 -13
  388. solace_agent_mesh/cli/commands/init/create_config_file_step.py +0 -65
  389. solace_agent_mesh/cli/commands/init/create_other_project_files_step.py +0 -147
  390. solace_agent_mesh/cli/commands/init/file_service_step.py +0 -73
  391. solace_agent_mesh/cli/commands/init/init.py +0 -92
  392. solace_agent_mesh/cli/commands/init/project_structure_step.py +0 -16
  393. solace_agent_mesh/cli/commands/init/web_init_step.py +0 -32
  394. solace_agent_mesh/cli/commands/plugin/__init__.py +0 -3
  395. solace_agent_mesh/cli/commands/plugin/add.py +0 -100
  396. solace_agent_mesh/cli/commands/plugin/build.py +0 -268
  397. solace_agent_mesh/cli/commands/plugin/create.py +0 -117
  398. solace_agent_mesh/cli/commands/plugin/plugin.py +0 -124
  399. solace_agent_mesh/cli/commands/plugin/remove.py +0 -73
  400. solace_agent_mesh/cli/commands/run.py +0 -68
  401. solace_agent_mesh/cli/commands/visualizer.py +0 -138
  402. solace_agent_mesh/cli/config.py +0 -85
  403. solace_agent_mesh/common/action.py +0 -91
  404. solace_agent_mesh/common/action_list.py +0 -37
  405. solace_agent_mesh/common/action_response.py +0 -340
  406. solace_agent_mesh/common/mysql_database.py +0 -40
  407. solace_agent_mesh/common/postgres_database.py +0 -85
  408. solace_agent_mesh/common/prompt_templates.py +0 -28
  409. solace_agent_mesh/common/stimulus_utils.py +0 -152
  410. solace_agent_mesh/common/time.py +0 -24
  411. solace_agent_mesh/common/utils.py +0 -712
  412. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-a-zJ6rLx.js +0 -46
  413. solace_agent_mesh/config_portal/frontend/static/client/assets/components-ZIfdTbrV.js +0 -191
  414. solace_agent_mesh/config_portal/frontend/static/client/assets/index-BJHAE5s4.js +0 -17
  415. solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-44c41103.js +0 -1
  416. solace_agent_mesh/config_portal/frontend/static/client/assets/root-DX4gQ516.css +0 -1
  417. solace_agent_mesh/configs/agent_global.yaml +0 -74
  418. solace_agent_mesh/configs/agent_image_processing.yaml +0 -82
  419. solace_agent_mesh/configs/agent_slack.yaml +0 -64
  420. solace_agent_mesh/configs/agent_web_request.yaml +0 -75
  421. solace_agent_mesh/configs/conversation_to_file.yaml +0 -56
  422. solace_agent_mesh/configs/error_catcher.yaml +0 -56
  423. solace_agent_mesh/configs/monitor.yaml +0 -0
  424. solace_agent_mesh/configs/monitor_stim_and_errors_to_slack.yaml +0 -109
  425. solace_agent_mesh/configs/monitor_user_feedback.yaml +0 -58
  426. solace_agent_mesh/configs/orchestrator.yaml +0 -241
  427. solace_agent_mesh/configs/service_embedding.yaml +0 -81
  428. solace_agent_mesh/configs/service_llm.yaml +0 -265
  429. solace_agent_mesh/configs/visualize_websocket.yaml +0 -55
  430. solace_agent_mesh/gateway/components/gateway_base.py +0 -47
  431. solace_agent_mesh/gateway/components/gateway_input.py +0 -278
  432. solace_agent_mesh/gateway/components/gateway_output.py +0 -298
  433. solace_agent_mesh/gateway/identity/bamboohr_identity.py +0 -18
  434. solace_agent_mesh/gateway/identity/identity_base.py +0 -10
  435. solace_agent_mesh/gateway/identity/identity_provider.py +0 -60
  436. solace_agent_mesh/gateway/identity/no_identity.py +0 -9
  437. solace_agent_mesh/gateway/identity/passthru_identity.py +0 -9
  438. solace_agent_mesh/monitors/base_monitor_component.py +0 -26
  439. solace_agent_mesh/monitors/feedback/user_feedback_monitor.py +0 -75
  440. solace_agent_mesh/monitors/stim_and_errors/stim_and_error_monitor.py +0 -560
  441. solace_agent_mesh/orchestrator/__init__.py +0 -0
  442. solace_agent_mesh/orchestrator/action_manager.py +0 -237
  443. solace_agent_mesh/orchestrator/components/__init__.py +0 -0
  444. solace_agent_mesh/orchestrator/components/orchestrator_action_manager_timeout_component.py +0 -58
  445. solace_agent_mesh/orchestrator/components/orchestrator_action_response_component.py +0 -179
  446. solace_agent_mesh/orchestrator/components/orchestrator_register_component.py +0 -107
  447. solace_agent_mesh/orchestrator/components/orchestrator_stimulus_processor_component.py +0 -527
  448. solace_agent_mesh/orchestrator/components/orchestrator_streaming_output_component.py +0 -260
  449. solace_agent_mesh/orchestrator/orchestrator_main.py +0 -172
  450. solace_agent_mesh/orchestrator/orchestrator_prompt.py +0 -539
  451. solace_agent_mesh/services/__init__.py +0 -0
  452. solace_agent_mesh/services/authorization/providers/base_authorization_provider.py +0 -56
  453. solace_agent_mesh/services/bamboo_hr_service/__init__.py +0 -3
  454. solace_agent_mesh/services/bamboo_hr_service/bamboo_hr.py +0 -182
  455. solace_agent_mesh/services/common/__init__.py +0 -4
  456. solace_agent_mesh/services/common/auto_expiry.py +0 -45
  457. solace_agent_mesh/services/common/singleton.py +0 -18
  458. solace_agent_mesh/services/file_service/__init__.py +0 -14
  459. solace_agent_mesh/services/file_service/file_manager/__init__.py +0 -0
  460. solace_agent_mesh/services/file_service/file_manager/bucket_file_manager.py +0 -149
  461. solace_agent_mesh/services/file_service/file_manager/file_manager_base.py +0 -162
  462. solace_agent_mesh/services/file_service/file_manager/memory_file_manager.py +0 -64
  463. solace_agent_mesh/services/file_service/file_manager/volume_file_manager.py +0 -106
  464. solace_agent_mesh/services/file_service/file_service.py +0 -437
  465. solace_agent_mesh/services/file_service/file_service_constants.py +0 -54
  466. solace_agent_mesh/services/file_service/file_transformations.py +0 -141
  467. solace_agent_mesh/services/file_service/file_utils.py +0 -324
  468. solace_agent_mesh/services/file_service/transformers/__init__.py +0 -5
  469. solace_agent_mesh/services/history_service/__init__.py +0 -3
  470. solace_agent_mesh/services/history_service/history_providers/__init__.py +0 -0
  471. solace_agent_mesh/services/history_service/history_providers/base_history_provider.py +0 -54
  472. solace_agent_mesh/services/history_service/history_providers/file_history_provider.py +0 -74
  473. solace_agent_mesh/services/history_service/history_providers/index.py +0 -40
  474. solace_agent_mesh/services/history_service/history_providers/memory_history_provider.py +0 -33
  475. solace_agent_mesh/services/history_service/history_providers/mongodb_history_provider.py +0 -66
  476. solace_agent_mesh/services/history_service/history_providers/redis_history_provider.py +0 -66
  477. solace_agent_mesh/services/history_service/history_providers/sql_history_provider.py +0 -93
  478. solace_agent_mesh/services/history_service/history_service.py +0 -413
  479. solace_agent_mesh/services/history_service/long_term_memory/__init__.py +0 -0
  480. solace_agent_mesh/services/history_service/long_term_memory/long_term_memory.py +0 -399
  481. solace_agent_mesh/services/llm_service/components/llm_request_component.py +0 -340
  482. solace_agent_mesh/services/llm_service/components/llm_service_component_base.py +0 -152
  483. solace_agent_mesh/services/middleware_service/__init__.py +0 -0
  484. solace_agent_mesh/services/middleware_service/middleware_service.py +0 -20
  485. solace_agent_mesh/templates/action.py +0 -38
  486. solace_agent_mesh/templates/agent.py +0 -29
  487. solace_agent_mesh/templates/agent.yaml +0 -70
  488. solace_agent_mesh/templates/gateway-config-template.yaml +0 -6
  489. solace_agent_mesh/templates/gateway-default-config.yaml +0 -28
  490. solace_agent_mesh/templates/gateway-flows.yaml +0 -78
  491. solace_agent_mesh/templates/gateway-header.yaml +0 -16
  492. solace_agent_mesh/templates/gateway_base.py +0 -15
  493. solace_agent_mesh/templates/gateway_input.py +0 -98
  494. solace_agent_mesh/templates/gateway_output.py +0 -71
  495. solace_agent_mesh/templates/plugin-gateway-default-config.yaml +0 -29
  496. solace_agent_mesh/templates/plugin-pyproject.toml +0 -30
  497. solace_agent_mesh/templates/rest-api-default-config.yaml +0 -31
  498. solace_agent_mesh/templates/rest-api-flows.yaml +0 -81
  499. solace_agent_mesh/templates/slack-default-config.yaml +0 -16
  500. solace_agent_mesh/templates/slack-flows.yaml +0 -81
  501. solace_agent_mesh/templates/solace-agent-mesh-default.yaml +0 -86
  502. solace_agent_mesh/templates/solace-agent-mesh-plugin-default.yaml +0 -8
  503. solace_agent_mesh/templates/web-default-config.yaml +0 -10
  504. solace_agent_mesh/templates/web-flows.yaml +0 -76
  505. solace_agent_mesh/tools/__init__.py +0 -0
  506. solace_agent_mesh/tools/components/__init__.py +0 -0
  507. solace_agent_mesh/tools/components/conversation_formatter.py +0 -111
  508. solace_agent_mesh/tools/components/file_resolver_component.py +0 -58
  509. solace_agent_mesh/tools/config/runtime_config.py +0 -26
  510. solace_agent_mesh-0.2.4.dist-info/METADATA +0 -176
  511. solace_agent_mesh-0.2.4.dist-info/RECORD +0 -193
  512. solace_agent_mesh-0.2.4.dist-info/entry_points.txt +0 -3
  513. /solace_agent_mesh/{agents → agent}/__init__.py +0 -0
  514. /solace_agent_mesh/{agents/global → agent/adk}/__init__.py +0 -0
  515. /solace_agent_mesh/{agents/global/actions → agent/protocol}/__init__.py +0 -0
  516. /solace_agent_mesh/{agents/image_processing → agent/sac}/__init__.py +0 -0
  517. /solace_agent_mesh/{agents/image_processing/actions → agent/utils}/__init__.py +0 -0
  518. /solace_agent_mesh/{agents/web_request → config_portal/backend/plugin_catalog}/__init__.py +0 -0
  519. /solace_agent_mesh/{agents/web_request/actions → evaluation}/__init__.py +0 -0
  520. /solace_agent_mesh/gateway/{components → http_sse}/__init__.py +0 -0
  521. {solace_agent_mesh-0.2.4.dist-info → solace_agent_mesh-1.0.2.dist-info}/WHEEL +0 -0
@@ -0,0 +1,816 @@
1
+ """
2
+ Defines modifier implementation functions and their contracts.
3
+ """
4
+
5
+ import re
6
+ from typing import Any, Callable, Dict, Optional, Tuple, List
7
+
8
+ from solace_ai_connector.common.log import log
9
+
10
+ from .constants import EARLY_EMBED_TYPES, LATE_EMBED_TYPES
11
+
12
+ try:
13
+ from jsonpath_ng.ext import parse as jsonpath_parse
14
+
15
+ JSONPATH_NG_AVAILABLE = True
16
+ except ImportError:
17
+ JSONPATH_NG_AVAILABLE = False
18
+
19
+ try:
20
+ import pystache
21
+
22
+ PYSTACHE_AVAILABLE = True
23
+ except ImportError:
24
+ PYSTACHE_AVAILABLE = False
25
+
26
+ from google.adk.artifacts import BaseArtifactService
27
+
28
+ from .types import DataFormat
29
+
30
+
31
+ def _apply_jsonpath(
32
+ current_data: Any, expression: str, mime_type: Optional[str], log_id: str
33
+ ) -> Tuple[Any, Optional[str], Optional[str]]:
34
+ """
35
+ Applies a JSONPath expression to parsed JSON data.
36
+
37
+ Args:
38
+ current_data: The input data (expected to be dict or list).
39
+ expression: The JSONPath expression string.
40
+ mime_type: The original mime type (passed through).
41
+ log_id: Identifier for logging.
42
+
43
+ Returns:
44
+ Tuple: (result_data, original_mime_type, error_string)
45
+ result_data is typically a list of matched values.
46
+ """
47
+ if not JSONPATH_NG_AVAILABLE:
48
+ return (
49
+ current_data,
50
+ mime_type,
51
+ "JSONPath modifier skipped: 'jsonpath-ng' not installed.",
52
+ )
53
+
54
+ if not isinstance(current_data, (dict, list)):
55
+ return (
56
+ current_data,
57
+ mime_type,
58
+ f"Input data for 'jsonpath' must be a JSON object or list, got {type(current_data).__name__}.",
59
+ )
60
+
61
+ try:
62
+ jsonpath_expr = jsonpath_parse(expression)
63
+ matches = [match.value for match in jsonpath_expr.find(current_data)]
64
+ return matches, mime_type, None
65
+ except Exception as e:
66
+ return (
67
+ current_data,
68
+ mime_type,
69
+ f"Error applying JSONPath expression '{expression}': {e}",
70
+ )
71
+
72
+
73
+ def _apply_select_cols(
74
+ current_data: List[Dict], cols_str: str, mime_type: Optional[str], log_id: str
75
+ ) -> Tuple[Any, Optional[str], Optional[str]]:
76
+ """
77
+ Selects specific columns from data represented as a list of dictionaries.
78
+
79
+ Args:
80
+ current_data: The input data (expected List[Dict]).
81
+ cols_str: Comma-separated string of column names to keep.
82
+ mime_type: The original mime type (passed through).
83
+ log_id: Identifier for logging.
84
+
85
+ Returns:
86
+ Tuple: (result_data, original_mime_type, error_string)
87
+ result_data is List[Dict] containing only selected columns.
88
+ """
89
+ if not isinstance(current_data, list) or (
90
+ current_data and not isinstance(current_data[0], dict)
91
+ ):
92
+ return (
93
+ current_data,
94
+ mime_type,
95
+ f"Input data for 'select_cols' must be a list of dictionaries, got {type(current_data).__name__}.",
96
+ )
97
+
98
+ if not current_data:
99
+ return [], mime_type, None
100
+
101
+ try:
102
+ header = list(current_data[0].keys())
103
+ target_cols = [col.strip() for col in cols_str.split(",")]
104
+ output_list = []
105
+
106
+ for target_col in target_cols:
107
+ if target_col not in header:
108
+ return (
109
+ current_data,
110
+ mime_type,
111
+ f"Column '{target_col}' not found in data keys: {header}",
112
+ )
113
+
114
+ for row_dict in current_data:
115
+ new_row = {col: row_dict.get(col) for col in target_cols}
116
+ output_list.append(new_row)
117
+
118
+ return output_list, mime_type, None
119
+
120
+ except Exception as e:
121
+ return current_data, mime_type, f"Error selecting columns '{cols_str}': {e}"
122
+
123
+
124
+ def _apply_filter_rows_eq(
125
+ current_data: List[Dict], filter_spec: str, mime_type: Optional[str], log_id: str
126
+ ) -> Tuple[Any, Optional[str], Optional[str]]:
127
+ """
128
+ Filters a list of dictionaries based on a column's value equality.
129
+
130
+ Args:
131
+ current_data: The input data (expected List[Dict]).
132
+ filter_spec: String in the format 'column_name:value'.
133
+ mime_type: The original mime type (passed through).
134
+ log_id: Identifier for logging.
135
+
136
+ Returns:
137
+ Tuple: (result_data, original_mime_type, error_string)
138
+ result_data is List[Dict] containing only filtered rows.
139
+ """
140
+ if not isinstance(current_data, list) or (
141
+ current_data and not isinstance(current_data[0], dict)
142
+ ):
143
+ return (
144
+ current_data,
145
+ mime_type,
146
+ f"Input data for 'filter_rows_eq' must be a list of dictionaries, got {type(current_data).__name__}.",
147
+ )
148
+
149
+ if not current_data:
150
+ return [], mime_type, None
151
+
152
+ try:
153
+ parts = filter_spec.split(":", 1)
154
+ if len(parts) != 2:
155
+ return (
156
+ current_data,
157
+ mime_type,
158
+ f"Invalid filter format '{filter_spec}'. Expected 'column_name:value'.",
159
+ )
160
+ col_name, filter_value = parts[0].strip(), parts[1].strip()
161
+
162
+ header = list(current_data[0].keys())
163
+ if col_name not in header:
164
+ return (
165
+ current_data,
166
+ mime_type,
167
+ f"Filter column '{col_name}' not found in data keys: {header}",
168
+ )
169
+
170
+ output_list = [
171
+ row for row in current_data if str(row.get(col_name)) == filter_value
172
+ ]
173
+
174
+ return output_list, mime_type, None
175
+
176
+ except Exception as e:
177
+ return current_data, mime_type, f"Error filtering rows by '{filter_spec}': {e}"
178
+
179
+
180
+ def _apply_slice_rows(
181
+ current_data: List[Dict], slice_spec: str, mime_type: Optional[str], log_id: str
182
+ ) -> Tuple[Any, Optional[str], Optional[str]]:
183
+ """
184
+ Selects a slice of rows from a list of dictionaries.
185
+
186
+ Args:
187
+ current_data: The input data (expected List[Dict]).
188
+ slice_spec: String in Python slice format 'start:end'.
189
+ mime_type: The original mime type (passed through).
190
+ log_id: Identifier for logging.
191
+
192
+ Returns:
193
+ Tuple: (result_data, original_mime_type, error_string)
194
+ result_data is List[Dict] containing the sliced rows.
195
+ """
196
+ if not isinstance(current_data, list):
197
+ return (
198
+ current_data,
199
+ mime_type,
200
+ f"Input data for 'slice_rows' must be a list, got {type(current_data).__name__}.",
201
+ )
202
+
203
+ try:
204
+ start_str, end_str = None, None
205
+ if ":" in slice_spec:
206
+ parts = slice_spec.split(":", 1)
207
+ start_str, end_str = parts[0].strip(), parts[1].strip()
208
+ else:
209
+ return (
210
+ current_data,
211
+ mime_type,
212
+ f"Invalid slice format '{slice_spec}'. Expected 'start:end'.",
213
+ )
214
+
215
+ start = int(start_str) if start_str else 0
216
+ end = int(end_str) if end_str else None
217
+
218
+ sliced_data = current_data[start:end]
219
+
220
+ return sliced_data, mime_type, None
221
+
222
+ except (ValueError, TypeError) as e:
223
+ return current_data, mime_type, f"Invalid slice indices in '{slice_spec}': {e}"
224
+ except Exception as e:
225
+ return current_data, mime_type, f"Error slicing rows '{slice_spec}': {e}"
226
+
227
+
228
+ def _apply_slice_lines(
229
+ current_data: str, slice_spec: str, mime_type: Optional[str], log_id: str
230
+ ) -> Tuple[Any, Optional[str], Optional[str]]:
231
+ """
232
+ Selects a slice of lines from text data.
233
+
234
+ Args:
235
+ current_data: The input data (expected str).
236
+ slice_spec: String in Python slice format 'start:end'.
237
+ mime_type: The original mime type (passed through).
238
+ log_id: Identifier for logging.
239
+
240
+ Returns:
241
+ Tuple: (result_data, original_mime_type, error_string)
242
+ result_data is str containing the sliced lines.
243
+ """
244
+ if not isinstance(current_data, str):
245
+ return (
246
+ current_data,
247
+ mime_type,
248
+ f"Input data for 'slice_lines' must be a string, got {type(current_data).__name__}.",
249
+ )
250
+
251
+ try:
252
+ start_str, end_str = None, None
253
+ if ":" in slice_spec:
254
+ parts = slice_spec.split(":", 1)
255
+ start_str, end_str = parts[0].strip(), parts[1].strip()
256
+ else:
257
+ return (
258
+ current_data,
259
+ mime_type,
260
+ f"Invalid slice format '{slice_spec}'. Expected 'start:end'.",
261
+ )
262
+
263
+ start = int(start_str) if start_str else 0
264
+ end = int(end_str) if end_str else None
265
+
266
+ lines = current_data.splitlines(keepends=True)
267
+ sliced_lines = lines[start:end]
268
+
269
+ return "".join(sliced_lines), mime_type, None
270
+
271
+ except (ValueError, TypeError) as e:
272
+ return current_data, mime_type, f"Invalid slice indices in '{slice_spec}': {e}"
273
+ except Exception as e:
274
+ return current_data, mime_type, f"Error slicing text lines '{slice_spec}': {e}"
275
+
276
+
277
+ def _apply_grep(
278
+ current_data: str, pattern: str, mime_type: Optional[str], log_id: str
279
+ ) -> Tuple[Any, Optional[str], Optional[str]]:
280
+ """
281
+ Filters lines matching a regex pattern from text data.
282
+
283
+ Args:
284
+ current_data: The input data (expected str).
285
+ pattern: The regex pattern string.
286
+ mime_type: The original mime type (passed through).
287
+ log_id: Identifier for logging.
288
+
289
+ Returns:
290
+ Tuple: (result_data, original_mime_type, error_string)
291
+ result_data is str containing only matching lines.
292
+ """
293
+ if not isinstance(current_data, str):
294
+ return (
295
+ current_data,
296
+ mime_type,
297
+ f"Input data for 'grep' must be a string, got {type(current_data).__name__}.",
298
+ )
299
+
300
+ try:
301
+ regex = re.compile(pattern)
302
+ lines = current_data.splitlines(keepends=True)
303
+ filtered_lines = [line for line in lines if regex.search(line)]
304
+ return "".join(filtered_lines), mime_type, None
305
+ except re.error as e:
306
+ return current_data, mime_type, f"Invalid regex pattern '{pattern}': {e}"
307
+ except Exception as e:
308
+ return current_data, mime_type, f"Error applying grep pattern '{pattern}': {e}"
309
+
310
+
311
+ def _apply_head(
312
+ current_data: str, n_str: str, mime_type: Optional[str], log_id: str
313
+ ) -> Tuple[Any, Optional[str], Optional[str]]:
314
+ """
315
+ Returns the first N lines of text data.
316
+
317
+ Args:
318
+ current_data: The input data (expected str).
319
+ n_str: String representing the number of lines (N).
320
+ mime_type: The original mime type (passed through).
321
+ log_id: Identifier for logging.
322
+
323
+ Returns:
324
+ Tuple: (result_data, original_mime_type, error_string)
325
+ result_data is str containing the first N lines.
326
+ """
327
+ if not isinstance(current_data, str):
328
+ return (
329
+ current_data,
330
+ mime_type,
331
+ f"Input data for 'head' must be a string, got {type(current_data).__name__}.",
332
+ )
333
+
334
+ try:
335
+ n = int(n_str.strip())
336
+ if n < 0:
337
+ return current_data, mime_type, "Head count N cannot be negative."
338
+
339
+ lines = current_data.splitlines(keepends=True)
340
+ head_lines = lines[:n]
341
+ return "".join(head_lines), mime_type, None
342
+ except (ValueError, TypeError) as e:
343
+ return current_data, mime_type, f"Invalid head count N '{n_str}': {e}"
344
+ except Exception as e:
345
+ return current_data, mime_type, f"Error applying head '{n_str}': {e}"
346
+
347
+
348
+ def _apply_tail(
349
+ current_data: str, n_str: str, mime_type: Optional[str], log_id: str
350
+ ) -> Tuple[Any, Optional[str], Optional[str]]:
351
+ """
352
+ Returns the last N lines of text data.
353
+
354
+ Args:
355
+ current_data: The input data (expected str).
356
+ n_str: String representing the number of lines (N).
357
+ mime_type: The original mime type (passed through).
358
+ log_id: Identifier for logging.
359
+
360
+ Returns:
361
+ Tuple: (result_data, original_mime_type, error_string)
362
+ result_data is str containing the last N lines.
363
+ """
364
+ if not isinstance(current_data, str):
365
+ return (
366
+ current_data,
367
+ mime_type,
368
+ f"Input data for 'tail' must be a string, got {type(current_data).__name__}.",
369
+ )
370
+
371
+ try:
372
+ n = int(n_str.strip())
373
+ if n < 0:
374
+ return current_data, mime_type, "Tail count N cannot be negative."
375
+ if n == 0:
376
+ return "", mime_type, None
377
+
378
+ lines = current_data.splitlines(keepends=True)
379
+ tail_lines = lines[-n:]
380
+ return "".join(tail_lines), mime_type, None
381
+ except (ValueError, TypeError) as e:
382
+ return current_data, mime_type, f"Invalid tail count N '{n_str}': {e}"
383
+ except Exception as e:
384
+ return current_data, mime_type, f"Error applying tail '{n_str}': {e}"
385
+
386
+
387
+ def _apply_select_fields(
388
+ current_data: List[Dict], fields_str: str, mime_type: Optional[str], log_id: str
389
+ ) -> Tuple[Any, Optional[str], Optional[str]]:
390
+ """
391
+ Selects specific fields from a list of dictionaries.
392
+
393
+ Args:
394
+ current_data: The input data (expected List[Dict]).
395
+ fields_str: Comma-separated string of field names to keep.
396
+ mime_type: The original mime type (passed through).
397
+ log_id: Identifier for logging.
398
+
399
+ Returns:
400
+ Tuple: (result_data, original_mime_type, error_string)
401
+ result_data is List[Dict] containing only selected fields.
402
+ """
403
+ if not isinstance(current_data, list) or (
404
+ current_data and not isinstance(current_data[0], dict)
405
+ ):
406
+ return (
407
+ current_data,
408
+ mime_type,
409
+ f"Input data for 'select_fields' must be a list of dictionaries, got {type(current_data).__name__}.",
410
+ )
411
+
412
+ target_fields = [field.strip() for field in fields_str.split(",")]
413
+ if not target_fields:
414
+ return current_data, mime_type, "No fields specified for 'select_fields'."
415
+
416
+ output_list = []
417
+ try:
418
+ for item in current_data:
419
+ if isinstance(item, dict):
420
+ new_item = {
421
+ field: item.get(field) for field in target_fields if field in item
422
+ }
423
+ output_list.append(new_item)
424
+ else:
425
+ log.warning(
426
+ "%s Skipping non-dictionary item in list during select_fields.",
427
+ log_id,
428
+ )
429
+ continue
430
+ return output_list, mime_type, None
431
+ except Exception as e:
432
+ return current_data, mime_type, f"Error selecting fields '{fields_str}': {e}"
433
+
434
+
435
+ async def _apply_template(
436
+ current_data: Any,
437
+ template_spec: str,
438
+ mime_type: Optional[str],
439
+ log_id: str,
440
+ context: Any,
441
+ ) -> Tuple[Any, Optional[str], Optional[str]]:
442
+ """
443
+ Applies a Mustache template loaded from an artifact to the input data.
444
+ This version first renders the template, then resolves embeds on the result.
445
+
446
+ Args:
447
+ current_data: The input data (expected dict, list, or str).
448
+ template_spec: String 'template_filename[:version]'.
449
+ mime_type: The original mime type (passed through).
450
+ log_id: Identifier for logging.
451
+ context: The Gateway context dictionary containing artifact_service and session_context.
452
+
453
+ Returns:
454
+ Tuple: (result_data, original_mime_type, error_string)
455
+ result_data is the rendered and resolved string.
456
+ """
457
+ from .resolver import resolve_embeds_recursively_in_string, evaluate_embed
458
+
459
+ if not PYSTACHE_AVAILABLE:
460
+ return (
461
+ current_data,
462
+ mime_type,
463
+ "Template modifier skipped: 'pystache' not installed.",
464
+ )
465
+
466
+ if not isinstance(current_data, (dict, list, str)):
467
+ return (
468
+ current_data,
469
+ mime_type,
470
+ f"Input data for 'apply_to_template' must be dict, list, or string, got {type(current_data).__name__}.",
471
+ )
472
+
473
+ parts = template_spec.strip().split(":", 1)
474
+ template_filename = parts[0]
475
+ template_version_str = parts[1] if len(parts) > 1 else None
476
+ template_version = None
477
+
478
+ if not template_filename:
479
+ return current_data, mime_type, "Template filename cannot be empty."
480
+
481
+ if not isinstance(context, dict):
482
+ return current_data, mime_type, "Invalid context for template loading."
483
+ artifact_service: Optional[BaseArtifactService] = context.get("artifact_service")
484
+ session_context = context.get("session_context")
485
+ if not artifact_service or not session_context:
486
+ return (
487
+ current_data,
488
+ mime_type,
489
+ "ArtifactService or session context not available for template loading.",
490
+ )
491
+
492
+ app_name = session_context.get("app_name")
493
+ user_id = session_context.get("user_id")
494
+ session_id = session_context.get("session_id")
495
+ if not all([app_name, user_id, session_id]):
496
+ return (
497
+ current_data,
498
+ mime_type,
499
+ "Missing required session identifiers in context for template loading.",
500
+ )
501
+
502
+ try:
503
+ if template_version_str:
504
+ template_version = int(template_version_str)
505
+ else:
506
+ versions = await artifact_service.list_versions(
507
+ app_name=app_name,
508
+ user_id=user_id,
509
+ session_id=session_id,
510
+ filename=template_filename,
511
+ )
512
+ if not versions:
513
+ return (
514
+ current_data,
515
+ mime_type,
516
+ f"Template artifact '{template_filename}' (latest) not found.",
517
+ )
518
+ template_version = max(versions)
519
+
520
+ template_part = await artifact_service.load_artifact(
521
+ app_name=app_name,
522
+ user_id=user_id,
523
+ session_id=session_id,
524
+ filename=template_filename,
525
+ version=template_version,
526
+ )
527
+
528
+ if not template_part or not template_part.inline_data:
529
+ return (
530
+ current_data,
531
+ mime_type,
532
+ f"Template artifact '{template_filename}' v{template_version} not found or empty.",
533
+ )
534
+
535
+ template_bytes = template_part.inline_data.data
536
+ try:
537
+ raw_template_string = template_bytes.decode("utf-8")
538
+ except UnicodeDecodeError:
539
+ return (
540
+ current_data,
541
+ mime_type,
542
+ f"Cannot render non-UTF-8 decodable binary template '{template_filename}' v{template_version}.",
543
+ )
544
+
545
+ except FileNotFoundError:
546
+ return (
547
+ current_data,
548
+ mime_type,
549
+ f"Template artifact '{template_filename}' v{template_version_str or 'latest'} not found.",
550
+ )
551
+ except ValueError as e:
552
+ return (
553
+ current_data,
554
+ mime_type,
555
+ f"Invalid version specified for template: '{template_version_str}' or other value error: {e}",
556
+ )
557
+ except Exception as e:
558
+ return (
559
+ current_data,
560
+ mime_type,
561
+ f"Error loading template artifact '{template_filename}' v{template_version_str or 'latest'}: {e}",
562
+ )
563
+
564
+ try:
565
+ log.info(
566
+ "%s [apply_to_template] Preparing render context. Input data type: %s, Original MIME: %s",
567
+ log_id,
568
+ type(current_data).__name__,
569
+ mime_type,
570
+ )
571
+ render_context: Dict[str, Any]
572
+
573
+ if isinstance(current_data, list):
574
+ if mime_type and "csv" in mime_type.lower():
575
+ log.info(
576
+ "%s [apply_to_template] Input is a list and original MIME is CSV. Structuring context with 'headers' and 'data_rows'.",
577
+ log_id,
578
+ )
579
+ if not current_data:
580
+ render_context = {"headers": [], "data_rows": []}
581
+ else:
582
+ if all(isinstance(item, dict) for item in current_data):
583
+ headers = list(current_data[0].keys()) if current_data else []
584
+ data_rows = [list(row.values()) for row in current_data]
585
+ render_context = {"headers": headers, "data_rows": data_rows}
586
+ else:
587
+ log.warning(
588
+ "%s [apply_to_template] Input is list from CSV, but items are not all dictionaries. Falling back to 'items' context.",
589
+ log_id,
590
+ )
591
+ render_context = {"items": current_data}
592
+ else:
593
+ log.info(
594
+ "%s [apply_to_template] Input is a list (from JSON/YAML). Data available under 'items' key.",
595
+ log_id,
596
+ )
597
+ render_context = {"items": current_data}
598
+ elif isinstance(current_data, dict):
599
+ render_context = current_data
600
+ log.info(
601
+ "%s [apply_to_template] Input is dict. Keys directly available in template.",
602
+ log_id,
603
+ )
604
+ elif isinstance(current_data, str):
605
+ render_context = {"text": current_data}
606
+ log.info(
607
+ "%s [apply_to_template] Input is string. Data available under 'text' key.",
608
+ log_id,
609
+ )
610
+ else:
611
+ log.warning(
612
+ "%s [apply_to_template] Input is unexpected type %s. Converting to string and placing under 'value' key.",
613
+ log_id,
614
+ type(current_data).__name__,
615
+ )
616
+ render_context = {"value": str(current_data)}
617
+
618
+ log.info(
619
+ "%s [apply_to_template] Render context keys: %s",
620
+ log_id,
621
+ list(render_context.keys()),
622
+ )
623
+ if "items" in render_context and isinstance(render_context["items"], list):
624
+ log.info(
625
+ "%s [apply_to_template] Render context 'items' length: %d",
626
+ log_id,
627
+ len(render_context["items"]),
628
+ )
629
+
630
+ intermediate_rendered_string = pystache.render(
631
+ raw_template_string, render_context
632
+ )
633
+ log.debug(
634
+ "%s [apply_to_template] Intermediate rendered string: %s",
635
+ log_id,
636
+ intermediate_rendered_string[:200] + "...",
637
+ )
638
+
639
+ except Exception as e:
640
+ return (
641
+ current_data,
642
+ mime_type,
643
+ f"Error preparing context or rendering template '{template_filename}' v{template_version}: {e}",
644
+ )
645
+
646
+ try:
647
+ log.debug(
648
+ "%s [apply_to_template] Resolving embeds on rendered template output.",
649
+ log_id,
650
+ )
651
+ resolver_config = context.get("config", {})
652
+ if not resolver_config:
653
+ log.warning(
654
+ "%s 'config' not found in context for template embed resolution. Using defaults.",
655
+ log_id,
656
+ )
657
+
658
+ final_rendered_string = await resolve_embeds_recursively_in_string(
659
+ text=intermediate_rendered_string,
660
+ context=context,
661
+ resolver_func=evaluate_embed,
662
+ types_to_resolve=EARLY_EMBED_TYPES.union(LATE_EMBED_TYPES),
663
+ log_identifier=f"{log_id}[TemplateEmbeds]",
664
+ config=resolver_config,
665
+ max_depth=resolver_config.get("gateway_recursive_embed_depth", 12),
666
+ current_depth=0,
667
+ visited_artifacts=set(),
668
+ accumulated_size=0,
669
+ max_total_size=resolver_config.get(
670
+ "gateway_max_artifact_resolve_size_bytes", -1
671
+ ),
672
+ )
673
+ log.debug(
674
+ "%s [apply_to_template] Final rendered string after embed resolution: %s",
675
+ log_id,
676
+ final_rendered_string[:200] + "...",
677
+ )
678
+ except Exception as recurse_err:
679
+ log.exception(
680
+ "%s Error during recursive resolution of rendered template: %s",
681
+ log_id,
682
+ recurse_err,
683
+ )
684
+ return (
685
+ current_data,
686
+ mime_type,
687
+ f"Error resolving embeds within rendered template: {recurse_err}",
688
+ )
689
+
690
+ return final_rendered_string, mime_type, None
691
+
692
+
693
+ MODIFIER_IMPLEMENTATIONS: Dict[
694
+ str, Callable[..., Tuple[Any, Optional[str], Optional[str]]]
695
+ ] = {
696
+ "jsonpath": _apply_jsonpath,
697
+ "select_cols": _apply_select_cols,
698
+ "filter_rows_eq": _apply_filter_rows_eq,
699
+ "slice_rows": _apply_slice_rows,
700
+ "slice_lines": _apply_slice_lines,
701
+ "grep": _apply_grep,
702
+ "head": _apply_head,
703
+ "tail": _apply_tail,
704
+ "select_fields": _apply_select_fields,
705
+ "apply_to_template": _apply_template,
706
+ }
707
+
708
+ MODIFIER_DEFINITIONS: Dict[str, Dict[str, Any]] = {
709
+ "jsonpath": {
710
+ "function": _apply_jsonpath,
711
+ "accepts": [DataFormat.JSON_OBJECT],
712
+ "produces": DataFormat.JSON_OBJECT,
713
+ },
714
+ "select_cols": {
715
+ "function": _apply_select_cols,
716
+ "accepts": [DataFormat.LIST_OF_DICTS],
717
+ "produces": DataFormat.LIST_OF_DICTS,
718
+ },
719
+ "filter_rows_eq": {
720
+ "function": _apply_filter_rows_eq,
721
+ "accepts": [DataFormat.LIST_OF_DICTS],
722
+ "produces": DataFormat.LIST_OF_DICTS,
723
+ },
724
+ "slice_rows": {
725
+ "function": _apply_slice_rows,
726
+ "accepts": [DataFormat.LIST_OF_DICTS],
727
+ "produces": DataFormat.LIST_OF_DICTS,
728
+ },
729
+ "slice_lines": {
730
+ "function": _apply_slice_lines,
731
+ "accepts": [DataFormat.STRING],
732
+ "produces": DataFormat.STRING,
733
+ },
734
+ "grep": {
735
+ "function": _apply_grep,
736
+ "accepts": [DataFormat.STRING],
737
+ "produces": DataFormat.STRING,
738
+ },
739
+ "head": {
740
+ "function": _apply_head,
741
+ "accepts": [DataFormat.STRING],
742
+ "produces": DataFormat.STRING,
743
+ },
744
+ "tail": {
745
+ "function": _apply_tail,
746
+ "accepts": [DataFormat.STRING],
747
+ "produces": DataFormat.STRING,
748
+ },
749
+ "select_fields": {
750
+ "function": _apply_select_fields,
751
+ "accepts": [DataFormat.LIST_OF_DICTS],
752
+ "produces": DataFormat.LIST_OF_DICTS,
753
+ },
754
+ "apply_to_template": {
755
+ "function": _apply_template,
756
+ "accepts": [
757
+ DataFormat.JSON_OBJECT,
758
+ DataFormat.LIST_OF_DICTS,
759
+ DataFormat.STRING,
760
+ ],
761
+ "produces": DataFormat.STRING,
762
+ },
763
+ }
764
+
765
+
766
+ def _parse_modifier_chain(
767
+ expression: str,
768
+ ) -> Tuple[str, List[Tuple[str, str]], Optional[str]]:
769
+ """
770
+ Parses the expression part of an artifact_content embed.
771
+
772
+ Separates the artifact specifier, modifier chain, and final format specifier.
773
+
774
+ Args:
775
+ expression: The full expression string after 'artifact_content:'.
776
+
777
+ Returns:
778
+ A tuple containing:
779
+ - artifact_spec (str): The filename and optional version (e.g., "data.csv:1").
780
+ - modifiers (List[Tuple[str, str]]): A list of (prefix, value) tuples for modifiers.
781
+ - output_format (Optional[str]): The final output format string (e.g., "text", "json").
782
+ Returns None if the format step is missing or invalid.
783
+ """
784
+ from .constants import EMBED_CHAIN_DELIMITER
785
+
786
+ parts = expression.split(EMBED_CHAIN_DELIMITER)
787
+ if not parts:
788
+ return expression, [], None
789
+
790
+ artifact_spec = parts[0].strip()
791
+ modifiers = []
792
+ output_format = None
793
+
794
+ for i in range(1, len(parts)):
795
+ part = parts[i].strip()
796
+ if not part:
797
+ continue
798
+
799
+ if i == len(parts) - 1:
800
+ format_match = re.match(r"format:(.*)", part, re.DOTALL)
801
+ if format_match:
802
+ output_format = format_match.group(1).strip()
803
+ continue
804
+
805
+ modifier_parts = part.split(":", 1)
806
+ if len(modifier_parts) == 2:
807
+ prefix = modifier_parts[0].strip()
808
+ value = modifier_parts[1].strip()
809
+ if prefix and value:
810
+ modifiers.append((prefix, value))
811
+ else:
812
+ log.warning("Ignoring invalid modifier step format: '%s'", part)
813
+ else:
814
+ log.warning("Ignoring invalid modifier step format: '%s'", part)
815
+
816
+ return artifact_spec, modifiers, output_format