agent-starter-pack 0.3.3__py3-none-any.whl → 0.21.0__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.
Files changed (255) hide show
  1. agent_starter_pack/agents/README.md +7 -0
  2. agents/langgraph_base_react/template/.templateconfig.yaml → agent_starter_pack/agents/adk_a2a_base/.template/templateconfig.yaml +5 -10
  3. agent_starter_pack/agents/adk_a2a_base/README.md +37 -0
  4. src/deployment_targets/cloud_run/Dockerfile → agent_starter_pack/agents/adk_a2a_base/app/__init__.py +2 -14
  5. agent_starter_pack/agents/adk_a2a_base/app/agent.py +70 -0
  6. agent_starter_pack/agents/adk_a2a_base/notebooks/adk_a2a_app_testing.ipynb +583 -0
  7. agents/crewai_coding_crew/notebooks/evaluating_crewai_agent.ipynb → agent_starter_pack/agents/adk_a2a_base/notebooks/evaluating_adk_agent.ipynb +163 -199
  8. {agents/adk_base → agent_starter_pack/agents/adk_a2a_base}/tests/integration/test_agent.py +2 -2
  9. agents/adk_base/template/.templateconfig.yaml → agent_starter_pack/agents/adk_base/.template/templateconfig.yaml +4 -1
  10. {agents → agent_starter_pack/agents}/adk_base/README.md +1 -1
  11. agent_starter_pack/agents/adk_base/app/__init__.py +17 -0
  12. {agents → agent_starter_pack/agents}/adk_base/app/agent.py +5 -2
  13. {agents → agent_starter_pack/agents}/adk_base/notebooks/adk_app_testing.ipynb +128 -82
  14. agents/langgraph_base_react/notebooks/evaluating_langgraph_agent.ipynb → agent_starter_pack/agents/adk_base/notebooks/evaluating_adk_agent.ipynb +181 -207
  15. agent_starter_pack/agents/adk_base/tests/integration/test_agent.py +58 -0
  16. agents/crewai_coding_crew/template/.templateconfig.yaml → agent_starter_pack/agents/adk_live/.template/templateconfig.yaml +5 -9
  17. agent_starter_pack/agents/adk_live/README.md +32 -0
  18. agent_starter_pack/agents/adk_live/app/__init__.py +17 -0
  19. agent_starter_pack/agents/adk_live/app/agent.py +51 -0
  20. agent_starter_pack/agents/adk_live/tests/unit/test_dummy.py +38 -0
  21. agents/agentic_rag/template/.templateconfig.yaml → agent_starter_pack/agents/agentic_rag/.template/templateconfig.yaml +7 -3
  22. {agents → agent_starter_pack/agents}/agentic_rag/README.md +1 -1
  23. agent_starter_pack/agents/agentic_rag/app/__init__.py +17 -0
  24. {agents → agent_starter_pack/agents}/agentic_rag/app/agent.py +8 -4
  25. {agents → agent_starter_pack/agents}/agentic_rag/notebooks/adk_app_testing.ipynb +128 -82
  26. agent_starter_pack/agents/agentic_rag/notebooks/evaluating_adk_agent.ipynb +1535 -0
  27. {agents → agent_starter_pack/agents}/agentic_rag/tests/integration/test_agent.py +3 -3
  28. agent_starter_pack/agents/langgraph_base/.template/templateconfig.yaml +31 -0
  29. agent_starter_pack/agents/langgraph_base/README.md +30 -0
  30. agent_starter_pack/agents/langgraph_base/app/__init__.py +17 -0
  31. agent_starter_pack/agents/langgraph_base/app/agent.py +34 -0
  32. {agents/crewai_coding_crew → agent_starter_pack/agents/langgraph_base}/notebooks/evaluating_langgraph_agent.ipynb +30 -17
  33. {agents/langgraph_base_react → agent_starter_pack/agents/langgraph_base}/tests/integration/test_agent.py +2 -2
  34. {src → agent_starter_pack}/base_template/.gitignore +5 -3
  35. agent_starter_pack/base_template/GEMINI.md +5 -0
  36. agent_starter_pack/base_template/Makefile +339 -0
  37. agent_starter_pack/base_template/README.md +267 -0
  38. agent_starter_pack/base_template/deployment/README.md +11 -0
  39. {src → agent_starter_pack}/base_template/deployment/terraform/apis.tf +2 -2
  40. {src → agent_starter_pack}/base_template/deployment/terraform/dev/apis.tf +6 -1
  41. {src → agent_starter_pack}/base_template/deployment/terraform/dev/iam.tf +12 -11
  42. {src → agent_starter_pack}/base_template/deployment/terraform/dev/providers.tf +5 -1
  43. {src → agent_starter_pack}/base_template/deployment/terraform/dev/storage.tf +1 -1
  44. {src → agent_starter_pack}/base_template/deployment/terraform/dev/variables.tf +10 -10
  45. agent_starter_pack/base_template/deployment/terraform/dev/{% if cookiecutter.is_adk %}telemetry.tf{% else %}unused_telemetry.tf{% endif %} +193 -0
  46. agent_starter_pack/base_template/deployment/terraform/github.tf +337 -0
  47. {src → agent_starter_pack}/base_template/deployment/terraform/iam.tf +20 -41
  48. {src → agent_starter_pack}/base_template/deployment/terraform/locals.tf +10 -3
  49. {src/resources/setup_cicd → agent_starter_pack/base_template/deployment/terraform}/providers.tf +8 -1
  50. {src → agent_starter_pack}/base_template/deployment/terraform/service_accounts.tf +7 -8
  51. agent_starter_pack/base_template/deployment/terraform/sql/completions.sql +138 -0
  52. {src → agent_starter_pack}/base_template/deployment/terraform/storage.tf +7 -16
  53. {src → agent_starter_pack}/base_template/deployment/terraform/variables.tf +61 -28
  54. {src → agent_starter_pack}/base_template/deployment/terraform/vars/env.tfvars +6 -1
  55. agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'github_actions' %}wif.tf{% else %}unused_wif.tf{% endif %} +43 -0
  56. src/base_template/deployment/terraform/build_triggers.tf → agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}build_triggers.tf{% else %}unused_build_triggers.tf{% endif %} +55 -38
  57. agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.is_adk %}telemetry.tf{% else %}unused_telemetry.tf{% endif %} +206 -0
  58. {src → agent_starter_pack}/base_template/pyproject.toml +24 -37
  59. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/deploy-to-prod.yaml +132 -0
  60. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/pr_checks.yaml +65 -0
  61. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/staging.yaml +259 -0
  62. src/base_template/deployment/cd/deploy-to-prod.yaml → agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/deploy-to-prod.yaml +38 -30
  63. src/base_template/deployment/ci/pr_checks.yaml → agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/pr_checks.yaml +5 -5
  64. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/staging.yaml +322 -0
  65. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/telemetry.py +96 -0
  66. {src/base_template/app/utils → agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils}/typing.py +7 -9
  67. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}converters{% else %}unused_converters{% endif %}/__init__.py +25 -0
  68. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}converters{% else %}unused_converters{% endif %}/part_converter.py +138 -0
  69. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}executor{% else %}unused_executor{% endif %}/__init__.py +13 -0
  70. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}executor{% else %}unused_executor{% endif %}/a2a_agent_executor.py +265 -0
  71. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}executor{% else %}unused_executor{% endif %}/task_result_aggregator.py +152 -0
  72. agent_starter_pack/cli/commands/create.py +1256 -0
  73. agent_starter_pack/cli/commands/enhance.py +611 -0
  74. agent_starter_pack/cli/commands/list.py +203 -0
  75. agent_starter_pack/cli/commands/register_gemini_enterprise.py +1070 -0
  76. agent_starter_pack/cli/commands/setup_cicd.py +862 -0
  77. {src → agent_starter_pack}/cli/main.py +10 -2
  78. {src → agent_starter_pack}/cli/utils/cicd.py +139 -48
  79. agent_starter_pack/cli/utils/gcp.py +263 -0
  80. agent_starter_pack/cli/utils/logging.py +103 -0
  81. agent_starter_pack/cli/utils/remote_template.py +677 -0
  82. agent_starter_pack/cli/utils/template.py +1466 -0
  83. {src → agent_starter_pack}/data_ingestion/data_ingestion_pipeline/components/process_data.py +1 -1
  84. {src → agent_starter_pack}/data_ingestion/data_ingestion_pipeline/submit_pipeline.py +20 -6
  85. {src → agent_starter_pack}/data_ingestion/pyproject.toml +1 -0
  86. {src → agent_starter_pack}/data_ingestion/uv.lock +602 -494
  87. agent_starter_pack/deployment_targets/agent_engine/tests/integration/test_agent_engine_app.py +484 -0
  88. agent_starter_pack/deployment_targets/agent_engine/tests/load_test/README.md +84 -0
  89. agent_starter_pack/deployment_targets/agent_engine/tests/load_test/load_test.py +424 -0
  90. agent_starter_pack/deployment_targets/agent_engine/tests/{% if cookiecutter.is_a2a %}helpers.py{% else %}unused_helpers.py{% endif %} +138 -0
  91. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/agent_engine_app.py +263 -0
  92. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/app_utils/deploy.py +414 -0
  93. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_adk_live %}expose_app.py{% else %}unused_expose_app.py{% endif %} +519 -0
  94. agent_starter_pack/deployment_targets/cloud_run/Dockerfile +51 -0
  95. agent_starter_pack/deployment_targets/cloud_run/deployment/terraform/dev/service.tf +243 -0
  96. agent_starter_pack/deployment_targets/cloud_run/deployment/terraform/service.tf +417 -0
  97. agent_starter_pack/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +705 -0
  98. agent_starter_pack/deployment_targets/cloud_run/tests/load_test/.results/.placeholder +321 -0
  99. agent_starter_pack/deployment_targets/cloud_run/tests/load_test/README.md +165 -0
  100. agent_starter_pack/deployment_targets/cloud_run/tests/load_test/load_test.py +329 -0
  101. agent_starter_pack/deployment_targets/cloud_run/{{cookiecutter.agent_directory}}/fast_api_app.py +556 -0
  102. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/package-lock.json +79 -1044
  103. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/package.json +1 -9
  104. agent_starter_pack/frontends/adk_live_react/frontend/src/App.tsx +65 -0
  105. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/logger/Logger.tsx +8 -3
  106. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/logger/logger.scss +26 -0
  107. agent_starter_pack/frontends/adk_live_react/frontend/src/components/side-panel/SidePanel.tsx +516 -0
  108. agent_starter_pack/frontends/adk_live_react/frontend/src/components/side-panel/side-panel.scss +563 -0
  109. agent_starter_pack/frontends/adk_live_react/frontend/src/components/transcription-preview/TranscriptionPreview.tsx +106 -0
  110. agent_starter_pack/frontends/adk_live_react/frontend/src/components/transcription-preview/transcription-preview.scss +150 -0
  111. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/hooks/use-live-api.ts +8 -2
  112. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/multimodal-live-types.ts +40 -2
  113. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/audio-recorder.ts +1 -1
  114. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/audio-streamer.ts +1 -1
  115. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/multimodal-live-client.ts +210 -24
  116. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/utils.ts +27 -5
  117. agent_starter_pack/resources/docs/adk-cheatsheet.md +1628 -0
  118. agent_starter_pack/resources/locks/uv-adk_a2a_base-agent_engine.lock +4966 -0
  119. agent_starter_pack/resources/locks/uv-adk_a2a_base-cloud_run.lock +5011 -0
  120. agent_starter_pack/resources/locks/uv-adk_base-agent_engine.lock +4946 -0
  121. agent_starter_pack/resources/locks/uv-adk_base-cloud_run.lock +4991 -0
  122. agent_starter_pack/resources/locks/uv-adk_live-agent_engine.lock +4963 -0
  123. agent_starter_pack/resources/locks/uv-adk_live-cloud_run.lock +5006 -0
  124. agent_starter_pack/resources/locks/uv-agentic_rag-agent_engine.lock +5487 -0
  125. agent_starter_pack/resources/locks/uv-agentic_rag-cloud_run.lock +5532 -0
  126. agent_starter_pack/resources/locks/uv-langgraph_base-agent_engine.lock +5788 -0
  127. agent_starter_pack/resources/locks/uv-langgraph_base-cloud_run.lock +5811 -0
  128. {src → agent_starter_pack}/utils/generate_locks.py +15 -12
  129. {src → agent_starter_pack}/utils/lock_utils.py +4 -7
  130. {src → agent_starter_pack}/utils/watch_and_rebuild.py +2 -2
  131. agent_starter_pack-0.21.0.dist-info/METADATA +182 -0
  132. agent_starter_pack-0.21.0.dist-info/RECORD +171 -0
  133. agent_starter_pack-0.21.0.dist-info/entry_points.txt +2 -0
  134. llm.txt +362 -0
  135. agent_starter_pack-0.3.3.dist-info/METADATA +0 -164
  136. agent_starter_pack-0.3.3.dist-info/RECORD +0 -176
  137. agent_starter_pack-0.3.3.dist-info/entry_points.txt +0 -2
  138. agents/crewai_coding_crew/README.md +0 -34
  139. agents/crewai_coding_crew/app/agent.py +0 -86
  140. agents/crewai_coding_crew/app/crew/config/agents.yaml +0 -39
  141. agents/crewai_coding_crew/app/crew/config/tasks.yaml +0 -37
  142. agents/crewai_coding_crew/app/crew/crew.py +0 -71
  143. agents/crewai_coding_crew/tests/integration/test_agent.py +0 -47
  144. agents/langgraph_base_react/README.md +0 -9
  145. agents/langgraph_base_react/app/agent.py +0 -73
  146. agents/live_api/README.md +0 -37
  147. agents/live_api/app/agent.py +0 -78
  148. agents/live_api/app/server.py +0 -196
  149. agents/live_api/app/templates.py +0 -51
  150. agents/live_api/app/vector_store.py +0 -55
  151. agents/live_api/template/.templateconfig.yaml +0 -29
  152. agents/live_api/tests/integration/test_server_e2e.py +0 -254
  153. agents/live_api/tests/load_test/load_test.py +0 -40
  154. agents/live_api/tests/unit/test_server.py +0 -143
  155. src/base_template/Makefile +0 -72
  156. src/base_template/README.md +0 -208
  157. src/base_template/app/__init__.py +0 -3
  158. src/base_template/app/utils/tracing.py +0 -155
  159. src/base_template/deployment/README.md +0 -126
  160. src/base_template/deployment/cd/staging.yaml +0 -216
  161. src/base_template/deployment/terraform/dev/log_sinks.tf +0 -63
  162. src/base_template/deployment/terraform/log_sinks.tf +0 -70
  163. src/base_template/deployment/terraform/providers.tf +0 -37
  164. src/cli/commands/create.py +0 -664
  165. src/cli/commands/setup_cicd.py +0 -829
  166. src/cli/utils/gcp.py +0 -117
  167. src/cli/utils/logging.py +0 -51
  168. src/cli/utils/template.py +0 -737
  169. src/deployment_targets/agent_engine/app/agent_engine_app.py +0 -336
  170. src/deployment_targets/agent_engine/notebooks/intro_agent_engine.ipynb +0 -1025
  171. src/deployment_targets/agent_engine/tests/integration/test_agent_engine_app.py +0 -183
  172. src/deployment_targets/agent_engine/tests/load_test/README.md +0 -42
  173. src/deployment_targets/agent_engine/tests/load_test/load_test.py +0 -107
  174. src/deployment_targets/cloud_run/app/server.py +0 -154
  175. src/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +0 -249
  176. src/deployment_targets/cloud_run/tests/load_test/.results/.placeholder +0 -0
  177. src/deployment_targets/cloud_run/tests/load_test/README.md +0 -83
  178. src/deployment_targets/cloud_run/tests/load_test/load_test.py +0 -118
  179. src/deployment_targets/cloud_run/uv.lock +0 -6952
  180. src/frontends/live_api_react/frontend/src/App.tsx +0 -205
  181. src/frontends/live_api_react/frontend/src/components/control-tray/ControlTray.tsx +0 -217
  182. src/frontends/live_api_react/frontend/src/components/control-tray/control-tray.scss +0 -201
  183. src/frontends/live_api_react/frontend/src/components/side-panel/SidePanel.tsx +0 -161
  184. src/frontends/live_api_react/frontend/src/components/side-panel/side-panel.scss +0 -285
  185. src/frontends/streamlit/frontend/side_bar.py +0 -214
  186. src/frontends/streamlit/frontend/streamlit_app.py +0 -265
  187. src/frontends/streamlit/frontend/style/app_markdown.py +0 -37
  188. src/frontends/streamlit/frontend/utils/chat_utils.py +0 -67
  189. src/frontends/streamlit/frontend/utils/local_chat_history.py +0 -125
  190. src/frontends/streamlit/frontend/utils/message_editing.py +0 -59
  191. src/frontends/streamlit/frontend/utils/multimodal_utils.py +0 -217
  192. src/frontends/streamlit/frontend/utils/stream_handler.py +0 -301
  193. src/frontends/streamlit/frontend/utils/title_summary.py +0 -94
  194. src/frontends/streamlit_adk/frontend/side_bar.py +0 -214
  195. src/frontends/streamlit_adk/frontend/streamlit_app.py +0 -314
  196. src/frontends/streamlit_adk/frontend/style/app_markdown.py +0 -37
  197. src/frontends/streamlit_adk/frontend/utils/chat_utils.py +0 -84
  198. src/frontends/streamlit_adk/frontend/utils/local_chat_history.py +0 -110
  199. src/frontends/streamlit_adk/frontend/utils/message_editing.py +0 -61
  200. src/frontends/streamlit_adk/frontend/utils/multimodal_utils.py +0 -223
  201. src/frontends/streamlit_adk/frontend/utils/stream_handler.py +0 -311
  202. src/frontends/streamlit_adk/frontend/utils/title_summary.py +0 -129
  203. src/resources/containers/data_processing/Dockerfile +0 -27
  204. src/resources/containers/e2e-tests/Dockerfile +0 -19
  205. src/resources/idx/.idx/dev.nix +0 -57
  206. src/resources/idx/idx-template.json +0 -21
  207. src/resources/idx/idx-template.nix +0 -26
  208. src/resources/locks/uv-adk_base-agent_engine.lock +0 -5338
  209. src/resources/locks/uv-adk_base-cloud_run.lock +0 -5930
  210. src/resources/locks/uv-agentic_rag-agent_engine.lock +0 -5528
  211. src/resources/locks/uv-agentic_rag-cloud_run.lock +0 -6120
  212. src/resources/locks/uv-crewai_coding_crew-agent_engine.lock +0 -6231
  213. src/resources/locks/uv-crewai_coding_crew-cloud_run.lock +0 -6839
  214. src/resources/locks/uv-langgraph_base_react-agent_engine.lock +0 -5233
  215. src/resources/locks/uv-langgraph_base_react-cloud_run.lock +0 -5862
  216. src/resources/locks/uv-live_api-cloud_run.lock +0 -5832
  217. src/resources/setup_cicd/cicd_variables.tf +0 -41
  218. src/resources/setup_cicd/github.tf +0 -87
  219. {agents → agent_starter_pack/agents}/agentic_rag/app/retrievers.py +0 -0
  220. {agents → agent_starter_pack/agents}/agentic_rag/app/templates.py +0 -0
  221. {src → agent_starter_pack}/base_template/deployment/terraform/dev/vars/env.tfvars +0 -0
  222. {src → agent_starter_pack}/base_template/tests/unit/test_dummy.py +0 -0
  223. {src/deployment_targets/agent_engine/app/utils → agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils}/gcs.py +0 -0
  224. {src → agent_starter_pack}/cli/utils/__init__.py +0 -0
  225. {src → agent_starter_pack}/cli/utils/datastores.py +0 -0
  226. {src → agent_starter_pack}/cli/utils/version.py +0 -0
  227. {src → agent_starter_pack}/data_ingestion/README.md +0 -0
  228. {src → agent_starter_pack}/data_ingestion/data_ingestion_pipeline/components/ingest_data.py +0 -0
  229. {src → agent_starter_pack}/data_ingestion/data_ingestion_pipeline/pipeline.py +0 -0
  230. {src → agent_starter_pack}/deployment_targets/agent_engine/deployment_metadata.json +0 -0
  231. {src → agent_starter_pack}/deployment_targets/agent_engine/tests/load_test/.results/.placeholder +0 -0
  232. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/public/favicon.ico +0 -0
  233. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/public/index.html +0 -0
  234. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/public/robots.txt +0 -0
  235. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/App.scss +0 -0
  236. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/App.test.tsx +0 -0
  237. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/audio-pulse/AudioPulse.tsx +0 -0
  238. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/audio-pulse/audio-pulse.scss +0 -0
  239. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/logger/mock-logs.ts +0 -0
  240. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/contexts/LiveAPIContext.tsx +0 -0
  241. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/hooks/use-media-stream-mux.ts +0 -0
  242. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/hooks/use-screen-capture.ts +0 -0
  243. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/hooks/use-webcam.ts +0 -0
  244. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/index.css +0 -0
  245. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/index.tsx +0 -0
  246. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/react-app-env.d.ts +0 -0
  247. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/reportWebVitals.ts +0 -0
  248. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/setupTests.ts +0 -0
  249. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/audioworklet-registry.ts +0 -0
  250. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/store-logger.ts +0 -0
  251. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/worklets/audio-processing.ts +0 -0
  252. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/worklets/vol-meter.ts +0 -0
  253. {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/tsconfig.json +0 -0
  254. {agent_starter_pack-0.3.3.dist-info → agent_starter_pack-0.21.0.dist-info}/WHEEL +0 -0
  255. {agent_starter_pack-0.3.3.dist-info → agent_starter_pack-0.21.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,217 +0,0 @@
1
- # Copyright 2025 Google LLC
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- import base64
16
- from typing import Any
17
- from urllib.parse import quote
18
-
19
- from google.cloud import storage
20
-
21
- HELP_MESSAGE_MULTIMODALITY = (
22
- "For Gemini models to access the URIs you provide, store them in "
23
- "Google Cloud Storage buckets within the same project used by Gemini."
24
- )
25
-
26
- HELP_GCS_CHECKBOX = (
27
- "Enabling GCS upload will increase the app observability by avoiding"
28
- " forwarding and logging large byte strings within the app."
29
- )
30
-
31
-
32
- def format_content(content: str | list[dict[str, Any]]) -> str:
33
- """Formats content as a string, handling both text and multimedia inputs."""
34
- if isinstance(content, str):
35
- return content
36
- if len(content) == 1 and content[0]["type"] == "text":
37
- return content[0]["text"]
38
- markdown = """Media:
39
- """
40
- text = ""
41
- for part in content:
42
- if part["type"] == "text":
43
- text = part["text"]
44
- # Local Images:
45
- if part["type"] == "image_url":
46
- image_url = part["image_url"]["url"]
47
- image_markdown = f'<img src="{image_url}" width="100">'
48
- markdown = (
49
- markdown
50
- + f"""
51
- - {image_markdown}
52
- """
53
- )
54
- if part["type"] == "media":
55
- # Local other media
56
- if "data" in part:
57
- markdown = markdown + f"- Local media: {part['file_name']}\n"
58
- # From GCS:
59
- if "file_uri" in part:
60
- # GCS images
61
- if "image" in part["mime_type"]:
62
- image_url = gs_uri_to_https_url(part["file_uri"])
63
- image_markdown = f'<img src="{image_url}" width="100">'
64
- markdown = (
65
- markdown
66
- + f"""
67
- - {image_markdown}
68
- """
69
- )
70
- # GCS other media
71
- else:
72
- image_url = gs_uri_to_https_url(part["file_uri"])
73
- markdown = (
74
- markdown + f"- Remote media: "
75
- f"[{part['file_uri']}]({image_url})\n"
76
- )
77
- markdown = (
78
- markdown
79
- + f"""
80
-
81
- {text}"""
82
- )
83
- return markdown
84
-
85
-
86
- def get_gcs_blob_mime_type(gcs_uri: str) -> str | None:
87
- """Fetches the MIME type (content type) of a Google Cloud Storage blob.
88
-
89
- Args:
90
- gcs_uri (str): The GCS URI of the blob in the format "gs://bucket-name/object-name".
91
-
92
- Returns:
93
- str: The MIME type of the blob (e.g., "image/jpeg", "text/plain") if found,
94
- or None if the blob does not exist or an error occurs.
95
- """
96
- storage_client = storage.Client()
97
-
98
- try:
99
- bucket_name, object_name = gcs_uri.replace("gs://", "").split("/", 1)
100
-
101
- bucket = storage_client.bucket(bucket_name)
102
- blob = bucket.blob(object_name)
103
- blob.reload()
104
- return blob.content_type
105
- except Exception as e:
106
- print(f"Error retrieving MIME type for {gcs_uri}: {e}")
107
- return None # Indicate failure
108
-
109
-
110
- def get_parts_from_files(
111
- upload_gcs_checkbox: bool, uploaded_files: list[Any], gcs_uris: str
112
- ) -> list[dict[str, Any]]:
113
- """Processes uploaded files and GCS URIs to create a list of content parts."""
114
- parts = []
115
- # read from local directly
116
- if not upload_gcs_checkbox:
117
- for uploaded_file in uploaded_files:
118
- im_bytes = uploaded_file.read()
119
- if "image" in uploaded_file.type:
120
- content = {
121
- "type": "image_url",
122
- "image_url": {
123
- "url": f"data:{uploaded_file.type};base64,"
124
- f"{base64.b64encode(im_bytes).decode('utf-8')}"
125
- },
126
- "file_name": uploaded_file.name,
127
- }
128
- else:
129
- content = {
130
- "type": "media",
131
- "data": base64.b64encode(im_bytes).decode("utf-8"),
132
- "file_name": uploaded_file.name,
133
- "mime_type": uploaded_file.type,
134
- }
135
-
136
- parts.append(content)
137
- if gcs_uris != "":
138
- for uri in gcs_uris.split(","):
139
- content = {
140
- "type": "media",
141
- "file_uri": uri,
142
- "mime_type": get_gcs_blob_mime_type(uri),
143
- }
144
- parts.append(content)
145
- return parts
146
-
147
-
148
- def upload_bytes_to_gcs(
149
- bucket_name: str,
150
- blob_name: str,
151
- file_bytes: bytes,
152
- content_type: str | None = None,
153
- ) -> str:
154
- """Uploads a bytes object to Google Cloud Storage and returns the GCS URI.
155
-
156
- Args:
157
- bucket_name: The name of the GCS bucket.
158
- blob_name: The desired name for the uploaded file in GCS.
159
- file_bytes: The file's content as a bytes object.
160
- content_type (optional): The MIME type of the file (e.g., "image/png").
161
- If not provided, GCS will try to infer it.
162
-
163
- Returns:
164
- str: The GCS URI (gs://bucket_name/blob_name) of the uploaded file.
165
-
166
- Raises:
167
- GoogleCloudError: If there's an issue with the GCS operation.
168
- """
169
- storage_client = storage.Client()
170
- bucket = storage_client.bucket(bucket_name)
171
- blob = bucket.blob(blob_name)
172
- blob.upload_from_string(data=file_bytes, content_type=content_type)
173
- # Construct and return the GCS URI
174
- gcs_uri = f"gs://{bucket_name}/{blob_name}"
175
- return gcs_uri
176
-
177
-
178
- def gs_uri_to_https_url(gs_uri: str) -> str:
179
- """Converts a GS URI to an HTTPS URL without authentication.
180
-
181
- Args:
182
- gs_uri: The GS URI in the format gs://<bucket>/<object>.
183
-
184
- Returns:
185
- The corresponding HTTPS URL, or None if the GS URI is invalid.
186
- """
187
-
188
- if not gs_uri.startswith("gs://"):
189
- raise ValueError("Invalid GS URI format")
190
-
191
- gs_uri = gs_uri[5:]
192
-
193
- # Extract bucket and object names, then URL encode the object name
194
- bucket_name, object_name = gs_uri.split("/", 1)
195
- object_name = quote(object_name)
196
-
197
- # Construct the HTTPS URL
198
- https_url = f"https://storage.mtls.cloud.google.com/{bucket_name}/{object_name}"
199
- return https_url
200
-
201
-
202
- def upload_files_to_gcs(st: Any, bucket_name: str, files_to_upload: list[Any]) -> None:
203
- """Upload multiple files to Google Cloud Storage and store URIs in session state."""
204
- bucket_name = bucket_name.replace("gs://", "")
205
- uploaded_uris = []
206
- for file in files_to_upload:
207
- if file:
208
- file_bytes = file.read()
209
- gcs_uri = upload_bytes_to_gcs(
210
- bucket_name=bucket_name,
211
- blob_name=file.name,
212
- file_bytes=file_bytes,
213
- content_type=file.type,
214
- )
215
- uploaded_uris.append(gcs_uri)
216
- st.session_state.uploader_key += 1
217
- st.session_state["gcs_uris_to_be_sent"] = ",".join(uploaded_uris)
@@ -1,301 +0,0 @@
1
- # Copyright 2025 Google LLC
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- # mypy: disable-error-code="unreachable"
16
- import importlib
17
- import json
18
- import uuid
19
- from collections.abc import Generator
20
- from typing import Any
21
- from urllib.parse import urljoin
22
-
23
- import google.auth
24
- import google.auth.transport.requests
25
- import google.oauth2.id_token
26
- import requests
27
- import streamlit as st
28
- import vertexai
29
- from google.auth.exceptions import DefaultCredentialsError
30
- from langchain_core.messages import AIMessage, ToolMessage
31
- from vertexai import agent_engines
32
-
33
- from frontend.utils.multimodal_utils import format_content
34
-
35
- st.cache_resource.clear()
36
-
37
-
38
- @st.cache_resource
39
- def get_remote_agent(remote_agent_engine_id: str) -> Any:
40
- """Get cached remote agent instance."""
41
- # Extract location and engine ID from the full resource ID.
42
- parts = remote_agent_engine_id.split("/")
43
- project_id = parts[1]
44
- location = parts[3]
45
- vertexai.init(project=project_id, location=location)
46
- return agent_engines.AgentEngine(remote_agent_engine_id)
47
-
48
-
49
- @st.cache_resource
50
- def get_remote_url_config(url: str, authenticate_request: bool) -> dict[str, Any]:
51
- """Get cached remote URL agent configuration."""
52
- stream_url = urljoin(url, "stream_messages")
53
- creds, _ = google.auth.default()
54
- id_token = None
55
- if authenticate_request:
56
- auth_req = google.auth.transport.requests.Request()
57
- try:
58
- id_token = google.oauth2.id_token.fetch_id_token(auth_req, stream_url)
59
- except DefaultCredentialsError:
60
- creds.refresh(auth_req)
61
- id_token = creds.id_token
62
- return {
63
- "url": stream_url,
64
- "authenticate_request": authenticate_request,
65
- "creds": creds,
66
- "id_token": id_token,
67
- }
68
-
69
-
70
- @st.cache_resource()
71
- def get_local_agent(agent_callable_path: str) -> Any:
72
- """Get cached local agent instance."""
73
- module_path, class_name = agent_callable_path.rsplit(".", 1)
74
- module = importlib.import_module(module_path)
75
- agent = getattr(module, class_name)()
76
- agent.set_up()
77
- return agent
78
-
79
-
80
- class Client:
81
- """A client for streaming events from a server."""
82
-
83
- def __init__(
84
- self,
85
- agent_callable_path: str | None = None,
86
- remote_agent_engine_id: str | None = None,
87
- url: str | None = None,
88
- authenticate_request: bool = False,
89
- ) -> None:
90
- """Initialize the Client with appropriate configuration.
91
-
92
- Args:
93
- agent_callable_path: Path to local agent class
94
- remote_agent_engine_id: ID of remote Agent engine
95
- url: URL for remote service
96
- authenticate_request: Whether to authenticate requests to remote URL
97
- """
98
- if url:
99
- remote_config = get_remote_url_config(url, authenticate_request)
100
- self.url = remote_config["url"]
101
- self.authenticate_request = remote_config["authenticate_request"]
102
- self.creds = remote_config["creds"]
103
- self.id_token = remote_config["id_token"]
104
- self.agent = None
105
- elif remote_agent_engine_id:
106
- self.agent = get_remote_agent(remote_agent_engine_id)
107
- self.url = None
108
- else:
109
- self.url = None
110
- if agent_callable_path is None:
111
- raise ValueError("agent_callable_path cannot be None")
112
- self.agent = get_local_agent(agent_callable_path)
113
-
114
- def log_feedback(self, feedback_dict: dict[str, Any], run_id: str) -> None:
115
- """Log user feedback for a specific run."""
116
- score = feedback_dict["score"]
117
- if score == "😞":
118
- score = 0.0
119
- elif score == "🙁":
120
- score = 0.25
121
- elif score == "😐":
122
- score = 0.5
123
- elif score == "🙂":
124
- score = 0.75
125
- elif score == "😀":
126
- score = 1.0
127
- feedback_dict["score"] = score
128
- feedback_dict["run_id"] = run_id
129
- feedback_dict["log_type"] = "feedback"
130
- feedback_dict.pop("type")
131
- url = urljoin(self.url, "feedback")
132
- headers = {
133
- "Content-Type": "application/json",
134
- }
135
- if self.url:
136
- url = urljoin(self.url, "feedback")
137
- headers = {
138
- "Content-Type": "application/json",
139
- }
140
- if self.authenticate_request:
141
- headers["Authorization"] = f"Bearer {self.id_token}"
142
- requests.post(
143
- url, data=json.dumps(feedback_dict), headers=headers, timeout=10
144
- )
145
- elif self.agent is not None:
146
- self.agent.register_feedback(feedback=feedback_dict)
147
- else:
148
- raise ValueError("No agent or URL configured for feedback logging")
149
-
150
- def stream_messages(
151
- self, data: dict[str, Any]
152
- ) -> Generator[dict[str, Any], None, None]:
153
- """Stream events from the server, yielding parsed event data."""
154
- if self.url:
155
- headers = {
156
- "Content-Type": "application/json",
157
- "Accept": "text/event-stream",
158
- }
159
- if self.authenticate_request:
160
- headers["Authorization"] = f"Bearer {self.id_token}"
161
- with requests.post(
162
- self.url, json=data, headers=headers, stream=True, timeout=60
163
- ) as response:
164
- for line in response.iter_lines():
165
- if line:
166
- try:
167
- event = json.loads(line.decode("utf-8"))
168
- yield event
169
- except json.JSONDecodeError:
170
- print(f"Failed to parse event: {line.decode('utf-8')}")
171
- elif self.agent is not None:
172
- yield from self.agent.stream_query(**data)
173
-
174
-
175
- class StreamHandler:
176
- """Handles streaming updates to a Streamlit interface."""
177
-
178
- def __init__(self, st: Any, initial_text: str = "") -> None:
179
- """Initialize the StreamHandler with Streamlit context and initial text."""
180
- self.st = st
181
- self.tool_expander = st.expander("Tool Calls:", expanded=False)
182
- self.container = st.empty()
183
- self.text = initial_text
184
- self.tools_logs = initial_text
185
-
186
- def new_token(self, token: str) -> None:
187
- """Add a new token to the main text display."""
188
- self.text += token
189
- self.container.markdown(format_content(self.text), unsafe_allow_html=True)
190
-
191
- def new_status(self, status_update: str) -> None:
192
- """Add a new status update to the tool calls expander."""
193
- self.tools_logs += status_update
194
- self.tool_expander.markdown(status_update)
195
-
196
-
197
- class EventProcessor:
198
- """Processes events from the stream and updates the UI accordingly."""
199
-
200
- def __init__(self, st: Any, client: Client, stream_handler: StreamHandler) -> None:
201
- """Initialize the EventProcessor with Streamlit context, client, and stream handler."""
202
- self.st = st
203
- self.client = client
204
- self.stream_handler = stream_handler
205
- self.final_content = ""
206
- self.tool_calls: list[dict[str, Any]] = []
207
- self.current_run_id: str | None = None
208
- self.additional_kwargs: dict[str, Any] = {}
209
-
210
- def process_events(self) -> None:
211
- """Process events from the stream, handling each event type appropriately."""
212
- messages = self.st.session_state.user_chats[
213
- self.st.session_state["session_id"]
214
- ]["messages"]
215
- self.current_run_id = str(uuid.uuid4())
216
- # Set run_id in session state at start of processing
217
- self.st.session_state["run_id"] = self.current_run_id
218
- stream = self.client.stream_messages(
219
- data={
220
- "input": {"messages": messages},
221
- "config": {
222
- "run_id": self.current_run_id,
223
- "metadata": {
224
- "user_id": self.st.session_state["user_id"],
225
- "session_id": self.st.session_state["session_id"],
226
- },
227
- },
228
- }
229
- )
230
- # Each event is a tuple message, metadata. https://langchain-ai.github.io/langgraph/how-tos/streaming/#messages
231
- for message, _ in stream:
232
- if isinstance(message, dict):
233
- if message.get("type") == "constructor":
234
- message = message["kwargs"]
235
-
236
- # Handle tool calls
237
- if message.get("tool_calls"):
238
- tool_calls = message["tool_calls"]
239
- ai_message = AIMessage(content="", tool_calls=tool_calls)
240
- self.tool_calls.append(ai_message.model_dump())
241
- for tool_call in tool_calls:
242
- msg = f"\n\nCalling tool: `{tool_call['name']}` with args: `{tool_call['args']}`"
243
- self.stream_handler.new_status(msg)
244
-
245
- # Handle tool responses
246
- elif message.get("tool_call_id"):
247
- content = message["content"]
248
- tool_call_id = message["tool_call_id"]
249
- tool_message = ToolMessage(
250
- content=content, type="tool", tool_call_id=tool_call_id
251
- ).model_dump()
252
- self.tool_calls.append(tool_message)
253
- msg = f"\n\nTool response: `{content}`"
254
- self.stream_handler.new_status(msg)
255
-
256
- # Handle AI responses
257
- elif content := message.get("content"):
258
- self.final_content += content
259
- self.stream_handler.new_token(content)
260
-
261
- # Handle end of stream
262
- if self.final_content:
263
- final_message = AIMessage(
264
- content=self.final_content,
265
- id=self.current_run_id,
266
- additional_kwargs=self.additional_kwargs,
267
- ).model_dump()
268
- session = self.st.session_state["session_id"]
269
- self.st.session_state.user_chats[session]["messages"] = (
270
- self.st.session_state.user_chats[session]["messages"] + self.tool_calls
271
- )
272
- self.st.session_state.user_chats[session]["messages"].append(final_message)
273
- self.st.session_state.run_id = self.current_run_id
274
-
275
-
276
- def get_chain_response(st: Any, client: Client, stream_handler: StreamHandler) -> None:
277
- """Process the chain response update the Streamlit UI.
278
-
279
- This function initiates the event processing for a chain of operations,
280
- involving an AI model's response generation and potential tool calls.
281
- It creates an EventProcessor instance and starts the event processing loop.
282
-
283
- Args:
284
- st (Any): The Streamlit app instance, used for accessing session state
285
- and updating the UI.
286
- client (Client): An instance of the Client class used to stream events
287
- from the server.
288
- stream_handler (StreamHandler): An instance of the StreamHandler class
289
- used to update the Streamlit UI with
290
- streaming content.
291
-
292
- Returns:
293
- None
294
-
295
- Side effects:
296
- - Updates the Streamlit UI with streaming tokens and tool call information.
297
- - Modifies the session state to include the final AI message and run ID.
298
- - Handles various events like chain starts/ends, tool calls, and model outputs.
299
- """
300
- processor = EventProcessor(st, client, stream_handler)
301
- processor.process_events()
@@ -1,94 +0,0 @@
1
- # Copyright 2025 Google LLC
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- # mypy: disable-error-code="assignment"
16
- import os
17
- from typing import Any
18
-
19
- import google.auth
20
- from langchain_core.messages import AIMessage
21
- from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
22
- from langchain_google_vertexai import ChatVertexAI
23
-
24
- title_template = ChatPromptTemplate.from_messages(
25
- [
26
- (
27
- "system",
28
- """Given a list of messages between a human and AI, come up with a short and relevant title for the conversation. Use up to 10 words. The title needs to be concise.
29
- Examples:
30
- **Input:**
31
- ```
32
- Human: hi, what is the best italian dish?
33
- AI: That's a tough one! Italy has so many amazing dishes, it's hard to pick just one "best." To help me give you a great suggestion, tell me a little more about what you're looking for.
34
- ```
35
- **Output:** Best italian dish
36
-
37
- **Input:**
38
-
39
- ```
40
- Human: How to fix a broken laptop screen?
41
- AI: Fixing a broken laptop screen can be tricky and often requires professional help. However, there are a few things you can try at home before resorting to a repair shop.
42
- ```
43
-
44
- **Output:** Fixing a broken laptop screen
45
-
46
- **Input:**
47
-
48
- ```
49
- Human: Can you write me a poem about the beach?
50
- AI: As the sun dips down below the horizon
51
- And the waves gently kiss the shore,
52
- I sit here and watch the ocean
53
- And feel its power evermore.
54
- ```
55
-
56
- **Output:** Poem about the beach
57
-
58
- **Input:**
59
-
60
- ```
61
- Human: What's the best way to learn to code?
62
- AI: There are many ways to learn to code, and the best method for you will depend on your learning style and goals.
63
- ```
64
-
65
- **Output:** How to learn to code
66
-
67
- If there's not enough context in the conversation to create a meaningful title, create a generic title like "New Conversation", or "A simple greeting".
68
-
69
- """,
70
- ),
71
- MessagesPlaceholder(variable_name="messages"),
72
- ]
73
- )
74
- try:
75
- # Initialize Vertex AI with default project credentials
76
- _, project_id = google.auth.default()
77
-
78
- llm = ChatVertexAI(
79
- model_name="gemini-2.0-flash-001",
80
- temperature=0,
81
- project=project_id,
82
- location=os.getenv("LOCATION", "us-central1"),
83
- )
84
- chain_title = title_template | llm
85
-
86
- except Exception:
87
- # Fallback to a simple title generator when Vertex AI is unavailable
88
- print("WARNING: Failed to initialize Vertex AI. Using dummy LLM instead.")
89
-
90
- class DummyChain:
91
- def invoke(*args: Any, **kwargs: Any) -> AIMessage:
92
- return AIMessage(content="conversation")
93
-
94
- chain_title = DummyChain()