agent-starter-pack 0.0.1b0__py3-none-any.whl

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

Potentially problematic release.


This version of agent-starter-pack might be problematic. Click here for more details.

Files changed (162) hide show
  1. agent_starter_pack-0.0.1b0.dist-info/METADATA +143 -0
  2. agent_starter_pack-0.0.1b0.dist-info/RECORD +162 -0
  3. agent_starter_pack-0.0.1b0.dist-info/WHEEL +4 -0
  4. agent_starter_pack-0.0.1b0.dist-info/entry_points.txt +2 -0
  5. agent_starter_pack-0.0.1b0.dist-info/licenses/LICENSE +201 -0
  6. agents/agentic_rag_vertexai_search/README.md +22 -0
  7. agents/agentic_rag_vertexai_search/app/agent.py +145 -0
  8. agents/agentic_rag_vertexai_search/app/retrievers.py +79 -0
  9. agents/agentic_rag_vertexai_search/app/templates.py +53 -0
  10. agents/agentic_rag_vertexai_search/notebooks/evaluating_langgraph_agent.ipynb +1561 -0
  11. agents/agentic_rag_vertexai_search/template/.templateconfig.yaml +14 -0
  12. agents/agentic_rag_vertexai_search/tests/integration/test_agent.py +57 -0
  13. agents/crewai_coding_crew/README.md +34 -0
  14. agents/crewai_coding_crew/app/agent.py +86 -0
  15. agents/crewai_coding_crew/app/crew/config/agents.yaml +39 -0
  16. agents/crewai_coding_crew/app/crew/config/tasks.yaml +37 -0
  17. agents/crewai_coding_crew/app/crew/crew.py +71 -0
  18. agents/crewai_coding_crew/notebooks/evaluating_crewai_agent.ipynb +1571 -0
  19. agents/crewai_coding_crew/notebooks/evaluating_langgraph_agent.ipynb +1561 -0
  20. agents/crewai_coding_crew/template/.templateconfig.yaml +12 -0
  21. agents/crewai_coding_crew/tests/integration/test_agent.py +47 -0
  22. agents/langgraph_base_react/README.md +9 -0
  23. agents/langgraph_base_react/app/agent.py +73 -0
  24. agents/langgraph_base_react/notebooks/evaluating_langgraph_agent.ipynb +1561 -0
  25. agents/langgraph_base_react/template/.templateconfig.yaml +13 -0
  26. agents/langgraph_base_react/tests/integration/test_agent.py +48 -0
  27. agents/multimodal_live_api/README.md +50 -0
  28. agents/multimodal_live_api/app/agent.py +86 -0
  29. agents/multimodal_live_api/app/server.py +193 -0
  30. agents/multimodal_live_api/app/templates.py +51 -0
  31. agents/multimodal_live_api/app/vector_store.py +55 -0
  32. agents/multimodal_live_api/template/.templateconfig.yaml +15 -0
  33. agents/multimodal_live_api/tests/integration/test_server_e2e.py +254 -0
  34. agents/multimodal_live_api/tests/load_test/load_test.py +40 -0
  35. agents/multimodal_live_api/tests/unit/test_server.py +143 -0
  36. src/base_template/.gitignore +197 -0
  37. src/base_template/Makefile +37 -0
  38. src/base_template/README.md +91 -0
  39. src/base_template/app/utils/tracing.py +143 -0
  40. src/base_template/app/utils/typing.py +115 -0
  41. src/base_template/deployment/README.md +123 -0
  42. src/base_template/deployment/cd/deploy-to-prod.yaml +98 -0
  43. src/base_template/deployment/cd/staging.yaml +215 -0
  44. src/base_template/deployment/ci/pr_checks.yaml +51 -0
  45. src/base_template/deployment/terraform/apis.tf +34 -0
  46. src/base_template/deployment/terraform/build_triggers.tf +122 -0
  47. src/base_template/deployment/terraform/dev/apis.tf +42 -0
  48. src/base_template/deployment/terraform/dev/iam.tf +90 -0
  49. src/base_template/deployment/terraform/dev/log_sinks.tf +66 -0
  50. src/base_template/deployment/terraform/dev/providers.tf +29 -0
  51. src/base_template/deployment/terraform/dev/storage.tf +76 -0
  52. src/base_template/deployment/terraform/dev/variables.tf +126 -0
  53. src/base_template/deployment/terraform/dev/vars/env.tfvars +21 -0
  54. src/base_template/deployment/terraform/iam.tf +130 -0
  55. src/base_template/deployment/terraform/locals.tf +50 -0
  56. src/base_template/deployment/terraform/log_sinks.tf +72 -0
  57. src/base_template/deployment/terraform/providers.tf +35 -0
  58. src/base_template/deployment/terraform/service_accounts.tf +42 -0
  59. src/base_template/deployment/terraform/storage.tf +100 -0
  60. src/base_template/deployment/terraform/variables.tf +202 -0
  61. src/base_template/deployment/terraform/vars/env.tfvars +43 -0
  62. src/base_template/pyproject.toml +113 -0
  63. src/base_template/tests/unit/test_utils/test_tracing_exporter.py +140 -0
  64. src/cli/commands/create.py +534 -0
  65. src/cli/commands/setup_cicd.py +730 -0
  66. src/cli/main.py +35 -0
  67. src/cli/utils/__init__.py +35 -0
  68. src/cli/utils/cicd.py +662 -0
  69. src/cli/utils/gcp.py +120 -0
  70. src/cli/utils/logging.py +51 -0
  71. src/cli/utils/template.py +644 -0
  72. src/data_ingestion/README.md +79 -0
  73. src/data_ingestion/data_ingestion_pipeline/components/ingest_data.py +175 -0
  74. src/data_ingestion/data_ingestion_pipeline/components/process_data.py +321 -0
  75. src/data_ingestion/data_ingestion_pipeline/pipeline.py +58 -0
  76. src/data_ingestion/data_ingestion_pipeline/submit_pipeline.py +184 -0
  77. src/data_ingestion/pyproject.toml +17 -0
  78. src/data_ingestion/uv.lock +999 -0
  79. src/deployment_targets/agent_engine/app/agent_engine_app.py +238 -0
  80. src/deployment_targets/agent_engine/app/utils/gcs.py +42 -0
  81. src/deployment_targets/agent_engine/deployment_metadata.json +4 -0
  82. src/deployment_targets/agent_engine/notebooks/intro_reasoning_engine.ipynb +869 -0
  83. src/deployment_targets/agent_engine/tests/integration/test_agent_engine_app.py +120 -0
  84. src/deployment_targets/agent_engine/tests/load_test/.results/.placeholder +0 -0
  85. src/deployment_targets/agent_engine/tests/load_test/.results/report.html +264 -0
  86. src/deployment_targets/agent_engine/tests/load_test/.results/results_exceptions.csv +1 -0
  87. src/deployment_targets/agent_engine/tests/load_test/.results/results_failures.csv +1 -0
  88. src/deployment_targets/agent_engine/tests/load_test/.results/results_stats.csv +3 -0
  89. src/deployment_targets/agent_engine/tests/load_test/.results/results_stats_history.csv +22 -0
  90. src/deployment_targets/agent_engine/tests/load_test/README.md +42 -0
  91. src/deployment_targets/agent_engine/tests/load_test/load_test.py +100 -0
  92. src/deployment_targets/agent_engine/tests/unit/test_dummy.py +22 -0
  93. src/deployment_targets/cloud_run/Dockerfile +29 -0
  94. src/deployment_targets/cloud_run/app/server.py +128 -0
  95. src/deployment_targets/cloud_run/deployment/terraform/artifact_registry.tf +22 -0
  96. src/deployment_targets/cloud_run/deployment/terraform/dev/service_accounts.tf +20 -0
  97. src/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +192 -0
  98. src/deployment_targets/cloud_run/tests/load_test/.results/.placeholder +0 -0
  99. src/deployment_targets/cloud_run/tests/load_test/README.md +79 -0
  100. src/deployment_targets/cloud_run/tests/load_test/load_test.py +85 -0
  101. src/deployment_targets/cloud_run/tests/unit/test_server.py +142 -0
  102. src/deployment_targets/cloud_run/uv.lock +6952 -0
  103. src/frontends/live_api_react/frontend/package-lock.json +19405 -0
  104. src/frontends/live_api_react/frontend/package.json +56 -0
  105. src/frontends/live_api_react/frontend/public/favicon.ico +0 -0
  106. src/frontends/live_api_react/frontend/public/index.html +62 -0
  107. src/frontends/live_api_react/frontend/public/robots.txt +3 -0
  108. src/frontends/live_api_react/frontend/src/App.scss +189 -0
  109. src/frontends/live_api_react/frontend/src/App.test.tsx +25 -0
  110. src/frontends/live_api_react/frontend/src/App.tsx +205 -0
  111. src/frontends/live_api_react/frontend/src/components/audio-pulse/AudioPulse.tsx +64 -0
  112. src/frontends/live_api_react/frontend/src/components/audio-pulse/audio-pulse.scss +68 -0
  113. src/frontends/live_api_react/frontend/src/components/control-tray/ControlTray.tsx +217 -0
  114. src/frontends/live_api_react/frontend/src/components/control-tray/control-tray.scss +201 -0
  115. src/frontends/live_api_react/frontend/src/components/logger/Logger.tsx +241 -0
  116. src/frontends/live_api_react/frontend/src/components/logger/logger.scss +133 -0
  117. src/frontends/live_api_react/frontend/src/components/logger/mock-logs.ts +151 -0
  118. src/frontends/live_api_react/frontend/src/components/side-panel/SidePanel.tsx +161 -0
  119. src/frontends/live_api_react/frontend/src/components/side-panel/side-panel.scss +285 -0
  120. src/frontends/live_api_react/frontend/src/contexts/LiveAPIContext.tsx +48 -0
  121. src/frontends/live_api_react/frontend/src/hooks/use-live-api.ts +115 -0
  122. src/frontends/live_api_react/frontend/src/hooks/use-media-stream-mux.ts +23 -0
  123. src/frontends/live_api_react/frontend/src/hooks/use-screen-capture.ts +72 -0
  124. src/frontends/live_api_react/frontend/src/hooks/use-webcam.ts +69 -0
  125. src/frontends/live_api_react/frontend/src/index.css +28 -0
  126. src/frontends/live_api_react/frontend/src/index.tsx +35 -0
  127. src/frontends/live_api_react/frontend/src/multimodal-live-types.ts +242 -0
  128. src/frontends/live_api_react/frontend/src/react-app-env.d.ts +17 -0
  129. src/frontends/live_api_react/frontend/src/reportWebVitals.ts +31 -0
  130. src/frontends/live_api_react/frontend/src/setupTests.ts +21 -0
  131. src/frontends/live_api_react/frontend/src/utils/audio-recorder.ts +111 -0
  132. src/frontends/live_api_react/frontend/src/utils/audio-streamer.ts +270 -0
  133. src/frontends/live_api_react/frontend/src/utils/audioworklet-registry.ts +43 -0
  134. src/frontends/live_api_react/frontend/src/utils/multimodal-live-client.ts +329 -0
  135. src/frontends/live_api_react/frontend/src/utils/store-logger.ts +64 -0
  136. src/frontends/live_api_react/frontend/src/utils/utils.ts +86 -0
  137. src/frontends/live_api_react/frontend/src/utils/worklets/audio-processing.ts +73 -0
  138. src/frontends/live_api_react/frontend/src/utils/worklets/vol-meter.ts +65 -0
  139. src/frontends/live_api_react/frontend/tsconfig.json +25 -0
  140. src/frontends/streamlit/frontend/side_bar.py +213 -0
  141. src/frontends/streamlit/frontend/streamlit_app.py +263 -0
  142. src/frontends/streamlit/frontend/style/app_markdown.py +37 -0
  143. src/frontends/streamlit/frontend/utils/chat_utils.py +67 -0
  144. src/frontends/streamlit/frontend/utils/local_chat_history.py +125 -0
  145. src/frontends/streamlit/frontend/utils/message_editing.py +59 -0
  146. src/frontends/streamlit/frontend/utils/multimodal_utils.py +217 -0
  147. src/frontends/streamlit/frontend/utils/stream_handler.py +282 -0
  148. src/frontends/streamlit/frontend/utils/title_summary.py +77 -0
  149. src/resources/containers/data_processing/Dockerfile +25 -0
  150. src/resources/locks/uv-agentic_rag_vertexai_search-agent_engine.lock +4684 -0
  151. src/resources/locks/uv-agentic_rag_vertexai_search-cloud_run.lock +5799 -0
  152. src/resources/locks/uv-crewai_coding_crew-agent_engine.lock +5509 -0
  153. src/resources/locks/uv-crewai_coding_crew-cloud_run.lock +6688 -0
  154. src/resources/locks/uv-langgraph_base_react-agent_engine.lock +4595 -0
  155. src/resources/locks/uv-langgraph_base_react-cloud_run.lock +5710 -0
  156. src/resources/locks/uv-multimodal_live_api-cloud_run.lock +5665 -0
  157. src/resources/setup_cicd/cicd_variables.tf +36 -0
  158. src/resources/setup_cicd/github.tf +85 -0
  159. src/resources/setup_cicd/providers.tf +39 -0
  160. src/utils/generate_locks.py +135 -0
  161. src/utils/lock_utils.py +82 -0
  162. src/utils/watch_and_rebuild.py +190 -0
@@ -0,0 +1,202 @@
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
+ variable "prod_project_id" {
16
+ type = string
17
+ description = "**Production** Google Cloud Project ID for resource deployment."
18
+ }
19
+
20
+ variable "staging_project_id" {
21
+ type = string
22
+ description = "**Staging** Google Cloud Project ID for resource deployment."
23
+ }
24
+
25
+ variable "cicd_runner_project_id" {
26
+ type = string
27
+ description = "Google Cloud Project ID where CI/CD pipelines will execute."
28
+ }
29
+
30
+ variable "region" {
31
+ type = string
32
+ description = "Google Cloud region for resource deployment."
33
+ default = "us-central1"
34
+ }
35
+
36
+ variable "host_connection_name" {
37
+ description = "Name of the host connection you created in Cloud Build"
38
+ type = string
39
+ }
40
+
41
+ variable "repository_name" {
42
+ description = "Name of the repository you'd like to connect to Cloud Build"
43
+ type = string
44
+ }
45
+
46
+ variable "telemetry_bigquery_dataset_id" {
47
+ type = string
48
+ description = "BigQuery dataset ID for telemetry data export."
49
+ default = "telemetry_genai_app_sample_sink"
50
+ }
51
+
52
+ variable "feedback_bigquery_dataset_id" {
53
+ type = string
54
+ description = "BigQuery dataset ID for feedback data export."
55
+ default = "feedback_genai_app_sample_sink"
56
+ }
57
+
58
+ variable "telemetry_logs_filter" {
59
+ type = string
60
+ description = "Log Sink filter for capturing telemetry data. Captures logs with the `traceloop.association.properties.log_type` attribute set to `tracing`."
61
+ default = "jsonPayload.attributes.\"traceloop.association.properties.log_type\"=\"tracing\" jsonPayload.resource.attributes.\"service.name\"=\"Sample Chatbot Application\""
62
+ }
63
+
64
+ variable "feedback_logs_filter" {
65
+ type = string
66
+ description = "Log Sink filter for capturing feedback data. Captures logs where the `log_type` field is `feedback`."
67
+ default = "jsonPayload.log_type=\"feedback\""
68
+ }
69
+
70
+ variable "telemetry_sink_name" {
71
+ type = string
72
+ description = "Name of the telemetry data Log Sink."
73
+ default = "telemetry_logs_genai_app_sample"
74
+ }
75
+
76
+ variable "feedback_sink_name" {
77
+ type = string
78
+ description = "Name of the feedback data Log Sink."
79
+ default = "feedback_logs_genai_app_sample"
80
+ }
81
+
82
+ variable "cicd_runner_sa_name" {
83
+ description = "Service account name to be used for the CICD processes"
84
+ type = string
85
+ default = "cicd-runner"
86
+ }
87
+
88
+ variable "suffix_bucket_name_load_test_results" {
89
+ description = "Suffix Name of the bucket that will be used to store the results of the load test. Prefix will be project id."
90
+ type = string
91
+ default = "cicd-load-test-results"
92
+ }
93
+ {%- if cookiecutter.deployment_target == 'cloud_run' %}
94
+ variable "cloud_run_app_sa_name" {
95
+ description = "Service account name to be used for the Cloud Run service"
96
+ type = string
97
+ default = "{{cookiecutter.project_name}}-cr"
98
+ }
99
+
100
+ variable "artifact_registry_repo_name" {
101
+ description = "Name of the Artifact registry repository to be used to push containers"
102
+ type = string
103
+ default = "genai-containers"
104
+ }
105
+
106
+ variable "cloud_run_app_roles" {
107
+ description = "List of roles to assign to the Cloud Run app service account"
108
+ {%- elif cookiecutter.deployment_target == 'agent_engine' %}
109
+ variable "agentengine_sa_roles" {
110
+ description = "List of roles to assign to the Agent Engine service account"
111
+ {%- endif %}
112
+ type = list(string)
113
+ default = [
114
+ {%- if cookiecutter.deployment_target == 'cloud_run' %}
115
+ "roles/run.invoker",
116
+ {%- endif %}
117
+ "roles/aiplatform.user",
118
+ "roles/discoveryengine.editor",
119
+ "roles/logging.logWriter",
120
+ "roles/cloudtrace.agent",
121
+ "roles/storage.admin"
122
+ ]
123
+ }
124
+
125
+ variable "cicd_roles" {
126
+ description = "List of roles to assign to the CICD runner service account in the CICD project"
127
+ type = list(string)
128
+ default = [
129
+ {%- if cookiecutter.deployment_target == 'cloud_run' %}
130
+ "roles/run.invoker",
131
+ {%- endif %}
132
+ "roles/storage.admin",
133
+ "roles/aiplatform.user",
134
+ "roles/discoveryengine.editor",
135
+ "roles/logging.logWriter",
136
+ "roles/cloudtrace.agent",
137
+ "roles/artifactregistry.writer",
138
+ "roles/cloudbuild.builds.builder"
139
+ ]
140
+ }
141
+
142
+ variable "cicd_sa_deployment_required_roles" {
143
+ description = "List of roles to assign to the CICD runner service account for the Staging and Prod projects."
144
+ type = list(string)
145
+ default = [
146
+ {%- if cookiecutter.deployment_target == 'cloud_run' %}
147
+ "roles/run.developer",
148
+ {%- endif %}
149
+ "roles/iam.serviceAccountUser",
150
+ "roles/aiplatform.user",
151
+ "roles/storage.admin"
152
+ ]
153
+ }
154
+
155
+ {%- if cookiecutter.data_ingestion %}
156
+ variable "vertexai_pipeline_sa_name" {
157
+ description = "Service account name to be used for the Vertex AI service"
158
+ type = string
159
+ default = "data-ingestion-vertexai-sa"
160
+ }
161
+
162
+ variable "pipeline_cron_schedule" {
163
+ type = string
164
+ description = "Cron expression defining the schedule for automated data ingestion."
165
+ default = "0 0 * * 0" # Run at 00:00 UTC every Sunday
166
+ }
167
+
168
+ variable "data_store_region" {
169
+ type = string
170
+ description = "Google Cloud region for resource deployment."
171
+ default = "us"
172
+ }
173
+
174
+ variable "pipelines_roles" {
175
+ description = "List of roles to assign to the Vertex AI Pipelines service account"
176
+ type = list(string)
177
+ default = [
178
+ "roles/storage.admin",
179
+ "roles/aiplatform.user",
180
+ "roles/discoveryengine.admin",
181
+ "roles/logging.logWriter",
182
+ "roles/artifactregistry.writer",
183
+ "roles/bigquery.dataEditor",
184
+ "roles/bigquery.jobUser",
185
+ "roles/bigquery.readSessionUser",
186
+ "roles/bigquery.connectionAdmin",
187
+ "roles/resourcemanager.projectIamAdmin"
188
+ ]
189
+ }
190
+
191
+ variable "datastore_name" {
192
+ description = "The name of the datastore"
193
+ type = string
194
+ default = "sample-datastore"
195
+ }
196
+
197
+ variable "search_engine_name" {
198
+ description = "The name of the search engine"
199
+ type = string
200
+ default = "sample-search-engine"
201
+ }
202
+ {%- endif %}
@@ -0,0 +1,43 @@
1
+ # Your Production Google Cloud project id
2
+ prod_project_id = "your-production-project-id"
3
+
4
+ # Your Staging / Test Google Cloud project id
5
+ staging_project_id = "your-staging-project-id"
6
+
7
+ # Your Google Cloud project ID that will be used to host the Cloud Build pipelines.
8
+ cicd_runner_project_id = "your-cicd-project-id"
9
+
10
+ # Name of the host connection you created in Cloud Build
11
+ host_connection_name = "your-host-connection-name"
12
+
13
+ # Name of the repository you added to Cloud Build
14
+ repository_name = "your-repository-name"
15
+
16
+ # The Google Cloud region you will use to deploy the infrastructure
17
+ region = "us-central1"
18
+
19
+ {%- if cookiecutter.deployment_target == 'cloud_run' %}
20
+ cloud_run_app_sa_name = "{{cookiecutter.project_name}}-cr"
21
+ {%- endif %}
22
+
23
+ telemetry_bigquery_dataset_id = "telemetry_genai_app_sample_sink"
24
+ telemetry_sink_name = "telemetry_logs_genai_app_sample"
25
+ telemetry_logs_filter = "jsonPayload.attributes.\"traceloop.association.properties.log_type\"=\"tracing\" jsonPayload.resource.attributes.\"service.name\"=\"Sample Chatbot Application\""
26
+
27
+ feedback_bigquery_dataset_id = "feedback_genai_app_sample_sink"
28
+ feedback_sink_name = "feedback_logs_genai_app_sample"
29
+ feedback_logs_filter = "jsonPayload.log_type=\"feedback\""
30
+
31
+ cicd_runner_sa_name = "cicd-runner"
32
+
33
+ suffix_bucket_name_load_test_results = "cicd-load-test-results"
34
+
35
+ {%- if cookiecutter.data_ingestion %}
36
+ search_engine_name = "sample-search-engine"
37
+ datastore_name = "sample-datastore"
38
+ vertexai_pipeline_sa_name = "vertexai-pipelines-sa"
39
+ pipeline_cron_schedule = "0 0 * * 0"
40
+
41
+ #The value can only be one of "global", "us" and "eu".
42
+ data_store_region = "us"
43
+ {%- endif %}
@@ -0,0 +1,113 @@
1
+ [project]
2
+ name = "{{cookiecutter.project_name}}"
3
+ version = "0.1.0"
4
+ description = ""
5
+ authors = [
6
+ {name = "Your Name", email = "your@email.com"},
7
+ ]
8
+ dependencies = [
9
+ {%- for dep in cookiecutter.extra_dependencies %}
10
+ "{{ dep }}",
11
+ {%- endfor %}
12
+ "langchain-core~=0.3.9",
13
+ "opentelemetry-exporter-gcp-trace~=1.9.0",
14
+ "traceloop-sdk~=0.38.7",
15
+ "google-cloud-logging~=3.11.4",
16
+ {%- if cookiecutter.deployment_target == 'cloud_run' %}
17
+ "google-cloud-aiplatform[evaluation]~=1.80.0",
18
+ "fastapi~=0.115.8",
19
+ "uvicorn~=0.34.0"
20
+ {%- elif cookiecutter.deployment_target == 'agent_engine' %}
21
+ "google-cloud-aiplatform[evaluation,langchain,reasoningengine]~=1.77.0"
22
+ {%- endif %}
23
+ ]
24
+ {% if cookiecutter.deployment_target == 'cloud_run' %}
25
+ requires-python = ">=3.10,<=3.13"
26
+ {% elif cookiecutter.deployment_target == 'agent_engine' %}
27
+ requires-python = ">=3.10,<=3.11"
28
+ {%- endif %}
29
+
30
+ [dependency-groups]
31
+ dev = [
32
+ "pytest>=8.3.4",
33
+ "pytest-asyncio>=0.23.8",
34
+ "nest-asyncio>=1.6.0",
35
+ ]
36
+
37
+ [project.optional-dependencies]
38
+ streamlit = [
39
+ "streamlit~=1.42.0",
40
+ "streamlit-extras~=0.4.3",
41
+ "extra-streamlit-components~=0.1.71",
42
+ "streamlit-feedback~=0.1.3",
43
+ ]
44
+ jupyter = [
45
+ "jupyter~=1.0.0",
46
+ ]
47
+ lint = [
48
+ "ruff>=0.4.6",
49
+ "mypy~=1.15.0",
50
+ "codespell~=2.2.0",
51
+ "types-pyyaml~=6.0.12.20240917",
52
+ "types-requests~=2.32.0.20240914",
53
+ ]
54
+
55
+ [tool.ruff]
56
+ line-length = 88
57
+ target-version = "py310"
58
+
59
+ [tool.ruff.lint]
60
+ select = [
61
+ "E", # pycodestyle
62
+ "F", # pyflakes
63
+ "W", # pycodestyle warnings
64
+ "I", # isort
65
+ "C", # flake8-comprehensions
66
+ "B", # flake8-bugbear
67
+ "UP", # pyupgrade
68
+ "RUF", # ruff specific rules
69
+ ]
70
+ ignore = ["E501", "C901"] # ignore line too long, too complex
71
+
72
+ [tool.ruff.lint.isort]
73
+ known-first-party = ["app", "frontend"]
74
+
75
+ [tool.mypy]
76
+ disallow_untyped_calls = true
77
+ disallow_untyped_defs = true
78
+ disallow_incomplete_defs = true
79
+ no_implicit_optional = true
80
+ check_untyped_defs = true
81
+ disallow_subclassing_any = true
82
+ warn_incomplete_stub = true
83
+ warn_redundant_casts = true
84
+ warn_unused_ignores = true
85
+ warn_unreachable = true
86
+ follow_imports = "silent"
87
+ ignore_missing_imports = true
88
+ explicit_package_bases = true
89
+ disable_error_code = ["misc", "no-untyped-call", "no-any-return"]
90
+ {% if cookiecutter.agent_name == 'multimodal_live_api' %}
91
+ exclude = [".venv","./frontend"]
92
+ {% else %}
93
+ exclude = [".venv"]
94
+ {%- endif %}
95
+
96
+ [tool.codespell]
97
+ ignore-words-list = "rouge"
98
+ {% if cookiecutter.agent_name == 'multimodal_live_api' %}
99
+ skip = "./locust_env/*,uv.lock,.venv,./frontend"
100
+ {% else %}
101
+ skip = "./locust_env/*,uv.lock,.venv"
102
+ {%- endif %}
103
+
104
+ [build-system]
105
+ requires = ["hatchling"]
106
+ build-backend = "hatchling.build"
107
+
108
+
109
+ [tool.pytest.ini_options]
110
+ pythonpath = "."
111
+
112
+ [tool.hatch.build.targets.wheel]
113
+ packages = ["app","frontend"]
@@ -0,0 +1,140 @@
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
+ from collections.abc import Generator
16
+ from typing import Any
17
+ from unittest.mock import Mock, patch
18
+
19
+ import pytest
20
+ from google.cloud import logging as google_cloud_logging
21
+ from google.cloud import storage
22
+ from opentelemetry.sdk.trace import ReadableSpan
23
+
24
+ from app.utils.tracing import CloudTraceLoggingSpanExporter
25
+
26
+
27
+ @pytest.fixture
28
+ def mock_logging_client() -> Mock:
29
+ """Create a mock logging client."""
30
+ return Mock(spec=google_cloud_logging.Client)
31
+
32
+
33
+ @pytest.fixture
34
+ def mock_storage_client() -> Mock:
35
+ """Create a mock storage client."""
36
+ return Mock(spec=storage.Client)
37
+
38
+
39
+ @pytest.fixture
40
+ def mock_credentials() -> Any:
41
+ """Create mock credentials."""
42
+ return Mock()
43
+
44
+
45
+ @pytest.fixture
46
+ def patch_auth(mock_credentials: Any) -> Generator[Mock, None, None]:
47
+ """Patch the google.auth.default function."""
48
+ with patch(
49
+ "google.auth.default", return_value=(mock_credentials, "project")
50
+ ) as mock_auth:
51
+ yield mock_auth
52
+
53
+
54
+ @pytest.fixture
55
+ def patch_clients(
56
+ mock_logging_client: Mock, mock_storage_client: Mock
57
+ ) -> Generator[None, None, None]:
58
+ """Patch the logging and storage clients."""
59
+ with patch("google.cloud.logging.Client", return_value=mock_logging_client):
60
+ with patch("google.cloud.storage.Client", return_value=mock_storage_client):
61
+ yield
62
+
63
+
64
+ @pytest.fixture
65
+ def exporter(
66
+ mock_logging_client: Mock,
67
+ mock_storage_client: Mock,
68
+ patch_auth: Any,
69
+ mock_credentials: Any,
70
+ patch_clients: Any,
71
+ ) -> CloudTraceLoggingSpanExporter:
72
+ """Create a CloudTraceLoggingSpanExporter instance for testing."""
73
+ exporter = CloudTraceLoggingSpanExporter(
74
+ project_id="test-project",
75
+ logging_client=mock_logging_client,
76
+ storage_client=mock_storage_client,
77
+ bucket_name="test-bucket",
78
+ )
79
+ return exporter
80
+
81
+
82
+ def test_init(exporter: CloudTraceLoggingSpanExporter) -> None:
83
+ """Test the initialization of CloudTraceLoggingSpanExporter."""
84
+ assert exporter.project_id == "test-project"
85
+ assert exporter.bucket_name == "test-bucket"
86
+ assert exporter.debug is False
87
+
88
+
89
+ def test_store_in_gcs(exporter: CloudTraceLoggingSpanExporter) -> None:
90
+ """Test the store_in_gcs method of CloudTraceLoggingSpanExporter."""
91
+ span_id = "test-span-id"
92
+ content = "test-content"
93
+ uri = exporter.store_in_gcs(content, span_id)
94
+ assert uri == f"gs://test-bucket/spans/{span_id}.json"
95
+ exporter.bucket.blob.assert_called_once_with(f"spans/{span_id}.json")
96
+
97
+
98
+ @patch("json.dumps")
99
+ def test_process_large_attributes_small_payload(
100
+ mock_json_dumps: Mock, exporter: CloudTraceLoggingSpanExporter
101
+ ) -> None:
102
+ """Test processing of small payload attributes."""
103
+ mock_json_dumps.return_value = "a" * 100 # Small payload
104
+ span_dict = {"attributes": {"key": "value"}}
105
+ result = exporter._process_large_attributes(span_dict, "span-id")
106
+ assert result == span_dict
107
+
108
+
109
+ @patch("json.dumps")
110
+ def test_process_large_attributes_large_payload(
111
+ mock_json_dumps: Mock, exporter: CloudTraceLoggingSpanExporter
112
+ ) -> None:
113
+ """Test processing of large payload attributes."""
114
+ mock_json_dumps.return_value = "a" * (400 * 1024 + 1) # Large payload
115
+ span_dict = {
116
+ "attributes": {
117
+ "key1": "value1",
118
+ }
119
+ }
120
+ result = exporter._process_large_attributes(span_dict, "span-id")
121
+ assert "uri_payload" in result["attributes"]
122
+ assert "url_payload" in result["attributes"]
123
+
124
+
125
+ @patch.object(CloudTraceLoggingSpanExporter, "_process_large_attributes")
126
+ def test_export(
127
+ mock_process_large_attributes: Mock, exporter: CloudTraceLoggingSpanExporter
128
+ ) -> None:
129
+ """Test the export method of CloudTraceLoggingSpanExporter."""
130
+ mock_span = Mock(spec=ReadableSpan)
131
+ mock_span.get_span_context.return_value.trace_id = 123
132
+ mock_span.get_span_context.return_value.span_id = 456
133
+ mock_span.to_json.return_value = '{"key": "value"}'
134
+
135
+ mock_process_large_attributes.return_value = {"processed": "data"}
136
+
137
+ exporter.export([mock_span])
138
+
139
+ mock_process_large_attributes.assert_called_once()
140
+ exporter.logger.log_struct.assert_called_once()