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,40 +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 time
16
-
17
- from locust import HttpUser, between, task
18
-
19
-
20
- class DummyUser(HttpUser):
21
- """Simulates a user for testing purposes."""
22
-
23
- wait_time = between(1, 3) # Wait 1-3 seconds between tasks
24
-
25
- @task
26
- def dummy_task(self) -> None:
27
- """A dummy task that simulates work without making actual requests."""
28
- # Simulate some processing time
29
- time.sleep(0.1)
30
-
31
- # Record a successful dummy request
32
- self.environment.events.request.fire(
33
- request_type="POST",
34
- name="dummy_endpoint",
35
- response_time=100,
36
- response_length=1024,
37
- response=None,
38
- context={},
39
- exception=None,
40
- )
@@ -1,143 +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 json
16
- import logging
17
- import os
18
- from collections.abc import Generator
19
- from unittest.mock import AsyncMock, MagicMock, patch
20
-
21
- import pytest
22
- from fastapi.testclient import TestClient
23
- from google.auth.credentials import Credentials
24
-
25
- # Set up logging
26
- logging.basicConfig(level=logging.INFO)
27
- logger = logging.getLogger(__name__)
28
-
29
-
30
- @pytest.fixture(autouse=True)
31
- def mock_google_cloud_credentials() -> Generator[None, None, None]:
32
- """Mock Google Cloud credentials for testing."""
33
- with patch.dict(
34
- os.environ,
35
- {
36
- "GOOGLE_APPLICATION_CREDENTIALS": "/path/to/mock/credentials.json",
37
- "GOOGLE_CLOUD_PROJECT_ID": "mock-project-id",
38
- },
39
- ):
40
- yield
41
-
42
-
43
- @pytest.fixture(autouse=True)
44
- def mock_google_auth_default() -> Generator[None, None, None]:
45
- """Mock the google.auth.default function for testing."""
46
- mock_credentials = MagicMock(spec=Credentials)
47
- mock_project = "mock-project-id"
48
-
49
- with patch("google.auth.default", return_value=(mock_credentials, mock_project)):
50
- yield
51
-
52
-
53
- @pytest.fixture(autouse=True)
54
- def mock_dependencies() -> Generator[None, None, None]:
55
- """
56
- Mock Vertex AI dependencies for testing.
57
- Patches genai client and tool functions.
58
- """
59
- with (
60
- patch("app.server.genai_client") as mock_genai,
61
- patch("app.server.tool_functions") as mock_tools,
62
- ):
63
- mock_genai.aio.live.connect = AsyncMock()
64
- mock_tools.return_value = {}
65
- yield
66
-
67
-
68
- @pytest.mark.asyncio
69
- async def test_websocket_endpoint() -> None:
70
- """
71
- Test the websocket endpoint to ensure it correctly handles
72
- websocket connections and messages.
73
- """
74
- from app.server import app
75
-
76
- mock_session = AsyncMock()
77
- mock_session._ws = AsyncMock()
78
- # Configure mock to return proper response format and close after one message
79
- mock_session._ws.recv.side_effect = [
80
- json.dumps(
81
- {
82
- "serverContent": {
83
- "modelTurn": {
84
- "role": "model",
85
- "parts": [{"text": "Hello, how can I help you?"}],
86
- }
87
- }
88
- }
89
- ).encode(), # Encode as bytes since recv(decode=False) is used
90
- None, # Add None to trigger StopAsyncIteration after first message
91
- ]
92
-
93
- with patch("app.server.genai_client") as mock_genai:
94
- mock_genai.aio.live.connect.return_value.__aenter__.return_value = mock_session
95
- client = TestClient(app)
96
- with client.websocket_connect("/ws") as websocket:
97
- # Test initial connection message
98
- data = websocket.receive_json()
99
- assert data["status"] == "Backend is ready for conversation"
100
-
101
- # Test sending a message
102
- websocket.send_json(
103
- {"setup": {"run_id": "test-run", "user_id": "test-user"}}
104
- )
105
-
106
- # Test sending audio stream
107
- dummy_audio = bytes([0] * 1024) # 1KB of silence
108
- websocket.send_json(
109
- {
110
- "realtimeInput": {
111
- "mediaChunks": [
112
- {
113
- "mimeType": "audio/pcm;rate=16000",
114
- "data": dummy_audio.hex(),
115
- }
116
- ]
117
- }
118
- }
119
- )
120
-
121
- # Receive response as bytes
122
- response = websocket.receive_bytes()
123
- response_data = json.loads(response.decode())
124
- assert "serverContent" in response_data
125
-
126
- # Verify mock interactions
127
- mock_genai.aio.live.connect.assert_called_once()
128
- assert mock_session._ws.recv.called
129
-
130
-
131
- @pytest.mark.asyncio
132
- async def test_websocket_error_handling() -> None:
133
- """Test websocket error handling."""
134
- from app.server import app
135
-
136
- with patch("app.server.genai_client") as mock_genai:
137
- mock_genai.aio.live.connect.side_effect = Exception("Connection failed")
138
-
139
- client = TestClient(app)
140
- with pytest.raises(Exception) as exc:
141
- with client.websocket_connect("/ws"):
142
- pass
143
- assert str(exc.value) == "Connection failed"
@@ -1,72 +0,0 @@
1
- install:
2
- @command -v uv >/dev/null 2>&1 || { echo "uv is not installed. Installing uv..."; curl -LsSf https://astral.sh/uv/0.6.12/install.sh | sh; source ~/.bashrc; }
3
- uv sync --dev{% if cookiecutter.agent_name != 'live_api' and "adk" not in cookiecutter.tags %} --extra streamlit{%- endif %} --extra jupyter --frozen{% if cookiecutter.agent_name == 'live_api' %} && npm --prefix frontend install{%- endif %}
4
-
5
- test:
6
- uv run pytest tests/unit && uv run pytest tests/integration
7
-
8
- playground:
9
- {%- if "adk" in cookiecutter.tags %}
10
- @echo "+-----------------------------------------------------------------------------+"
11
- @echo "| Starting ADK Web Server via 'adk web' command. |"
12
- @echo "| |"
13
- @echo "| Please select the app folder to start interacting with your agent. |"
14
- @echo "+-----------------------------------------------------------------------------+"
15
- uv run adk web
16
- {%- else %}
17
- {%- if cookiecutter.deployment_target == 'cloud_run' %}
18
- uv run uvicorn app.server:app --host 0.0.0.0 --port 8000 --reload &
19
- {%- endif %}
20
- {%- if cookiecutter.agent_name == 'live_api' %}
21
- npm --prefix frontend start
22
- {%- else %}
23
- {% if cookiecutter.deployment_target == 'agent_engine' %}PYTHONPATH=. {% endif %}uv run streamlit run frontend/streamlit_app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false
24
- {%- endif %}
25
- {%- endif %}
26
-
27
- backend:
28
- {%- if cookiecutter.deployment_target == 'cloud_run' %}
29
- uv run uvicorn app.server:app --host 0.0.0.0 --port 8000 --reload
30
- {%- elif cookiecutter.deployment_target == 'agent_engine' %}
31
- # Export dependencies to requirements file using uv export (preferred method), otherwise fall back to uv pip freeze
32
- uv export --no-hashes --no-sources --no-header --no-dev --no-emit-project --no-annotate --frozen > .requirements.txt 2>/dev/null || \
33
- uv pip freeze --exclude-editable > .requirements.txt && uv run app/agent_engine_app.py
34
- {%- endif %}
35
-
36
- {% if cookiecutter.deployment_target == 'cloud_run' -%}
37
- ui:
38
- {%- if cookiecutter.agent_name == 'live_api' %}
39
- npm --prefix frontend start
40
- {%- else %}
41
- uv run streamlit run streamlit/streamlit_app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false
42
- {%- endif %}
43
- {%- endif %}
44
-
45
- setup-dev-env:
46
- @if [ -z "$$PROJECT_ID" ]; then echo "Error: PROJECT_ID environment variable is not set"; exit 1; fi
47
- (cd deployment/terraform/dev && terraform init && terraform apply --var-file vars/env.tfvars --var dev_project_id=$$PROJECT_ID --auto-approve)
48
- {% if cookiecutter.data_ingestion %}
49
- data-ingestion:
50
- @if [ -z "$$PROJECT_ID" ]; then echo "Error: PROJECT_ID environment variable is not set"; exit 1; fi
51
- $(MAKE) install
52
- (cd data_ingestion && uv run data_ingestion_pipeline/submit_pipeline.py \
53
- --project-id=$$PROJECT_ID \
54
- --region="us-central1" \
55
- {%- if cookiecutter.datastore_type == "vertex_ai_search" %}
56
- --data-store-id="{{cookiecutter.project_name}}-datastore" \
57
- --data-store-region="us" \
58
- {%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
59
- --vector-search-index="{{cookiecutter.project_name}}-vector-search" \
60
- --vector-search-index-endpoint="{{cookiecutter.project_name}}-vector-search-endpoint" \
61
- --vector-search-data-bucket-name="$$PROJECT_ID-{{cookiecutter.project_name}}-vs" \
62
- {%- endif %}
63
- --service-account="{{cookiecutter.project_name}}-rag@$$PROJECT_ID.iam.gserviceaccount.com" \
64
- --pipeline-root="gs://$$PROJECT_ID-{{cookiecutter.project_name}}-rag" \
65
- --pipeline-name="data-ingestion-pipeline")
66
- {%- endif %}
67
-
68
- lint:
69
- uv run codespell
70
- uv run ruff check . --diff
71
- uv run ruff format . --check --diff
72
- uv run mypy .
@@ -1,208 +0,0 @@
1
- # {{cookiecutter.project_name}}
2
-
3
- {{cookiecutter.agent_description}}
4
- Agent generated with [`googleCloudPlatform/agent-starter-pack`](https://github.com/GoogleCloudPlatform/agent-starter-pack) version `{{ cookiecutter.package_version }}`
5
-
6
- ## Project Structure
7
-
8
- This project is organized as follows:
9
-
10
- ```
11
- {{cookiecutter.project_name}}/
12
- ├── app/ # Core application code
13
- │ ├── agent.py # Main agent logic
14
- {%- if cookiecutter.deployment_target == 'cloud_run' %}
15
- │ ├── server.py # FastAPI Backend server
16
- {%- elif cookiecutter.deployment_target == 'agent_engine' %}
17
- │ ├── agent_engine_app.py # Agent Engine application logic
18
- {%- endif %}
19
- │ └── utils/ # Utility functions and helpers
20
- ├── deployment/ # Infrastructure and deployment scripts
21
- ├── notebooks/ # Jupyter notebooks for prototyping and evaluation
22
- ├── tests/ # Unit, integration, and load tests
23
- ├── Makefile # Makefile for common commands
24
- └── pyproject.toml # Project dependencies and configuration
25
- ```
26
-
27
- ## Requirements
28
-
29
- Before you begin, ensure you have:
30
- - **uv**: Python package manager - [Install](https://docs.astral.sh/uv/getting-started/installation/)
31
- - **Google Cloud SDK**: For GCP services - [Install](https://cloud.google.com/sdk/docs/install)
32
- - **Terraform**: For infrastructure deployment - [Install](https://developer.hashicorp.com/terraform/downloads)
33
- - **make**: Build automation tool - [Install](https://www.gnu.org/software/make/) (pre-installed on most Unix-based systems)
34
-
35
-
36
- ## Quick Start (Local Testing)
37
-
38
- Install required packages and launch the local development environment:
39
-
40
- ```bash
41
- make install && make playground
42
- ```
43
-
44
- ## Commands
45
-
46
- | Command | Description |
47
- | -------------------- | ------------------------------------------------------------------------------------------- |
48
- | `make install` | Install all required dependencies using uv |
49
- {%- if cookiecutter.deployment_target == 'cloud_run' %}
50
- | `make playground` | Launch local development environment with backend and frontend{%- if "adk" in cookiecutter.tags %} - leveraging `adk web` command. {%- endif %}|
51
- | `make backend` | Start backend server only |
52
- | `make ui` | Launch Streamlit frontend without local backend |
53
- {%- elif cookiecutter.deployment_target == 'agent_engine' %}
54
- | `make playground` | Launch Streamlit interface for testing agent locally and remotely |
55
- | `make backend` | Deploy agent to Agent Engine service |
56
- {%- endif %}
57
- | `make test` | Run unit and integration tests |
58
- | `make lint` | Run code quality checks (codespell, ruff, mypy) |
59
- | `make setup-dev-env` | Set up development environment resources using Terraform |
60
- {%- if cookiecutter.data_ingestion %}
61
- | `make data-ingestion`| Run data ingestion pipeline in the Dev environment |
62
- {%- endif %}
63
- | `uv run jupyter lab` | Launch Jupyter notebook |
64
-
65
- For full command options and usage, refer to the [Makefile](Makefile).
66
-
67
- {% if cookiecutter.agent_name == 'live_api' %}
68
- ## Usage
69
-
70
- This template follows a "bring your own agent" approach - you focus on your business logic in `app/agent.py`, and the template handles the surrounding components (UI, infrastructure, deployment, monitoring).
71
-
72
- Here’s the recommended workflow for local development:
73
-
74
- 1. **Install Dependencies (if needed):**
75
- ```bash
76
- make install
77
- ```
78
-
79
- 2. **Start the Backend Server:**
80
- Open a terminal and run:
81
- ```bash
82
- make backend
83
- ```
84
- The backend is ready when you see `INFO: Application startup complete.` Wait for this message before starting the frontend.
85
-
86
- <details>
87
- <summary><b>Optional: Use AI Studio / API Key instead of Vertex AI</b></summary>
88
-
89
- By default, the backend uses Vertex AI and Application Default Credentials. If you prefer to use Google AI Studio and an API key:
90
-
91
- ```bash
92
- export VERTEXAI=false
93
- export GOOGLE_API_KEY="your-google-api-key" # Replace with your actual key
94
- make backend
95
- ```
96
- Ensure `GOOGLE_API_KEY` is set correctly in your environment.
97
- </details>
98
- <br>
99
-
100
- 3. **Start the Frontend UI:**
101
- Open *another* terminal and run:
102
- ```bash
103
- make ui
104
- ```
105
- This launches the Streamlit application, which connects to the backend server (by default at `http://localhost:8000`).
106
-
107
- 4. **Interact and Iterate:**
108
- * Open the Streamlit UI in your browser (usually `http://localhost:3000` or `http://localhost:3001`).
109
- * Click the play button in the UI to connect to the backend.
110
- * Interact with the agent! Try prompts like: *"Using the tool you have, define Governance in the context MLOPs"*
111
- * Modify the agent logic in `app/agent.py`. The backend server (FastAPI with `uvicorn --reload`) should automatically restart when you save changes. Refresh the frontend if needed to see behavioral changes.
112
-
113
- <details>
114
- <summary><b>Cloud Shell Usage</b></summary>
115
-
116
- To run the agent using Google Cloud Shell:
117
-
118
- 1. **Start the Frontend:**
119
- In a Cloud Shell tab, run:
120
- ```bash
121
- make ui
122
- ```
123
- Accept prompts to use a different port if 3000 is busy. Click the `localhost:PORT` link for the web preview.
124
-
125
- 2. **Start the Backend:**
126
- Open a *new* Cloud Shell tab. Set your project: `gcloud config set project [PROJECT_ID]`. Then run:
127
- ```bash
128
- make backend
129
- ```
130
-
131
- 3. **Configure Backend Web Preview:**
132
- Use the Cloud Shell Web Preview feature to expose port 8000. Change the default port from 8080 to 8000. See [Cloud Shell Web Preview documentation](https://cloud.google.com/shell/docs/using-web-preview#preview_the_application).
133
-
134
- 4. **Connect Frontend to Backend:**
135
- * Copy the URL generated by the backend web preview (e.g., `https://8000-cs-....cloudshell.dev/`).
136
- * Paste this URL into the "Server URL" field in the frontend UI settings (in the first tab).
137
- * Click the "Play button" to connect.
138
-
139
- * **Note:** The feedback feature in the frontend might not work reliably in Cloud Shell due to cross-origin issues between the preview URLs.
140
- </details>
141
-
142
- </details>
143
- {%- else %}
144
- ## Usage
145
-
146
- This template follows a "bring your own agent" approach - you focus on your business logic, and the template handles everything else (UI, infrastructure, deployment, monitoring).
147
-
148
- 1. **Prototype:** Build your Generative AI Agent using the intro notebooks in `notebooks/` for guidance. Use Vertex AI Evaluation to assess performance.
149
- 2. **Integrate:** Import your agent into the app by editing `app/agent.py`.
150
- 3. **Test:** Explore your agent functionality using the Streamlit playground with `make playground`. The playground offers features like chat history, user feedback, and various input types, and automatically reloads your agent on code changes.
151
- 4. **Deploy:** Set up and initiate the CI/CD pipelines, customizing tests as necessary. Refer to the [deployment section](#deployment) for comprehensive instructions. For streamlined infrastructure deployment, simply run `agent-starter-pack setup-cicd`. Check out the [`agent-starter-pack setup-cicd` CLI command](https://github.com/GoogleCloudPlatform/agent-starter-pack/blob/main/docs/cli/setup_cicd.md). Currently only supporting Github.
152
- 5. **Monitor:** Track performance and gather insights using Cloud Logging, Tracing, and the Looker Studio dashboard to iterate on your application.
153
- {% endif %}
154
-
155
- ## Deployment
156
-
157
- > **Note:** For a streamlined one-command deployment of the entire CI/CD pipeline and infrastructure using Terraform, you can use the [`agent-starter-pack setup-cicd` CLI command](https://github.com/GoogleCloudPlatform/agent-starter-pack/blob/main/docs/cli/setup_cicd.md). Currently only supporting Github.
158
-
159
- ### Dev Environment
160
-
161
- {%- if cookiecutter.deployment_target == 'agent_engine' %}
162
- You can test deployment towards a Dev Environment using the following command:
163
-
164
- ```bash
165
- gcloud config set project <your-dev-project-id>
166
- make backend
167
- ```
168
- {%- elif cookiecutter.deployment_target == 'cloud_run' %}
169
- Deploy the application directly to Cloud Run from your source code using the following `gcloud` command:
170
-
171
- ```bash
172
- gcloud run deploy genai-app-sample \
173
- --source . \
174
- --project YOUR_PROJECT_ID \
175
- --region YOUR_GCP_REGION \
176
- --memory "4Gi" \
177
- ```
178
- Replace `YOUR_PROJECT_ID` with your Google Cloud project ID and `YOUR_GCP_REGION` with the desired region (e.g., `us-central1`). Adjust memory and other flags as needed for your environment.
179
- {% if cookiecutter.agent_name == 'live_api' %}
180
- **Accessing the Deployed Backend Locally:**
181
-
182
- To connect your local frontend (`make ui`) to the backend deployed on Cloud Run, use the `gcloud` proxy:
183
-
184
- 1. **Start the proxy:**
185
- ```bash
186
- # Replace with your actual service name, project, and region
187
- gcloud run services proxy gemini-agent-service --port 8000 --project $PROJECT_ID --region $REGION
188
- ```
189
- Keep this terminal running.
190
-
191
- 2. **Connect Frontend:** Your deployed backend is now accessible locally at `http://localhost:8000`. Point your Streamlit UI to this address.
192
- {%- endif %}
193
- {%- endif %}
194
-
195
- The repository includes a Terraform configuration for the setup of the Dev Google Cloud project.
196
- See [deployment/README.md](deployment/README.md) for instructions.
197
-
198
- ### Production Deployment
199
-
200
- The repository includes a Terraform configuration for the setup of a production Google Cloud project. Refer to [deployment/README.md](deployment/README.md) for detailed instructions on how to deploy the infrastructure and application.
201
-
202
- {% if cookiecutter.agent_name != 'live_api' %}
203
- ## Monitoring and Observability
204
-
205
- > You can use [this Looker Studio dashboard](https://lookerstudio.google.com/c/reporting/fa742264-4b4b-4c56-81e6-a667dd0f853f/page/tEnnC) template for visualizing events being logged in BigQuery. See the "Setup Instructions" tab to getting started.
206
-
207
- The application uses OpenTelemetry for comprehensive observability with all events being sent to Google Cloud Trace and Logging for monitoring and to BigQuery for long term storage.
208
- {%- endif %}
@@ -1,3 +0,0 @@
1
- from app.agent import root_agent
2
-
3
- __all__ = ["root_agent"]
@@ -1,155 +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 json
16
- import logging
17
- from collections.abc import Sequence
18
- from typing import Any
19
-
20
- import google.cloud.storage as storage
21
- from google.cloud import logging as google_cloud_logging
22
- from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
23
- from opentelemetry.sdk.trace import ReadableSpan
24
- from opentelemetry.sdk.trace.export import SpanExportResult
25
-
26
-
27
- class CloudTraceLoggingSpanExporter(CloudTraceSpanExporter):
28
- """
29
- An extended version of CloudTraceSpanExporter that logs span data to Google Cloud Logging
30
- and handles large attribute values by storing them in Google Cloud Storage.
31
-
32
- This class helps bypass the 256 character limit of Cloud Trace for attribute values
33
- by leveraging Cloud Logging (which has a 256KB limit) and Cloud Storage for larger payloads.
34
- """
35
-
36
- def __init__(
37
- self,
38
- logging_client: google_cloud_logging.Client | None = None,
39
- storage_client: storage.Client | None = None,
40
- bucket_name: str | None = None,
41
- debug: bool = False,
42
- **kwargs: Any,
43
- ) -> None:
44
- """
45
- Initialize the exporter with Google Cloud clients and configuration.
46
-
47
- :param logging_client: Google Cloud Logging client
48
- :param storage_client: Google Cloud Storage client
49
- :param bucket_name: Name of the GCS bucket to store large payloads
50
- :param debug: Enable debug mode for additional logging
51
- :param kwargs: Additional arguments to pass to the parent class
52
- """
53
- super().__init__(**kwargs)
54
- self.debug = debug
55
- self.logging_client = logging_client or google_cloud_logging.Client(
56
- project=self.project_id
57
- )
58
- self.logger = self.logging_client.logger(__name__)
59
- self.storage_client = storage_client or storage.Client(project=self.project_id)
60
- self.bucket_name = (
61
- bucket_name or f"{self.project_id}-{{cookiecutter.project_name}}-logs-data"
62
- )
63
- self.bucket = self.storage_client.bucket(self.bucket_name)
64
-
65
- def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
66
- """
67
- Export the spans to Google Cloud Logging and Cloud Trace.
68
-
69
- :param spans: A sequence of spans to export
70
- :return: The result of the export operation
71
- """
72
- for span in spans:
73
- span_context = span.get_span_context()
74
- trace_id = format(span_context.trace_id, "x")
75
- span_id = format(span_context.span_id, "x")
76
- span_dict = json.loads(span.to_json())
77
-
78
- span_dict["trace"] = f"projects/{self.project_id}/traces/{trace_id}"
79
- span_dict["span_id"] = span_id
80
-
81
- span_dict = self._process_large_attributes(
82
- span_dict=span_dict, span_id=span_id
83
- )
84
-
85
- if self.debug:
86
- print(span_dict)
87
-
88
- # Log the span data to Google Cloud Logging
89
- {%- if "adk" in cookiecutter.tags %}
90
- self.logger.log_struct(
91
- span_dict,
92
- labels={
93
- "type": "agent_telemetry",
94
- "service_name": "{{cookiecutter.project_name}}",
95
- },
96
- severity="INFO",
97
- )
98
- {%- else %}
99
- self.logger.log_struct(span_dict, severity="INFO")
100
- {%- endif %}
101
- # Export spans to Google Cloud Trace using the parent class method
102
- return super().export(spans)
103
-
104
- def store_in_gcs(self, content: str, span_id: str) -> str:
105
- """
106
- Initiate storing large content in Google Cloud Storage/
107
-
108
- :param content: The content to store
109
- :param span_id: The ID of the span
110
- :return: The GCS URI of the stored content
111
- """
112
- if not self.storage_client.bucket(self.bucket_name).exists():
113
- logging.warning(
114
- f"Bucket {self.bucket_name} not found. "
115
- "Unable to store span attributes in GCS."
116
- )
117
- return "GCS bucket not found"
118
-
119
- blob_name = f"spans/{span_id}.json"
120
- blob = self.bucket.blob(blob_name)
121
-
122
- blob.upload_from_string(content, "application/json")
123
- return f"gs://{self.bucket_name}/{blob_name}"
124
-
125
- def _process_large_attributes(self, span_dict: dict, span_id: str) -> dict:
126
- """
127
- Process large attribute values by storing them in GCS if they exceed the size
128
- limit of Google Cloud Logging.
129
-
130
- :param span_dict: The span data dictionary
131
- :param trace_id: The trace ID
132
- :param span_id: The span ID
133
- :return: The updated span dictionary
134
- """
135
- attributes = span_dict["attributes"]
136
- if len(json.dumps(attributes).encode()) > 255 * 1024: # 250 KB
137
- # Separate large payload from other attributes
138
- attributes_payload = dict(attributes.items())
139
- attributes_retain = dict(attributes.items())
140
-
141
- # Store large payload in GCS
142
- gcs_uri = self.store_in_gcs(json.dumps(attributes_payload), span_id)
143
- attributes_retain["uri_payload"] = gcs_uri
144
- attributes_retain["url_payload"] = (
145
- f"https://storage.mtls.cloud.google.com/"
146
- f"{self.bucket_name}/spans/{span_id}.json"
147
- )
148
-
149
- span_dict["attributes"] = attributes_retain
150
- logging.info(
151
- "Length of payload span above 250 KB, storing attributes in GCS "
152
- "to avoid large log entry errors"
153
- )
154
-
155
- return span_dict