agent-starter-pack 0.18.2__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 (114) hide show
  1. agent_starter_pack/agents/{langgraph_base_react → adk_a2a_base}/.template/templateconfig.yaml +5 -12
  2. agent_starter_pack/agents/adk_a2a_base/README.md +37 -0
  3. agent_starter_pack/{frontends/streamlit/frontend/style/app_markdown.py → agents/adk_a2a_base/app/__init__.py} +3 -23
  4. agent_starter_pack/agents/adk_a2a_base/app/agent.py +70 -0
  5. agent_starter_pack/agents/adk_a2a_base/notebooks/adk_a2a_app_testing.ipynb +583 -0
  6. agent_starter_pack/agents/{crewai_coding_crew/notebooks/evaluating_crewai_agent.ipynb → adk_a2a_base/notebooks/evaluating_adk_agent.ipynb} +163 -199
  7. agent_starter_pack/agents/adk_a2a_base/tests/integration/test_agent.py +58 -0
  8. agent_starter_pack/agents/adk_base/app/__init__.py +2 -2
  9. agent_starter_pack/agents/adk_base/app/agent.py +3 -0
  10. agent_starter_pack/agents/adk_base/notebooks/adk_app_testing.ipynb +13 -28
  11. agent_starter_pack/agents/adk_live/app/__init__.py +17 -0
  12. agent_starter_pack/agents/adk_live/app/agent.py +3 -0
  13. agent_starter_pack/agents/agentic_rag/app/__init__.py +2 -2
  14. agent_starter_pack/agents/agentic_rag/app/agent.py +3 -0
  15. agent_starter_pack/agents/agentic_rag/notebooks/adk_app_testing.ipynb +13 -28
  16. agent_starter_pack/agents/{crewai_coding_crew → langgraph_base}/.template/templateconfig.yaml +12 -9
  17. agent_starter_pack/agents/langgraph_base/README.md +30 -0
  18. agent_starter_pack/agents/langgraph_base/app/__init__.py +17 -0
  19. agent_starter_pack/agents/{langgraph_base_react → langgraph_base}/app/agent.py +4 -4
  20. agent_starter_pack/agents/{langgraph_base_react → langgraph_base}/tests/integration/test_agent.py +1 -1
  21. agent_starter_pack/base_template/.gitignore +4 -2
  22. agent_starter_pack/base_template/Makefile +110 -16
  23. agent_starter_pack/base_template/README.md +97 -12
  24. agent_starter_pack/base_template/deployment/terraform/dev/apis.tf +4 -6
  25. agent_starter_pack/base_template/deployment/terraform/dev/providers.tf +5 -1
  26. agent_starter_pack/base_template/deployment/terraform/dev/variables.tf +5 -3
  27. agent_starter_pack/base_template/deployment/terraform/dev/{% if cookiecutter.is_adk %}telemetry.tf{% else %}unused_telemetry.tf{% endif %} +193 -0
  28. agent_starter_pack/base_template/deployment/terraform/github.tf +16 -9
  29. agent_starter_pack/base_template/deployment/terraform/locals.tf +7 -7
  30. agent_starter_pack/base_template/deployment/terraform/providers.tf +5 -1
  31. agent_starter_pack/base_template/deployment/terraform/sql/completions.sql +138 -0
  32. agent_starter_pack/base_template/deployment/terraform/storage.tf +0 -9
  33. agent_starter_pack/base_template/deployment/terraform/variables.tf +15 -19
  34. agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}build_triggers.tf{% else %}unused_build_triggers.tf{% endif %} +20 -22
  35. agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.is_adk %}telemetry.tf{% else %}unused_telemetry.tf{% endif %} +206 -0
  36. agent_starter_pack/base_template/pyproject.toml +5 -17
  37. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/deploy-to-prod.yaml +19 -4
  38. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/staging.yaml +36 -11
  39. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/deploy-to-prod.yaml +24 -5
  40. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/staging.yaml +44 -9
  41. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/telemetry.py +96 -0
  42. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/{utils → app_utils}/typing.py +4 -6
  43. agent_starter_pack/{agents/crewai_coding_crew/app/crew/config/agents.yaml → base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}converters{% else %}unused_converters{% endif %}/__init__.py } +9 -23
  44. 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
  45. 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
  46. 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
  47. 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
  48. agent_starter_pack/cli/commands/create.py +40 -4
  49. agent_starter_pack/cli/commands/enhance.py +1 -1
  50. agent_starter_pack/cli/commands/register_gemini_enterprise.py +1070 -0
  51. agent_starter_pack/cli/main.py +2 -0
  52. agent_starter_pack/cli/utils/cicd.py +20 -4
  53. agent_starter_pack/cli/utils/template.py +257 -25
  54. agent_starter_pack/deployment_targets/agent_engine/tests/integration/test_agent_engine_app.py +113 -16
  55. agent_starter_pack/deployment_targets/agent_engine/tests/load_test/README.md +2 -2
  56. agent_starter_pack/deployment_targets/agent_engine/tests/load_test/load_test.py +178 -9
  57. agent_starter_pack/deployment_targets/agent_engine/tests/{% if cookiecutter.is_a2a %}helpers.py{% else %}unused_helpers.py{% endif %} +138 -0
  58. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/agent_engine_app.py +193 -307
  59. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/app_utils/deploy.py +414 -0
  60. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/{utils → app_utils}/{% if cookiecutter.is_adk_live %}expose_app.py{% else %}unused_expose_app.py{% endif %} +13 -14
  61. agent_starter_pack/deployment_targets/cloud_run/Dockerfile +4 -1
  62. agent_starter_pack/deployment_targets/cloud_run/deployment/terraform/dev/service.tf +85 -86
  63. agent_starter_pack/deployment_targets/cloud_run/deployment/terraform/service.tf +139 -107
  64. agent_starter_pack/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +228 -12
  65. agent_starter_pack/deployment_targets/cloud_run/tests/load_test/README.md +4 -4
  66. agent_starter_pack/deployment_targets/cloud_run/tests/load_test/load_test.py +92 -12
  67. agent_starter_pack/deployment_targets/cloud_run/{{cookiecutter.agent_directory}}/{server.py → fast_api_app.py} +194 -121
  68. agent_starter_pack/frontends/adk_live_react/frontend/package-lock.json +18 -18
  69. agent_starter_pack/frontends/adk_live_react/frontend/src/multimodal-live-types.ts +5 -3
  70. agent_starter_pack/resources/docs/adk-cheatsheet.md +198 -41
  71. agent_starter_pack/resources/locks/uv-adk_a2a_base-agent_engine.lock +4966 -0
  72. agent_starter_pack/resources/locks/uv-adk_a2a_base-cloud_run.lock +5011 -0
  73. agent_starter_pack/resources/locks/uv-adk_base-agent_engine.lock +1443 -709
  74. agent_starter_pack/resources/locks/uv-adk_base-cloud_run.lock +1058 -874
  75. agent_starter_pack/resources/locks/uv-adk_live-agent_engine.lock +1443 -709
  76. agent_starter_pack/resources/locks/uv-adk_live-cloud_run.lock +1058 -874
  77. agent_starter_pack/resources/locks/uv-agentic_rag-agent_engine.lock +1568 -749
  78. agent_starter_pack/resources/locks/uv-agentic_rag-cloud_run.lock +1123 -929
  79. agent_starter_pack/resources/locks/{uv-langgraph_base_react-agent_engine.lock → uv-langgraph_base-agent_engine.lock} +1714 -1689
  80. agent_starter_pack/resources/locks/{uv-langgraph_base_react-cloud_run.lock → uv-langgraph_base-cloud_run.lock} +1285 -2374
  81. agent_starter_pack/utils/watch_and_rebuild.py +1 -1
  82. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/METADATA +3 -6
  83. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/RECORD +89 -93
  84. agent_starter_pack-0.21.0.dist-info/entry_points.txt +2 -0
  85. llm.txt +4 -5
  86. agent_starter_pack/agents/crewai_coding_crew/README.md +0 -34
  87. agent_starter_pack/agents/crewai_coding_crew/app/agent.py +0 -47
  88. agent_starter_pack/agents/crewai_coding_crew/app/crew/config/tasks.yaml +0 -37
  89. agent_starter_pack/agents/crewai_coding_crew/app/crew/crew.py +0 -71
  90. agent_starter_pack/agents/crewai_coding_crew/tests/integration/test_agent.py +0 -47
  91. agent_starter_pack/agents/langgraph_base_react/README.md +0 -9
  92. agent_starter_pack/agents/langgraph_base_react/notebooks/evaluating_langgraph_agent.ipynb +0 -1574
  93. agent_starter_pack/base_template/deployment/terraform/dev/log_sinks.tf +0 -69
  94. agent_starter_pack/base_template/deployment/terraform/log_sinks.tf +0 -79
  95. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/utils/tracing.py +0 -155
  96. agent_starter_pack/cli/utils/register_gemini_enterprise.py +0 -406
  97. agent_starter_pack/deployment_targets/agent_engine/deployment/terraform/{% if not cookiecutter.is_adk_live %}service.tf{% else %}unused_service.tf{% endif %} +0 -82
  98. agent_starter_pack/deployment_targets/agent_engine/notebooks/intro_agent_engine.ipynb +0 -1025
  99. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/utils/deployment.py +0 -99
  100. agent_starter_pack/frontends/streamlit/frontend/side_bar.py +0 -214
  101. agent_starter_pack/frontends/streamlit/frontend/streamlit_app.py +0 -265
  102. agent_starter_pack/frontends/streamlit/frontend/utils/chat_utils.py +0 -67
  103. agent_starter_pack/frontends/streamlit/frontend/utils/local_chat_history.py +0 -127
  104. agent_starter_pack/frontends/streamlit/frontend/utils/message_editing.py +0 -59
  105. agent_starter_pack/frontends/streamlit/frontend/utils/multimodal_utils.py +0 -217
  106. agent_starter_pack/frontends/streamlit/frontend/utils/stream_handler.py +0 -310
  107. agent_starter_pack/frontends/streamlit/frontend/utils/title_summary.py +0 -94
  108. agent_starter_pack/resources/locks/uv-crewai_coding_crew-agent_engine.lock +0 -6650
  109. agent_starter_pack/resources/locks/uv-crewai_coding_crew-cloud_run.lock +0 -7825
  110. agent_starter_pack-0.18.2.dist-info/entry_points.txt +0 -3
  111. /agent_starter_pack/agents/{crewai_coding_crew → langgraph_base}/notebooks/evaluating_langgraph_agent.ipynb +0 -0
  112. /agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/{utils → app_utils}/gcs.py +0 -0
  113. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/WHEEL +0 -0
  114. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,152 @@
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 __future__ import annotations
16
+
17
+ from a2a.types import (
18
+ FilePart,
19
+ FileWithBytes,
20
+ FileWithUri,
21
+ Message,
22
+ Part,
23
+ Role,
24
+ TaskState,
25
+ TextPart,
26
+ )
27
+ from langchain_core.messages import AIMessage, ToolMessage
28
+
29
+
30
+ class LangGraphTaskResultAggregator:
31
+ """Aggregates streaming LangGraph messages into a final consolidated result."""
32
+
33
+ def __init__(self) -> None:
34
+ self._task_state = TaskState.working
35
+ self._accumulated_content = "" # Accumulate text content across chunks
36
+ self._task_status_message: Message | None = None
37
+ self._media_parts: list[Part] = [] # Track media parts from tool responses
38
+
39
+ def process_message(self, message: AIMessage | ToolMessage) -> None:
40
+ """Process a streaming message chunk from LangGraph."""
41
+
42
+ # Handle tool responses to extract media
43
+ if isinstance(message, ToolMessage):
44
+ self._extract_media_from_tool_response(message)
45
+ return
46
+
47
+ if not message.content:
48
+ return
49
+
50
+ if isinstance(message.content, str):
51
+ self._accumulated_content += message.content
52
+
53
+ elif isinstance(message.content, list):
54
+ for item in message.content:
55
+ if isinstance(item, str):
56
+ self._accumulated_content += item
57
+ elif isinstance(item, dict) and item.get("type") == "text":
58
+ self._accumulated_content += item.get("text", "")
59
+
60
+ # Update the task status message with current accumulated content
61
+ if self._accumulated_content or self._media_parts:
62
+ parts = []
63
+ if self._accumulated_content:
64
+ parts.append(Part(root=TextPart(text=self._accumulated_content)))
65
+ parts.extend(self._media_parts)
66
+
67
+ self._task_status_message = Message(
68
+ message_id="aggregated",
69
+ role=Role.agent,
70
+ parts=parts,
71
+ )
72
+
73
+ def _extract_media_from_tool_response(self, message: ToolMessage) -> None:
74
+ """Extract media parts from a ToolMessage."""
75
+
76
+ if not message.content:
77
+ return
78
+
79
+ if isinstance(message.content, list):
80
+ for item in message.content:
81
+ if isinstance(item, dict):
82
+ content_type = item.get("type")
83
+ if content_type == "image":
84
+ self._media_parts.append(
85
+ self._convert_media_to_a2a_part(item, "image")
86
+ )
87
+ elif content_type == "audio":
88
+ self._media_parts.append(
89
+ self._convert_media_to_a2a_part(item, "audio")
90
+ )
91
+ elif content_type == "video":
92
+ self._media_parts.append(
93
+ self._convert_media_to_a2a_part(item, "video")
94
+ )
95
+
96
+ def _convert_media_to_a2a_part(
97
+ self, content: dict[str, str], media_type: str
98
+ ) -> Part:
99
+ """Convert a media content block to an A2A Part."""
100
+
101
+ mime_type = content.get("mime_type")
102
+
103
+ if "url" in content:
104
+ return Part(
105
+ root=FilePart(file=FileWithUri(uri=content["url"], mime_type=mime_type))
106
+ )
107
+ elif "base64" in content:
108
+ return Part(
109
+ root=FilePart(
110
+ file=FileWithBytes(bytes=content["base64"], mime_type=mime_type)
111
+ )
112
+ )
113
+ elif "file_id" in content:
114
+ # For now, store file_id as a URI
115
+ return Part(
116
+ root=FilePart(
117
+ file=FileWithUri(
118
+ uri=f"file://{content['file_id']}", mime_type=mime_type
119
+ )
120
+ )
121
+ )
122
+
123
+ # Fallback to empty text part
124
+ return Part(root=TextPart(text=f"[{media_type} content]"))
125
+
126
+ def get_final_parts(self) -> list[Part]:
127
+ """Get the final consolidated parts for the artifact."""
128
+
129
+ parts = []
130
+ if self._accumulated_content:
131
+ parts.append(Part(root=TextPart(text=self._accumulated_content)))
132
+ parts.extend(self._media_parts)
133
+ return parts if parts else []
134
+
135
+ @property
136
+ def task_state(self) -> TaskState:
137
+ """Get the current task state."""
138
+ return self._task_state
139
+
140
+ @property
141
+ def task_status_message(self) -> Message | None:
142
+ """Get the current task status message with accumulated content."""
143
+ return self._task_status_message
144
+
145
+ def set_failed(self, error_message: str) -> None:
146
+ """Set the task state to failed."""
147
+ self._task_state = TaskState.failed
148
+ self._task_status_message = Message(
149
+ message_id="error",
150
+ role=Role.agent,
151
+ parts=[Part(root=TextPart(text=error_message))],
152
+ )
@@ -37,6 +37,7 @@ from ..utils.remote_template import (
37
37
  parse_agent_spec,
38
38
  )
39
39
  from ..utils.template import (
40
+ add_base_template_dependencies_interactively,
40
41
  get_available_agents,
41
42
  get_deployment_targets,
42
43
  get_template_path,
@@ -81,7 +82,7 @@ def shared_template_options(f: Callable) -> Callable:
81
82
  f = click.option("--debug", is_flag=True, help="Enable debug logging")(f)
82
83
  f = click.option(
83
84
  "--session-type",
84
- type=click.Choice(["in_memory", "alloydb", "agent_engine"]),
85
+ type=click.Choice(["in_memory", "cloud_sql", "agent_engine"]),
85
86
  help="Type of session storage to use",
86
87
  )(f)
87
88
  f = click.option(
@@ -112,6 +113,11 @@ def shared_template_options(f: Callable) -> Callable:
112
113
  "-dir",
113
114
  help="Name of the agent directory (overrides template default)",
114
115
  )(f)
116
+ f = click.option(
117
+ "--base-template",
118
+ "-bt",
119
+ help="Base template to use (overrides template default, only for remote templates)",
120
+ )(f)
115
121
  return f
116
122
 
117
123
 
@@ -474,6 +480,18 @@ def create(
474
480
  if cli_overrides is None:
475
481
  cli_overrides = {}
476
482
  if base_template:
483
+ # Validate that the base template exists
484
+ if not validate_base_template(base_template):
485
+ available_templates = get_available_base_templates()
486
+ console.print(
487
+ f"Error: Base template '{base_template}' not found.",
488
+ style="bold red",
489
+ )
490
+ console.print(
491
+ f"Available base templates: {', '.join(available_templates)}",
492
+ style="yellow",
493
+ )
494
+ raise click.Abort()
477
495
  cli_overrides["base_template"] = base_template
478
496
 
479
497
  # Load remote template config
@@ -707,9 +725,9 @@ def create(
707
725
  try:
708
726
  # Process template (handles both local and remote templates)
709
727
  process_template(
710
- final_agent,
711
- template_path,
712
- project_name,
728
+ agent_name=final_agent,
729
+ template_dir=template_path,
730
+ project_name=project_name,
713
731
  deployment_target=final_deployment,
714
732
  cicd_runner=final_cicd_runner,
715
733
  include_data_ingestion=include_data_ingestion,
@@ -727,6 +745,24 @@ def create(
727
745
  # Replace region in all files if a different region was specified
728
746
  if region != "us-central1":
729
747
  replace_region_in_files(project_path, region, debug=debug)
748
+
749
+ # Handle base template dependencies if override was used
750
+ if base_template and template_source_path and remote_config:
751
+ # Load base template config to get extra_dependencies
752
+ base_template_path = get_template_path(base_template, debug=debug)
753
+ base_config = load_template_config(base_template_path)
754
+ base_deps = base_config.get("settings", {}).get(
755
+ "extra_dependencies", []
756
+ )
757
+
758
+ if base_deps:
759
+ # Call interactive dependency addition
760
+ add_base_template_dependencies_interactively(
761
+ project_path,
762
+ base_deps,
763
+ base_template,
764
+ auto_approve=auto_approve,
765
+ )
730
766
  finally:
731
767
  # Clean up the temporary directory if one was created
732
768
  if temp_dir_to_clean:
@@ -225,7 +225,7 @@ def display_agent_directory_selection(
225
225
  @click.option(
226
226
  "--base-template",
227
227
  "-b",
228
- help="Base template to inherit from (e.g., adk_base, langgraph_base_react, agentic_rag)",
228
+ help="Base template to inherit from (e.g., adk_base, langgraph_base, agentic_rag)",
229
229
  )
230
230
  @click.option(
231
231
  "--adk",