solace-agent-mesh 1.6.3__py3-none-any.whl → 1.7.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 (244) hide show
  1. solace_agent_mesh/agent/adk/adk_llm.txt +12 -18
  2. solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +1 -1
  3. solace_agent_mesh/agent/adk/callbacks.py +138 -20
  4. solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +2 -0
  5. solace_agent_mesh/agent/adk/models/lite_llm.py +38 -5
  6. solace_agent_mesh/agent/adk/models/models_llm.txt +82 -35
  7. solace_agent_mesh/agent/adk/runner.py +9 -0
  8. solace_agent_mesh/agent/adk/stream_parser.py +6 -1
  9. solace_agent_mesh/agent/adk/tool_wrapper.py +3 -0
  10. solace_agent_mesh/agent/agent_llm.txt +61 -70
  11. solace_agent_mesh/agent/protocol/event_handlers.py +29 -1
  12. solace_agent_mesh/agent/protocol/protocol_llm.txt +1 -1
  13. solace_agent_mesh/agent/proxies/a2a/a2a_llm.txt +190 -0
  14. solace_agent_mesh/agent/proxies/base/base_llm.txt +148 -0
  15. solace_agent_mesh/agent/proxies/proxies_llm.txt +283 -0
  16. solace_agent_mesh/agent/sac/app.py +22 -0
  17. solace_agent_mesh/agent/sac/component.py +76 -40
  18. solace_agent_mesh/agent/sac/sac_llm.txt +1 -1
  19. solace_agent_mesh/agent/sac/task_execution_context.py +21 -0
  20. solace_agent_mesh/agent/testing/testing_llm.txt +2 -1
  21. solace_agent_mesh/agent/tools/builtin_artifact_tools.py +13 -148
  22. solace_agent_mesh/agent/tools/dynamic_tool.py +2 -0
  23. solace_agent_mesh/agent/tools/tools_llm.txt +93 -80
  24. solace_agent_mesh/agent/tools/tools_llm_detail.txt +3 -2
  25. solace_agent_mesh/agent/utils/artifact_helpers.py +4 -0
  26. solace_agent_mesh/agent/utils/utils_llm.txt +16 -2
  27. solace_agent_mesh/assets/docs/404.html +3 -3
  28. solace_agent_mesh/assets/docs/assets/js/05749d90.c70b2be9.js +1 -0
  29. solace_agent_mesh/assets/docs/assets/js/15ba94aa.92fea363.js +1 -0
  30. solace_agent_mesh/assets/docs/assets/js/15e40e79.36003774.js +1 -0
  31. solace_agent_mesh/assets/docs/assets/js/2987107d.a80604f9.js +1 -0
  32. solace_agent_mesh/assets/docs/assets/js/3ac1795d.e4870a49.js +1 -0
  33. solace_agent_mesh/assets/docs/assets/js/3ff0015d.b63ee53a.js +1 -0
  34. solace_agent_mesh/assets/docs/assets/js/547e15cc.2f7790c1.js +1 -0
  35. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.45b32c2b.js +1 -0
  36. solace_agent_mesh/assets/docs/assets/js/631738c7.fa471607.js +1 -0
  37. solace_agent_mesh/assets/docs/assets/js/64195356.c498c4d0.js +1 -0
  38. solace_agent_mesh/assets/docs/assets/js/6a520c9d.b6e3f2ce.js +1 -0
  39. solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.a5b36a60.js +1 -0
  40. solace_agent_mesh/assets/docs/assets/js/71da7b71.374b9d54.js +1 -0
  41. solace_agent_mesh/assets/docs/assets/js/8024126c.fa0e7186.js +1 -0
  42. solace_agent_mesh/assets/docs/assets/js/8b032486.91a91afc.js +1 -0
  43. solace_agent_mesh/assets/docs/assets/js/94e8668d.09ed9234.js +1 -0
  44. solace_agent_mesh/assets/docs/assets/js/{ab9708a8.3e6dd091.js → ab9708a8.245ae0ef.js} +1 -1
  45. solace_agent_mesh/assets/docs/assets/js/ad87452a.9d73dad6.js +1 -0
  46. solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.f902fad8.js +1 -0
  47. solace_agent_mesh/assets/docs/assets/js/da0b5bad.b62f7b08.js +1 -0
  48. solace_agent_mesh/assets/docs/assets/js/db5d6442.3daf1696.js +1 -0
  49. solace_agent_mesh/assets/docs/assets/js/dd817ffc.c37a755e.js +1 -0
  50. solace_agent_mesh/assets/docs/assets/js/dd81e2b8.b682e9c2.js +1 -0
  51. solace_agent_mesh/assets/docs/assets/js/de915948.44a432bc.js +1 -0
  52. solace_agent_mesh/assets/docs/assets/js/e04b235d.c9c50c7b.js +1 -0
  53. solace_agent_mesh/assets/docs/assets/js/e3d9abda.d11c67a7.js +1 -0
  54. solace_agent_mesh/assets/docs/assets/js/{e6f9706b.e74a984d.js → e6f9706b.045d0fa1.js} +1 -1
  55. solace_agent_mesh/assets/docs/assets/js/e92d0134.3bda61dd.js +1 -0
  56. solace_agent_mesh/assets/docs/assets/js/f284c35a.5099c51e.js +1 -0
  57. solace_agent_mesh/assets/docs/assets/js/ff4d71f2.74710fc1.js +1 -0
  58. solace_agent_mesh/assets/docs/assets/js/main.f213fe0c.js +2 -0
  59. solace_agent_mesh/assets/docs/assets/js/runtime~main.d9606d6a.js +1 -0
  60. solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +4 -4
  61. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +4 -4
  62. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +4 -4
  63. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +4 -4
  64. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +18 -4
  65. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +4 -4
  66. solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +4 -4
  67. solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +5 -5
  68. solace_agent_mesh/assets/docs/docs/documentation/components/index.html +4 -4
  69. solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +4 -4
  70. solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +4 -4
  71. solace_agent_mesh/assets/docs/docs/documentation/components/projects/index.html +196 -0
  72. solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +4 -4
  73. solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +5 -5
  74. solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +6 -7
  75. solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +4 -4
  76. solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes-deployment/index.html +47 -0
  77. solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +4 -4
  78. solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +4 -4
  79. solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +4 -4
  80. solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +160 -169
  81. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +4 -4
  82. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +4 -4
  83. solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +4 -4
  84. solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +4 -4
  85. solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +4 -4
  86. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +4 -4
  87. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +5 -5
  88. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +4 -4
  89. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +4 -4
  90. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +4 -4
  91. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +4 -4
  92. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +4 -4
  93. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +4 -4
  94. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +4 -4
  95. solace_agent_mesh/assets/docs/docs/documentation/enterprise/agent-builder/index.html +59 -0
  96. solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +62 -0
  97. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +10 -6
  98. solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +4 -4
  99. solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +4 -4
  100. solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +440 -0
  101. solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +27 -4
  102. solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +62 -0
  103. solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +4 -4
  104. solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +5 -4
  105. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +3 -3
  106. solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +3 -3
  107. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/artifact-storage/index.html +290 -0
  108. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +9 -9
  109. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +4 -4
  110. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +4 -4
  111. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +4 -4
  112. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +4 -4
  113. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/session-storage/index.html +251 -0
  114. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +88 -0
  115. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +3 -3
  116. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +3 -3
  117. solace_agent_mesh/assets/docs/lunr-index-1762283454666.json +1 -0
  118. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  119. solace_agent_mesh/assets/docs/search-doc-1762283454666.json +1 -0
  120. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  121. solace_agent_mesh/assets/docs/sitemap.xml +1 -1
  122. solace_agent_mesh/cli/__init__.py +1 -1
  123. solace_agent_mesh/cli/commands/docs_cmd.py +4 -1
  124. solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +1 -1
  125. solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-D4_RMYRh.js → authCallback-tcIFZLis.js} +1 -1
  126. solace_agent_mesh/client/webui/frontend/static/assets/{client-UZ3qU6Bq.js → client-CRYdKo2Q.js} +3 -3
  127. solace_agent_mesh/client/webui/frontend/static/assets/main-CojeY_1w.css +1 -0
  128. solace_agent_mesh/client/webui/frontend/static/assets/main-ILja9MCG.js +353 -0
  129. solace_agent_mesh/client/webui/frontend/static/assets/vendor-CINwxvwV.js +470 -0
  130. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
  131. solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
  132. solace_agent_mesh/common/a2a/a2a_llm.txt +13 -20
  133. solace_agent_mesh/common/a2a/protocol.py +5 -0
  134. solace_agent_mesh/common/a2a/types.py +1 -0
  135. solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +49 -11
  136. solace_agent_mesh/common/a2a_spec/schemas/artifact_creation_progress.json +23 -6
  137. solace_agent_mesh/common/a2a_spec/schemas/feedback_event.json +51 -0
  138. solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +26 -9
  139. solace_agent_mesh/common/common_llm.txt +13 -34
  140. solace_agent_mesh/common/data_parts.py +20 -4
  141. solace_agent_mesh/common/middleware/middleware_llm.txt +1 -1
  142. solace_agent_mesh/common/sac/sac_llm.txt +1 -1
  143. solace_agent_mesh/common/sam_events/sam_events_llm.txt +1 -1
  144. solace_agent_mesh/common/services/employee_service.py +1 -1
  145. solace_agent_mesh/common/services/providers/providers_llm.txt +3 -2
  146. solace_agent_mesh/common/services/services_llm.txt +9 -4
  147. solace_agent_mesh/common/utils/embeds/constants.py +1 -0
  148. solace_agent_mesh/common/utils/embeds/embeds_llm.txt +1 -1
  149. solace_agent_mesh/common/utils/embeds/modifiers.py +2 -1
  150. solace_agent_mesh/common/utils/embeds/resolver.py +58 -6
  151. solace_agent_mesh/common/utils/embeds/types.py +8 -0
  152. solace_agent_mesh/common/utils/utils_llm.txt +5 -6
  153. solace_agent_mesh/core_a2a/core_a2a_llm.txt +1 -1
  154. solace_agent_mesh/gateway/adapter/__init__.py +1 -0
  155. solace_agent_mesh/gateway/adapter/base.py +143 -0
  156. solace_agent_mesh/gateway/adapter/types.py +221 -0
  157. solace_agent_mesh/gateway/base/app.py +29 -2
  158. solace_agent_mesh/gateway/base/base_llm.txt +10 -8
  159. solace_agent_mesh/gateway/base/component.py +573 -142
  160. solace_agent_mesh/gateway/gateway_llm.txt +55 -59
  161. solace_agent_mesh/gateway/generic/__init__.py +1 -0
  162. solace_agent_mesh/gateway/generic/app.py +50 -0
  163. solace_agent_mesh/gateway/generic/component.py +650 -0
  164. solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +99 -49
  165. solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_fulltext_search_indexes.py +92 -0
  166. solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_project_users_table.py +72 -0
  167. solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_soft_delete_and_search.py +150 -0
  168. solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_default_agent_to_projects.py +26 -0
  169. solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_projects_table.py +135 -0
  170. solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +26 -20
  171. solace_agent_mesh/gateway/http_sse/app.py +0 -14
  172. solace_agent_mesh/gateway/http_sse/component.py +17 -56
  173. solace_agent_mesh/gateway/http_sse/components/components_llm.txt +1 -1
  174. solace_agent_mesh/gateway/http_sse/dependencies.py +21 -3
  175. solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +8 -8
  176. solace_agent_mesh/gateway/http_sse/main.py +23 -5
  177. solace_agent_mesh/gateway/http_sse/repository/__init__.py +19 -1
  178. solace_agent_mesh/gateway/http_sse/repository/entities/entities_llm.txt +56 -98
  179. solace_agent_mesh/gateway/http_sse/repository/entities/project.py +81 -0
  180. solace_agent_mesh/gateway/http_sse/repository/entities/project_user.py +47 -0
  181. solace_agent_mesh/gateway/http_sse/repository/entities/session.py +23 -1
  182. solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +47 -0
  183. solace_agent_mesh/gateway/http_sse/repository/interfaces.py +112 -4
  184. solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +9 -1
  185. solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +51 -60
  186. solace_agent_mesh/gateway/http_sse/repository/models/project_model.py +51 -0
  187. solace_agent_mesh/gateway/http_sse/repository/models/project_user_model.py +75 -0
  188. solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +7 -1
  189. solace_agent_mesh/gateway/http_sse/repository/project_repository.py +172 -0
  190. solace_agent_mesh/gateway/http_sse/repository/project_user_repository.py +186 -0
  191. solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +125 -157
  192. solace_agent_mesh/gateway/http_sse/repository/session_repository.py +269 -8
  193. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +143 -51
  194. solace_agent_mesh/gateway/http_sse/routers/config.py +69 -0
  195. solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +198 -94
  196. solace_agent_mesh/gateway/http_sse/routers/dto/requests/project_requests.py +48 -0
  197. solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +68 -18
  198. solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +13 -0
  199. solace_agent_mesh/gateway/http_sse/routers/dto/responses/project_responses.py +30 -0
  200. solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +51 -35
  201. solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +2 -0
  202. solace_agent_mesh/gateway/http_sse/routers/feedback.py +133 -2
  203. solace_agent_mesh/gateway/http_sse/routers/projects.py +542 -0
  204. solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +9 -11
  205. solace_agent_mesh/gateway/http_sse/routers/sessions.py +154 -3
  206. solace_agent_mesh/gateway/http_sse/routers/tasks.py +296 -4
  207. solace_agent_mesh/gateway/http_sse/services/project_service.py +403 -0
  208. solace_agent_mesh/gateway/http_sse/services/services_llm.txt +16 -10
  209. solace_agent_mesh/gateway/http_sse/services/session_service.py +178 -6
  210. solace_agent_mesh/gateway/http_sse/shared/exception_handlers.py +2 -3
  211. solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +48 -14
  212. solace_agent_mesh/solace_agent_mesh_llm.txt +1 -1
  213. {solace_agent_mesh-1.6.3.dist-info → solace_agent_mesh-1.7.1.dist-info}/METADATA +3 -5
  214. {solace_agent_mesh-1.6.3.dist-info → solace_agent_mesh-1.7.1.dist-info}/RECORD +218 -175
  215. solace_agent_mesh/assets/docs/assets/js/15ba94aa.932dd2db.js +0 -1
  216. solace_agent_mesh/assets/docs/assets/js/3ac1795d.76654dd9.js +0 -1
  217. solace_agent_mesh/assets/docs/assets/js/3ff0015d.2be20244.js +0 -1
  218. solace_agent_mesh/assets/docs/assets/js/547e15cc.2cbb060a.js +0 -1
  219. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.eda4bcb2.js +0 -1
  220. solace_agent_mesh/assets/docs/assets/js/631738c7.7c4594c9.js +0 -1
  221. solace_agent_mesh/assets/docs/assets/js/6a520c9d.ba015d81.js +0 -1
  222. solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.f4b15f3b.js +0 -1
  223. solace_agent_mesh/assets/docs/assets/js/71da7b71.ddbdfbe2.js +0 -1
  224. solace_agent_mesh/assets/docs/assets/js/8024126c.56e59919.js +0 -1
  225. solace_agent_mesh/assets/docs/assets/js/94e8668d.3b883666.js +0 -1
  226. solace_agent_mesh/assets/docs/assets/js/da0b5bad.d08a9466.js +0 -1
  227. solace_agent_mesh/assets/docs/assets/js/dd817ffc.0aa9630a.js +0 -1
  228. solace_agent_mesh/assets/docs/assets/js/dd81e2b8.d590bc9e.js +0 -1
  229. solace_agent_mesh/assets/docs/assets/js/de915948.27d6b065.js +0 -1
  230. solace_agent_mesh/assets/docs/assets/js/e3d9abda.6b9493d0.js +0 -1
  231. solace_agent_mesh/assets/docs/assets/js/e92d0134.4f395c6b.js +0 -1
  232. solace_agent_mesh/assets/docs/assets/js/f284c35a.720d2ef2.js +0 -1
  233. solace_agent_mesh/assets/docs/assets/js/ff4d71f2.15b02f97.js +0 -1
  234. solace_agent_mesh/assets/docs/assets/js/main.ed05b14d.js +0 -2
  235. solace_agent_mesh/assets/docs/assets/js/runtime~main.a8a75e0b.js +0 -1
  236. solace_agent_mesh/assets/docs/lunr-index-1761744323675.json +0 -1
  237. solace_agent_mesh/assets/docs/search-doc-1761744323675.json +0 -1
  238. solace_agent_mesh/client/webui/frontend/static/assets/main--3yJYl7S.css +0 -1
  239. solace_agent_mesh/client/webui/frontend/static/assets/main-DojKHS49.js +0 -342
  240. solace_agent_mesh/client/webui/frontend/static/assets/vendor-DSqhjwq_.js +0 -405
  241. /solace_agent_mesh/assets/docs/assets/js/{main.ed05b14d.js.LICENSE.txt → main.f213fe0c.js.LICENSE.txt} +0 -0
  242. {solace_agent_mesh-1.6.3.dist-info → solace_agent_mesh-1.7.1.dist-info}/WHEEL +0 -0
  243. {solace_agent_mesh-1.6.3.dist-info → solace_agent_mesh-1.7.1.dist-info}/entry_points.txt +0 -0
  244. {solace_agent_mesh-1.6.3.dist-info → solace_agent_mesh-1.7.1.dist-info}/licenses/LICENSE +0 -0
@@ -11,6 +11,7 @@ Once initialized, the `AppLlmAgent` (a custom agent class) is managed by the `ru
11
11
  - **Direct files:**
12
12
  - `__init__.py`: Standard Python package initializer
13
13
  - `adk_llm.txt`: Documentation file containing developer guide content
14
+ - `adk_llm_detail.txt`: Concatenated LLM summary file from all subdirectories
14
15
  - `app_llm_agent.py`: Defines a custom `LlmAgent` subclass that holds a reference to its host component
15
16
  - `callbacks.py`: Provides a rich set of ADK callback functions for dynamic instructions, metadata injection, and Solace integration
16
17
  - `embed_resolving_mcp_toolset.py`: Custom MCPToolset that resolves embeds in tool parameters before calling MCP tools
@@ -158,10 +159,11 @@ from solace_agent_mesh.agent.adk.artifacts.s3_artifact_service import S3Artifact
158
159
 
159
160
  #### models/
160
161
  **Purpose:** Contains concrete `BaseLlm` implementations for interfacing with various LLM providers
161
- **Key Exports:** `LiteLlm` class for broad model provider compatibility
162
+ **Key Exports:** `LiteLlm` class for broad model provider compatibility, `OAuth2ClientCredentialsTokenManager` for OAuth authentication
162
163
  **Import Examples:**
163
164
  ```python
164
165
  from solace_agent_mesh.agent.adk.models.lite_llm import LiteLlm
166
+ from solace_agent_mesh.agent.adk.models.oauth2_token_manager import OAuth2ClientCredentialsTokenManager
165
167
  ```
166
168
 
167
169
  ## Complete Usage Guide
@@ -198,7 +200,8 @@ from solace_agent_mesh.agent.adk.models.lite_llm import LiteLlm
198
200
  llm = LiteLlm(
199
201
  model="gpt-4-turbo",
200
202
  temperature=0.7,
201
- max_completion_tokens=1000
203
+ max_completion_tokens=1000,
204
+ cache_strategy="5m"
202
205
  )
203
206
 
204
207
  # Anthropic
@@ -212,21 +215,12 @@ llm = LiteLlm(
212
215
  model="gemini-pro",
213
216
  temperature=0.3
214
217
  )
215
- ```
216
-
217
- ### 3. Artifact Service Usage
218
218
 
219
- ```python
220
- from solace_agent_mesh.agent.adk.artifacts.filesystem_artifact_service import FilesystemArtifactService
221
- from solace_agent_mesh.agent.adk.artifacts.s3_artifact_service import S3ArtifactService
222
- from google.genai import types as adk_types
223
-
224
- # Initialize filesystem artifact service
225
- artifact_service = FilesystemArtifactService(base_path="/tmp/artifacts")
226
-
227
- # Or initialize S3 artifact service
228
- artifact_service = S3ArtifactService(bucket_name="my-artifacts-bucket")
229
-
230
- # Save an artifact
219
+ # With OAuth authentication
220
+ llm = LiteLlm(
221
+ model="custom-model",
222
+ oauth_token_url="https://auth.example.com/oauth/token",
223
+ oauth_client_id="your-client-id",
224
+ oauth_client_secret="your-client-secret",
231
225
 
232
- # content_hash: def8e8563d73ee6354aa959a4073a5474c225a2159f7c8fd37cf396040adeb5d
226
+ # content_hash: c689f024368fe41a8310f8060beb396353bdb6708fb095fd2a1857ab21e68b50
@@ -168,4 +168,4 @@ await artifact_service.delete_artifact(
168
168
  )
169
169
  ```
170
170
 
171
- # content_hash: c4df3504afaa30b614cafc8cda2c977b18d0036faabaaec82b2f7a9bc5b082f6
171
+ # content_hash: 8edcfe37e688e203ddb9d14f62b8e5f8dcb6129fc3c08816eea26de02ff6eb69
@@ -170,13 +170,40 @@ async def process_artifact_blocks_callback(
170
170
  event.params,
171
171
  )
172
172
  filename = event.params.get("filename", "unknown_artifact")
173
+ if filename == "unknown_artifact":
174
+ log.warning(
175
+ "%s Fenced artifact block started without a 'filename' parameter.",
176
+ log_identifier,
177
+ )
178
+ description = event.params.get("description")
179
+ if filename == "unknown_artifact":
180
+ log.warning(
181
+ "%s Fenced artifact block started without a 'filename' parameter.",
182
+ log_identifier,
183
+ )
173
184
  if a2a_context:
185
+ status_text = f"Receiving artifact `{filename}`..."
186
+ if description:
187
+ status_text = (
188
+ f"Receiving artifact `{filename}`: {description}"
189
+ )
174
190
  progress_data = AgentProgressUpdateData(
175
- status_text=f"Receiving artifact `{filename}`..."
191
+ status_text=status_text
176
192
  )
177
193
  await _publish_data_part_status_update(
178
194
  host_component, a2a_context, progress_data
179
195
  )
196
+ # Also send an initial in-progress event to create the UI bubble
197
+ artifact_progress_data = ArtifactCreationProgressData(
198
+ filename=filename,
199
+ description=description,
200
+ status="in-progress",
201
+ bytes_transferred=0,
202
+ artifact_chunk=None,
203
+ )
204
+ await _publish_data_part_status_update(
205
+ host_component, a2a_context, artifact_progress_data
206
+ )
180
207
  params_str = " ".join(
181
208
  [f'{k}="{v}"' for k, v in event.params.items()]
182
209
  )
@@ -189,12 +216,19 @@ async def process_artifact_blocks_callback(
189
216
  log_identifier,
190
217
  event.buffered_size,
191
218
  )
192
- params = parser._block_params
219
+ params = event.params
193
220
  filename = params.get("filename", "unknown_artifact")
221
+ if filename == "unknown_artifact":
222
+ log.warning(
223
+ "%s Fenced artifact block progressed without a 'filename' parameter.",
224
+ log_identifier,
225
+ )
194
226
  if a2a_context:
195
227
  progress_data = ArtifactCreationProgressData(
196
228
  filename=filename,
197
- bytes_saved=event.buffered_size,
229
+ description=params.get("description"),
230
+ status="in-progress",
231
+ bytes_transferred=event.buffered_size,
198
232
  artifact_chunk=event.chunk,
199
233
  )
200
234
  await _publish_data_part_status_update(
@@ -236,6 +270,18 @@ async def process_artifact_blocks_callback(
236
270
  "original_text": original_text,
237
271
  }
238
272
  )
273
+ if a2a_context:
274
+ if not filename or not filename.strip():
275
+ filename = "unknown_artifact"
276
+ progress_data = ArtifactCreationProgressData(
277
+ filename=filename or "unknown_artifact",
278
+ description=params.get("description"),
279
+ status="failed",
280
+ bytes_transferred=0,
281
+ )
282
+ await _publish_data_part_status_update(
283
+ host_component, a2a_context, progress_data
284
+ )
239
285
  continue
240
286
 
241
287
  kwargs_for_call = {
@@ -257,7 +303,6 @@ async def process_artifact_blocks_callback(
257
303
  log_identifier,
258
304
  params["schema_max_keys"],
259
305
  )
260
-
261
306
  wrapped_creator = ADKToolWrapper(
262
307
  original_func=_internal_create_artifact,
263
308
  tool_config=None, # No specific config for this internal tool
@@ -299,9 +344,33 @@ async def process_artifact_blocks_callback(
299
344
  log_identifier,
300
345
  e_track,
301
346
  )
347
+ # Publish completion status immediately via SSE
348
+ if a2a_context:
349
+ progress_data = ArtifactCreationProgressData(
350
+ filename=filename,
351
+ description=params.get("description"),
352
+ status="completed",
353
+ bytes_transferred=len(event.content),
354
+ mime_type=params.get("mime_type"),
355
+ version=version_for_tool,
356
+ )
357
+ await _publish_data_part_status_update(
358
+ host_component, a2a_context, progress_data
359
+ )
302
360
  else:
303
361
  status_for_tool = "error"
304
362
  version_for_tool = 0
363
+ # Publish failure status immediately via SSE
364
+ if a2a_context:
365
+ progress_data = ArtifactCreationProgressData(
366
+ filename=filename,
367
+ description=params.get("description"),
368
+ status="failed",
369
+ bytes_transferred=len(event.content),
370
+ )
371
+ await _publish_data_part_status_update(
372
+ host_component, a2a_context, progress_data
373
+ )
305
374
 
306
375
  session.state["completed_artifact_blocks_list"].append(
307
376
  {
@@ -347,6 +416,11 @@ async def process_artifact_blocks_callback(
347
416
  )
348
417
  params = event.params
349
418
  filename = params.get("filename", "unknown_artifact")
419
+ if filename == "unknown_artifact":
420
+ log.warning(
421
+ "%s Unterminated fenced artifact block is missing a valid 'filename'. Failing operation.",
422
+ log_identifier,
423
+ )
350
424
  if (
351
425
  "completed_artifact_blocks_list" not in session.state
352
426
  or session.state["completed_artifact_blocks_list"] is None
@@ -775,21 +849,55 @@ def _generate_fenced_artifact_instruction() -> str:
775
849
  close_delim = ARTIFACT_BLOCK_DELIMITER_CLOSE
776
850
  return f"""\
777
851
  **Creating Text-Based Artifacts:**
778
- To create an artifact from content you generate (like code, a report, or a document), you MUST use a special `save_artifact` block. This is the only reliable way to ensure your content is saved correctly.
779
852
 
780
- **Syntax:**
853
+ **When to Create Text-based Artifacts:**
854
+ Create an artifact when the content provides value as a standalone file:
855
+ - Content with special formatting (HTML, Markdown, CSS, structured markup) that requires proper rendering
856
+ - Content explicitly intended for use outside this conversation (reports, emails, presentations, reference documents)
857
+ - Structured reference content users will save or follow (schedules, guides, templates)
858
+ - Content that will be edited, expanded, or reused
859
+ - Substantial text documents
860
+ - Technical documentation meant as reference material
861
+
862
+ **When NOT to Create Text-based Artifacts:**
863
+ - Simple answers, explanations, or conversational responses
864
+ - Brief advice, opinions, or quick information
865
+ - Short lists, summaries, or single paragraphs
866
+ - Temporary content only relevant to the immediate conversation
867
+ - Basic explanations that don't require reference material
868
+
869
+ **Behaviour of created artifacts:**
870
+ - they are sent back to the UI inline with the text and show up as an interactive file component
871
+ - the user can easily see the content so there is no need to return or embed it again.
872
+ - do not embed the same artifact again, since the user already has it to expand and view
873
+
874
+ **How to create artifacts:**
875
+ To create an artifact from content you generate (like code, a report, or a document), you MUST use a fenced artifact block with the EXACT syntax shown below. This is the only reliable way to ensure your content is saved correctly.
876
+
877
+ **EXACT SYNTAX (copy this pattern exactly):**
781
878
  {open_delim}save_artifact: filename="your_filename.ext" mime_type="text/plain" description="A brief description."
782
879
  The full content you want to save goes here.
783
880
  It can span multiple lines.
784
881
  {close_delim}
785
882
 
786
- - **Rules:**
787
- - The parameters `filename` and `mime_type` are required. `description` is optional but recommended.
788
- - All parameter values **MUST** be enclosed in double quotes.
789
- - You **MUST NOT** use double quotes `"` inside the parameter values (e.g., within the description string). Use single quotes or rephrase instead.
790
- - Do not surround a save_artifact block with '```' (triple backticks). This will create rendering issues.
791
-
792
- The system will automatically save the content and give you a confirmation in the next turn."""
883
+ **CRITICAL FORMATTING RULES:**
884
+ 1. The opening delimiter MUST be EXACTLY three angle brackets: `{open_delim}` (not `{open_delim[0:2]}` or `{open_delim[0:1]}`)
885
+ 2. Immediately after the opening delimiter, write `save_artifact:` with a colon and NO space before the colon
886
+ 3. Parameters (filename, mime_type, description) must be on the SAME line as the opening delimiter
887
+ 4. All parameter values **MUST** be enclosed in double quotes: `filename="example.txt"`
888
+ 5. You **MUST NOT** use double quotes `"` inside parameter values. Use single quotes or rephrase instead
889
+ 6. After all parameters, press enter/newline, then write your content
890
+ 7. Close the block with EXACTLY three angle brackets: `{close_delim}` on its own line
891
+ 8. Do NOT surround the block with triple backticks (```). The delimiters `{open_delim}` and `{close_delim}` are sufficient
892
+
893
+ **COMMON ERRORS TO AVOID:**
894
+ ❌ WRONG: `{open_delim[0:2]}save_artifact:` (only 2 angle brackets)
895
+ ❌ WRONG: `{open_delim[0:1]}save_artifact:` (only 1 angle bracket)
896
+ ❌ WRONG: `{open_delim}save_artifact` (missing colon)
897
+ ✅ CORRECT: `{open_delim}save_artifact: filename="test.txt" mime_type="text/plain"`
898
+
899
+ The system will automatically save the content and give you a confirmation in the next turn by way of an automatically injected _notify_artifact_save tool call.
900
+ """
793
901
 
794
902
 
795
903
  def _generate_artifact_creation_instruction() -> str:
@@ -828,7 +936,7 @@ def _generate_embed_instruction(
828
936
  )
829
937
 
830
938
  base_instruction = f"""\
831
- You can use dynamic embeds in your text responses and tool parameters using the syntax {open_delim}type:expression {chain_delim} format{close_delim}. This allows you to
939
+ You can use dynamic embeds in your text responses and tool parameters using the syntax {open_delim}type:expression {chain_delim} format{close_delim}. NOTE that this differs from 'save_artifact', which has different delimiters. This allows you to
832
940
  always have correct information in your output. Specifically, make sure you always use embeds for math, even if it is simple. You will make mistakes if you try to do math yourself.
833
941
  Use HTML entities to escape the delimiters.
834
942
  This host resolves the following embed types *early* (before sending to the LLM or tool): {early_types}. This means the embed is replaced with its resolved value.
@@ -836,10 +944,18 @@ This host resolves the following embed types *early* (before sending to the LLM
836
944
  - `{open_delim}datetime:format_or_keyword{close_delim}`: Inserts current date/time. Use Python strftime format (e.g., `%Y-%m-%d`) or keywords (`iso`, `timestamp`, `date`, `time`, `now`).
837
945
  - `{open_delim}uuid:{close_delim}`: Inserts a random UUID.
838
946
  - `{open_delim}artifact_meta:filename[:version]{close_delim}`: Inserts a summary of the artifact's metadata (latest version if unspecified).
839
- - `{open_delim}status_update:Your message here{close_delim}`: Generates an immediate, distinct status message event that is displayed to the user (e.g., 'Thinking...', 'Searching database...'). This message appears in a status area, not as part of the main chat conversation. Use this to provide interim feedback during processing."""
947
+ - `{open_delim}status_update:Your message here{close_delim}`: Generates an immediate, distinct status message event that is displayed to the user (e.g., 'Thinking...', 'Searching database...'). This message appears in a status area, not as part of the main chat conversation. Use this to provide interim feedback during processing.
948
+
949
+ Examples:
950
+ - `{open_delim}status_update:Analyzing data...{close_delim}` (Shows 'Analyzing data...' as a status update)
951
+ - `The result of 23.5 * 4.2 is {open_delim}math:23.5 * 4.2 | .2f{close_delim}` (Embeds calculated result with 2 decimal places)
952
+
953
+ The following embeds are resolved *late* (by the gateway before final display):
954
+ - `{open_delim}artifact_return:filename[:version]{close_delim}`: **This is the primary way to return an artifact to the user.** It attaches the specified artifact to the message. The embed itself is removed from the text. Use this instead of describing a file and expecting the user to download it. Note: artifact_return is not necessary if the artifact was just created by you in this same response, since newly created artifacts are automatically attached to your message."""
840
955
 
841
956
  artifact_content_instruction = f"""
842
957
  - `{open_delim}artifact_content:filename[:version] {chain_delim} modifier1:value1 {chain_delim} ... {chain_delim} format:output_format{close_delim}`: Embeds artifact content after applying a chain of modifiers. This is resolved *late* (typically by a gateway before final display).
958
+ - If this embed resolves to binary content (like an image), it will be automatically converted into an attached file, similar to `artifact_return`.
843
959
  - Use `{chain_delim}` to separate the artifact identifier from the modifier steps and the final format step.
844
960
  - Available modifiers: {modifier_list}.
845
961
  - The `format:output_format` step *must* be the last step in the chain. Supported formats include `text`, `datauri`, `json`, `json_pretty`, `csv`. Formatting as datauri, will include the data URI prefix, so do not add it yourself.
@@ -860,7 +976,8 @@ This host resolves the following embed types *early* (before sending to the LLM
860
976
  - `{open_delim}artifact_content:products.csv {chain_delim} apply_to_template:product_table.html.mustache {chain_delim} format:text{close_delim}` (CSV is auto-parsed to `headers` and `data_rows` for the HTML template)
861
977
  - `{open_delim}artifact_content:config.json {chain_delim} jsonpath:$.userPreferences.theme {chain_delim} format:text{close_delim}` (Extract a single value from a JSON artifact)
862
978
  - `{open_delim}artifact_content:sensor_readings.csv {chain_delim} filter_rows_eq:status:critical {chain_delim} select_cols:timestamp,sensor_id,value {chain_delim} format:csv{close_delim}` (Filter critical sensor readings and select specific columns, output as CSV)
863
- - `{open_delim}artifact_content:server.log {chain_delim} tail:100 {chain_delim} grep:WARN {chain_delim} format:text{close_delim}` (Get warning lines from the last 100 lines of a log file)"""
979
+ - `{open_delim}artifact_content:server.log {chain_delim} tail:100 {chain_delim} grep:WARN {chain_delim} format:text{close_delim}` (Get warning lines from the last 100 lines of a log file)
980
+ """
864
981
 
865
982
  final_instruction = base_instruction
866
983
  if include_artifact_content:
@@ -882,6 +999,10 @@ def _generate_tool_instructions_from_registry(
882
999
 
883
1000
  instructions_by_category = defaultdict(list)
884
1001
  for tool in sorted(active_tools, key=lambda t: (t.category, t.name)):
1002
+ # Skip internal tools (those starting with underscore)
1003
+ if tool.name.startswith("_"):
1004
+ continue
1005
+
885
1006
  param_parts = []
886
1007
  if tool.parameters and tool.parameters.properties:
887
1008
  for name, schema in tool.parameters.properties.items():
@@ -947,15 +1068,12 @@ Simple, direct requests like 'create an image of a dog' or 'write an email to th
947
1068
 
948
1069
  If a plan is created:
949
1070
  1. It should be a terse, hierarchical list describing the steps needed, with each checkbox item on its own line.
950
- 2. Use '' (empty checkbox emoji) for pending items and '' (checked checkbox emoji) for completed items.
1071
+ 2. Use '' for pending items, '✅' for completed items, and '' for cancelled items.
951
1072
  3. If the plan changes significantly during execution, restate the updated plan.
952
1073
  4. As items are completed, update the plan to check them off.
953
1074
 
954
1075
  """
955
1076
  injected_instructions.append(planning_instruction)
956
- log.debug("%s Added hardcoded planning instructions.", log_identifier)
957
- artifact_creation_instruction = _generate_artifact_creation_instruction()
958
- injected_instructions.append(artifact_creation_instruction)
959
1077
  fenced_artifact_instruction = _generate_fenced_artifact_instruction()
960
1078
  injected_instructions.append(fenced_artifact_instruction)
961
1079
 
@@ -23,6 +23,7 @@ from ...common.utils.embeds import (
23
23
  evaluate_embed,
24
24
  resolve_embeds_in_string,
25
25
  )
26
+ from ...common.utils.embeds.types import ResolutionMode
26
27
  from ..utils.context_helpers import get_original_session_id
27
28
 
28
29
  log = logging.getLogger(__name__)
@@ -184,6 +185,7 @@ class EmbedResolvingMCPTool(_BaseMcpToolClass):
184
185
  context=resolution_context,
185
186
  resolver_func=evaluate_embed,
186
187
  types_to_resolve=EARLY_EMBED_TYPES.union(LATE_EMBED_TYPES),
188
+ resolution_mode=ResolutionMode.TOOL_PARAMETER,
187
189
  log_identifier=log_identifier,
188
190
  config=self._tool_config,
189
191
  )
@@ -15,6 +15,7 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  import base64
18
+ import hashlib
18
19
  import json
19
20
  import logging
20
21
  from typing import Any
@@ -144,6 +145,38 @@ def _safe_json_serialize(obj) -> str:
144
145
  return str(obj)
145
146
 
146
147
 
148
+ def _truncate_tool_call_id(tool_call_id: str, max_length: int = 40) -> str:
149
+ """Truncates tool call ID to meet OpenAI's maximum length requirement.
150
+
151
+ OpenAI requires tool_call_id to be at most 40 characters. If the ID exceeds
152
+ this limit, we create a deterministic hash-based truncation to ensure:
153
+ 1. The ID stays within the limit
154
+ 2. The same input always produces the same output (deterministic)
155
+ 3. Collisions are extremely unlikely
156
+
157
+ Args:
158
+ tool_call_id: The original tool call ID
159
+ max_length: Maximum allowed length (default: 40 for OpenAI)
160
+
161
+ Returns:
162
+ Truncated tool call ID that meets the length requirement
163
+ """
164
+ if len(tool_call_id) <= max_length:
165
+ return tool_call_id
166
+
167
+ # Use first part of ID + hash of full ID to maintain uniqueness
168
+ # Format: prefix_hash where prefix is from original and hash ensures uniqueness
169
+ prefix_length = max_length - 33 # Reserve 33 chars for hash (32) + underscore (1)
170
+ if prefix_length < 1:
171
+ prefix_length = 1
172
+
173
+ prefix = tool_call_id[:prefix_length]
174
+ # Use SHA256 and take first 32 hex characters for uniqueness
175
+ hash_suffix = hashlib.sha256(tool_call_id.encode()).hexdigest()[:32]
176
+
177
+ return f"{prefix}_{hash_suffix}"
178
+
179
+
147
180
  def _content_to_message_param(
148
181
  content: types.Content,
149
182
  ) -> Union[Message, list[Message]]:
@@ -165,7 +198,7 @@ def _content_to_message_param(
165
198
  tool_messages.append(
166
199
  ChatCompletionToolMessage(
167
200
  role="tool",
168
- tool_call_id=part.function_response.id,
201
+ tool_call_id=_truncate_tool_call_id(part.function_response.id),
169
202
  content=_safe_json_serialize(part.function_response.response),
170
203
  )
171
204
  )
@@ -185,7 +218,7 @@ def _content_to_message_param(
185
218
  tool_calls.append(
186
219
  ChatCompletionAssistantToolCall(
187
220
  type="function",
188
- id=part.function_call.id,
221
+ id=_truncate_tool_call_id(part.function_call.id),
189
222
  function=Function(
190
223
  name=part.function_call.name,
191
224
  arguments=_safe_json_serialize(part.function_call.args),
@@ -464,7 +497,7 @@ def _message_to_generate_content_response(
464
497
  name=tool_call.function.name,
465
498
  args=json.loads(tool_call.function.arguments or "{}"),
466
499
  )
467
- part.function_call.id = tool_call.id
500
+ part.function_call.id = _truncate_tool_call_id(tool_call.id)
468
501
  parts.append(part)
469
502
  except json.JSONDecodeError as e:
470
503
  logger.error(
@@ -887,7 +920,7 @@ class LiteLlm(BaseLlm):
887
920
  tool_calls.append(
888
921
  ChatCompletionMessageToolCall(
889
922
  type="function",
890
- id=func_data["id"],
923
+ id=_truncate_tool_call_id(func_data["id"]),
891
924
  function=Function(
892
925
  name=func_data["name"],
893
926
  arguments=func_data["args"],
@@ -916,7 +949,7 @@ class LiteLlm(BaseLlm):
916
949
  tool_calls.append(
917
950
  ChatCompletionMessageToolCall(
918
951
  type="function",
919
- id=func_data["id"],
952
+ id=_truncate_tool_call_id(func_data["id"]),
920
953
  function=Function(
921
954
  name=func_data["name"],
922
955
  arguments=func_data["args"],
@@ -5,6 +5,7 @@ This directory contains concrete implementations of the `BaseLlm` interface, pro
5
5
 
6
6
  ## Files Overview
7
7
  - `lite_llm.py` - LLM client using the `litellm` library to support hundreds of models from different providers
8
+ - `oauth2_token_manager.py` - OAuth 2.0 Client Credentials token manager for LLM authentication
8
9
 
9
10
  ## Developer API Reference
10
11
 
@@ -14,7 +15,7 @@ This directory contains concrete implementations of the `BaseLlm` interface, pro
14
15
  **Import:** `from solace_agent_mesh.agent.adk.models.lite_llm import LiteLlm`
15
16
 
16
17
  **Classes:**
17
- - `LiteLlm(model: str, **kwargs)` - Wrapper around `litellm` supporting any model it recognizes
18
+ - `LiteLlm(model: str, cache_strategy: str = "5m", **kwargs)` - Wrapper around `litellm` supporting any model it recognizes
18
19
  - `generate_content_async(llm_request: LlmRequest, stream: bool = False) -> AsyncGenerator[LlmResponse, None]` - Generates content asynchronously with optional streaming
19
20
  - `supported_models() -> list[str]` - Returns list of supported models (empty for LiteLlm due to dynamic model support)
20
21
  - `model: str` - The name of the LiteLlm model
@@ -64,7 +65,8 @@ async def main():
64
65
  llm = LiteLlm(
65
66
  model="gpt-4-turbo",
66
67
  temperature=0.7,
67
- max_completion_tokens=150
68
+ max_completion_tokens=150,
69
+ cache_strategy="5m" # Options: "none", "5m", "1h"
68
70
  )
69
71
 
70
72
  # Create a request
@@ -96,47 +98,92 @@ async def main():
96
98
  if response.usage_metadata:
97
99
  print(f"\nTotal tokens: {response.usage_metadata.total_token_count}")
98
100
 
99
- # Example with function calling
100
- async def function_calling_example():
101
- from google.genai.types import FunctionDeclaration, Schema, Type, Tool
102
-
103
- # Define a function for the LLM to call
104
- get_weather_func = FunctionDeclaration(
105
- name="get_weather",
106
- description="Get current weather for a location",
107
- parameters=Schema(
108
- type=Type.OBJECT,
109
- properties={
110
- "location": Schema(type=Type.STRING, description="City name"),
111
- "unit": Schema(type=Type.STRING, description="Temperature unit")
112
- },
113
- required=["location"]
114
- )
101
+ # Example with OAuth authentication
102
+ async def oauth_example():
103
+ llm = LiteLlm(
104
+ model="custom-model",
105
+ oauth_token_url="https://auth.example.com/oauth/token",
106
+ oauth_client_id="your-client-id",
107
+ oauth_client_secret="your-client-secret",
108
+ oauth_scope="llm.read llm.write",
109
+ oauth_ca_cert="/path/to/ca.crt", # Optional
110
+ oauth_token_refresh_buffer_seconds=300, # Optional
111
+ oauth_max_retries=3 # Optional
115
112
  )
116
113
 
117
- llm = LiteLlm(model="gpt-4-turbo")
118
-
119
114
  request = LlmRequest(
120
- contents=[
121
- Content(
122
- role="user",
123
- parts=[Part.from_text("What's the weather like in Tokyo?")]
124
- )
125
- ],
126
- config=LlmConfig(
127
- tools=[Tool(function_declarations=[get_weather_func])]
128
- )
115
+ contents=[Content(role="user", parts=[Part.from_text("Hello!")])]
129
116
  )
130
117
 
131
118
  async for response in llm.generate_content_async(request):
132
- if response.function_calls:
133
- for func_call in response.function_calls:
134
- print(f"Function called: {func_call.name}")
135
- print(f"Arguments: {func_call.args}")
119
+ print(response.text)
120
+
121
+ if __name__ == "__main__":
122
+ asyncio.run(main())
123
+ ```
124
+
125
+ ### oauth2_token_manager.py
126
+ **Purpose:** Provides OAuth 2.0 Client Credentials flow implementation for LLM authentication with automatic token management, caching, and refresh capabilities.
127
+
128
+ **Import:** `from solace_agent_mesh.agent.adk.models.oauth2_token_manager import OAuth2ClientCredentialsTokenManager`
129
+
130
+ **Classes:**
131
+ - `OAuth2ClientCredentialsTokenManager(token_url: str, client_id: str, client_secret: str, scope: Optional[str] = None, ca_cert_path: Optional[str] = None, refresh_buffer_seconds: int = 300, max_retries: int = 3)` - Manages OAuth 2.0 Client Credentials tokens with caching and automatic refresh
132
+ - `get_token() -> str` - Get a valid OAuth 2.0 access token (async)
133
+ - `token_url: str` - OAuth 2.0 token endpoint URL
134
+ - `client_id: str` - OAuth client identifier
135
+ - `client_secret: str` - OAuth client secret
136
+ - `scope: Optional[str]` - OAuth scope (space-separated string)
137
+ - `ca_cert_path: Optional[str]` - Path to custom CA certificate file
138
+ - `refresh_buffer_seconds: int` - Seconds before actual expiry to refresh token
139
+ - `max_retries: int` - Maximum number of retry attempts for token requests
140
+
141
+ **Usage Examples:**
142
+ ```python
143
+ import asyncio
144
+ from solace_agent_mesh.agent.adk.models.oauth2_token_manager import OAuth2ClientCredentialsTokenManager
145
+
146
+ async def main():
147
+ # Initialize OAuth token manager
148
+ token_manager = OAuth2ClientCredentialsTokenManager(
149
+ token_url="https://auth.example.com/oauth/token",
150
+ client_id="your-client-id",
151
+ client_secret="your-client-secret",
152
+ scope="llm.read llm.write", # Optional
153
+ ca_cert_path="/path/to/ca.crt", # Optional for custom CA
154
+ refresh_buffer_seconds=300, # Refresh 5 minutes before expiry
155
+ max_retries=3 # Retry failed requests up to 3 times
156
+ )
157
+
158
+ try:
159
+ # Get a valid access token
160
+ access_token = await token_manager.get_token()
161
+ print(f"Access token: {access_token[:20]}...")
162
+
163
+ # Token is automatically cached and reused
164
+ # Subsequent calls will return cached token if still valid
165
+ cached_token = await token_manager.get_token()
166
+ print(f"Cached token: {cached_token[:20]}...")
167
+
168
+ except Exception as e:
169
+ print(f"Failed to get OAuth token: {e}")
170
+
171
+ # Example with custom SSL configuration
172
+ async def custom_ssl_example():
173
+ token_manager = OAuth2ClientCredentialsTokenManager(
174
+ token_url="https://secure-auth.example.com/oauth/token",
175
+ client_id="client-123",
176
+ client_secret="secret-456",
177
+ ca_cert_path="/etc/ssl/certs/custom-ca.pem", # Custom CA certificate
178
+ refresh_buffer_seconds=600, # Refresh 10 minutes early
179
+ max_retries=5 # More retries for unreliable networks
180
+ )
181
+
182
+ token = await token_manager.get_token()
183
+ print(f"Token obtained with custom SSL: {token[:20]}...")
136
184
 
137
185
  if __name__ == "__main__":
138
186
  asyncio.run(main())
139
- # asyncio.run(function_calling_example())
140
187
  ```
141
188
 
142
- # content_hash: 97abaea0097e0d6fe18f1d747ed54ced092c0a96829dc5be8448b087ac5f7c20
189
+ # content_hash: 29d771563355d8e4b320350d4fe586f19717d8b16707487efb4372125d5e0f10
@@ -124,6 +124,15 @@ async def run_adk_async_task_thread_wrapper(
124
124
  a2a_context,
125
125
  )
126
126
 
127
+ # Mark task as paused if it's waiting for peer response or user input
128
+ if task_context and is_paused:
129
+ task_context.set_paused(True)
130
+ log.debug(
131
+ "%s Task %s marked as paused, waiting for peer response or user input.",
132
+ component.log_identifier,
133
+ logical_task_id,
134
+ )
135
+
127
136
  log.debug(
128
137
  "%s ADK task %s awaited and completed (Paused: %s).",
129
138
  component.log_identifier,
@@ -46,6 +46,7 @@ class BlockStartedEvent(ParserEvent):
46
46
  class BlockProgressedEvent(ParserEvent):
47
47
  """Emitted periodically while content is being buffered for a block."""
48
48
 
49
+ params: Dict[str, Any]
49
50
  buffered_size: int
50
51
  chunk: str
51
52
 
@@ -216,6 +217,10 @@ class FencedBlockStreamParser:
216
217
  self._last_progress_update_size : current_size
217
218
  ]
218
219
  events.append(
219
- BlockProgressedEvent(buffered_size=current_size, chunk=new_chunk)
220
+ BlockProgressedEvent(
221
+ params=self._block_params,
222
+ buffered_size=current_size,
223
+ chunk=new_chunk,
224
+ )
220
225
  )
221
226
  self._last_progress_update_size = current_size
@@ -15,6 +15,7 @@ from ...common.utils.embeds import (
15
15
  LATE_EMBED_TYPES,
16
16
  EMBED_DELIMITER_OPEN,
17
17
  )
18
+ from ...common.utils.embeds.types import ResolutionMode
18
19
 
19
20
  log = logging.getLogger(__name__)
20
21
 
@@ -102,6 +103,7 @@ class ADKToolWrapper:
102
103
  context=context_for_embeds,
103
104
  resolver_func=evaluate_embed,
104
105
  types_to_resolve=self._types_to_resolve,
106
+ resolution_mode=ResolutionMode.TOOL_PARAMETER,
105
107
  log_identifier=log_identifier,
106
108
  config=self._tool_config,
107
109
  )
@@ -123,6 +125,7 @@ class ADKToolWrapper:
123
125
  context=context_for_embeds,
124
126
  resolver_func=evaluate_embed,
125
127
  types_to_resolve=self._types_to_resolve,
128
+ resolution_mode=ResolutionMode.TOOL_PARAMETER,
126
129
  log_identifier=log_identifier,
127
130
  config=self._tool_config,
128
131
  )