agent-starter-pack 0.15.7__py3-none-any.whl → 0.17.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.
Potentially problematic release.
This version of agent-starter-pack might be problematic. Click here for more details.
- {agents → agent_starter_pack/agents}/adk_base/.template/templateconfig.yaml +1 -1
- {agents/live_api → agent_starter_pack/agents/adk_live}/.template/templateconfig.yaml +5 -7
- agent_starter_pack/agents/adk_live/README.md +32 -0
- agent_starter_pack/agents/adk_live/app/agent.py +48 -0
- agent_starter_pack/agents/adk_live/tests/unit/test_dummy.py +38 -0
- {agents → agent_starter_pack/agents}/agentic_rag/.template/templateconfig.yaml +1 -1
- agent_starter_pack/agents/crewai_coding_crew/app/agent.py +47 -0
- agent_starter_pack/agents/langgraph_base_react/app/agent.py +34 -0
- {src → agent_starter_pack}/base_template/GEMINI.md +1 -1
- {src → agent_starter_pack}/base_template/Makefile +130 -61
- {src → agent_starter_pack}/base_template/README.md +6 -6
- {src → agent_starter_pack}/base_template/deployment/terraform/dev/apis.tf +1 -1
- {src → agent_starter_pack}/base_template/deployment/terraform/dev/log_sinks.tf +31 -25
- {src → agent_starter_pack}/base_template/deployment/terraform/dev/providers.tf +1 -1
- {src → agent_starter_pack}/base_template/deployment/terraform/dev/variables.tf +1 -1
- {src → agent_starter_pack}/base_template/deployment/terraform/github.tf +14 -0
- {src → agent_starter_pack}/base_template/deployment/terraform/locals.tf +1 -1
- {src → agent_starter_pack}/base_template/deployment/terraform/log_sinks.tf +37 -28
- {src → agent_starter_pack}/base_template/deployment/terraform/providers.tf +1 -1
- {src → agent_starter_pack}/base_template/deployment/terraform/variables.tf +1 -1
- {src → agent_starter_pack}/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}build_triggers.tf{% else %}unused_build_triggers.tf{% endif %} +4 -2
- {src → agent_starter_pack}/base_template/pyproject.toml +22 -21
- {src → agent_starter_pack}/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/deploy-to-prod.yaml +5 -5
- {src → agent_starter_pack}/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/pr_checks.yaml +3 -3
- {src → agent_starter_pack}/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/staging.yaml +74 -11
- {src → agent_starter_pack}/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/deploy-to-prod.yaml +6 -6
- {src → agent_starter_pack}/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/pr_checks.yaml +4 -4
- {src → agent_starter_pack}/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/staging.yaml +95 -13
- {src → agent_starter_pack}/base_template/{{cookiecutter.agent_directory}}/utils/tracing.py +1 -1
- {src → agent_starter_pack}/base_template/{{cookiecutter.agent_directory}}/utils/typing.py +4 -4
- {src → agent_starter_pack}/cli/commands/setup_cicd.py +1 -1
- {src → agent_starter_pack}/cli/main.py +2 -2
- {src → agent_starter_pack}/cli/utils/gcp.py +1 -1
- {src → agent_starter_pack}/cli/utils/remote_template.py +12 -9
- {src → agent_starter_pack}/cli/utils/template.py +19 -15
- agent_starter_pack/deployment_targets/agent_engine/deployment/terraform/{% if not cookiecutter.is_adk_live %}service.tf{% else %}unused_service.tf{% endif %} +82 -0
- agent_starter_pack/deployment_targets/agent_engine/tests/integration/test_agent_engine_app.py +387 -0
- agent_starter_pack/deployment_targets/agent_engine/tests/load_test/README.md +84 -0
- agent_starter_pack/deployment_targets/agent_engine/tests/load_test/load_test.py +255 -0
- {src → agent_starter_pack}/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/agent_engine_app.py +40 -14
- {src → agent_starter_pack}/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/utils/deployment.py +13 -4
- agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/utils/{% if cookiecutter.is_adk_live %}expose_app.py{% else %}unused_expose_app.py{% endif %} +520 -0
- {src → agent_starter_pack}/deployment_targets/cloud_run/Dockerfile +3 -3
- {src → agent_starter_pack}/deployment_targets/cloud_run/deployment/terraform/dev/service.tf +4 -4
- {src → agent_starter_pack}/deployment_targets/cloud_run/deployment/terraform/service.tf +7 -7
- {src → agent_starter_pack}/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +207 -5
- {src → agent_starter_pack}/deployment_targets/cloud_run/tests/load_test/README.md +82 -0
- agent_starter_pack/deployment_targets/cloud_run/tests/load_test/load_test.py +249 -0
- {src → agent_starter_pack}/deployment_targets/cloud_run/{{cookiecutter.agent_directory}}/server.py +190 -146
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/package-lock.json +39 -1007
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/package.json +1 -9
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/App.tsx +1 -1
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/logger/Logger.tsx +8 -3
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/logger/logger.scss +26 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/side-panel/SidePanel.tsx +11 -5
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/side-panel/side-panel.scss +146 -115
- agent_starter_pack/frontends/adk_live_react/frontend/src/components/transcription-preview/TranscriptionPreview.tsx +106 -0
- agent_starter_pack/frontends/adk_live_react/frontend/src/components/transcription-preview/transcription-preview.scss +150 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/hooks/use-live-api.ts +8 -2
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/multimodal-live-types.ts +38 -2
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/audio-recorder.ts +1 -1
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/audio-streamer.ts +1 -1
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/multimodal-live-client.ts +204 -23
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/utils.ts +27 -5
- {src → agent_starter_pack}/frontends/streamlit/frontend/utils/local_chat_history.py +2 -0
- {src → agent_starter_pack}/resources/docs/adk-cheatsheet.md +5 -5
- agent_starter_pack/resources/idx/.idx/dev.nix +64 -0
- agent_starter_pack/resources/idx/idx-template.json +6 -0
- {src → agent_starter_pack}/resources/idx/idx-template.nix +2 -3
- {src → agent_starter_pack}/resources/locks/uv-adk_base-agent_engine.lock +1079 -954
- {src → agent_starter_pack}/resources/locks/uv-adk_base-cloud_run.lock +1441 -1309
- agent_starter_pack/resources/locks/uv-adk_live-agent_engine.lock +4229 -0
- agent_starter_pack/resources/locks/uv-adk_live-cloud_run.lock +4822 -0
- {src → agent_starter_pack}/resources/locks/uv-agentic_rag-agent_engine.lock +1107 -997
- {src → agent_starter_pack}/resources/locks/uv-agentic_rag-cloud_run.lock +1485 -1368
- {src → agent_starter_pack}/resources/locks/uv-crewai_coding_crew-agent_engine.lock +1294 -1297
- {src → agent_starter_pack}/resources/locks/uv-crewai_coding_crew-cloud_run.lock +2028 -1807
- {src → agent_starter_pack}/resources/locks/uv-langgraph_base_react-agent_engine.lock +1176 -1197
- {src → agent_starter_pack}/resources/locks/uv-langgraph_base_react-cloud_run.lock +1947 -1679
- {src → agent_starter_pack}/utils/generate_locks.py +12 -7
- {src → agent_starter_pack}/utils/lock_utils.py +2 -2
- {src → agent_starter_pack}/utils/watch_and_rebuild.py +1 -1
- {agent_starter_pack-0.15.7.dist-info → agent_starter_pack-0.17.0.dist-info}/METADATA +17 -18
- agent_starter_pack-0.17.0.dist-info/RECORD +179 -0
- agent_starter_pack-0.17.0.dist-info/entry_points.txt +2 -0
- llm.txt +1 -1
- agent_starter_pack-0.15.7.dist-info/RECORD +0 -176
- agent_starter_pack-0.15.7.dist-info/entry_points.txt +0 -2
- agents/crewai_coding_crew/app/agent.py +0 -86
- agents/langgraph_base_react/app/agent.py +0 -73
- agents/live_api/README.md +0 -37
- agents/live_api/app/agent.py +0 -72
- agents/live_api/tests/integration/test_server_e2e.py +0 -260
- agents/live_api/tests/load_test/load_test.py +0 -40
- agents/live_api/tests/unit/test_server.py +0 -144
- src/deployment_targets/agent_engine/tests/integration/test_agent_engine_app.py +0 -186
- src/deployment_targets/agent_engine/tests/load_test/README.md +0 -37
- src/deployment_targets/agent_engine/tests/load_test/load_test.py +0 -126
- src/deployment_targets/cloud_run/tests/load_test/load_test.py +0 -122
- src/resources/idx/.idx/dev.nix +0 -50
- src/resources/idx/idx-template.json +0 -21
- src/resources/locks/uv-live_api-cloud_run.lock +0 -6118
- {agents → agent_starter_pack/agents}/README.md +0 -0
- {agents → agent_starter_pack/agents}/adk_base/README.md +0 -0
- {agents → agent_starter_pack/agents}/adk_base/app/__init__.py +0 -0
- {agents → agent_starter_pack/agents}/adk_base/app/agent.py +0 -0
- {agents → agent_starter_pack/agents}/adk_base/notebooks/adk_app_testing.ipynb +0 -0
- {agents → agent_starter_pack/agents}/adk_base/notebooks/evaluating_adk_agent.ipynb +0 -0
- {agents → agent_starter_pack/agents}/adk_base/tests/integration/test_agent.py +0 -0
- {agents → agent_starter_pack/agents}/agentic_rag/README.md +0 -0
- {agents → agent_starter_pack/agents}/agentic_rag/app/__init__.py +0 -0
- {agents → agent_starter_pack/agents}/agentic_rag/app/agent.py +0 -0
- {agents → agent_starter_pack/agents}/agentic_rag/app/retrievers.py +0 -0
- {agents → agent_starter_pack/agents}/agentic_rag/app/templates.py +0 -0
- {agents → agent_starter_pack/agents}/agentic_rag/notebooks/adk_app_testing.ipynb +0 -0
- {agents → agent_starter_pack/agents}/agentic_rag/notebooks/evaluating_adk_agent.ipynb +0 -0
- {agents → agent_starter_pack/agents}/agentic_rag/tests/integration/test_agent.py +0 -0
- {agents → agent_starter_pack/agents}/crewai_coding_crew/.template/templateconfig.yaml +0 -0
- {agents → agent_starter_pack/agents}/crewai_coding_crew/README.md +0 -0
- {agents → agent_starter_pack/agents}/crewai_coding_crew/app/crew/config/agents.yaml +0 -0
- {agents → agent_starter_pack/agents}/crewai_coding_crew/app/crew/config/tasks.yaml +0 -0
- {agents → agent_starter_pack/agents}/crewai_coding_crew/app/crew/crew.py +0 -0
- {agents → agent_starter_pack/agents}/crewai_coding_crew/notebooks/evaluating_crewai_agent.ipynb +0 -0
- {agents → agent_starter_pack/agents}/crewai_coding_crew/notebooks/evaluating_langgraph_agent.ipynb +0 -0
- {agents → agent_starter_pack/agents}/crewai_coding_crew/tests/integration/test_agent.py +0 -0
- {agents → agent_starter_pack/agents}/langgraph_base_react/.template/templateconfig.yaml +0 -0
- {agents → agent_starter_pack/agents}/langgraph_base_react/README.md +0 -0
- {agents → agent_starter_pack/agents}/langgraph_base_react/notebooks/evaluating_langgraph_agent.ipynb +0 -0
- {agents → agent_starter_pack/agents}/langgraph_base_react/tests/integration/test_agent.py +0 -0
- {src → agent_starter_pack}/base_template/.gitignore +0 -0
- {src → agent_starter_pack}/base_template/deployment/README.md +0 -0
- {src → agent_starter_pack}/base_template/deployment/terraform/apis.tf +0 -0
- {src → agent_starter_pack}/base_template/deployment/terraform/dev/iam.tf +0 -0
- {src → agent_starter_pack}/base_template/deployment/terraform/dev/storage.tf +0 -0
- {src → agent_starter_pack}/base_template/deployment/terraform/dev/vars/env.tfvars +0 -0
- {src → agent_starter_pack}/base_template/deployment/terraform/iam.tf +0 -0
- {src → agent_starter_pack}/base_template/deployment/terraform/service_accounts.tf +0 -0
- {src → agent_starter_pack}/base_template/deployment/terraform/storage.tf +0 -0
- {src → agent_starter_pack}/base_template/deployment/terraform/vars/env.tfvars +0 -0
- {src → agent_starter_pack}/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'github_actions' %}wif.tf{% else %}unused_wif.tf{% endif %} +0 -0
- {src → agent_starter_pack}/base_template/tests/unit/test_dummy.py +0 -0
- {src → agent_starter_pack}/base_template/{{cookiecutter.agent_directory}}/utils/gcs.py +0 -0
- {src → agent_starter_pack}/cli/commands/create.py +0 -0
- {src → agent_starter_pack}/cli/commands/enhance.py +0 -0
- {src → agent_starter_pack}/cli/commands/list.py +0 -0
- {src → agent_starter_pack}/cli/utils/__init__.py +0 -0
- {src → agent_starter_pack}/cli/utils/cicd.py +0 -0
- {src → agent_starter_pack}/cli/utils/datastores.py +0 -0
- {src → agent_starter_pack}/cli/utils/logging.py +0 -0
- {src → agent_starter_pack}/cli/utils/version.py +0 -0
- {src → agent_starter_pack}/data_ingestion/README.md +0 -0
- {src → agent_starter_pack}/data_ingestion/data_ingestion_pipeline/components/ingest_data.py +0 -0
- {src → agent_starter_pack}/data_ingestion/data_ingestion_pipeline/components/process_data.py +0 -0
- {src → agent_starter_pack}/data_ingestion/data_ingestion_pipeline/pipeline.py +0 -0
- {src → agent_starter_pack}/data_ingestion/data_ingestion_pipeline/submit_pipeline.py +0 -0
- {src → agent_starter_pack}/data_ingestion/pyproject.toml +0 -0
- {src → agent_starter_pack}/data_ingestion/uv.lock +0 -0
- {src → agent_starter_pack}/deployment_targets/agent_engine/deployment_metadata.json +0 -0
- {src → agent_starter_pack}/deployment_targets/agent_engine/notebooks/intro_agent_engine.ipynb +0 -0
- {src → agent_starter_pack}/deployment_targets/agent_engine/tests/load_test/.results/.placeholder +0 -0
- {src → agent_starter_pack}/deployment_targets/cloud_run/tests/load_test/.results/.placeholder +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/public/favicon.ico +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/public/index.html +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/public/robots.txt +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/App.scss +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/App.test.tsx +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/audio-pulse/AudioPulse.tsx +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/audio-pulse/audio-pulse.scss +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/logger/mock-logs.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/contexts/LiveAPIContext.tsx +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/hooks/use-media-stream-mux.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/hooks/use-screen-capture.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/hooks/use-webcam.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/index.css +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/index.tsx +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/react-app-env.d.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/reportWebVitals.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/setupTests.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/audioworklet-registry.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/store-logger.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/worklets/audio-processing.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/worklets/vol-meter.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/tsconfig.json +0 -0
- {src → agent_starter_pack}/frontends/streamlit/frontend/side_bar.py +0 -0
- {src → agent_starter_pack}/frontends/streamlit/frontend/streamlit_app.py +0 -0
- {src → agent_starter_pack}/frontends/streamlit/frontend/style/app_markdown.py +0 -0
- {src → agent_starter_pack}/frontends/streamlit/frontend/utils/chat_utils.py +0 -0
- {src → agent_starter_pack}/frontends/streamlit/frontend/utils/message_editing.py +0 -0
- {src → agent_starter_pack}/frontends/streamlit/frontend/utils/multimodal_utils.py +0 -0
- {src → agent_starter_pack}/frontends/streamlit/frontend/utils/stream_handler.py +0 -0
- {src → agent_starter_pack}/frontends/streamlit/frontend/utils/title_summary.py +0 -0
- {src → agent_starter_pack}/resources/containers/data_processing/Dockerfile +0 -0
- {src → agent_starter_pack}/resources/containers/e2e-tests/Dockerfile +0 -0
- {agent_starter_pack-0.15.7.dist-info → agent_starter_pack-0.17.0.dist-info}/WHEEL +0 -0
- {agent_starter_pack-0.15.7.dist-info → agent_starter_pack-0.17.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -76,6 +76,10 @@ export function useLiveAPI({
|
|
|
76
76
|
setConnected(false);
|
|
77
77
|
};
|
|
78
78
|
|
|
79
|
+
const onSetupComplete = () => {
|
|
80
|
+
setConnected(true);
|
|
81
|
+
};
|
|
82
|
+
|
|
79
83
|
const stopAudioStreamer = () => audioStreamerRef.current?.stop();
|
|
80
84
|
|
|
81
85
|
const onAudio = (data: ArrayBuffer) =>
|
|
@@ -83,12 +87,14 @@ export function useLiveAPI({
|
|
|
83
87
|
|
|
84
88
|
client
|
|
85
89
|
.on("close", onClose)
|
|
90
|
+
.on("setupcomplete", onSetupComplete)
|
|
86
91
|
.on("interrupted", stopAudioStreamer)
|
|
87
92
|
.on("audio", onAudio);
|
|
88
93
|
|
|
89
94
|
return () => {
|
|
90
95
|
client
|
|
91
96
|
.off("close", onClose)
|
|
97
|
+
.off("setupcomplete", onSetupComplete)
|
|
92
98
|
.off("interrupted", stopAudioStreamer)
|
|
93
99
|
.off("audio", onAudio);
|
|
94
100
|
};
|
|
@@ -97,8 +103,8 @@ export function useLiveAPI({
|
|
|
97
103
|
const connect = useCallback(async () => {
|
|
98
104
|
client.disconnect();
|
|
99
105
|
await client.connect();
|
|
100
|
-
|
|
101
|
-
}, [client
|
|
106
|
+
// Don't set connected here - wait for setupcomplete event
|
|
107
|
+
}, [client]);
|
|
102
108
|
|
|
103
109
|
const disconnect = useCallback(async () => {
|
|
104
110
|
client.disconnect();
|
|
@@ -94,7 +94,8 @@ export type LiveIncomingMessage =
|
|
|
94
94
|
| ToolCallMessage
|
|
95
95
|
| ToolCallCancellationMessage
|
|
96
96
|
| SetupCompleteMessage
|
|
97
|
-
| ServerContentMessage
|
|
97
|
+
| ServerContentMessage
|
|
98
|
+
| AdkEvent;
|
|
98
99
|
|
|
99
100
|
export type SetupCompleteMessage = { setupComplete: {} };
|
|
100
101
|
|
|
@@ -148,7 +149,7 @@ export type StreamingLog = {
|
|
|
148
149
|
|
|
149
150
|
// Type-Guards
|
|
150
151
|
|
|
151
|
-
const prop = (a: any, prop: string
|
|
152
|
+
const prop = (a: any, prop: string) =>
|
|
152
153
|
typeof a === "object" && typeof a[prop] === "object";
|
|
153
154
|
|
|
154
155
|
// outgoing messages
|
|
@@ -240,3 +241,38 @@ export const isToolCallCancellation = (
|
|
|
240
241
|
a: unknown,
|
|
241
242
|
): a is ToolCallCancellationMessage["toolCallCancellation"] =>
|
|
242
243
|
typeof a === "object" && Array.isArray((a as any).ids);
|
|
244
|
+
|
|
245
|
+
// ADK Event types
|
|
246
|
+
export interface AdkEvent {
|
|
247
|
+
invocation_id: string;
|
|
248
|
+
author: string;
|
|
249
|
+
actions: {
|
|
250
|
+
state_delta: any;
|
|
251
|
+
artifact_delta: any;
|
|
252
|
+
requested_auth_configs: any;
|
|
253
|
+
requested_tool_confirmations: any;
|
|
254
|
+
};
|
|
255
|
+
id: string;
|
|
256
|
+
timestamp: number;
|
|
257
|
+
// Optional ADK fields
|
|
258
|
+
input_transcription?: { text: string };
|
|
259
|
+
output_transcription?: { text: string };
|
|
260
|
+
content?: any;
|
|
261
|
+
interrupted?: boolean;
|
|
262
|
+
turn_complete?: boolean;
|
|
263
|
+
partial?: boolean;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// ADK Event type guards
|
|
267
|
+
export const isAdkEvent = (a: unknown): a is AdkEvent =>
|
|
268
|
+
typeof a === "object" &&
|
|
269
|
+
a !== null &&
|
|
270
|
+
typeof (a as any).invocation_id === "string" &&
|
|
271
|
+
typeof (a as any).author === "string" &&
|
|
272
|
+
typeof (a as any).actions === "object";
|
|
273
|
+
|
|
274
|
+
export const isInputTranscription = (a: unknown): a is AdkEvent =>
|
|
275
|
+
isAdkEvent(a) && (a as AdkEvent).input_transcription !== undefined;
|
|
276
|
+
|
|
277
|
+
export const isOutputTranscription = (a: unknown): a is AdkEvent =>
|
|
278
|
+
isAdkEvent(a) && (a as AdkEvent).output_transcription !== undefined;
|
|
@@ -50,7 +50,7 @@ export class AudioRecorder extends EventEmitter {
|
|
|
50
50
|
throw new Error("Could not request user media");
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
this.starting = new Promise(async (resolve
|
|
53
|
+
this.starting = new Promise(async (resolve) => {
|
|
54
54
|
this.stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
55
55
|
this.audioContext = await audioContext({ sampleRate: this.sampleRate });
|
|
56
56
|
this.source = this.audioContext.createMediaStreamSource(this.stream);
|
|
@@ -154,7 +154,7 @@ export class AudioStreamer {
|
|
|
154
154
|
const worklets = registeredWorklets.get(this.context);
|
|
155
155
|
|
|
156
156
|
if (worklets) {
|
|
157
|
-
Object.entries(worklets).forEach(([
|
|
157
|
+
Object.entries(worklets).forEach(([, graph]) => {
|
|
158
158
|
const { node, handlers } = graph;
|
|
159
159
|
if (node) {
|
|
160
160
|
source.connect(node);
|
|
@@ -18,7 +18,6 @@ import { Content, GenerativeContentBlob, Part } from "@google/generative-ai";
|
|
|
18
18
|
import { EventEmitter } from "eventemitter3";
|
|
19
19
|
import { difference } from "lodash";
|
|
20
20
|
import {
|
|
21
|
-
ClientContentMessage,
|
|
22
21
|
isInterrupted,
|
|
23
22
|
isModelTurn,
|
|
24
23
|
isServerContenteMessage,
|
|
@@ -26,15 +25,18 @@ import {
|
|
|
26
25
|
isToolCallCancellationMessage,
|
|
27
26
|
isToolCallMessage,
|
|
28
27
|
isTurnComplete,
|
|
28
|
+
isAdkEvent,
|
|
29
|
+
isInputTranscription,
|
|
30
|
+
isOutputTranscription,
|
|
29
31
|
LiveIncomingMessage,
|
|
30
32
|
ModelTurn,
|
|
31
|
-
RealtimeInputMessage,
|
|
32
33
|
ServerContent,
|
|
33
34
|
StreamingLog,
|
|
34
35
|
ToolCall,
|
|
35
36
|
ToolCallCancellation,
|
|
36
37
|
ToolResponseMessage,
|
|
37
38
|
type LiveConfig,
|
|
39
|
+
type AdkEvent,
|
|
38
40
|
} from "../multimodal-live-types";
|
|
39
41
|
import { blobToJSON, base64ToArrayBuffer } from "./utils";
|
|
40
42
|
|
|
@@ -53,6 +55,10 @@ interface MultimodalLiveClientEventTypes {
|
|
|
53
55
|
turncomplete: () => void;
|
|
54
56
|
toolcall: (toolCall: ToolCall) => void;
|
|
55
57
|
toolcallcancellation: (toolcallCancellation: ToolCallCancellation) => void;
|
|
58
|
+
// ADK events
|
|
59
|
+
inputtranscription: (text: string) => void;
|
|
60
|
+
outputtranscription: (text: string) => void;
|
|
61
|
+
adkevent: (event: AdkEvent) => void;
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
export type MultimodalLiveAPIClientConnection = {
|
|
@@ -72,6 +78,13 @@ export class MultimodalLiveClient extends EventEmitter<MultimodalLiveClientEvent
|
|
|
72
78
|
public url: string = "";
|
|
73
79
|
private runId: string;
|
|
74
80
|
private userId?: string;
|
|
81
|
+
private firstContentSent: boolean = false;
|
|
82
|
+
private audioChunksSent: number = 0;
|
|
83
|
+
private lastAudioSendTime: number = 0;
|
|
84
|
+
private readonly INITIAL_SEND_INTERVAL_MS = 300; // Start slow: 300ms between chunks
|
|
85
|
+
private readonly NORMAL_SEND_INTERVAL_MS = 125; // Normal rate: 125ms (8 chunks/sec)
|
|
86
|
+
private readonly RAMPUP_CHUNKS = 10; // Number of chunks to send at reduced rate
|
|
87
|
+
|
|
75
88
|
constructor({ url, userId, runId }: MultimodalLiveAPIClientConnection) {
|
|
76
89
|
super();
|
|
77
90
|
const defaultWsUrl = `${window.location.protocol === 'https:' ? 'wss:' : 'ws:'}//${window.location.host}/ws`;
|
|
@@ -103,15 +116,37 @@ export class MultimodalLiveClient extends EventEmitter<MultimodalLiveClientEvent
|
|
|
103
116
|
this.runId = newRunId;
|
|
104
117
|
}
|
|
105
118
|
|
|
119
|
+
// Reset connection state
|
|
120
|
+
this.firstContentSent = false;
|
|
121
|
+
this.audioChunksSent = 0;
|
|
122
|
+
this.lastAudioSendTime = 0;
|
|
123
|
+
|
|
106
124
|
ws.addEventListener("message", async (evt: MessageEvent) => {
|
|
107
125
|
if (evt.data instanceof Blob) {
|
|
108
126
|
this.receive(evt.data);
|
|
109
127
|
} else if (typeof evt.data === "string") {
|
|
110
128
|
try {
|
|
111
129
|
const jsonData = JSON.parse(evt.data);
|
|
112
|
-
|
|
130
|
+
|
|
131
|
+
// Handle different message types from backend
|
|
132
|
+
if (jsonData.setupComplete) {
|
|
133
|
+
this.emit("setupcomplete");
|
|
134
|
+
this.log("server.setupComplete", "Session ready");
|
|
135
|
+
} else if (jsonData.serverContent) {
|
|
136
|
+
// Handle serverContent messages
|
|
137
|
+
this.receive(new Blob([JSON.stringify(jsonData)], {type: 'application/json'}));
|
|
138
|
+
} else if (jsonData.toolCall) {
|
|
139
|
+
// Handle tool calls
|
|
140
|
+
this.receive(new Blob([JSON.stringify(jsonData)], {type: 'application/json'}));
|
|
141
|
+
} else if (jsonData.status) {
|
|
113
142
|
this.log("server.status", jsonData.status);
|
|
114
|
-
console.log("Status:", jsonData.status);
|
|
143
|
+
console.log("Status:", jsonData.status);
|
|
144
|
+
} else if (jsonData.error) {
|
|
145
|
+
this.log("server.error", jsonData.error);
|
|
146
|
+
console.error("Server error:", jsonData.error);
|
|
147
|
+
} else {
|
|
148
|
+
// Try to process as a regular message
|
|
149
|
+
this.receive(new Blob([JSON.stringify(jsonData)], {type: 'application/json'}));
|
|
115
150
|
}
|
|
116
151
|
} catch (error) {
|
|
117
152
|
console.error("Error parsing message:", error);
|
|
@@ -134,11 +169,12 @@ export class MultimodalLiveClient extends EventEmitter<MultimodalLiveClientEvent
|
|
|
134
169
|
this.emit("open");
|
|
135
170
|
|
|
136
171
|
this.ws = ws;
|
|
137
|
-
// Send initial setup message with
|
|
172
|
+
// Send initial setup message with user_id for backend
|
|
138
173
|
const setupMessage = {
|
|
174
|
+
user_id: this.userId || "default_user",
|
|
139
175
|
setup: {
|
|
140
176
|
run_id: this.runId,
|
|
141
|
-
user_id: this.userId,
|
|
177
|
+
user_id: this.userId || "default_user",
|
|
142
178
|
},
|
|
143
179
|
};
|
|
144
180
|
this._sendDirect(setupMessage);
|
|
@@ -218,11 +254,18 @@ export class MultimodalLiveClient extends EventEmitter<MultimodalLiveClientEvent
|
|
|
218
254
|
if (isModelTurn(serverContent)) {
|
|
219
255
|
let parts: Part[] = serverContent.modelTurn.parts;
|
|
220
256
|
|
|
221
|
-
// when its audio that is returned for modelTurn
|
|
257
|
+
// when its audio that is returned for modelTurn (check both camelCase and snake_case)
|
|
222
258
|
const audioParts = parts.filter(
|
|
223
|
-
(p) =>
|
|
259
|
+
(p: any) => {
|
|
260
|
+
const inlineData = p.inlineData || p.inline_data;
|
|
261
|
+
const mimeType = inlineData?.mimeType || inlineData?.mime_type;
|
|
262
|
+
return inlineData && mimeType && mimeType.startsWith("audio/pcm");
|
|
263
|
+
}
|
|
224
264
|
);
|
|
225
|
-
const base64s = audioParts.map((p) =>
|
|
265
|
+
const base64s = audioParts.map((p: any) => {
|
|
266
|
+
const inlineData = p.inlineData || p.inline_data;
|
|
267
|
+
return inlineData?.data;
|
|
268
|
+
});
|
|
226
269
|
|
|
227
270
|
// strip the audio parts out of the modelTurn
|
|
228
271
|
const otherParts = difference(parts, audioParts);
|
|
@@ -245,6 +288,98 @@ export class MultimodalLiveClient extends EventEmitter<MultimodalLiveClientEvent
|
|
|
245
288
|
this.emit("content", content);
|
|
246
289
|
this.log(`server.content`, response);
|
|
247
290
|
}
|
|
291
|
+
} else if (isAdkEvent(response)) {
|
|
292
|
+
// Handle ADK events
|
|
293
|
+
this.emit("adkevent", response);
|
|
294
|
+
|
|
295
|
+
// Handle specific ADK event types
|
|
296
|
+
if (isInputTranscription(response)) {
|
|
297
|
+
this.emit("inputtranscription", response.input_transcription!.text);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (isOutputTranscription(response)) {
|
|
301
|
+
this.emit("outputtranscription", response.output_transcription!.text);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Handle ADK content (text responses from agent)
|
|
305
|
+
if (response.content && response.content.parts) {
|
|
306
|
+
const parts = response.content.parts;
|
|
307
|
+
|
|
308
|
+
// Extract function calls for tool call logging
|
|
309
|
+
const functionCallParts = parts.filter((p: any) => p.function_call);
|
|
310
|
+
|
|
311
|
+
// Log function calls as tool calls for the console
|
|
312
|
+
if (functionCallParts.length > 0) {
|
|
313
|
+
const functionCalls = functionCallParts.map((p: any) => ({
|
|
314
|
+
id: p.function_call.id,
|
|
315
|
+
name: p.function_call.name,
|
|
316
|
+
args: p.function_call.args || {}
|
|
317
|
+
}));
|
|
318
|
+
|
|
319
|
+
const toolCallMessage = {
|
|
320
|
+
toolCall: {
|
|
321
|
+
functionCalls: functionCalls
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
this.log("server.toolCall", toolCallMessage);
|
|
326
|
+
this.emit("toolcall", toolCallMessage.toolCall);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Extract audio parts for playing (check both camelCase and snake_case)
|
|
330
|
+
const audioParts = parts.filter(
|
|
331
|
+
(p: any) => {
|
|
332
|
+
const inlineData = p.inlineData || p.inline_data;
|
|
333
|
+
const mimeType = inlineData?.mimeType || inlineData?.mime_type;
|
|
334
|
+
return inlineData && mimeType && mimeType.startsWith("audio/");
|
|
335
|
+
}
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
// Play audio if present
|
|
339
|
+
audioParts.forEach((audioPart: any) => {
|
|
340
|
+
const inlineData = audioPart.inlineData || audioPart.inline_data;
|
|
341
|
+
if (inlineData && inlineData.data) {
|
|
342
|
+
const audioData = base64ToArrayBuffer(inlineData.data);
|
|
343
|
+
|
|
344
|
+
// Only emit audio if we have a valid buffer with data
|
|
345
|
+
if (audioData.byteLength > 0) {
|
|
346
|
+
this.emit("audio", audioData);
|
|
347
|
+
this.log(`server.audio`, `buffer (${audioData.byteLength}) - ${inlineData.mime_type || inlineData.mimeType}`);
|
|
348
|
+
} else {
|
|
349
|
+
this.log(`server.audio`, `invalid audio buffer - skipped`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
// Send content for other parts (text, etc.) - exclude function calls and audio
|
|
355
|
+
const nonAudioNonFunctionParts = parts.filter(
|
|
356
|
+
(p: any) => {
|
|
357
|
+
const inlineData = p.inlineData || p.inline_data;
|
|
358
|
+
const mimeType = inlineData?.mimeType || inlineData?.mime_type;
|
|
359
|
+
const hasAudio = inlineData && mimeType && mimeType.startsWith("audio/");
|
|
360
|
+
const hasFunctionCall = p.function_call;
|
|
361
|
+
return !hasAudio && !hasFunctionCall;
|
|
362
|
+
}
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
if (nonAudioNonFunctionParts.length > 0) {
|
|
366
|
+
const content: ModelTurn = { modelTurn: { parts: nonAudioNonFunctionParts } };
|
|
367
|
+
this.emit("content", content);
|
|
368
|
+
this.log("server.content", `content with ${nonAudioNonFunctionParts.length} non-audio, non-function parts`);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Handle turn complete
|
|
373
|
+
if (response.turn_complete) {
|
|
374
|
+
this.emit("turncomplete");
|
|
375
|
+
this.log("server.turncomplete", "ADK turn complete");
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Handle interruption
|
|
379
|
+
if (response.interrupted) {
|
|
380
|
+
this.emit("interrupted");
|
|
381
|
+
this.log("server.interrupted", "ADK interrupted");
|
|
382
|
+
}
|
|
248
383
|
} else {
|
|
249
384
|
console.log("received unmatched message", response);
|
|
250
385
|
this.log("received unmatched message", response);
|
|
@@ -255,6 +390,12 @@ export class MultimodalLiveClient extends EventEmitter<MultimodalLiveClientEvent
|
|
|
255
390
|
* send realtimeInput, this is base64 chunks of "audio/pcm" and/or "image/jpg"
|
|
256
391
|
*/
|
|
257
392
|
sendRealtimeInput(chunks: GenerativeContentBlob[]) {
|
|
393
|
+
// Don't send if WebSocket is not open - this prevents flooding the queue
|
|
394
|
+
// during connection setup
|
|
395
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
|
|
258
399
|
let hasAudio = false;
|
|
259
400
|
let hasVideo = false;
|
|
260
401
|
for (let i = 0; i < chunks.length; i++) {
|
|
@@ -269,6 +410,25 @@ export class MultimodalLiveClient extends EventEmitter<MultimodalLiveClientEvent
|
|
|
269
410
|
break;
|
|
270
411
|
}
|
|
271
412
|
}
|
|
413
|
+
|
|
414
|
+
// Throttle audio chunks during initial connection phase
|
|
415
|
+
if (hasAudio && !hasVideo) {
|
|
416
|
+
const now = Date.now();
|
|
417
|
+
|
|
418
|
+
// Calculate required interval based on how many chunks we've sent
|
|
419
|
+
const requiredInterval = this.audioChunksSent < this.RAMPUP_CHUNKS
|
|
420
|
+
? this.INITIAL_SEND_INTERVAL_MS
|
|
421
|
+
: this.NORMAL_SEND_INTERVAL_MS;
|
|
422
|
+
|
|
423
|
+
// If not enough time has passed since last send, drop this chunk
|
|
424
|
+
if (this.lastAudioSendTime > 0 && (now - this.lastAudioSendTime) < requiredInterval) {
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
this.lastAudioSendTime = now;
|
|
429
|
+
this.audioChunksSent++;
|
|
430
|
+
}
|
|
431
|
+
|
|
272
432
|
const message =
|
|
273
433
|
hasAudio && hasVideo
|
|
274
434
|
? "audio + video"
|
|
@@ -278,12 +438,26 @@ export class MultimodalLiveClient extends EventEmitter<MultimodalLiveClientEvent
|
|
|
278
438
|
? "video"
|
|
279
439
|
: "unknown";
|
|
280
440
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
441
|
+
// Convert to LiveRequest format for backend
|
|
442
|
+
for (const chunk of chunks) {
|
|
443
|
+
let data: any = {
|
|
444
|
+
blob: {
|
|
445
|
+
mimeType: chunk.mimeType,
|
|
446
|
+
data: chunk.data,
|
|
447
|
+
},
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
// For remote mode: wrap first content in {user_id, live_request} format
|
|
451
|
+
if (!this.firstContentSent) {
|
|
452
|
+
data = {
|
|
453
|
+
user_id: this.userId || "default_user",
|
|
454
|
+
live_request: data,
|
|
455
|
+
};
|
|
456
|
+
this.firstContentSent = true;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
this._sendDirect(data);
|
|
460
|
+
}
|
|
287
461
|
this.log(`client.realtimeInput`, message);
|
|
288
462
|
}
|
|
289
463
|
|
|
@@ -302,22 +476,29 @@ export class MultimodalLiveClient extends EventEmitter<MultimodalLiveClientEvent
|
|
|
302
476
|
/**
|
|
303
477
|
* send normal content parts such as { text }
|
|
304
478
|
*/
|
|
305
|
-
send(parts: Part | Part[],
|
|
479
|
+
send(parts: Part | Part[], _turnComplete: boolean = true) {
|
|
306
480
|
parts = Array.isArray(parts) ? parts : [parts];
|
|
307
481
|
const content: Content = {
|
|
308
482
|
role: "user",
|
|
309
483
|
parts,
|
|
310
484
|
};
|
|
311
485
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
turnComplete,
|
|
316
|
-
},
|
|
486
|
+
// Convert to LiveRequest format for backend
|
|
487
|
+
let data: any = {
|
|
488
|
+
content: content,
|
|
317
489
|
};
|
|
318
490
|
|
|
319
|
-
|
|
320
|
-
this.
|
|
491
|
+
// For remote mode: wrap first content in {user_id, live_request} format
|
|
492
|
+
if (!this.firstContentSent) {
|
|
493
|
+
data = {
|
|
494
|
+
user_id: this.userId || "default_user",
|
|
495
|
+
live_request: data,
|
|
496
|
+
};
|
|
497
|
+
this.firstContentSent = true;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
this._sendDirect(data);
|
|
501
|
+
this.log(`client.send`, `content with ${parts.length} parts`);
|
|
321
502
|
}
|
|
322
503
|
|
|
323
504
|
/**
|
|
@@ -76,11 +76,33 @@ export const blobToJSON = (blob: Blob) =>
|
|
|
76
76
|
reader.readAsText(blob);
|
|
77
77
|
});
|
|
78
78
|
|
|
79
|
+
function cleanBase64String(base64: string): string {
|
|
80
|
+
// Convert URL-safe base64 to standard base64
|
|
81
|
+
let cleaned = base64
|
|
82
|
+
.replace(/-/g, '+') // Replace - with +
|
|
83
|
+
.replace(/_/g, '/') // Replace _ with /
|
|
84
|
+
.replace(/[^A-Za-z0-9+/=]/g, ''); // Remove any other invalid characters
|
|
85
|
+
|
|
86
|
+
// Ensure proper padding (base64 strings must be multiples of 4)
|
|
87
|
+
return cleaned + '='.repeat((4 - cleaned.length % 4) % 4);
|
|
88
|
+
}
|
|
89
|
+
|
|
79
90
|
export function base64ToArrayBuffer(base64: string) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
91
|
+
const cleanedBase64 = cleanBase64String(base64);
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
var binaryString = atob(cleanedBase64);
|
|
95
|
+
var bytes = new Uint8Array(binaryString.length);
|
|
96
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
97
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
98
|
+
}
|
|
99
|
+
return bytes.buffer;
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error('Failed to decode base64 audio data:', error);
|
|
102
|
+
console.error('Original base64 length:', base64.length);
|
|
103
|
+
console.error('Cleaned base64 length:', cleanedBase64.length);
|
|
104
|
+
console.error('First 100 chars:', base64.substring(0, 100));
|
|
105
|
+
// Return empty buffer on error
|
|
106
|
+
return new ArrayBuffer(0);
|
|
84
107
|
}
|
|
85
|
-
return bytes.buffer;
|
|
86
108
|
}
|
|
@@ -109,6 +109,8 @@ class LocalChatMessageHistory(BaseChatMessageHistory):
|
|
|
109
109
|
for msg in messages
|
|
110
110
|
if msg["type"] in ("ai", "human") and isinstance(msg["content"], str)
|
|
111
111
|
]
|
|
112
|
+
# Convert messages to the format expected by chain_title.invoke
|
|
113
|
+
messages = {"messages": messages}
|
|
112
114
|
|
|
113
115
|
response = chain_title.invoke(messages)
|
|
114
116
|
title = (
|
|
@@ -1464,8 +1464,8 @@ if __name__ == "__main__":
|
|
|
1464
1464
|
|
|
1465
1465
|
For detailed specifications of all classes, methods, and commands, refer to the official reference documentation.
|
|
1466
1466
|
|
|
1467
|
-
* [Python API Reference](
|
|
1468
|
-
* [Java API Reference](
|
|
1469
|
-
* [CLI Reference](
|
|
1470
|
-
* [REST API Reference](
|
|
1471
|
-
* [Agent Config YAML Reference](
|
|
1467
|
+
* [Python API Reference](https://github.com/google/adk-docs/tree/main/docs/api-reference/python)
|
|
1468
|
+
* [Java API Reference](https://github.com/google/adk-docs/tree/main/docs/api-reference/java)
|
|
1469
|
+
* [CLI Reference](https://github.com/google/adk-docs/tree/main/docs/api-reference/cli)
|
|
1470
|
+
* [REST API Reference](https://github.com/google/adk-docs/tree/main/docs/api-reference/rest)
|
|
1471
|
+
* [Agent Config YAML Reference](https://github.com/google/adk-docs/tree/main/docs/api-reference/agentconfig)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
|
|
2
|
+
# To learn more about how to use Nix to configure your environment
|
|
3
|
+
# see: https://firebase.google.com/docs/studio/customize-workspace
|
|
4
|
+
{ pkgs, ... }: {
|
|
5
|
+
# Which nixpkgs channel to use.
|
|
6
|
+
channel = "stable-24.11"; # or "unstable"
|
|
7
|
+
|
|
8
|
+
# Use https://search.nixos.org/packages to find packages
|
|
9
|
+
packages = [
|
|
10
|
+
pkgs.uv
|
|
11
|
+
pkgs.gnumake
|
|
12
|
+
pkgs.terraform
|
|
13
|
+
pkgs.gh
|
|
14
|
+
];
|
|
15
|
+
# Sets environment variables in the workspace
|
|
16
|
+
env = {};
|
|
17
|
+
idx = {
|
|
18
|
+
# Search for the extensions you want on https://open-vsx.org/ and use "publisher.id"
|
|
19
|
+
extensions = [
|
|
20
|
+
];
|
|
21
|
+
workspace = {
|
|
22
|
+
# Runs when a workspace is first created with this `dev.nix` file
|
|
23
|
+
onCreate = {
|
|
24
|
+
create-venv = ''
|
|
25
|
+
# Load environment variables from .env file if it exists
|
|
26
|
+
source .env
|
|
27
|
+
|
|
28
|
+
# Beautiful prints for gcloud setup
|
|
29
|
+
echo ""
|
|
30
|
+
echo "╔════════════════════════════════════════════════════════════╗"
|
|
31
|
+
echo "║ 🔐 GCLOUD SETUP REQUIRED ║"
|
|
32
|
+
echo "╚════════════════════════════════════════════════════════════╝"
|
|
33
|
+
echo ""
|
|
34
|
+
echo "📝 Before proceeding, please ensure:"
|
|
35
|
+
echo " 1️⃣ You are logged in to gcloud"
|
|
36
|
+
echo " 2️⃣ You have selected the correct project"
|
|
37
|
+
echo ""
|
|
38
|
+
|
|
39
|
+
auth_status=$(gcloud auth list --quiet 2>&1)
|
|
40
|
+
|
|
41
|
+
echo ""
|
|
42
|
+
echo "⚙️ We will now set the project you want to use..."
|
|
43
|
+
gcloud config get project
|
|
44
|
+
|
|
45
|
+
echo ""
|
|
46
|
+
echo "💡 Need to setup? Run these commands:"
|
|
47
|
+
echo " → gcloud auth login"
|
|
48
|
+
echo " → gcloud config set project YOUR_PROJECT_ID"
|
|
49
|
+
echo ""
|
|
50
|
+
|
|
51
|
+
echo "Running agent starter pack creation..."
|
|
52
|
+
uvx agent-starter-pack create $WS_NAME
|
|
53
|
+
code ~/$WS_NAME/$WS_NAME/README.md
|
|
54
|
+
exec bash
|
|
55
|
+
'';
|
|
56
|
+
# Open editors for the following files by default, if they exist:
|
|
57
|
+
default.openFiles = [];
|
|
58
|
+
};
|
|
59
|
+
# To run something each time the workspace is (re)started, use the `onStart` hook
|
|
60
|
+
};
|
|
61
|
+
# Enable previews and customize configuration
|
|
62
|
+
previews = {};
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Agent Starter Pack",
|
|
3
|
+
"description": "Production-ready Gen AI Agent templates for Google Cloud. Addressing common challenges (Deployment & Operations, Evaluation, Customization, Observability) in building and deploying GenAI agents.",
|
|
4
|
+
"icon": "https://github.com/GoogleCloudPlatform/agent-starter-pack/blob/main/docs/images/icon.png?raw=true",
|
|
5
|
+
"params": []
|
|
6
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
# No user-configurable parameters
|
|
2
3
|
# Accept additional arguments to this template corresponding to template
|
|
3
4
|
# parameter IDs
|
|
@@ -14,8 +15,6 @@
|
|
|
14
15
|
|
|
15
16
|
# Create .env file with the parameter values
|
|
16
17
|
cat > "$out/.env" << EOF
|
|
17
|
-
AGENT_NAME=${agent_name}
|
|
18
|
-
GOOGLE_CLOUD_PROJECT=${google_cloud_project_id}
|
|
19
18
|
WS_NAME=$WS_NAME
|
|
20
19
|
EOF
|
|
21
20
|
|
|
@@ -23,4 +22,4 @@
|
|
|
23
22
|
# Git repository
|
|
24
23
|
rm -rf "$out/.git" "$out/idx-template".{nix,json}
|
|
25
24
|
'';
|
|
26
|
-
}
|
|
25
|
+
}
|