mirror of
https://github.com/googleapis/genai-toolbox.git
synced 2026-02-04 12:15:09 -05:00
Compare commits
26 Commits
processing
...
refactor-t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70777b9d20 | ||
|
|
d8c90285d9 | ||
|
|
101dcb4411 | ||
|
|
1d692af160 | ||
|
|
919787562a | ||
|
|
2583c5adc9 | ||
|
|
9ff6fd6830 | ||
|
|
c6e1889b74 | ||
|
|
89a9321932 | ||
|
|
4ca592c366 | ||
|
|
9208b2b237 | ||
|
|
3dce8678f7 | ||
|
|
7fb56bfe67 | ||
|
|
99b71589b0 | ||
|
|
3f85c16f32 | ||
|
|
9e884f52ea | ||
|
|
8a0f179f15 | ||
|
|
87ae5ae816 | ||
|
|
0c5285c5c8 | ||
|
|
ac544d0878 | ||
|
|
54f9a3d312 | ||
|
|
62d96a662d | ||
|
|
46244458c4 | ||
|
|
b6fa798610 | ||
|
|
bb58baff70 | ||
|
|
32b2c9366d |
@@ -23,18 +23,13 @@ steps:
|
|||||||
- |
|
- |
|
||||||
set -ex
|
set -ex
|
||||||
export VERSION=$(cat ./cmd/version.txt)
|
export VERSION=$(cat ./cmd/version.txt)
|
||||||
chmod +x .ci/sample_tests/run_tests.sh
|
chmod +x .ci/quickstart_test/run_go_tests.sh
|
||||||
.ci/sample_tests/run_tests.sh
|
.ci/quickstart_test/run_go_tests.sh
|
||||||
env:
|
env:
|
||||||
- 'CLOUD_SQL_INSTANCE=${_CLOUD_SQL_INSTANCE}'
|
- 'CLOUD_SQL_INSTANCE=${_CLOUD_SQL_INSTANCE}'
|
||||||
- 'GCP_PROJECT=${_GCP_PROJECT}'
|
- 'GCP_PROJECT=${_GCP_PROJECT}'
|
||||||
- 'DATABASE_NAME=${_DATABASE_NAME}'
|
- 'DATABASE_NAME=${_DATABASE_NAME}'
|
||||||
- 'DB_USER=${_DB_USER}'
|
- 'DB_USER=${_DB_USER}'
|
||||||
- 'TARGET_ROOT=docs/en/getting-started/quickstart/go'
|
|
||||||
- 'TARGET_LANG=go'
|
|
||||||
- 'TABLE_NAME=hotels_go'
|
|
||||||
- 'SQL_FILE=.ci/sample_tests/setup_hotels.sql'
|
|
||||||
- 'AGENT_FILE_PATTERN=quickstart.go'
|
|
||||||
secretEnv: ['TOOLS_YAML_CONTENT', 'GOOGLE_API_KEY', 'DB_PASSWORD']
|
secretEnv: ['TOOLS_YAML_CONTENT', 'GOOGLE_API_KEY', 'DB_PASSWORD']
|
||||||
|
|
||||||
availableSecrets:
|
availableSecrets:
|
||||||
@@ -23,18 +23,13 @@ steps:
|
|||||||
- |
|
- |
|
||||||
set -ex
|
set -ex
|
||||||
export VERSION=$(cat ./cmd/version.txt)
|
export VERSION=$(cat ./cmd/version.txt)
|
||||||
chmod +x .ci/sample_tests/run_tests.sh
|
chmod +x .ci/quickstart_test/run_js_tests.sh
|
||||||
.ci/sample_tests/run_tests.sh
|
.ci/quickstart_test/run_js_tests.sh
|
||||||
env:
|
env:
|
||||||
- 'CLOUD_SQL_INSTANCE=${_CLOUD_SQL_INSTANCE}'
|
- 'CLOUD_SQL_INSTANCE=${_CLOUD_SQL_INSTANCE}'
|
||||||
- 'GCP_PROJECT=${_GCP_PROJECT}'
|
- 'GCP_PROJECT=${_GCP_PROJECT}'
|
||||||
- 'DATABASE_NAME=${_DATABASE_NAME}'
|
- 'DATABASE_NAME=${_DATABASE_NAME}'
|
||||||
- 'DB_USER=${_DB_USER}'
|
- 'DB_USER=${_DB_USER}'
|
||||||
- 'TARGET_ROOT=docs/en/getting-started/quickstart/js'
|
|
||||||
- 'TARGET_LANG=js'
|
|
||||||
- 'TABLE_NAME=hotels_js'
|
|
||||||
- 'SQL_FILE=.ci/sample_tests/setup_hotels.sql'
|
|
||||||
- 'AGENT_FILE_PATTERN=quickstart.js'
|
|
||||||
secretEnv: ['TOOLS_YAML_CONTENT', 'GOOGLE_API_KEY', 'DB_PASSWORD']
|
secretEnv: ['TOOLS_YAML_CONTENT', 'GOOGLE_API_KEY', 'DB_PASSWORD']
|
||||||
|
|
||||||
availableSecrets:
|
availableSecrets:
|
||||||
@@ -23,18 +23,13 @@ steps:
|
|||||||
- |
|
- |
|
||||||
set -ex
|
set -ex
|
||||||
export VERSION=$(cat ./cmd/version.txt)
|
export VERSION=$(cat ./cmd/version.txt)
|
||||||
chmod +x .ci/sample_tests/run_py_tests.sh
|
chmod +x .ci/quickstart_test/run_py_tests.sh
|
||||||
.ci/sample_tests/run_py_tests.sh
|
.ci/quickstart_test/run_py_tests.sh
|
||||||
env:
|
env:
|
||||||
- 'CLOUD_SQL_INSTANCE=${_CLOUD_SQL_INSTANCE}'
|
- 'CLOUD_SQL_INSTANCE=${_CLOUD_SQL_INSTANCE}'
|
||||||
- 'GCP_PROJECT=${_GCP_PROJECT}'
|
- 'GCP_PROJECT=${_GCP_PROJECT}'
|
||||||
- 'DATABASE_NAME=${_DATABASE_NAME}'
|
- 'DATABASE_NAME=${_DATABASE_NAME}'
|
||||||
- 'DB_USER=${_DB_USER}'
|
- 'DB_USER=${_DB_USER}'
|
||||||
- 'TARGET_ROOT=docs/en/getting-started/quickstart/python'
|
|
||||||
- 'TARGET_LANG=python'
|
|
||||||
- 'TABLE_NAME=hotels_python'
|
|
||||||
- 'SQL_FILE=.ci/sample_tests/setup_hotels.sql'
|
|
||||||
- 'AGENT_FILE_PATTERN=quickstart.py'
|
|
||||||
secretEnv: ['TOOLS_YAML_CONTENT', 'GOOGLE_API_KEY', 'DB_PASSWORD']
|
secretEnv: ['TOOLS_YAML_CONTENT', 'GOOGLE_API_KEY', 'DB_PASSWORD']
|
||||||
|
|
||||||
availableSecrets:
|
availableSecrets:
|
||||||
125
.ci/quickstart_test/run_go_tests.sh
Normal file
125
.ci/quickstart_test/run_go_tests.sh
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
# Copyright 2025 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
TABLE_NAME="hotels_go"
|
||||||
|
QUICKSTART_GO_DIR="docs/en/getting-started/quickstart/go"
|
||||||
|
SQL_FILE=".ci/quickstart_test/setup_hotels_sample.sql"
|
||||||
|
|
||||||
|
PROXY_PID=""
|
||||||
|
TOOLBOX_PID=""
|
||||||
|
|
||||||
|
install_system_packages() {
|
||||||
|
apt-get update && apt-get install -y \
|
||||||
|
postgresql-client \
|
||||||
|
wget \
|
||||||
|
gettext-base \
|
||||||
|
netcat-openbsd
|
||||||
|
}
|
||||||
|
|
||||||
|
start_cloud_sql_proxy() {
|
||||||
|
wget "https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.10.0/cloud-sql-proxy.linux.amd64" -O /usr/local/bin/cloud-sql-proxy
|
||||||
|
chmod +x /usr/local/bin/cloud-sql-proxy
|
||||||
|
cloud-sql-proxy "${CLOUD_SQL_INSTANCE}" &
|
||||||
|
PROXY_PID=$!
|
||||||
|
|
||||||
|
for i in {1..30}; do
|
||||||
|
if nc -z 127.0.0.1 5432; then
|
||||||
|
echo "Cloud SQL Proxy is up and running."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Cloud SQL Proxy failed to start within the timeout period."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_toolbox() {
|
||||||
|
TOOLBOX_YAML="/tools.yaml"
|
||||||
|
echo "${TOOLS_YAML_CONTENT}" > "$TOOLBOX_YAML"
|
||||||
|
if [ ! -f "$TOOLBOX_YAML" ]; then echo "Failed to create tools.yaml"; exit 1; fi
|
||||||
|
wget "https://storage.googleapis.com/genai-toolbox/v${VERSION}/linux/amd64/toolbox" -O "/toolbox"
|
||||||
|
chmod +x "/toolbox"
|
||||||
|
/toolbox --tools-file "$TOOLBOX_YAML" &
|
||||||
|
TOOLBOX_PID=$!
|
||||||
|
sleep 2
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_orch_table() {
|
||||||
|
export TABLE_NAME
|
||||||
|
envsubst < "$SQL_FILE" | psql -h "$PGHOST" -p "$PGPORT" -U "$DB_USER" -d "$DATABASE_NAME"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_orch_test() {
|
||||||
|
local orch_dir="$1"
|
||||||
|
local orch_name
|
||||||
|
orch_name=$(basename "$orch_dir")
|
||||||
|
|
||||||
|
if [ "$orch_name" == "openAI" ]; then
|
||||||
|
echo -e "\nSkipping framework '${orch_name}': Temporarily excluded."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
setup_orch_table
|
||||||
|
|
||||||
|
echo "--- Preparing module for $orch_name ---"
|
||||||
|
cd "$orch_dir"
|
||||||
|
|
||||||
|
if [ -f "go.mod" ]; then
|
||||||
|
go mod tidy
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
export ORCH_NAME="$orch_name"
|
||||||
|
|
||||||
|
echo "--- Running tests for $orch_name ---"
|
||||||
|
go test -v ./...
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup_all() {
|
||||||
|
echo "--- Final cleanup: Shutting down processes and dropping table ---"
|
||||||
|
if [ -n "$TOOLBOX_PID" ]; then
|
||||||
|
kill $TOOLBOX_PID || true
|
||||||
|
fi
|
||||||
|
if [ -n "$PROXY_PID" ]; then
|
||||||
|
kill $PROXY_PID || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap cleanup_all EXIT
|
||||||
|
|
||||||
|
# Main script execution
|
||||||
|
install_system_packages
|
||||||
|
start_cloud_sql_proxy
|
||||||
|
|
||||||
|
export PGHOST=127.0.0.1
|
||||||
|
export PGPORT=5432
|
||||||
|
export PGPASSWORD="$DB_PASSWORD"
|
||||||
|
export GOOGLE_API_KEY="$GOOGLE_API_KEY"
|
||||||
|
|
||||||
|
setup_toolbox
|
||||||
|
|
||||||
|
for ORCH_DIR in "$QUICKSTART_GO_DIR"/*/; do
|
||||||
|
if [ ! -d "$ORCH_DIR" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
run_orch_test "$ORCH_DIR"
|
||||||
|
done
|
||||||
125
.ci/quickstart_test/run_js_tests.sh
Normal file
125
.ci/quickstart_test/run_js_tests.sh
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
# Copyright 2025 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
TABLE_NAME="hotels_js"
|
||||||
|
QUICKSTART_JS_DIR="docs/en/getting-started/quickstart/js"
|
||||||
|
SQL_FILE=".ci/quickstart_test/setup_hotels_sample.sql"
|
||||||
|
|
||||||
|
# Initialize process IDs to empty at the top of the script
|
||||||
|
PROXY_PID=""
|
||||||
|
TOOLBOX_PID=""
|
||||||
|
|
||||||
|
install_system_packages() {
|
||||||
|
apt-get update && apt-get install -y \
|
||||||
|
postgresql-client \
|
||||||
|
wget \
|
||||||
|
gettext-base \
|
||||||
|
netcat-openbsd
|
||||||
|
}
|
||||||
|
|
||||||
|
start_cloud_sql_proxy() {
|
||||||
|
wget "https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.10.0/cloud-sql-proxy.linux.amd64" -O /usr/local/bin/cloud-sql-proxy
|
||||||
|
chmod +x /usr/local/bin/cloud-sql-proxy
|
||||||
|
cloud-sql-proxy "${CLOUD_SQL_INSTANCE}" &
|
||||||
|
PROXY_PID=$!
|
||||||
|
|
||||||
|
for i in {1..30}; do
|
||||||
|
if nc -z 127.0.0.1 5432; then
|
||||||
|
echo "Cloud SQL Proxy is up and running."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Cloud SQL Proxy failed to start within the timeout period."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_toolbox() {
|
||||||
|
TOOLBOX_YAML="/tools.yaml"
|
||||||
|
echo "${TOOLS_YAML_CONTENT}" > "$TOOLBOX_YAML"
|
||||||
|
if [ ! -f "$TOOLBOX_YAML" ]; then echo "Failed to create tools.yaml"; exit 1; fi
|
||||||
|
wget "https://storage.googleapis.com/genai-toolbox/v${VERSION}/linux/amd64/toolbox" -O "/toolbox"
|
||||||
|
chmod +x "/toolbox"
|
||||||
|
/toolbox --tools-file "$TOOLBOX_YAML" &
|
||||||
|
TOOLBOX_PID=$!
|
||||||
|
sleep 2
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_orch_table() {
|
||||||
|
export TABLE_NAME
|
||||||
|
envsubst < "$SQL_FILE" | psql -h "$PGHOST" -p "$PGPORT" -U "$DB_USER" -d "$DATABASE_NAME"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_orch_test() {
|
||||||
|
local orch_dir="$1"
|
||||||
|
local orch_name
|
||||||
|
orch_name=$(basename "$orch_dir")
|
||||||
|
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
echo "--- Preparing environment for $orch_name ---"
|
||||||
|
setup_orch_table
|
||||||
|
|
||||||
|
cd "$orch_dir"
|
||||||
|
echo "Installing dependencies for $orch_name..."
|
||||||
|
if [ -f "package-lock.json" ]; then
|
||||||
|
npm ci
|
||||||
|
else
|
||||||
|
npm install
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
echo "--- Running tests for $orch_name ---"
|
||||||
|
export ORCH_NAME="$orch_name"
|
||||||
|
node --test quickstart.test.js
|
||||||
|
|
||||||
|
echo "--- Cleaning environment for $orch_name ---"
|
||||||
|
rm -rf "${orch_name}/node_modules"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup_all() {
|
||||||
|
echo "--- Final cleanup: Shutting down processes and dropping table ---"
|
||||||
|
if [ -n "$TOOLBOX_PID" ]; then
|
||||||
|
kill $TOOLBOX_PID || true
|
||||||
|
fi
|
||||||
|
if [ -n "$PROXY_PID" ]; then
|
||||||
|
kill $PROXY_PID || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap cleanup_all EXIT
|
||||||
|
|
||||||
|
# Main script execution
|
||||||
|
install_system_packages
|
||||||
|
start_cloud_sql_proxy
|
||||||
|
|
||||||
|
export PGHOST=127.0.0.1
|
||||||
|
export PGPORT=5432
|
||||||
|
export PGPASSWORD="$DB_PASSWORD"
|
||||||
|
export GOOGLE_API_KEY="$GOOGLE_API_KEY"
|
||||||
|
|
||||||
|
setup_toolbox
|
||||||
|
|
||||||
|
for ORCH_DIR in "$QUICKSTART_JS_DIR"/*/; do
|
||||||
|
if [ ! -d "$ORCH_DIR" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
run_orch_test "$ORCH_DIR"
|
||||||
|
done
|
||||||
115
.ci/quickstart_test/run_py_tests.sh
Normal file
115
.ci/quickstart_test/run_py_tests.sh
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
# Copyright 2025 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
TABLE_NAME="hotels_python"
|
||||||
|
QUICKSTART_PYTHON_DIR="docs/en/getting-started/quickstart/python"
|
||||||
|
SQL_FILE=".ci/quickstart_test/setup_hotels_sample.sql"
|
||||||
|
|
||||||
|
PROXY_PID=""
|
||||||
|
TOOLBOX_PID=""
|
||||||
|
|
||||||
|
install_system_packages() {
|
||||||
|
apt-get update && apt-get install -y \
|
||||||
|
postgresql-client \
|
||||||
|
python3-venv \
|
||||||
|
wget \
|
||||||
|
gettext-base \
|
||||||
|
netcat-openbsd
|
||||||
|
}
|
||||||
|
|
||||||
|
start_cloud_sql_proxy() {
|
||||||
|
wget "https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.10.0/cloud-sql-proxy.linux.amd64" -O /usr/local/bin/cloud-sql-proxy
|
||||||
|
chmod +x /usr/local/bin/cloud-sql-proxy
|
||||||
|
cloud-sql-proxy "${CLOUD_SQL_INSTANCE}" &
|
||||||
|
PROXY_PID=$!
|
||||||
|
|
||||||
|
for i in {1..30}; do
|
||||||
|
if nc -z 127.0.0.1 5432; then
|
||||||
|
echo "Cloud SQL Proxy is up and running."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Cloud SQL Proxy failed to start within the timeout period."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_toolbox() {
|
||||||
|
TOOLBOX_YAML="/tools.yaml"
|
||||||
|
echo "${TOOLS_YAML_CONTENT}" > "$TOOLBOX_YAML"
|
||||||
|
if [ ! -f "$TOOLBOX_YAML" ]; then echo "Failed to create tools.yaml"; exit 1; fi
|
||||||
|
wget "https://storage.googleapis.com/genai-toolbox/v${VERSION}/linux/amd64/toolbox" -O "/toolbox"
|
||||||
|
chmod +x "/toolbox"
|
||||||
|
/toolbox --tools-file "$TOOLBOX_YAML" &
|
||||||
|
TOOLBOX_PID=$!
|
||||||
|
sleep 2
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_orch_table() {
|
||||||
|
export TABLE_NAME
|
||||||
|
envsubst < "$SQL_FILE" | psql -h "$PGHOST" -p "$PGPORT" -U "$DB_USER" -d "$DATABASE_NAME"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_orch_test() {
|
||||||
|
local orch_dir="$1"
|
||||||
|
local orch_name
|
||||||
|
orch_name=$(basename "$orch_dir")
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
setup_orch_table
|
||||||
|
cd "$orch_dir"
|
||||||
|
local VENV_DIR=".venv"
|
||||||
|
python3 -m venv "$VENV_DIR"
|
||||||
|
source "$VENV_DIR/bin/activate"
|
||||||
|
pip install -r requirements.txt
|
||||||
|
echo "--- Running tests for $orch_name ---"
|
||||||
|
cd ..
|
||||||
|
ORCH_NAME="$orch_name" pytest
|
||||||
|
rm -rf "$VENV_DIR"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup_all() {
|
||||||
|
echo "--- Final cleanup: Shutting down processes and dropping table ---"
|
||||||
|
if [ -n "$TOOLBOX_PID" ]; then
|
||||||
|
kill $TOOLBOX_PID || true
|
||||||
|
fi
|
||||||
|
if [ -n "$PROXY_PID" ]; then
|
||||||
|
kill $PROXY_PID || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap cleanup_all EXIT
|
||||||
|
|
||||||
|
# Main script execution
|
||||||
|
install_system_packages
|
||||||
|
start_cloud_sql_proxy
|
||||||
|
|
||||||
|
export PGHOST=127.0.0.1
|
||||||
|
export PGPORT=5432
|
||||||
|
export PGPASSWORD="$DB_PASSWORD"
|
||||||
|
export GOOGLE_API_KEY="$GOOGLE_API_KEY"
|
||||||
|
|
||||||
|
setup_toolbox
|
||||||
|
|
||||||
|
for ORCH_DIR in "$QUICKSTART_PYTHON_DIR"/*/; do
|
||||||
|
if [ ! -d "$ORCH_DIR" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
run_orch_test "$ORCH_DIR"
|
||||||
|
done
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
# Copyright 2026 Google LLC
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: "${_IMAGE}"
|
|
||||||
id: "py-pre-post-processing-test"
|
|
||||||
entrypoint: "bash"
|
|
||||||
args:
|
|
||||||
- -c
|
|
||||||
- |
|
|
||||||
set -ex
|
|
||||||
chmod +x .ci/sample_tests/run_tests.sh
|
|
||||||
.ci/sample_tests/run_tests.sh
|
|
||||||
env:
|
|
||||||
- "CLOUD_SQL_INSTANCE=${_CLOUD_SQL_INSTANCE}"
|
|
||||||
- "GCP_PROJECT=${_GCP_PROJECT}"
|
|
||||||
- "DATABASE_NAME=${_DATABASE_NAME}"
|
|
||||||
- "DB_USER=${_DB_USER}"
|
|
||||||
- "TARGET_ROOT=${_TARGET_ROOT}"
|
|
||||||
- "TARGET_LANG=${_TARGET_LANG}"
|
|
||||||
- "TABLE_NAME=${_TABLE_NAME}"
|
|
||||||
- "SQL_FILE=${_SQL_FILE}"
|
|
||||||
- "AGENT_FILE_PATTERN=${_AGENT_FILE_PATTERN}"
|
|
||||||
secretEnv: ["TOOLS_YAML_CONTENT", "GOOGLE_API_KEY", "DB_PASSWORD"]
|
|
||||||
|
|
||||||
availableSecrets:
|
|
||||||
secretManager:
|
|
||||||
- versionName: projects/${_GCP_PROJECT}/secrets/${_TOOLS_YAML_SECRET}/versions/5
|
|
||||||
env: "TOOLS_YAML_CONTENT"
|
|
||||||
- versionName: projects/${_GCP_PROJECT_NUMBER}/secrets/${_API_KEY_SECRET}/versions/latest
|
|
||||||
env: "GOOGLE_API_KEY"
|
|
||||||
- versionName: projects/${_GCP_PROJECT}/secrets/${_DB_PASS_SECRET}/versions/latest
|
|
||||||
env: "DB_PASSWORD"
|
|
||||||
|
|
||||||
timeout: 1200s
|
|
||||||
|
|
||||||
substitutions:
|
|
||||||
_TARGET_LANG: "python"
|
|
||||||
_IMAGE: "gcr.io/google.com/cloudsdktool/cloud-sdk:537.0.0"
|
|
||||||
_TARGET_ROOT: "docs/en/samples/pre_post_processing/python"
|
|
||||||
_TABLE_NAME: "hotels_py_pre_post_processing"
|
|
||||||
_SQL_FILE: ".ci/sample_tests/setup_hotels.sql"
|
|
||||||
_AGENT_FILE_PATTERN: "agent.py"
|
|
||||||
|
|
||||||
options:
|
|
||||||
logging: CLOUD_LOGGING_ONLY
|
|
||||||
@@ -1,202 +0,0 @@
|
|||||||
# Copyright 2026 Google LLC
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# --- Configuration (from Environment Variables) ---
|
|
||||||
# TARGET_ROOT: The directory to search for tests (e.g., docs/en/getting-started/quickstart/js)
|
|
||||||
# TARGET_LANG: python, js, go
|
|
||||||
# TABLE_NAME: Database table name to use
|
|
||||||
# SQL_FILE: Path to the SQL setup file
|
|
||||||
# AGENT_FILE_PATTERN: Filename to look for (e.g., quickstart.js or agent.py)
|
|
||||||
|
|
||||||
VERSION=$(cat ./cmd/version.txt)
|
|
||||||
|
|
||||||
# Process IDs & Logs
|
|
||||||
PROXY_PID=""
|
|
||||||
TOOLBOX_PID=""
|
|
||||||
PROXY_LOG="cloud_sql_proxy.log"
|
|
||||||
TOOLBOX_LOG="toolbox_server.log"
|
|
||||||
|
|
||||||
install_system_packages() {
|
|
||||||
echo "Installing system packages..."
|
|
||||||
apt-get update && apt-get install -y \
|
|
||||||
postgresql-client \
|
|
||||||
wget \
|
|
||||||
gettext-base \
|
|
||||||
netcat-openbsd
|
|
||||||
|
|
||||||
if [[ "$TARGET_LANG" == "python" ]]; then
|
|
||||||
apt-get install -y python3-venv
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
start_cloud_sql_proxy() {
|
|
||||||
echo "Starting Cloud SQL Proxy..."
|
|
||||||
wget -q "https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.10.0/cloud-sql-proxy.linux.amd64" -O /usr/local/bin/cloud-sql-proxy
|
|
||||||
chmod +x /usr/local/bin/cloud-sql-proxy
|
|
||||||
cloud-sql-proxy "${CLOUD_SQL_INSTANCE}" > "$PROXY_LOG" 2>&1 &
|
|
||||||
PROXY_PID=$!
|
|
||||||
|
|
||||||
# Health Check
|
|
||||||
for i in {1..30}; do
|
|
||||||
if nc -z 127.0.0.1 5432; then
|
|
||||||
echo "Cloud SQL Proxy is up and running."
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
echo "ERROR: Cloud SQL Proxy failed to start. Logs:"
|
|
||||||
cat "$PROXY_LOG"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_toolbox() {
|
|
||||||
echo "Setting up Toolbox server..."
|
|
||||||
TOOLBOX_YAML="/tools.yaml"
|
|
||||||
echo "${TOOLS_YAML_CONTENT}" > "$TOOLBOX_YAML"
|
|
||||||
wget -q "https://storage.googleapis.com/genai-toolbox/v${VERSION}/linux/amd64/toolbox" -O "/toolbox"
|
|
||||||
chmod +x "/toolbox"
|
|
||||||
/toolbox --tools-file "$TOOLBOX_YAML" > "$TOOLBOX_LOG" 2>&1 &
|
|
||||||
TOOLBOX_PID=$!
|
|
||||||
|
|
||||||
# Health Check
|
|
||||||
for i in {1..15}; do
|
|
||||||
if nc -z 127.0.0.1 5000; then
|
|
||||||
echo "Toolbox server is up and running."
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
echo "ERROR: Toolbox server failed to start. Logs:"
|
|
||||||
cat "$TOOLBOX_LOG"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_db_table() {
|
|
||||||
echo "Setting up database table $TABLE_NAME using $SQL_FILE..."
|
|
||||||
export TABLE_NAME
|
|
||||||
envsubst < "$SQL_FILE" | psql -h 127.0.0.1 -p 5432 -U "$DB_USER" -d "$DATABASE_NAME"
|
|
||||||
}
|
|
||||||
|
|
||||||
run_python_test() {
|
|
||||||
local dir=$1
|
|
||||||
local name=$(basename "$dir")
|
|
||||||
echo "--- Running Python Test: $name ---"
|
|
||||||
(
|
|
||||||
cd "$dir"
|
|
||||||
python3 -m venv .venv
|
|
||||||
source .venv/bin/activate
|
|
||||||
pip install -q -r requirements.txt pytest
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
local test_file=$(find . -maxdepth 1 -name "*test.py" | head -n 1)
|
|
||||||
if [ -n "$test_file" ]; then
|
|
||||||
echo "Found native test: $test_file. Running pytest..."
|
|
||||||
export ORCH_NAME="$name"
|
|
||||||
export PYTHONPATH="../"
|
|
||||||
pytest "$test_file"
|
|
||||||
else
|
|
||||||
echo "No native test found. running agent directly..."
|
|
||||||
export PYTHONPATH="../"
|
|
||||||
python3 "${name}/${AGENT_FILE_PATTERN}"
|
|
||||||
fi
|
|
||||||
rm -rf "${name}/.venv"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
run_js_test() {
|
|
||||||
local dir=$1
|
|
||||||
local name=$(basename "$dir")
|
|
||||||
echo "--- Running JS Test: $name ---"
|
|
||||||
(
|
|
||||||
cd "$dir"
|
|
||||||
if [ -f "package-lock.json" ]; then npm ci -q; else npm install -q; fi
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
# Looking for a JS test file in the parent directory
|
|
||||||
local test_file=$(find . -maxdepth 1 -name "*test.js" | head -n 1)
|
|
||||||
if [ -n "$test_file" ]; then
|
|
||||||
echo "Found native test: $test_file. Running node --test..."
|
|
||||||
export ORCH_NAME="$name"
|
|
||||||
node --test "$test_file"
|
|
||||||
else
|
|
||||||
echo "No native test found. running agent directly..."
|
|
||||||
node "${name}/${AGENT_FILE_PATTERN}"
|
|
||||||
fi
|
|
||||||
rm -rf "${name}/node_modules"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
run_go_test() {
|
|
||||||
local dir=$1
|
|
||||||
local name=$(basename "$dir")
|
|
||||||
|
|
||||||
if [ "$name" == "openAI" ]; then
|
|
||||||
echo -e "\nSkipping framework '${name}': Temporarily excluded."
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "--- Running Go Test: $name ---"
|
|
||||||
(
|
|
||||||
cd "$dir"
|
|
||||||
if [ -f "go.mod" ]; then
|
|
||||||
go mod tidy
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
local test_file=$(find . -maxdepth 1 -name "*test.go" | head -n 1)
|
|
||||||
if [ -n "$test_file" ]; then
|
|
||||||
echo "Found native test: $test_file. Running go test..."
|
|
||||||
export ORCH_NAME="$name"
|
|
||||||
go test -v ./...
|
|
||||||
else
|
|
||||||
echo "No native test found. running agent directly..."
|
|
||||||
cd "$name"
|
|
||||||
go run "."
|
|
||||||
fi
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
echo "Cleaning up background processes..."
|
|
||||||
[ -n "$TOOLBOX_PID" ] && kill "$TOOLBOX_PID" || true
|
|
||||||
[ -n "$PROXY_PID" ] && kill "$PROXY_PID" || true
|
|
||||||
}
|
|
||||||
trap cleanup EXIT
|
|
||||||
|
|
||||||
# --- Execution ---
|
|
||||||
install_system_packages
|
|
||||||
start_cloud_sql_proxy
|
|
||||||
|
|
||||||
export PGHOST=127.0.0.1
|
|
||||||
export PGPORT=5432
|
|
||||||
export PGPASSWORD="$DB_PASSWORD"
|
|
||||||
export GOOGLE_API_KEY="$GOOGLE_API_KEY"
|
|
||||||
|
|
||||||
setup_toolbox
|
|
||||||
setup_db_table
|
|
||||||
|
|
||||||
echo "Scanning $TARGET_ROOT for tests with pattern $AGENT_FILE_PATTERN..."
|
|
||||||
|
|
||||||
find "$TARGET_ROOT" -name "$AGENT_FILE_PATTERN" | while read -r agent_file; do
|
|
||||||
sample_dir=$(dirname "$agent_file")
|
|
||||||
if [[ "$TARGET_LANG" == "python" ]]; then
|
|
||||||
run_python_test "$sample_dir"
|
|
||||||
elif [[ "$TARGET_LANG" == "js" ]]; then
|
|
||||||
run_js_test "$sample_dir"
|
|
||||||
elif [[ "$TARGET_LANG" == "go" ]]; then
|
|
||||||
run_go_test "$sample_dir"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
@@ -53,7 +53,7 @@ export async function main() {
|
|||||||
|
|
||||||
for (const query of queries) {
|
for (const query of queries) {
|
||||||
conversationHistory.push({ role: "user", content: [{ text: query }] });
|
conversationHistory.push({ role: "user", content: [{ text: query }] });
|
||||||
let response = await ai.generate({
|
const response = await ai.generate({
|
||||||
messages: conversationHistory,
|
messages: conversationHistory,
|
||||||
tools: tools,
|
tools: tools,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ The `invoke` command allows you to invoke tools defined in your configuration di
|
|||||||
|
|
||||||
{{< notice tip >}}
|
{{< notice tip >}}
|
||||||
**Keep configurations minimal:** The `invoke` command initializes *all* resources (sources, tools, etc.) defined in your configuration files during execution. To ensure fast response times, consider using a minimal configuration file containing only the tools you need for the specific invocation.
|
**Keep configurations minimal:** The `invoke` command initializes *all* resources (sources, tools, etc.) defined in your configuration files during execution. To ensure fast response times, consider using a minimal configuration file containing only the tools you need for the specific invocation.
|
||||||
{{< /notice >}}
|
{{< notice tip >}}
|
||||||
|
|
||||||
## Before you begin
|
## Prerequisites
|
||||||
|
|
||||||
1. Make sure you have the `toolbox` binary installed or built.
|
- You have the `toolbox` binary installed or built.
|
||||||
2. Make sure you have a valid tool configuration file (e.g., `tools.yaml`).
|
- You have a valid tool configuration file (e.g., `tools.yaml`).
|
||||||
|
|
||||||
## Basic Usage
|
## Basic Usage
|
||||||
|
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Pre and Post processing"
|
|
||||||
type: docs
|
|
||||||
weight: 1
|
|
||||||
description: >
|
|
||||||
Pre and Post processing in GenAI applications.
|
|
||||||
---
|
|
||||||
|
|
||||||
Pre and post processing allow developers to intercept and modify interactions between the agent and its tools or the user.
|
|
||||||
|
|
||||||
> **Note**: These capabilities are typically features of **orchestration frameworks** (like LangChain, LangGraph, or Agent Builder) rather than the Toolbox SDK itself. However, Toolbox tools are designed to fully leverage these framework capabilities to support robust, secure, and compliant agent architectures.
|
|
||||||
|
|
||||||
## Types of Processing
|
|
||||||
|
|
||||||
### Pre-processing
|
|
||||||
|
|
||||||
Pre-processing occurs before a tool is executed or an agent processes a message. Key types include:
|
|
||||||
|
|
||||||
- **Input Sanitization & Redaction**: Detecting and masking sensitive information (like PII) in user queries or tool arguments to prevent it from being logged or sent to unauthorized systems.
|
|
||||||
- **Business Logic Validation**: Verifying that the proposed action complies with business rules (e.g., ensuring a requested hotel stay does not exceed 14 days, or checking if a user has sufficient permission).
|
|
||||||
- **Security Guardrails**: Analyzing inputs for potential prompt injection attacks or malicious payloads.
|
|
||||||
|
|
||||||
### Post-processing
|
|
||||||
|
|
||||||
Post-processing occurs after a tool has executed or the model has generated a response. Key types include:
|
|
||||||
|
|
||||||
- **Response Enrichment**: Injecting additional data into the tool output that wasn't part of the raw API response (e.g., calculating loyalty points earned based on the booking value).
|
|
||||||
- **Output Formatting**: Transforming raw data (like JSON or XML) into a more human-readable or model-friendly format to improve the agent's understanding.
|
|
||||||
- **Compliance Auditing**: Logging the final outcome of transactions, including the original request and the result, to a secure audit trail.
|
|
||||||
|
|
||||||
## Processing Scopes
|
|
||||||
|
|
||||||
While processing logic can be applied at various levels (Agent, Model, Tool), this guide primarily focuses on **Tool Level** processing, which is most relevant for granular control over tool execution.
|
|
||||||
|
|
||||||
### Tool Level (Primary Focus)
|
|
||||||
|
|
||||||
Wraps individual tool executions. This is best for logic specific to a single tool or a set of tools.
|
|
||||||
|
|
||||||
- **Scope**: Intercepts the raw inputs (arguments) to a tool and its outputs.
|
|
||||||
- **Use Cases**: Argument validation, output formatting, specific privacy rules for sensitive tools.
|
|
||||||
|
|
||||||
### Comparison with Other Levels
|
|
||||||
|
|
||||||
It is helpful to understand how tool-level processing differs from other scopes:
|
|
||||||
|
|
||||||
- **Model Level**: Intercepts individual calls to the LLM (prompts and responses). Unlike tool-level, this applies globally to all text sent/received, making it better for global PII redaction or token tracking.
|
|
||||||
- **Agent Level**: Wraps the high-level execution loop (e.g., a "turn" in the conversation). Unlike tool-level, this envelopes the entire turn (user input to final response), making it suitable for session management or end-to-end auditing.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
Final Client Response:
|
|
||||||
AI:
|
|
||||||
Loyalty Points
|
|
||||||
POLICY CHECK: Intercepting 'update-hotel'
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
---
|
|
||||||
title: "(Python) Pre and post processing"
|
|
||||||
type: docs
|
|
||||||
weight: 4
|
|
||||||
description: >
|
|
||||||
How to add pre and post processing to your Python toolbox applications.
|
|
||||||
---
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
This tutorial assumes that you have set up a basic toolbox application as described in the [local quickstart](../../getting-started/local_quickstart).
|
|
||||||
|
|
||||||
This guide demonstrates how to implement these patterns in your Toolbox applications.
|
|
||||||
|
|
||||||
## Implementation
|
|
||||||
|
|
||||||
{{< tabpane persist=header >}}
|
|
||||||
{{% tab header="ADK" text=true %}}
|
|
||||||
Coming soon.
|
|
||||||
{{% /tab %}}
|
|
||||||
{{% tab header="Langchain" text=true %}}
|
|
||||||
The following example demonstrates how to use `ToolboxClient` with LangChain's middleware to implement pre and post processing for tool calls.
|
|
||||||
|
|
||||||
```py
|
|
||||||
{{< include "python/langchain/agent.py" >}}
|
|
||||||
```
|
|
||||||
|
|
||||||
For more information, see the [LangChain Middleware documentation](https://docs.langchain.com/oss/python/langchain/middleware/custom#wrap-style-hooks).
|
|
||||||
You can also add model-level (`wrap_model`) and agent-level (`before_agent`, `after_agent`) hooks to intercept messages at different stages of the execution loop. See the [LangChain Middleware documentation](https://docs.langchain.com/oss/python/langchain/middleware/custom#wrap-style-hooks) for details on these additional hook types.
|
|
||||||
{{% /tab %}}
|
|
||||||
{{< /tabpane >}}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
# This file makes the 'pre_post_processing/python' directory a Python package.
|
|
||||||
|
|
||||||
# You can include any package-level initialization logic here if needed.
|
|
||||||
# For now, this file is empty.
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
# Copyright 2026 Google LLC
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
import asyncio
|
|
||||||
import importlib
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
ORCH_NAME = os.environ.get("ORCH_NAME")
|
|
||||||
module_path = f"python.{ORCH_NAME}.agent"
|
|
||||||
agent = importlib.import_module(module_path)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
|
||||||
def golden_keywords():
|
|
||||||
"""Loads expected keywords from the golden.txt file."""
|
|
||||||
golden_file_path = Path(__file__).resolve().parent.parent / "golden.txt"
|
|
||||||
if not golden_file_path.exists():
|
|
||||||
pytest.fail(f"Golden file not found: {golden_file_path}")
|
|
||||||
try:
|
|
||||||
with open(golden_file_path, "r") as f:
|
|
||||||
return [line.strip() for line in f.readlines() if line.strip()]
|
|
||||||
except Exception as e:
|
|
||||||
pytest.fail(f"Could not read golden.txt: {e}")
|
|
||||||
|
|
||||||
|
|
||||||
# --- Execution Tests ---
|
|
||||||
class TestExecution:
|
|
||||||
"""Test framework execution and output validation."""
|
|
||||||
|
|
||||||
@pytest.fixture(scope="function")
|
|
||||||
def script_output(self, capsys):
|
|
||||||
"""Run the agent function and return its output."""
|
|
||||||
asyncio.run(agent.main())
|
|
||||||
return capsys.readouterr()
|
|
||||||
|
|
||||||
def test_script_runs_without_errors(self, script_output):
|
|
||||||
"""Test that the script runs and produces no stderr."""
|
|
||||||
assert script_output.err == "", f"Script produced stderr: {script_output.err}"
|
|
||||||
|
|
||||||
def test_keywords_in_output(self, script_output, golden_keywords):
|
|
||||||
"""Test that expected keywords are present in the script's output."""
|
|
||||||
output = script_output.out
|
|
||||||
print(f"\nAgent Output:\n{output}\n")
|
|
||||||
missing_keywords = [kw for kw in golden_keywords if kw not in output]
|
|
||||||
assert not missing_keywords, f"Missing keywords in output: {missing_keywords}"
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# Empty init for package resolution
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
# Copyright 2026 Google LLC
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
import asyncio
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
from langchain.agents import create_agent
|
|
||||||
from langchain.agents.middleware import wrap_tool_call
|
|
||||||
from langchain_core.messages import ToolMessage
|
|
||||||
from langchain_google_vertexai import ChatVertexAI
|
|
||||||
from toolbox_langchain import ToolboxClient
|
|
||||||
|
|
||||||
system_prompt = """
|
|
||||||
You're a helpful hotel assistant. You handle hotel searching, booking and
|
|
||||||
cancellations. When the user searches for a hotel, mention it's name, id,
|
|
||||||
location and price tier. Always mention hotel ids while performing any
|
|
||||||
searches. This is very important for any operations. For any bookings or
|
|
||||||
cancellations, please provide the appropriate confirmation. Be sure to
|
|
||||||
update checkin or checkout dates if mentioned by the user.
|
|
||||||
Don't ask for confirmations from the user.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
# Pre processing
|
|
||||||
@wrap_tool_call
|
|
||||||
async def enforce_business_rules(request, handler):
|
|
||||||
"""
|
|
||||||
Business Logic Validation:
|
|
||||||
Enforces max stay duration (e.g., max 14 days).
|
|
||||||
"""
|
|
||||||
tool_call = request.tool_call
|
|
||||||
name = tool_call["name"]
|
|
||||||
args = tool_call["args"]
|
|
||||||
|
|
||||||
print(f"POLICY CHECK: Intercepting '{name}'")
|
|
||||||
|
|
||||||
if name == "update-hotel":
|
|
||||||
if "checkin_date" in args and "checkout_date" in args:
|
|
||||||
try:
|
|
||||||
start = datetime.fromisoformat(args["checkin_date"])
|
|
||||||
end = datetime.fromisoformat(args["checkout_date"])
|
|
||||||
duration = (end - start).days
|
|
||||||
|
|
||||||
if duration > 14:
|
|
||||||
print("BLOCKED: Stay too long")
|
|
||||||
return ToolMessage(
|
|
||||||
content="Error: Maximum stay duration is 14 days.",
|
|
||||||
tool_call_id=tool_call["id"],
|
|
||||||
)
|
|
||||||
except ValueError:
|
|
||||||
pass # Ignore invalid date formats
|
|
||||||
|
|
||||||
return await handler(request)
|
|
||||||
|
|
||||||
|
|
||||||
# Post processing
|
|
||||||
@wrap_tool_call
|
|
||||||
async def enrich_response(request, handler):
|
|
||||||
"""
|
|
||||||
Post-Processing & Enrichment:
|
|
||||||
Adds loyalty points information to successful bookings.
|
|
||||||
Standardizes output format.
|
|
||||||
"""
|
|
||||||
result = await handler(request)
|
|
||||||
|
|
||||||
if isinstance(result, ToolMessage):
|
|
||||||
content = str(result.content)
|
|
||||||
tool_name = request.tool_call["name"]
|
|
||||||
|
|
||||||
if tool_name == "book-hotel" and "Error" not in content:
|
|
||||||
loyalty_bonus = 500
|
|
||||||
result.content = f"Booking Confirmed!\n You earned {loyalty_bonus} Loyalty Points with this stay.\n\nSystem Details: {content}"
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
|
||||||
async with ToolboxClient("http://127.0.0.1:5000") as client:
|
|
||||||
tools = await client.aload_toolset("my-toolset")
|
|
||||||
model = ChatVertexAI(model="gemini-2.5-flash")
|
|
||||||
agent = create_agent(
|
|
||||||
system_prompt=system_prompt,
|
|
||||||
model=model,
|
|
||||||
tools=tools,
|
|
||||||
middleware=[enforce_business_rules, enrich_response],
|
|
||||||
)
|
|
||||||
|
|
||||||
user_input = "Book hotel with id 3."
|
|
||||||
response = await agent.ainvoke(
|
|
||||||
{"messages": [{"role": "user", "content": user_input}]}
|
|
||||||
)
|
|
||||||
|
|
||||||
print("-" * 50)
|
|
||||||
print("Final Client Response:")
|
|
||||||
last_ai_msg = response["messages"][-1].content
|
|
||||||
print(f"AI: {last_ai_msg}")
|
|
||||||
|
|
||||||
# Test Pre-processing
|
|
||||||
print("-" * 50)
|
|
||||||
user_input = "Update my hotel with id 3 with checkin date 2025-01-18 and checkout date 2025-01-20"
|
|
||||||
response = await agent.ainvoke(
|
|
||||||
{"messages": [{"role": "user", "content": user_input}]}
|
|
||||||
)
|
|
||||||
last_ai_msg = response["messages"][-1].content
|
|
||||||
print(f"AI: {last_ai_msg}")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
asyncio.run(main())
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
langchain==1.2.6
|
|
||||||
langchain-google-vertexai==3.2.2
|
|
||||||
toolbox-langchain==0.5.8
|
|
||||||
@@ -19,7 +19,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/go-chi/chi/v5/middleware"
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
@@ -234,10 +233,11 @@ func toolInvokeHandler(s *Server, w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
params, err := parameters.ParseParams(tool.GetParameters(), data, claimsFromAuth)
|
params, err := parameters.ParseParams(tool.GetParameters(), data, claimsFromAuth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If auth error, return 401
|
// If auth error, return 401 or 403
|
||||||
if errors.Is(err, util.ErrUnauthorized) {
|
var clientServerErr *util.ClientServerError
|
||||||
|
if errors.As(err, &clientServerErr) && (clientServerErr.Code == http.StatusUnauthorized || clientServerErr.Code == http.StatusForbidden) {
|
||||||
s.logger.DebugContext(ctx, fmt.Sprintf("error parsing authenticated parameters from ID token: %s", err))
|
s.logger.DebugContext(ctx, fmt.Sprintf("error parsing authenticated parameters from ID token: %s", err))
|
||||||
_ = render.Render(w, r, newErrResponse(err, http.StatusUnauthorized))
|
_ = render.Render(w, r, newErrResponse(err, clientServerErr.Code))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = fmt.Errorf("provided parameters were invalid: %w", err)
|
err = fmt.Errorf("provided parameters were invalid: %w", err)
|
||||||
@@ -259,34 +259,49 @@ func toolInvokeHandler(s *Server, w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// Determine what error to return to the users.
|
// Determine what error to return to the users.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr := err.Error()
|
var tbErr util.ToolboxError
|
||||||
var statusCode int
|
|
||||||
|
|
||||||
// Upstream API auth error propagation
|
if errors.As(err, &tbErr) {
|
||||||
switch {
|
switch tbErr.Category() {
|
||||||
case strings.Contains(errStr, "Error 401"):
|
case util.CategoryAgent:
|
||||||
statusCode = http.StatusUnauthorized
|
// Agent Errors -> 200 OK
|
||||||
case strings.Contains(errStr, "Error 403"):
|
s.logger.DebugContext(ctx, fmt.Sprintf("Tool invocation agent error: %v", err))
|
||||||
statusCode = http.StatusForbidden
|
_ = render.Render(w, r, newErrResponse(err, http.StatusOK))
|
||||||
}
|
return
|
||||||
|
|
||||||
if statusCode == http.StatusUnauthorized || statusCode == http.StatusForbidden {
|
case util.CategoryServer:
|
||||||
if clientAuth {
|
// Server Errors -> Check the specific code inside
|
||||||
// Propagate the original 401/403 error.
|
var clientServerErr *util.ClientServerError
|
||||||
s.logger.DebugContext(ctx, fmt.Sprintf("error invoking tool. Client credentials lack authorization to the source: %v", err))
|
statusCode := http.StatusInternalServerError // Default to 500
|
||||||
|
|
||||||
|
if errors.As(err, &clientServerErr) {
|
||||||
|
if clientServerErr.Code != 0 {
|
||||||
|
statusCode = clientServerErr.Code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process auth error
|
||||||
|
if statusCode == http.StatusUnauthorized || statusCode == http.StatusForbidden {
|
||||||
|
if clientAuth {
|
||||||
|
// Token error, pass through 401/403
|
||||||
|
s.logger.DebugContext(ctx, fmt.Sprintf("Client credentials lack authorization: %v", err))
|
||||||
|
_ = render.Render(w, r, newErrResponse(err, statusCode))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// ADC/Config error, return 500
|
||||||
|
statusCode = http.StatusInternalServerError
|
||||||
|
}
|
||||||
|
|
||||||
|
s.logger.ErrorContext(ctx, fmt.Sprintf("Tool invocation server error: %v", err))
|
||||||
_ = render.Render(w, r, newErrResponse(err, statusCode))
|
_ = render.Render(w, r, newErrResponse(err, statusCode))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// ADC lacking permission or credentials configuration error.
|
} else {
|
||||||
internalErr := fmt.Errorf("unexpected auth error occured during Tool invocation: %w", err)
|
// Unknown error -> 500
|
||||||
s.logger.ErrorContext(ctx, internalErr.Error())
|
s.logger.ErrorContext(ctx, fmt.Sprintf("Tool invocation unknown error: %v", err))
|
||||||
_ = render.Render(w, r, newErrResponse(internalErr, http.StatusInternalServerError))
|
_ = render.Render(w, r, newErrResponse(err, http.StatusInternalServerError))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = fmt.Errorf("error while invoking tool: %w", err)
|
|
||||||
s.logger.DebugContext(ctx, err.Error())
|
|
||||||
_ = render.Render(w, r, newErrResponse(err, http.StatusBadRequest))
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resMarshal, err := json.Marshal(res)
|
resMarshal, err := json.Marshal(res)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/server/resources"
|
"github.com/googleapis/genai-toolbox/internal/server/resources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/telemetry"
|
"github.com/googleapis/genai-toolbox/internal/telemetry"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ type MockTool struct {
|
|||||||
requiresClientAuthrorization bool
|
requiresClientAuthrorization bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t MockTool) Invoke(context.Context, tools.SourceProvider, parameters.ParamValues, tools.AccessToken) (any, error) {
|
func (t MockTool) Invoke(context.Context, tools.SourceProvider, parameters.ParamValues, tools.AccessToken) (any, util.ToolboxError) {
|
||||||
mock := []any{t.Name}
|
mock := []any{t.Name}
|
||||||
return mock, nil
|
return mock, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -444,15 +443,17 @@ func httpHandler(s *Server, w http.ResponseWriter, r *http.Request) {
|
|||||||
code := rpcResponse.Error.Code
|
code := rpcResponse.Error.Code
|
||||||
switch code {
|
switch code {
|
||||||
case jsonrpc.INTERNAL_ERROR:
|
case jsonrpc.INTERNAL_ERROR:
|
||||||
|
// Map Internal RPC Error (-32603) to HTTP 500
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
case jsonrpc.INVALID_REQUEST:
|
case jsonrpc.INVALID_REQUEST:
|
||||||
errStr := err.Error()
|
var clientServerErr *util.ClientServerError
|
||||||
if errors.Is(err, util.ErrUnauthorized) {
|
if errors.As(err, &clientServerErr) {
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
switch clientServerErr.Code {
|
||||||
} else if strings.Contains(errStr, "Error 401") {
|
case http.StatusUnauthorized:
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
} else if strings.Contains(errStr, "Error 403") {
|
case http.StatusForbidden:
|
||||||
w.WriteHeader(http.StatusForbidden)
|
w.WriteHeader(http.StatusForbidden)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/googleapis/genai-toolbox/internal/prompts"
|
"github.com/googleapis/genai-toolbox/internal/prompts"
|
||||||
"github.com/googleapis/genai-toolbox/internal/server/mcp/jsonrpc"
|
"github.com/googleapis/genai-toolbox/internal/server/mcp/jsonrpc"
|
||||||
@@ -124,7 +123,11 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
|
|||||||
}
|
}
|
||||||
if clientAuth {
|
if clientAuth {
|
||||||
if accessToken == "" {
|
if accessToken == "" {
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, "missing access token in the 'Authorization' header", nil), util.ErrUnauthorized
|
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, "missing access token in the 'Authorization' header", nil), util.NewClientServerError(
|
||||||
|
"missing access token in the 'Authorization' header",
|
||||||
|
http.StatusUnauthorized,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +175,11 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
|
|||||||
// Check if any of the specified auth services is verified
|
// Check if any of the specified auth services is verified
|
||||||
isAuthorized := tool.Authorized(verifiedAuthServices)
|
isAuthorized := tool.Authorized(verifiedAuthServices)
|
||||||
if !isAuthorized {
|
if !isAuthorized {
|
||||||
err = fmt.Errorf("unauthorized Tool call: Please make sure your specify correct auth headers: %w", util.ErrUnauthorized)
|
err = util.NewClientServerError(
|
||||||
|
"unauthorized Tool call: Please make sure you specify correct auth headers",
|
||||||
|
http.StatusUnauthorized,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
||||||
}
|
}
|
||||||
logger.DebugContext(ctx, "tool invocation authorized")
|
logger.DebugContext(ctx, "tool invocation authorized")
|
||||||
@@ -194,30 +201,44 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
|
|||||||
// run tool invocation and generate response.
|
// run tool invocation and generate response.
|
||||||
results, err := tool.Invoke(ctx, resourceMgr, params, accessToken)
|
results, err := tool.Invoke(ctx, resourceMgr, params, accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr := err.Error()
|
var tbErr util.ToolboxError
|
||||||
// Missing authService tokens.
|
|
||||||
if errors.Is(err, util.ErrUnauthorized) {
|
if errors.As(err, &tbErr) {
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
switch tbErr.Category() {
|
||||||
}
|
case util.CategoryAgent:
|
||||||
// Upstream auth error
|
// MCP - Tool execution error
|
||||||
if strings.Contains(errStr, "Error 401") || strings.Contains(errStr, "Error 403") {
|
// Return SUCCESS but with IsError: true
|
||||||
if clientAuth {
|
text := TextContent{
|
||||||
// Error with client credentials should pass down to the client
|
Type: "text",
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
Text: err.Error(),
|
||||||
|
}
|
||||||
|
return jsonrpc.JSONRPCResponse{
|
||||||
|
Jsonrpc: jsonrpc.JSONRPC_VERSION,
|
||||||
|
Id: id,
|
||||||
|
Result: CallToolResult{Content: []TextContent{text}, IsError: true},
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
case util.CategoryServer:
|
||||||
|
// MCP Spec - Protocol error
|
||||||
|
// Return JSON-RPC ERROR
|
||||||
|
var clientServerErr *util.ClientServerError
|
||||||
|
rpcCode := jsonrpc.INTERNAL_ERROR // Default to Internal Error (-32603)
|
||||||
|
|
||||||
|
if errors.As(err, &clientServerErr) {
|
||||||
|
if clientServerErr.Code == http.StatusUnauthorized || clientServerErr.Code == http.StatusForbidden {
|
||||||
|
if clientAuth {
|
||||||
|
rpcCode = jsonrpc.INVALID_REQUEST
|
||||||
|
} else {
|
||||||
|
rpcCode = jsonrpc.INTERNAL_ERROR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsonrpc.NewError(id, rpcCode, err.Error(), nil), err
|
||||||
}
|
}
|
||||||
// Auth error with ADC should raise internal 500 error
|
} else {
|
||||||
|
// Unknown error -> 500
|
||||||
return jsonrpc.NewError(id, jsonrpc.INTERNAL_ERROR, err.Error(), nil), err
|
return jsonrpc.NewError(id, jsonrpc.INTERNAL_ERROR, err.Error(), nil), err
|
||||||
}
|
}
|
||||||
|
|
||||||
text := TextContent{
|
|
||||||
Type: "text",
|
|
||||||
Text: err.Error(),
|
|
||||||
}
|
|
||||||
return jsonrpc.JSONRPCResponse{
|
|
||||||
Jsonrpc: jsonrpc.JSONRPC_VERSION,
|
|
||||||
Id: id,
|
|
||||||
Result: CallToolResult{Content: []TextContent{text}, IsError: true},
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
content := make([]TextContent, 0)
|
content := make([]TextContent, 0)
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/googleapis/genai-toolbox/internal/prompts"
|
"github.com/googleapis/genai-toolbox/internal/prompts"
|
||||||
"github.com/googleapis/genai-toolbox/internal/server/mcp/jsonrpc"
|
"github.com/googleapis/genai-toolbox/internal/server/mcp/jsonrpc"
|
||||||
@@ -124,7 +123,11 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
|
|||||||
}
|
}
|
||||||
if clientAuth {
|
if clientAuth {
|
||||||
if accessToken == "" {
|
if accessToken == "" {
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, "missing access token in the 'Authorization' header", nil), util.ErrUnauthorized
|
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, "missing access token in the 'Authorization' header", nil), util.NewClientServerError(
|
||||||
|
"missing access token in the 'Authorization' header",
|
||||||
|
http.StatusUnauthorized,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +175,11 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
|
|||||||
// Check if any of the specified auth services is verified
|
// Check if any of the specified auth services is verified
|
||||||
isAuthorized := tool.Authorized(verifiedAuthServices)
|
isAuthorized := tool.Authorized(verifiedAuthServices)
|
||||||
if !isAuthorized {
|
if !isAuthorized {
|
||||||
err = fmt.Errorf("unauthorized Tool call: Please make sure your specify correct auth headers: %w", util.ErrUnauthorized)
|
err = util.NewClientServerError(
|
||||||
|
"unauthorized Tool call: Please make sure you specify correct auth headers",
|
||||||
|
http.StatusUnauthorized,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
||||||
}
|
}
|
||||||
logger.DebugContext(ctx, "tool invocation authorized")
|
logger.DebugContext(ctx, "tool invocation authorized")
|
||||||
@@ -194,31 +201,45 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
|
|||||||
// run tool invocation and generate response.
|
// run tool invocation and generate response.
|
||||||
results, err := tool.Invoke(ctx, resourceMgr, params, accessToken)
|
results, err := tool.Invoke(ctx, resourceMgr, params, accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr := err.Error()
|
var tbErr util.ToolboxError
|
||||||
// Missing authService tokens.
|
|
||||||
if errors.Is(err, util.ErrUnauthorized) {
|
if errors.As(err, &tbErr) {
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
switch tbErr.Category() {
|
||||||
}
|
case util.CategoryAgent:
|
||||||
// Upstream auth error
|
// MCP - Tool execution error
|
||||||
if strings.Contains(errStr, "Error 401") || strings.Contains(errStr, "Error 403") {
|
// Return SUCCESS but with IsError: true
|
||||||
if clientAuth {
|
text := TextContent{
|
||||||
// Error with client credentials should pass down to the client
|
Type: "text",
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
Text: err.Error(),
|
||||||
|
}
|
||||||
|
return jsonrpc.JSONRPCResponse{
|
||||||
|
Jsonrpc: jsonrpc.JSONRPC_VERSION,
|
||||||
|
Id: id,
|
||||||
|
Result: CallToolResult{Content: []TextContent{text}, IsError: true},
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
case util.CategoryServer:
|
||||||
|
// MCP Spec - Protocol error
|
||||||
|
// Return JSON-RPC ERROR
|
||||||
|
var clientServerErr *util.ClientServerError
|
||||||
|
rpcCode := jsonrpc.INTERNAL_ERROR // Default to Internal Error (-32603)
|
||||||
|
|
||||||
|
if errors.As(err, &clientServerErr) {
|
||||||
|
if clientServerErr.Code == http.StatusUnauthorized || clientServerErr.Code == http.StatusForbidden {
|
||||||
|
if clientAuth {
|
||||||
|
rpcCode = jsonrpc.INVALID_REQUEST
|
||||||
|
} else {
|
||||||
|
rpcCode = jsonrpc.INTERNAL_ERROR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsonrpc.NewError(id, rpcCode, err.Error(), nil), err
|
||||||
}
|
}
|
||||||
// Auth error with ADC should raise internal 500 error
|
} else {
|
||||||
|
// Unknown error -> 500
|
||||||
return jsonrpc.NewError(id, jsonrpc.INTERNAL_ERROR, err.Error(), nil), err
|
return jsonrpc.NewError(id, jsonrpc.INTERNAL_ERROR, err.Error(), nil), err
|
||||||
}
|
}
|
||||||
text := TextContent{
|
|
||||||
Type: "text",
|
|
||||||
Text: err.Error(),
|
|
||||||
}
|
|
||||||
return jsonrpc.JSONRPCResponse{
|
|
||||||
Jsonrpc: jsonrpc.JSONRPC_VERSION,
|
|
||||||
Id: id,
|
|
||||||
Result: CallToolResult{Content: []TextContent{text}, IsError: true},
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
content := make([]TextContent, 0)
|
content := make([]TextContent, 0)
|
||||||
|
|
||||||
sliceRes, ok := results.([]any)
|
sliceRes, ok := results.([]any)
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/googleapis/genai-toolbox/internal/prompts"
|
"github.com/googleapis/genai-toolbox/internal/prompts"
|
||||||
"github.com/googleapis/genai-toolbox/internal/server/mcp/jsonrpc"
|
"github.com/googleapis/genai-toolbox/internal/server/mcp/jsonrpc"
|
||||||
@@ -117,7 +116,12 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
|
|||||||
}
|
}
|
||||||
if clientAuth {
|
if clientAuth {
|
||||||
if accessToken == "" {
|
if accessToken == "" {
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, "missing access token in the 'Authorization' header", nil), util.ErrUnauthorized
|
errMsg := "missing access token in the 'Authorization' header"
|
||||||
|
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, errMsg, nil), util.NewClientServerError(
|
||||||
|
errMsg,
|
||||||
|
http.StatusUnauthorized,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +169,11 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
|
|||||||
// Check if any of the specified auth services is verified
|
// Check if any of the specified auth services is verified
|
||||||
isAuthorized := tool.Authorized(verifiedAuthServices)
|
isAuthorized := tool.Authorized(verifiedAuthServices)
|
||||||
if !isAuthorized {
|
if !isAuthorized {
|
||||||
err = fmt.Errorf("unauthorized Tool call: Please make sure your specify correct auth headers: %w", util.ErrUnauthorized)
|
err = util.NewClientServerError(
|
||||||
|
"unauthorized Tool call: Please make sure you specify correct auth headers",
|
||||||
|
http.StatusUnauthorized,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
||||||
}
|
}
|
||||||
logger.DebugContext(ctx, "tool invocation authorized")
|
logger.DebugContext(ctx, "tool invocation authorized")
|
||||||
@@ -187,29 +195,44 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
|
|||||||
// run tool invocation and generate response.
|
// run tool invocation and generate response.
|
||||||
results, err := tool.Invoke(ctx, resourceMgr, params, accessToken)
|
results, err := tool.Invoke(ctx, resourceMgr, params, accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr := err.Error()
|
var tbErr util.ToolboxError
|
||||||
// Missing authService tokens.
|
|
||||||
if errors.Is(err, util.ErrUnauthorized) {
|
if errors.As(err, &tbErr) {
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
switch tbErr.Category() {
|
||||||
}
|
case util.CategoryAgent:
|
||||||
// Upstream auth error
|
// MCP - Tool execution error
|
||||||
if strings.Contains(errStr, "Error 401") || strings.Contains(errStr, "Error 403") {
|
// Return SUCCESS but with IsError: true
|
||||||
if clientAuth {
|
text := TextContent{
|
||||||
// Error with client credentials should pass down to the client
|
Type: "text",
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
Text: err.Error(),
|
||||||
|
}
|
||||||
|
return jsonrpc.JSONRPCResponse{
|
||||||
|
Jsonrpc: jsonrpc.JSONRPC_VERSION,
|
||||||
|
Id: id,
|
||||||
|
Result: CallToolResult{Content: []TextContent{text}, IsError: true},
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
case util.CategoryServer:
|
||||||
|
// MCP Spec - Protocol error
|
||||||
|
// Return JSON-RPC ERROR
|
||||||
|
var clientServerErr *util.ClientServerError
|
||||||
|
rpcCode := jsonrpc.INTERNAL_ERROR // Default to Internal Error (-32603)
|
||||||
|
|
||||||
|
if errors.As(err, &clientServerErr) {
|
||||||
|
if clientServerErr.Code == http.StatusUnauthorized || clientServerErr.Code == http.StatusForbidden {
|
||||||
|
if clientAuth {
|
||||||
|
rpcCode = jsonrpc.INVALID_REQUEST
|
||||||
|
} else {
|
||||||
|
rpcCode = jsonrpc.INTERNAL_ERROR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsonrpc.NewError(id, rpcCode, err.Error(), nil), err
|
||||||
}
|
}
|
||||||
// Auth error with ADC should raise internal 500 error
|
} else {
|
||||||
|
// Unknown error -> 500
|
||||||
return jsonrpc.NewError(id, jsonrpc.INTERNAL_ERROR, err.Error(), nil), err
|
return jsonrpc.NewError(id, jsonrpc.INTERNAL_ERROR, err.Error(), nil), err
|
||||||
}
|
}
|
||||||
text := TextContent{
|
|
||||||
Type: "text",
|
|
||||||
Text: err.Error(),
|
|
||||||
}
|
|
||||||
return jsonrpc.JSONRPCResponse{
|
|
||||||
Jsonrpc: jsonrpc.JSONRPC_VERSION,
|
|
||||||
Id: id,
|
|
||||||
Result: CallToolResult{Content: []TextContent{text}, IsError: true},
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
content := make([]TextContent, 0)
|
content := make([]TextContent, 0)
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/googleapis/genai-toolbox/internal/prompts"
|
"github.com/googleapis/genai-toolbox/internal/prompts"
|
||||||
"github.com/googleapis/genai-toolbox/internal/server/mcp/jsonrpc"
|
"github.com/googleapis/genai-toolbox/internal/server/mcp/jsonrpc"
|
||||||
@@ -117,7 +116,11 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
|
|||||||
}
|
}
|
||||||
if clientAuth {
|
if clientAuth {
|
||||||
if accessToken == "" {
|
if accessToken == "" {
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, "missing access token in the 'Authorization' header", nil), util.ErrUnauthorized
|
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, "missing access token in the 'Authorization' header", nil), util.NewClientServerError(
|
||||||
|
"missing access token in the 'Authorization' header",
|
||||||
|
http.StatusUnauthorized,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +168,11 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
|
|||||||
// Check if any of the specified auth services is verified
|
// Check if any of the specified auth services is verified
|
||||||
isAuthorized := tool.Authorized(verifiedAuthServices)
|
isAuthorized := tool.Authorized(verifiedAuthServices)
|
||||||
if !isAuthorized {
|
if !isAuthorized {
|
||||||
err = fmt.Errorf("unauthorized Tool call: Please make sure your specify correct auth headers: %w", util.ErrUnauthorized)
|
err = util.NewClientServerError(
|
||||||
|
"unauthorized Tool call: Please make sure you specify correct auth headers",
|
||||||
|
http.StatusUnauthorized,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
||||||
}
|
}
|
||||||
logger.DebugContext(ctx, "tool invocation authorized")
|
logger.DebugContext(ctx, "tool invocation authorized")
|
||||||
@@ -187,29 +194,44 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
|
|||||||
// run tool invocation and generate response.
|
// run tool invocation and generate response.
|
||||||
results, err := tool.Invoke(ctx, resourceMgr, params, accessToken)
|
results, err := tool.Invoke(ctx, resourceMgr, params, accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr := err.Error()
|
var tbErr util.ToolboxError
|
||||||
// Missing authService tokens.
|
|
||||||
if errors.Is(err, util.ErrUnauthorized) {
|
if errors.As(err, &tbErr) {
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
switch tbErr.Category() {
|
||||||
}
|
case util.CategoryAgent:
|
||||||
// Upstream auth error
|
// MCP - Tool execution error
|
||||||
if strings.Contains(errStr, "Error 401") || strings.Contains(errStr, "Error 403") {
|
// Return SUCCESS but with IsError: true
|
||||||
if clientAuth {
|
text := TextContent{
|
||||||
// Error with client credentials should pass down to the client
|
Type: "text",
|
||||||
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
|
Text: err.Error(),
|
||||||
|
}
|
||||||
|
return jsonrpc.JSONRPCResponse{
|
||||||
|
Jsonrpc: jsonrpc.JSONRPC_VERSION,
|
||||||
|
Id: id,
|
||||||
|
Result: CallToolResult{Content: []TextContent{text}, IsError: true},
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
case util.CategoryServer:
|
||||||
|
// MCP Spec - Protocol error
|
||||||
|
// Return JSON-RPC ERROR
|
||||||
|
var clientServerErr *util.ClientServerError
|
||||||
|
rpcCode := jsonrpc.INTERNAL_ERROR // Default to Internal Error (-32603)
|
||||||
|
|
||||||
|
if errors.As(err, &clientServerErr) {
|
||||||
|
if clientServerErr.Code == http.StatusUnauthorized || clientServerErr.Code == http.StatusForbidden {
|
||||||
|
if clientAuth {
|
||||||
|
rpcCode = jsonrpc.INVALID_REQUEST
|
||||||
|
} else {
|
||||||
|
rpcCode = jsonrpc.INTERNAL_ERROR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsonrpc.NewError(id, rpcCode, err.Error(), nil), err
|
||||||
}
|
}
|
||||||
// Auth error with ADC should raise internal 500 error
|
} else {
|
||||||
|
// Unknown error -> 500
|
||||||
return jsonrpc.NewError(id, jsonrpc.INTERNAL_ERROR, err.Error(), nil), err
|
return jsonrpc.NewError(id, jsonrpc.INTERNAL_ERROR, err.Error(), nil), err
|
||||||
}
|
}
|
||||||
text := TextContent{
|
|
||||||
Type: "text",
|
|
||||||
Text: err.Error(),
|
|
||||||
}
|
|
||||||
return jsonrpc.JSONRPCResponse{
|
|
||||||
Jsonrpc: jsonrpc.JSONRPC_VERSION,
|
|
||||||
Id: id,
|
|
||||||
Result: CallToolResult{Content: []TextContent{text}, IsError: true},
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
content := make([]TextContent, 0)
|
content := make([]TextContent, 0)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -122,44 +123,49 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok || project == "" {
|
if !ok || project == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a non-empty string")
|
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a non-empty string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
location, ok := paramsMap["location"].(string)
|
location, ok := paramsMap["location"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid 'location' parameter; expected a string")
|
return nil, util.NewAgentError("invalid 'location' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
clusterID, ok := paramsMap["cluster"].(string)
|
clusterID, ok := paramsMap["cluster"].(string)
|
||||||
if !ok || clusterID == "" {
|
if !ok || clusterID == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'cluster' parameter; expected a non-empty string")
|
return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a non-empty string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
password, ok := paramsMap["password"].(string)
|
password, ok := paramsMap["password"].(string)
|
||||||
if !ok || password == "" {
|
if !ok || password == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'password' parameter; expected a non-empty string")
|
return nil, util.NewAgentError("invalid or missing 'password' parameter; expected a non-empty string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
network, ok := paramsMap["network"].(string)
|
network, ok := paramsMap["network"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid 'network' parameter; expected a string")
|
return nil, util.NewAgentError("invalid 'network' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
user, ok := paramsMap["user"].(string)
|
user, ok := paramsMap["user"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid 'user' parameter; expected a string")
|
return nil, util.NewAgentError("invalid 'user' parameter; expected a string", nil)
|
||||||
|
}
|
||||||
|
resp, err := source.CreateCluster(ctx, project, location, network, user, password, clusterID, string(accessToken))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return source.CreateCluster(ctx, project, location, network, user, password, clusterID, string(accessToken))
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -123,36 +124,36 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok || project == "" {
|
if !ok || project == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a non-empty string")
|
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a non-empty string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
location, ok := paramsMap["location"].(string)
|
location, ok := paramsMap["location"].(string)
|
||||||
if !ok || location == "" {
|
if !ok || location == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'location' parameter; expected a non-empty string")
|
return nil, util.NewAgentError("invalid or missing 'location' parameter; expected a non-empty string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
cluster, ok := paramsMap["cluster"].(string)
|
cluster, ok := paramsMap["cluster"].(string)
|
||||||
if !ok || cluster == "" {
|
if !ok || cluster == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'cluster' parameter; expected a non-empty string")
|
return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a non-empty string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceID, ok := paramsMap["instance"].(string)
|
instanceID, ok := paramsMap["instance"].(string)
|
||||||
if !ok || instanceID == "" {
|
if !ok || instanceID == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'instance' parameter; expected a non-empty string")
|
return nil, util.NewAgentError("invalid or missing 'instance' parameter; expected a non-empty string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceType, ok := paramsMap["instanceType"].(string)
|
instanceType, ok := paramsMap["instanceType"].(string)
|
||||||
if !ok || (instanceType != "READ_POOL" && instanceType != "PRIMARY") {
|
if !ok || (instanceType != "READ_POOL" && instanceType != "PRIMARY") {
|
||||||
return nil, fmt.Errorf("invalid 'instanceType' parameter; expected 'PRIMARY' or 'READ_POOL'")
|
return nil, util.NewAgentError("invalid 'instanceType' parameter; expected 'PRIMARY' or 'READ_POOL'", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
displayName, _ := paramsMap["displayName"].(string)
|
displayName, _ := paramsMap["displayName"].(string)
|
||||||
@@ -161,11 +162,15 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if instanceType == "READ_POOL" {
|
if instanceType == "READ_POOL" {
|
||||||
nodeCount, ok = paramsMap["nodeCount"].(int)
|
nodeCount, ok = paramsMap["nodeCount"].(int)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid 'nodeCount' parameter; expected an integer for READ_POOL")
|
return nil, util.NewAgentError("invalid 'nodeCount' parameter; expected an integer for READ_POOL", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return source.CreateInstance(ctx, project, location, cluster, instanceID, instanceType, displayName, nodeCount, string(accessToken))
|
resp, err := source.CreateInstance(ctx, project, location, cluster, instanceID, instanceType, displayName, nodeCount, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -122,43 +123,43 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok || project == "" {
|
if !ok || project == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a non-empty string")
|
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a non-empty string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
location, ok := paramsMap["location"].(string)
|
location, ok := paramsMap["location"].(string)
|
||||||
if !ok || location == "" {
|
if !ok || location == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing'location' parameter; expected a non-empty string")
|
return nil, util.NewAgentError("invalid or missing'location' parameter; expected a non-empty string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
cluster, ok := paramsMap["cluster"].(string)
|
cluster, ok := paramsMap["cluster"].(string)
|
||||||
if !ok || cluster == "" {
|
if !ok || cluster == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'cluster' parameter; expected a non-empty string")
|
return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a non-empty string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
userID, ok := paramsMap["user"].(string)
|
userID, ok := paramsMap["user"].(string)
|
||||||
if !ok || userID == "" {
|
if !ok || userID == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'user' parameter; expected a non-empty string")
|
return nil, util.NewAgentError("invalid or missing 'user' parameter; expected a non-empty string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
userType, ok := paramsMap["userType"].(string)
|
userType, ok := paramsMap["userType"].(string)
|
||||||
if !ok || (userType != "ALLOYDB_BUILT_IN" && userType != "ALLOYDB_IAM_USER") {
|
if !ok || (userType != "ALLOYDB_BUILT_IN" && userType != "ALLOYDB_IAM_USER") {
|
||||||
return nil, fmt.Errorf("invalid or missing 'userType' parameter; expected 'ALLOYDB_BUILT_IN' or 'ALLOYDB_IAM_USER'")
|
return nil, util.NewAgentError("invalid or missing 'userType' parameter; expected 'ALLOYDB_BUILT_IN' or 'ALLOYDB_IAM_USER'", nil)
|
||||||
}
|
}
|
||||||
var password string
|
var password string
|
||||||
|
|
||||||
if userType == "ALLOYDB_BUILT_IN" {
|
if userType == "ALLOYDB_BUILT_IN" {
|
||||||
password, ok = paramsMap["password"].(string)
|
password, ok = paramsMap["password"].(string)
|
||||||
if !ok || password == "" {
|
if !ok || password == "" {
|
||||||
return nil, fmt.Errorf("password is required when userType is ALLOYDB_BUILT_IN")
|
return nil, util.NewAgentError("password is required when userType is ALLOYDB_BUILT_IN", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +171,11 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.CreateUser(ctx, userType, password, roles, string(accessToken), project, location, cluster, userID)
|
resp, err := source.CreateUser(ctx, userType, password, roles, string(accessToken), project, location, cluster, userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -120,28 +121,32 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok || project == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
location, ok := paramsMap["location"].(string)
|
location, ok := paramsMap["location"].(string)
|
||||||
if !ok {
|
if !ok || location == "" {
|
||||||
return nil, fmt.Errorf("invalid 'location' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'location' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
cluster, ok := paramsMap["cluster"].(string)
|
cluster, ok := paramsMap["cluster"].(string)
|
||||||
if !ok {
|
if !ok || cluster == "" {
|
||||||
return nil, fmt.Errorf("invalid 'cluster' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return source.GetCluster(ctx, project, location, cluster, string(accessToken))
|
resp, err := source.GetCluster(ctx, project, location, cluster, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -120,32 +121,36 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok || project == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
location, ok := paramsMap["location"].(string)
|
location, ok := paramsMap["location"].(string)
|
||||||
if !ok {
|
if !ok || location == "" {
|
||||||
return nil, fmt.Errorf("invalid 'location' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'location' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
cluster, ok := paramsMap["cluster"].(string)
|
cluster, ok := paramsMap["cluster"].(string)
|
||||||
if !ok {
|
if !ok || cluster == "" {
|
||||||
return nil, fmt.Errorf("invalid 'cluster' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
instance, ok := paramsMap["instance"].(string)
|
instance, ok := paramsMap["instance"].(string)
|
||||||
if !ok {
|
if !ok || instance == "" {
|
||||||
return nil, fmt.Errorf("invalid 'instance' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'instance' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return source.GetInstance(ctx, project, location, cluster, instance, string(accessToken))
|
resp, err := source.GetInstance(ctx, project, location, cluster, instance, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -120,32 +121,36 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok || project == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
location, ok := paramsMap["location"].(string)
|
location, ok := paramsMap["location"].(string)
|
||||||
if !ok {
|
if !ok || location == "" {
|
||||||
return nil, fmt.Errorf("invalid 'location' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'location' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
cluster, ok := paramsMap["cluster"].(string)
|
cluster, ok := paramsMap["cluster"].(string)
|
||||||
if !ok {
|
if !ok || cluster == "" {
|
||||||
return nil, fmt.Errorf("invalid 'cluster' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
user, ok := paramsMap["user"].(string)
|
user, ok := paramsMap["user"].(string)
|
||||||
if !ok {
|
if !ok || user == "" {
|
||||||
return nil, fmt.Errorf("invalid 'user' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'user' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return source.GetUsers(ctx, project, location, cluster, user, string(accessToken))
|
resp, err := source.GetUsers(ctx, project, location, cluster, user, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -118,24 +119,28 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok || project == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
location, ok := paramsMap["location"].(string)
|
location, ok := paramsMap["location"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid 'location' parameter; expected a string")
|
return nil, util.NewAgentError("invalid 'location' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return source.ListCluster(ctx, project, location, string(accessToken))
|
resp, err := source.ListCluster(ctx, project, location, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -119,28 +120,32 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok || project == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
location, ok := paramsMap["location"].(string)
|
location, ok := paramsMap["location"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid 'location' parameter; expected a string")
|
return nil, util.NewAgentError("invalid 'location' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
cluster, ok := paramsMap["cluster"].(string)
|
cluster, ok := paramsMap["cluster"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid 'cluster' parameter; expected a string")
|
return nil, util.NewAgentError("invalid 'cluster' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return source.ListInstance(ctx, project, location, cluster, string(accessToken))
|
resp, err := source.ListInstance(ctx, project, location, cluster, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -119,28 +120,32 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok || project == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
location, ok := paramsMap["location"].(string)
|
location, ok := paramsMap["location"].(string)
|
||||||
if !ok {
|
if !ok || location == "" {
|
||||||
return nil, fmt.Errorf("invalid 'location' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'location' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
cluster, ok := paramsMap["cluster"].(string)
|
cluster, ok := paramsMap["cluster"].(string)
|
||||||
if !ok {
|
if !ok || cluster == "" {
|
||||||
return nil, fmt.Errorf("invalid 'cluster' parameter; expected a string")
|
return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return source.ListUsers(ctx, project, location, cluster, string(accessToken))
|
resp, err := source.ListUsers(ctx, project, location, cluster, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -213,25 +214,25 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'project' parameter")
|
return nil, util.NewAgentError("missing 'project' parameter", nil)
|
||||||
}
|
}
|
||||||
location, ok := paramsMap["location"].(string)
|
location, ok := paramsMap["location"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'location' parameter")
|
return nil, util.NewAgentError("missing 'location' parameter", nil)
|
||||||
}
|
}
|
||||||
operation, ok := paramsMap["operation"].(string)
|
operation, ok := paramsMap["operation"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'operation' parameter")
|
return nil, util.NewAgentError("missing 'operation' parameter", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(ctx, 30*time.Minute)
|
ctx, cancel := context.WithTimeout(ctx, 30*time.Minute)
|
||||||
@@ -246,14 +247,15 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
for retries < maxRetries {
|
for retries < maxRetries {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return nil, fmt.Errorf("timed out waiting for operation: %w", ctx.Err())
|
return nil, util.NewAgentError("timed out waiting for operation", ctx.Err())
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
op, err := source.GetOperations(ctx, project, location, operation, alloyDBConnectionMessageTemplate, delay, string(accessToken))
|
op, err := source.GetOperations(ctx, project, location, operation, alloyDBConnectionMessageTemplate, delay, string(accessToken))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.ProcessGcpError(err)
|
||||||
} else if op != nil {
|
}
|
||||||
|
if op != nil {
|
||||||
return op, nil
|
return op, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,7 +266,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
}
|
}
|
||||||
retries++
|
retries++
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("exceeded max retries waiting for operation")
|
return nil, util.NewAgentError("exceeded max retries waiting for operation", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package alloydbainl
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
)
|
)
|
||||||
@@ -127,10 +129,10 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sliceParams := params.AsSlice()
|
sliceParams := params.AsSlice()
|
||||||
@@ -143,7 +145,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
|
|
||||||
resp, err := source.RunSQL(ctx, t.Statement, allParamValues)
|
resp, err := source.RunSQL(ctx, t.Statement, allParamValues)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%w. Query: %v , Values: %v. Toolbox v0.19.0+ is only compatible with AlloyDB AI NL v1.0.3+. Please ensure that you are using the latest AlloyDB AI NL extension", err, t.Statement, allParamValues)
|
return nil, util.NewClientServerError(fmt.Sprintf("error running SQL query: %v. Query: %v , Values: %v. Toolbox v0.19.0+ is only compatible with AlloyDB AI NL v1.0.3+. Please ensure that you are using the latest AlloyDB AI NL extension", err, t.Statement, allParamValues), http.StatusBadRequest, err)
|
||||||
}
|
}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package bigqueryanalyzecontribution
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
bigqueryapi "cloud.google.com/go/bigquery"
|
bigqueryapi "cloud.google.com/go/bigquery"
|
||||||
@@ -27,6 +28,7 @@ import (
|
|||||||
bigqueryds "github.com/googleapis/genai-toolbox/internal/sources/bigquery"
|
bigqueryds "github.com/googleapis/genai-toolbox/internal/sources/bigquery"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
bqutil "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigquerycommon"
|
bqutil "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigquerycommon"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
bigqueryrestapi "google.golang.org/api/bigquery/v2"
|
bigqueryrestapi "google.golang.org/api/bigquery/v2"
|
||||||
)
|
)
|
||||||
@@ -154,21 +156,21 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke runs the contribution analysis.
|
// Invoke runs the contribution analysis.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
inputData, ok := paramsMap["input_data"].(string)
|
inputData, ok := paramsMap["input_data"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unable to cast input_data parameter %s", paramsMap["input_data"])
|
return nil, util.NewAgentError(fmt.Sprintf("unable to cast input_data parameter %s", paramsMap["input_data"]), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
bqClient, restService, err := source.RetrieveClientAndService(accessToken)
|
bqClient, restService, err := source.RetrieveClientAndService(accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
modelID := fmt.Sprintf("contribution_analysis_model_%s", strings.ReplaceAll(uuid.New().String(), "-", ""))
|
modelID := fmt.Sprintf("contribution_analysis_model_%s", strings.ReplaceAll(uuid.New().String(), "-", ""))
|
||||||
@@ -186,7 +188,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
}
|
}
|
||||||
options = append(options, fmt.Sprintf("DIMENSION_ID_COLS = [%s]", strings.Join(strCols, ", ")))
|
options = append(options, fmt.Sprintf("DIMENSION_ID_COLS = [%s]", strings.Join(strCols, ", ")))
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("unable to cast dimension_id_cols parameter %s", paramsMap["dimension_id_cols"])
|
return nil, util.NewAgentError(fmt.Sprintf("unable to cast dimension_id_cols parameter %s", paramsMap["dimension_id_cols"]), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if val, ok := paramsMap["top_k_insights_by_apriori_support"]; ok {
|
if val, ok := paramsMap["top_k_insights_by_apriori_support"]; ok {
|
||||||
@@ -195,7 +197,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if val, ok := paramsMap["pruning_method"].(string); ok {
|
if val, ok := paramsMap["pruning_method"].(string); ok {
|
||||||
upperVal := strings.ToUpper(val)
|
upperVal := strings.ToUpper(val)
|
||||||
if upperVal != "NO_PRUNING" && upperVal != "PRUNE_REDUNDANT_INSIGHTS" {
|
if upperVal != "NO_PRUNING" && upperVal != "PRUNE_REDUNDANT_INSIGHTS" {
|
||||||
return nil, fmt.Errorf("invalid pruning_method: %s", val)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid pruning_method: %s", val), nil)
|
||||||
}
|
}
|
||||||
options = append(options, fmt.Sprintf("PRUNING_METHOD = '%s'", upperVal))
|
options = append(options, fmt.Sprintf("PRUNING_METHOD = '%s'", upperVal))
|
||||||
}
|
}
|
||||||
@@ -207,7 +209,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
var connProps []*bigqueryapi.ConnectionProperty
|
var connProps []*bigqueryapi.ConnectionProperty
|
||||||
session, err := source.BigQuerySession()(ctx)
|
session, err := source.BigQuerySession()(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get BigQuery session: %w", err)
|
return nil, util.NewClientServerError("failed to get BigQuery session", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
if session != nil {
|
if session != nil {
|
||||||
connProps = []*bigqueryapi.ConnectionProperty{
|
connProps = []*bigqueryapi.ConnectionProperty{
|
||||||
@@ -216,22 +218,22 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
}
|
}
|
||||||
dryRunJob, err := bqutil.DryRunQuery(ctx, restService, source.BigQueryClient().Project(), source.BigQueryClient().Location, inputData, nil, connProps)
|
dryRunJob, err := bqutil.DryRunQuery(ctx, restService, source.BigQueryClient().Project(), source.BigQueryClient().Location, inputData, nil, connProps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("query validation failed: %w", err)
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
statementType := dryRunJob.Statistics.Query.StatementType
|
statementType := dryRunJob.Statistics.Query.StatementType
|
||||||
if statementType != "SELECT" {
|
if statementType != "SELECT" {
|
||||||
return nil, fmt.Errorf("the 'input_data' parameter only supports a table ID or a SELECT query. The provided query has statement type '%s'", statementType)
|
return nil, util.NewAgentError(fmt.Sprintf("the 'input_data' parameter only supports a table ID or a SELECT query. The provided query has statement type '%s'", statementType), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
queryStats := dryRunJob.Statistics.Query
|
queryStats := dryRunJob.Statistics.Query
|
||||||
if queryStats != nil {
|
if queryStats != nil {
|
||||||
for _, tableRef := range queryStats.ReferencedTables {
|
for _, tableRef := range queryStats.ReferencedTables {
|
||||||
if !source.IsDatasetAllowed(tableRef.ProjectId, tableRef.DatasetId) {
|
if !source.IsDatasetAllowed(tableRef.ProjectId, tableRef.DatasetId) {
|
||||||
return nil, fmt.Errorf("query in input_data accesses dataset '%s.%s', which is not in the allowed list", tableRef.ProjectId, tableRef.DatasetId)
|
return nil, util.NewAgentError(fmt.Sprintf("query in input_data accesses dataset '%s.%s', which is not in the allowed list", tableRef.ProjectId, tableRef.DatasetId), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("could not analyze query in input_data to validate against allowed datasets")
|
return nil, util.NewAgentError("could not analyze query in input_data to validate against allowed datasets", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inputDataSource = fmt.Sprintf("(%s)", inputData)
|
inputDataSource = fmt.Sprintf("(%s)", inputData)
|
||||||
@@ -245,10 +247,10 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
case 2: // dataset.table
|
case 2: // dataset.table
|
||||||
projectID, datasetID = source.BigQueryClient().Project(), parts[0]
|
projectID, datasetID = source.BigQueryClient().Project(), parts[0]
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("invalid table ID format for 'input_data': %q. Expected 'dataset.table' or 'project.dataset.table'", inputData)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid table ID format for 'input_data': %q. Expected 'dataset.table' or 'project.dataset.table'", inputData), nil)
|
||||||
}
|
}
|
||||||
if !source.IsDatasetAllowed(projectID, datasetID) {
|
if !source.IsDatasetAllowed(projectID, datasetID) {
|
||||||
return nil, fmt.Errorf("access to dataset '%s.%s' (from table '%s') is not allowed", projectID, datasetID, inputData)
|
return nil, util.NewAgentError(fmt.Sprintf("access to dataset '%s.%s' (from table '%s') is not allowed", projectID, datasetID, inputData), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inputDataSource = fmt.Sprintf("SELECT * FROM `%s`", inputData)
|
inputDataSource = fmt.Sprintf("SELECT * FROM `%s`", inputData)
|
||||||
@@ -268,7 +270,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
// Otherwise, a new session will be created by the first query.
|
// Otherwise, a new session will be created by the first query.
|
||||||
session, err := source.BigQuerySession()(ctx)
|
session, err := source.BigQuerySession()(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get BigQuery session: %w", err)
|
return nil, util.NewClientServerError("failed to get BigQuery session", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if session != nil {
|
if session != nil {
|
||||||
@@ -281,15 +283,15 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
}
|
}
|
||||||
createModelJob, err := createModelQuery.Run(ctx)
|
createModelJob, err := createModelQuery.Run(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to start create model job: %w", err)
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
status, err := createModelJob.Wait(ctx)
|
status, err := createModelJob.Wait(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to wait for create model job: %w", err)
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
if err := status.Err(); err != nil {
|
if err := status.Err(); err != nil {
|
||||||
return nil, fmt.Errorf("create model job failed: %w", err)
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the session ID to use for subsequent queries.
|
// Determine the session ID to use for subsequent queries.
|
||||||
@@ -300,12 +302,17 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
} else if status.Statistics != nil && status.Statistics.SessionInfo != nil {
|
} else if status.Statistics != nil && status.Statistics.SessionInfo != nil {
|
||||||
sessionID = status.Statistics.SessionInfo.SessionID
|
sessionID = status.Statistics.SessionInfo.SessionID
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("failed to get or create a BigQuery session ID")
|
return nil, util.NewClientServerError("failed to get or create a BigQuery session ID", http.StatusInternalServerError, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
getInsightsSQL := fmt.Sprintf("SELECT * FROM ML.GET_INSIGHTS(MODEL %s)", modelID)
|
getInsightsSQL := fmt.Sprintf("SELECT * FROM ML.GET_INSIGHTS(MODEL %s)", modelID)
|
||||||
connProps := []*bigqueryapi.ConnectionProperty{{Key: "session_id", Value: sessionID}}
|
connProps := []*bigqueryapi.ConnectionProperty{{Key: "session_id", Value: sessionID}}
|
||||||
return source.RunSQL(ctx, bqClient, getInsightsSQL, "SELECT", nil, connProps)
|
|
||||||
|
resp, err := source.RunSQL(ctx, bqClient, getInsightsSQL, "SELECT", nil, connProps)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -172,10 +172,10 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
@@ -184,26 +184,26 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
// Use client-side access token
|
// Use client-side access token
|
||||||
if accessToken == "" {
|
if accessToken == "" {
|
||||||
return nil, fmt.Errorf("tool is configured for client OAuth but no token was provided in the request header: %w", util.ErrUnauthorized)
|
return nil, util.NewClientServerError("tool is configured for client OAuth but no token was provided in the request header", http.StatusUnauthorized, nil)
|
||||||
}
|
}
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Get a token source for the Gemini Data Analytics API.
|
// Get a token source for the Gemini Data Analytics API.
|
||||||
tokenSource, err := source.BigQueryTokenSourceWithScope(ctx, nil)
|
tokenSource, err := source.BigQueryTokenSourceWithScope(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get token source: %w", err)
|
return nil, util.NewClientServerError("failed to get token source", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use cloud-platform token source for Gemini Data Analytics API
|
// Use cloud-platform token source for Gemini Data Analytics API
|
||||||
if tokenSource == nil {
|
if tokenSource == nil {
|
||||||
return nil, fmt.Errorf("cloud-platform token source is missing")
|
return nil, util.NewClientServerError("cloud-platform token source is missing", http.StatusInternalServerError, nil)
|
||||||
}
|
}
|
||||||
token, err := tokenSource.Token()
|
token, err := tokenSource.Token()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get token from cloud-platform token source: %w", err)
|
return nil, util.NewClientServerError("failed to get token from cloud-platform token source", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
tokenStr = token.AccessToken
|
tokenStr = token.AccessToken
|
||||||
}
|
}
|
||||||
@@ -218,14 +218,14 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
var tableRefs []BQTableReference
|
var tableRefs []BQTableReference
|
||||||
if tableRefsJSON != "" {
|
if tableRefsJSON != "" {
|
||||||
if err := json.Unmarshal([]byte(tableRefsJSON), &tableRefs); err != nil {
|
if err := json.Unmarshal([]byte(tableRefsJSON), &tableRefs); err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse 'table_references' JSON string: %w", err)
|
return nil, util.NewAgentError("failed to parse 'table_references' JSON string", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(source.BigQueryAllowedDatasets()) > 0 {
|
if len(source.BigQueryAllowedDatasets()) > 0 {
|
||||||
for _, tableRef := range tableRefs {
|
for _, tableRef := range tableRefs {
|
||||||
if !source.IsDatasetAllowed(tableRef.ProjectID, tableRef.DatasetID) {
|
if !source.IsDatasetAllowed(tableRef.ProjectID, tableRef.DatasetID) {
|
||||||
return nil, fmt.Errorf("access to dataset '%s.%s' (from table '%s') is not allowed", tableRef.ProjectID, tableRef.DatasetID, tableRef.TableID)
|
return nil, util.NewAgentError(fmt.Sprintf("access to dataset '%s.%s' (from table '%s') is not allowed", tableRef.ProjectID, tableRef.DatasetID, tableRef.TableID), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,7 +258,8 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
// Call the streaming API
|
// Call the streaming API
|
||||||
response, err := getStream(caURL, payload, headers, source.GetMaxQueryResultRows())
|
response, err := getStream(caURL, payload, headers, source.GetMaxQueryResultRows())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get response from conversational analytics API: %w", err)
|
// getStream wraps network errors or non-200 responses
|
||||||
|
return nil, util.NewClientServerError("failed to get response from conversational analytics API", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return response, nil
|
return response, nil
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
bigqueryapi "cloud.google.com/go/bigquery"
|
bigqueryapi "cloud.google.com/go/bigquery"
|
||||||
@@ -152,25 +153,25 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
sql, ok := paramsMap["sql"].(string)
|
sql, ok := paramsMap["sql"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unable to cast sql parameter %s", paramsMap["sql"])
|
return nil, util.NewAgentError(fmt.Sprintf("unable to cast sql parameter %s", paramsMap["sql"]), nil)
|
||||||
}
|
}
|
||||||
dryRun, ok := paramsMap["dry_run"].(bool)
|
dryRun, ok := paramsMap["dry_run"].(bool)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unable to cast dry_run parameter %s", paramsMap["dry_run"])
|
return nil, util.NewAgentError(fmt.Sprintf("unable to cast dry_run parameter %s", paramsMap["dry_run"]), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
bqClient, restService, err := source.RetrieveClientAndService(accessToken)
|
bqClient, restService, err := source.RetrieveClientAndService(accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var connProps []*bigqueryapi.ConnectionProperty
|
var connProps []*bigqueryapi.ConnectionProperty
|
||||||
@@ -178,7 +179,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if source.BigQueryWriteMode() == bigqueryds.WriteModeProtected {
|
if source.BigQueryWriteMode() == bigqueryds.WriteModeProtected {
|
||||||
session, err = source.BigQuerySession()(ctx)
|
session, err = source.BigQuerySession()(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get BigQuery session for protected mode: %w", err)
|
return nil, util.NewClientServerError("failed to get BigQuery session for protected mode", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
connProps = []*bigqueryapi.ConnectionProperty{
|
connProps = []*bigqueryapi.ConnectionProperty{
|
||||||
{Key: "session_id", Value: session.ID},
|
{Key: "session_id", Value: session.ID},
|
||||||
@@ -187,7 +188,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
|
|
||||||
dryRunJob, err := bqutil.DryRunQuery(ctx, restService, bqClient.Project(), bqClient.Location, sql, nil, connProps)
|
dryRunJob, err := bqutil.DryRunQuery(ctx, restService, bqClient.Project(), bqClient.Location, sql, nil, connProps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("query validation failed: %w", err)
|
return nil, util.NewClientServerError("query validation failed", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
statementType := dryRunJob.Statistics.Query.StatementType
|
statementType := dryRunJob.Statistics.Query.StatementType
|
||||||
@@ -195,13 +196,13 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
switch source.BigQueryWriteMode() {
|
switch source.BigQueryWriteMode() {
|
||||||
case bigqueryds.WriteModeBlocked:
|
case bigqueryds.WriteModeBlocked:
|
||||||
if statementType != "SELECT" {
|
if statementType != "SELECT" {
|
||||||
return nil, fmt.Errorf("write mode is 'blocked', only SELECT statements are allowed")
|
return nil, util.NewAgentError("write mode is 'blocked', only SELECT statements are allowed", nil)
|
||||||
}
|
}
|
||||||
case bigqueryds.WriteModeProtected:
|
case bigqueryds.WriteModeProtected:
|
||||||
if dryRunJob.Configuration != nil && dryRunJob.Configuration.Query != nil {
|
if dryRunJob.Configuration != nil && dryRunJob.Configuration.Query != nil {
|
||||||
if dest := dryRunJob.Configuration.Query.DestinationTable; dest != nil && dest.DatasetId != session.DatasetID {
|
if dest := dryRunJob.Configuration.Query.DestinationTable; dest != nil && dest.DatasetId != session.DatasetID {
|
||||||
return nil, fmt.Errorf("protected write mode only supports SELECT statements, or write operations in the anonymous "+
|
return nil, util.NewAgentError(fmt.Sprintf("protected write mode only supports SELECT statements, or write operations in the anonymous "+
|
||||||
"dataset of a BigQuery session, but destination was %q", dest.DatasetId)
|
"dataset of a BigQuery session, but destination was %q", dest.DatasetId), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -209,11 +210,11 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if len(source.BigQueryAllowedDatasets()) > 0 {
|
if len(source.BigQueryAllowedDatasets()) > 0 {
|
||||||
switch statementType {
|
switch statementType {
|
||||||
case "CREATE_SCHEMA", "DROP_SCHEMA", "ALTER_SCHEMA":
|
case "CREATE_SCHEMA", "DROP_SCHEMA", "ALTER_SCHEMA":
|
||||||
return nil, fmt.Errorf("dataset-level operations like '%s' are not allowed when dataset restrictions are in place", statementType)
|
return nil, util.NewAgentError(fmt.Sprintf("dataset-level operations like '%s' are not allowed when dataset restrictions are in place", statementType), nil)
|
||||||
case "CREATE_FUNCTION", "CREATE_TABLE_FUNCTION", "CREATE_PROCEDURE":
|
case "CREATE_FUNCTION", "CREATE_TABLE_FUNCTION", "CREATE_PROCEDURE":
|
||||||
return nil, fmt.Errorf("creating stored routines ('%s') is not allowed when dataset restrictions are in place, as their contents cannot be safely analyzed", statementType)
|
return nil, util.NewAgentError(fmt.Sprintf("creating stored routines ('%s') is not allowed when dataset restrictions are in place, as their contents cannot be safely analyzed", statementType), nil)
|
||||||
case "CALL":
|
case "CALL":
|
||||||
return nil, fmt.Errorf("calling stored procedures ('%s') is not allowed when dataset restrictions are in place, as their contents cannot be safely analyzed", statementType)
|
return nil, util.NewAgentError(fmt.Sprintf("calling stored procedures ('%s') is not allowed when dataset restrictions are in place, as their contents cannot be safely analyzed", statementType), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use a map to avoid duplicate table names.
|
// Use a map to avoid duplicate table names.
|
||||||
@@ -244,7 +245,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
parsedTables, parseErr := bqutil.TableParser(sql, source.BigQueryClient().Project())
|
parsedTables, parseErr := bqutil.TableParser(sql, source.BigQueryClient().Project())
|
||||||
if parseErr != nil {
|
if parseErr != nil {
|
||||||
// If parsing fails (e.g., EXECUTE IMMEDIATE), we cannot guarantee safety, so we must fail.
|
// If parsing fails (e.g., EXECUTE IMMEDIATE), we cannot guarantee safety, so we must fail.
|
||||||
return nil, fmt.Errorf("could not parse tables from query to validate against allowed datasets: %w", parseErr)
|
return nil, util.NewAgentError("could not parse tables from query to validate against allowed datasets", parseErr)
|
||||||
}
|
}
|
||||||
tableNames = parsedTables
|
tableNames = parsedTables
|
||||||
}
|
}
|
||||||
@@ -254,7 +255,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if len(parts) == 3 {
|
if len(parts) == 3 {
|
||||||
projectID, datasetID := parts[0], parts[1]
|
projectID, datasetID := parts[0], parts[1]
|
||||||
if !source.IsDatasetAllowed(projectID, datasetID) {
|
if !source.IsDatasetAllowed(projectID, datasetID) {
|
||||||
return nil, fmt.Errorf("query accesses dataset '%s.%s', which is not in the allowed list", projectID, datasetID)
|
return nil, util.NewAgentError(fmt.Sprintf("query accesses dataset '%s.%s', which is not in the allowed list", projectID, datasetID), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -264,7 +265,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if dryRunJob != nil {
|
if dryRunJob != nil {
|
||||||
jobJSON, err := json.MarshalIndent(dryRunJob, "", " ")
|
jobJSON, err := json.MarshalIndent(dryRunJob, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to marshal dry run job to JSON: %w", err)
|
return nil, util.NewClientServerError("failed to marshal dry run job to JSON", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
return string(jobJSON), nil
|
return string(jobJSON), nil
|
||||||
}
|
}
|
||||||
@@ -275,10 +276,14 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
// Log the query executed for debugging.
|
// Log the query executed for debugging.
|
||||||
logger, err := util.LoggerFromContext(ctx)
|
logger, err := util.LoggerFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error getting logger: %s", err)
|
return nil, util.NewClientServerError("error getting logger", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql))
|
logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql))
|
||||||
return source.RunSQL(ctx, bqClient, sql, statementType, nil, connProps)
|
resp, err := source.RunSQL(ctx, bqClient, sql, statementType, nil, connProps)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.NewClientServerError("error running sql", http.StatusInternalServerError, err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package bigqueryforecast
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
bigqueryapi "cloud.google.com/go/bigquery"
|
bigqueryapi "cloud.google.com/go/bigquery"
|
||||||
@@ -133,34 +134,34 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
historyData, ok := paramsMap["history_data"].(string)
|
historyData, ok := paramsMap["history_data"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unable to cast history_data parameter %v", paramsMap["history_data"])
|
return nil, util.NewAgentError(fmt.Sprintf("unable to cast history_data parameter %v", paramsMap["history_data"]), nil)
|
||||||
}
|
}
|
||||||
timestampCol, ok := paramsMap["timestamp_col"].(string)
|
timestampCol, ok := paramsMap["timestamp_col"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unable to cast timestamp_col parameter %v", paramsMap["timestamp_col"])
|
return nil, util.NewAgentError(fmt.Sprintf("unable to cast timestamp_col parameter %v", paramsMap["timestamp_col"]), nil)
|
||||||
}
|
}
|
||||||
dataCol, ok := paramsMap["data_col"].(string)
|
dataCol, ok := paramsMap["data_col"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unable to cast data_col parameter %v", paramsMap["data_col"])
|
return nil, util.NewAgentError(fmt.Sprintf("unable to cast data_col parameter %v", paramsMap["data_col"]), nil)
|
||||||
}
|
}
|
||||||
idColsRaw, ok := paramsMap["id_cols"].([]any)
|
idColsRaw, ok := paramsMap["id_cols"].([]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unable to cast id_cols parameter %v", paramsMap["id_cols"])
|
return nil, util.NewAgentError(fmt.Sprintf("unable to cast id_cols parameter %v", paramsMap["id_cols"]), nil)
|
||||||
}
|
}
|
||||||
var idCols []string
|
var idCols []string
|
||||||
for _, v := range idColsRaw {
|
for _, v := range idColsRaw {
|
||||||
s, ok := v.(string)
|
s, ok := v.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("id_cols contains non-string value: %v", v)
|
return nil, util.NewAgentError(fmt.Sprintf("id_cols contains non-string value: %v", v), nil)
|
||||||
}
|
}
|
||||||
idCols = append(idCols, s)
|
idCols = append(idCols, s)
|
||||||
}
|
}
|
||||||
@@ -169,13 +170,13 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if h, ok := paramsMap["horizon"].(float64); ok {
|
if h, ok := paramsMap["horizon"].(float64); ok {
|
||||||
horizon = int(h)
|
horizon = int(h)
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("unable to cast horizon parameter %v", paramsMap["horizon"])
|
return nil, util.NewAgentError(fmt.Sprintf("unable to cast horizon parameter %v", paramsMap["horizon"]), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bqClient, restService, err := source.RetrieveClientAndService(accessToken)
|
bqClient, restService, err := source.RetrieveClientAndService(accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var historyDataSource string
|
var historyDataSource string
|
||||||
@@ -185,7 +186,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
var connProps []*bigqueryapi.ConnectionProperty
|
var connProps []*bigqueryapi.ConnectionProperty
|
||||||
session, err := source.BigQuerySession()(ctx)
|
session, err := source.BigQuerySession()(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get BigQuery session: %w", err)
|
return nil, util.NewClientServerError("failed to get BigQuery session", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
if session != nil {
|
if session != nil {
|
||||||
connProps = []*bigqueryapi.ConnectionProperty{
|
connProps = []*bigqueryapi.ConnectionProperty{
|
||||||
@@ -194,22 +195,22 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
}
|
}
|
||||||
dryRunJob, err := bqutil.DryRunQuery(ctx, restService, source.BigQueryClient().Project(), source.BigQueryClient().Location, historyData, nil, connProps)
|
dryRunJob, err := bqutil.DryRunQuery(ctx, restService, source.BigQueryClient().Project(), source.BigQueryClient().Location, historyData, nil, connProps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("query validation failed: %w", err)
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
statementType := dryRunJob.Statistics.Query.StatementType
|
statementType := dryRunJob.Statistics.Query.StatementType
|
||||||
if statementType != "SELECT" {
|
if statementType != "SELECT" {
|
||||||
return nil, fmt.Errorf("the 'history_data' parameter only supports a table ID or a SELECT query. The provided query has statement type '%s'", statementType)
|
return nil, util.NewAgentError(fmt.Sprintf("the 'history_data' parameter only supports a table ID or a SELECT query. The provided query has statement type '%s'", statementType), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
queryStats := dryRunJob.Statistics.Query
|
queryStats := dryRunJob.Statistics.Query
|
||||||
if queryStats != nil {
|
if queryStats != nil {
|
||||||
for _, tableRef := range queryStats.ReferencedTables {
|
for _, tableRef := range queryStats.ReferencedTables {
|
||||||
if !source.IsDatasetAllowed(tableRef.ProjectId, tableRef.DatasetId) {
|
if !source.IsDatasetAllowed(tableRef.ProjectId, tableRef.DatasetId) {
|
||||||
return nil, fmt.Errorf("query in history_data accesses dataset '%s.%s', which is not in the allowed list", tableRef.ProjectId, tableRef.DatasetId)
|
return nil, util.NewAgentError(fmt.Sprintf("query in history_data accesses dataset '%s.%s', which is not in the allowed list", tableRef.ProjectId, tableRef.DatasetId), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("could not analyze query in history_data to validate against allowed datasets")
|
return nil, util.NewAgentError("could not analyze query in history_data to validate against allowed datasets", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
historyDataSource = fmt.Sprintf("(%s)", historyData)
|
historyDataSource = fmt.Sprintf("(%s)", historyData)
|
||||||
@@ -226,11 +227,11 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
projectID = source.BigQueryClient().Project()
|
projectID = source.BigQueryClient().Project()
|
||||||
datasetID = parts[0]
|
datasetID = parts[0]
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("invalid table ID format for 'history_data': %q. Expected 'dataset.table' or 'project.dataset.table'", historyData)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid table ID format for 'history_data': %q. Expected 'dataset.table' or 'project.dataset.table'", historyData), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !source.IsDatasetAllowed(projectID, datasetID) {
|
if !source.IsDatasetAllowed(projectID, datasetID) {
|
||||||
return nil, fmt.Errorf("access to dataset '%s.%s' (from table '%s') is not allowed", projectID, datasetID, historyData)
|
return nil, util.NewAgentError(fmt.Sprintf("access to dataset '%s.%s' (from table '%s') is not allowed", projectID, datasetID, historyData), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
historyDataSource = fmt.Sprintf("TABLE `%s`", historyData)
|
historyDataSource = fmt.Sprintf("TABLE `%s`", historyData)
|
||||||
@@ -243,15 +244,15 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
}
|
}
|
||||||
sql := fmt.Sprintf(`SELECT *
|
sql := fmt.Sprintf(`SELECT *
|
||||||
FROM AI.FORECAST(
|
FROM AI.FORECAST(
|
||||||
%s,
|
%s,
|
||||||
data_col => '%s',
|
data_col => '%s',
|
||||||
timestamp_col => '%s',
|
timestamp_col => '%s',
|
||||||
horizon => %d%s)`,
|
horizon => %d%s)`,
|
||||||
historyDataSource, dataCol, timestampCol, horizon, idColsArg)
|
historyDataSource, dataCol, timestampCol, horizon, idColsArg)
|
||||||
|
|
||||||
session, err := source.BigQuerySession()(ctx)
|
session, err := source.BigQuerySession()(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get BigQuery session: %w", err)
|
return nil, util.NewClientServerError("failed to get BigQuery session", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
var connProps []*bigqueryapi.ConnectionProperty
|
var connProps []*bigqueryapi.ConnectionProperty
|
||||||
if session != nil {
|
if session != nil {
|
||||||
@@ -264,11 +265,15 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
// Log the query executed for debugging.
|
// Log the query executed for debugging.
|
||||||
logger, err := util.LoggerFromContext(ctx)
|
logger, err := util.LoggerFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error getting logger: %s", err)
|
return nil, util.NewClientServerError("error getting logger", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql))
|
logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql))
|
||||||
|
|
||||||
return source.RunSQL(ctx, bqClient, sql, "SELECT", nil, connProps)
|
resp, err := source.RunSQL(ctx, bqClient, sql, "SELECT", nil, connProps)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package bigquerygetdatasetinfo
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
bigqueryapi "cloud.google.com/go/bigquery"
|
bigqueryapi "cloud.google.com/go/bigquery"
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
@@ -24,6 +25,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
bqutil "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigquerycommon"
|
bqutil "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigquerycommon"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
bigqueryrestapi "google.golang.org/api/bigquery/v2"
|
bigqueryrestapi "google.golang.org/api/bigquery/v2"
|
||||||
)
|
)
|
||||||
@@ -120,38 +122,38 @@ type Tool struct {
|
|||||||
func (t Tool) ToConfig() tools.ToolConfig {
|
func (t Tool) ToConfig() tools.ToolConfig {
|
||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mapParams := params.AsMap()
|
mapParams := params.AsMap()
|
||||||
projectId, ok := mapParams[projectKey].(string)
|
projectId, ok := mapParams[projectKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", projectKey)
|
// Updated: Use fmt.Sprintf for formatting, pass nil as cause
|
||||||
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", projectKey), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
datasetId, ok := mapParams[datasetKey].(string)
|
datasetId, ok := mapParams[datasetKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", datasetKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", datasetKey), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
bqClient, _, err := source.RetrieveClientAndService(accessToken)
|
bqClient, _, err := source.RetrieveClientAndService(accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !source.IsDatasetAllowed(projectId, datasetId) {
|
if !source.IsDatasetAllowed(projectId, datasetId) {
|
||||||
return nil, fmt.Errorf("access denied to dataset '%s' because it is not in the configured list of allowed datasets for project '%s'", datasetId, projectId)
|
return nil, util.NewClientServerError(fmt.Sprintf("access denied to dataset '%s' because it is not in the configured list of allowed datasets for project '%s'", datasetId, projectId), http.StatusInternalServerError, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
dsHandle := bqClient.DatasetInProject(projectId, datasetId)
|
dsHandle := bqClient.DatasetInProject(projectId, datasetId)
|
||||||
|
|
||||||
metadata, err := dsHandle.Metadata(ctx)
|
metadata, err := dsHandle.Metadata(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get metadata for dataset %s (in project %s): %w", datasetId, projectId, err)
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return metadata, nil
|
return metadata, nil
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package bigquerygettableinfo
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
bigqueryapi "cloud.google.com/go/bigquery"
|
bigqueryapi "cloud.google.com/go/bigquery"
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
@@ -24,6 +25,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
bqutil "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigquerycommon"
|
bqutil "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigquerycommon"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
bigqueryrestapi "google.golang.org/api/bigquery/v2"
|
bigqueryrestapi "google.golang.org/api/bigquery/v2"
|
||||||
)
|
)
|
||||||
@@ -125,35 +127,35 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mapParams := params.AsMap()
|
mapParams := params.AsMap()
|
||||||
projectId, ok := mapParams[projectKey].(string)
|
projectId, ok := mapParams[projectKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", projectKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", projectKey), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
datasetId, ok := mapParams[datasetKey].(string)
|
datasetId, ok := mapParams[datasetKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", datasetKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", datasetKey), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
tableId, ok := mapParams[tableKey].(string)
|
tableId, ok := mapParams[tableKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", tableKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", tableKey), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !source.IsDatasetAllowed(projectId, datasetId) {
|
if !source.IsDatasetAllowed(projectId, datasetId) {
|
||||||
return nil, fmt.Errorf("access denied to dataset '%s' because it is not in the configured list of allowed datasets for project '%s'", datasetId, projectId)
|
return nil, util.NewClientServerError(fmt.Sprintf("access denied to dataset '%s' because it is not in the configured list of allowed datasets for project '%s'", datasetId, projectId), http.StatusInternalServerError, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
bqClient, _, err := source.RetrieveClientAndService(accessToken)
|
bqClient, _, err := source.RetrieveClientAndService(accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dsHandle := bqClient.DatasetInProject(projectId, datasetId)
|
dsHandle := bqClient.DatasetInProject(projectId, datasetId)
|
||||||
@@ -161,7 +163,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
|
|
||||||
metadata, err := tableHandle.Metadata(ctx)
|
metadata, err := tableHandle.Metadata(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get metadata for table %s.%s.%s: %w", projectId, datasetId, tableId, err)
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return metadata, nil
|
return metadata, nil
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package bigquerylistdatasetids
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
bigqueryapi "cloud.google.com/go/bigquery"
|
bigqueryapi "cloud.google.com/go/bigquery"
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
bigqueryrestapi "google.golang.org/api/bigquery/v2"
|
bigqueryrestapi "google.golang.org/api/bigquery/v2"
|
||||||
"google.golang.org/api/iterator"
|
"google.golang.org/api/iterator"
|
||||||
@@ -120,10 +122,10 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(source.BigQueryAllowedDatasets()) > 0 {
|
if len(source.BigQueryAllowedDatasets()) > 0 {
|
||||||
@@ -132,12 +134,12 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
mapParams := params.AsMap()
|
mapParams := params.AsMap()
|
||||||
projectId, ok := mapParams[projectKey].(string)
|
projectId, ok := mapParams[projectKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", projectKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", projectKey), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
bqClient, _, err := source.RetrieveClientAndService(accessToken)
|
bqClient, _, err := source.RetrieveClientAndService(accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
datasetIterator := bqClient.Datasets(ctx)
|
datasetIterator := bqClient.Datasets(ctx)
|
||||||
datasetIterator.ProjectID = projectId
|
datasetIterator.ProjectID = projectId
|
||||||
@@ -149,7 +151,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to iterate through datasets: %w", err)
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove leading and trailing quotes
|
// Remove leading and trailing quotes
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package bigquerylisttableids
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
bigqueryapi "cloud.google.com/go/bigquery"
|
bigqueryapi "cloud.google.com/go/bigquery"
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
@@ -24,6 +25,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
bqutil "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigquerycommon"
|
bqutil "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigquerycommon"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
bigqueryrestapi "google.golang.org/api/bigquery/v2"
|
bigqueryrestapi "google.golang.org/api/bigquery/v2"
|
||||||
"google.golang.org/api/iterator"
|
"google.golang.org/api/iterator"
|
||||||
@@ -123,31 +125,30 @@ type Tool struct {
|
|||||||
func (t Tool) ToConfig() tools.ToolConfig {
|
func (t Tool) ToConfig() tools.ToolConfig {
|
||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mapParams := params.AsMap()
|
mapParams := params.AsMap()
|
||||||
projectId, ok := mapParams[projectKey].(string)
|
projectId, ok := mapParams[projectKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", projectKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", projectKey), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
datasetId, ok := mapParams[datasetKey].(string)
|
datasetId, ok := mapParams[datasetKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", datasetKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", datasetKey), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !source.IsDatasetAllowed(projectId, datasetId) {
|
if !source.IsDatasetAllowed(projectId, datasetId) {
|
||||||
return nil, fmt.Errorf("access denied to dataset '%s' because it is not in the configured list of allowed datasets for project '%s'", datasetId, projectId)
|
return nil, util.NewClientServerError(fmt.Sprintf("access denied to dataset '%s' because it is not in the configured list of allowed datasets for project '%s'", datasetId, projectId), http.StatusInternalServerError, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
bqClient, _, err := source.RetrieveClientAndService(accessToken)
|
bqClient, _, err := source.RetrieveClientAndService(accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dsHandle := bqClient.DatasetInProject(projectId, datasetId)
|
dsHandle := bqClient.DatasetInProject(projectId, datasetId)
|
||||||
@@ -160,7 +161,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to iterate through tables in dataset %s.%s: %w", projectId, datasetId, err)
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove leading and trailing quotes
|
// Remove leading and trailing quotes
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package bigquerysearchcatalog
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
dataplexapi "cloud.google.com/go/dataplex/apiv1"
|
dataplexapi "cloud.google.com/go/dataplex/apiv1"
|
||||||
@@ -26,6 +27,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
bigqueryds "github.com/googleapis/genai-toolbox/internal/sources/bigquery"
|
bigqueryds "github.com/googleapis/genai-toolbox/internal/sources/bigquery"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/iterator"
|
"google.golang.org/api/iterator"
|
||||||
)
|
)
|
||||||
@@ -186,28 +188,31 @@ func ExtractType(resourceString string) string {
|
|||||||
return typeMap[resourceString[lastIndex+1:]]
|
return typeMap[resourceString[lastIndex+1:]]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
pageSize := int32(paramsMap["pageSize"].(int))
|
pageSize := int32(paramsMap["pageSize"].(int))
|
||||||
prompt, _ := paramsMap["prompt"].(string)
|
prompt, _ := paramsMap["prompt"].(string)
|
||||||
|
|
||||||
projectIdSlice, err := parameters.ConvertAnySliceToTyped(paramsMap["projectIds"].([]any), "string")
|
projectIdSlice, err := parameters.ConvertAnySliceToTyped(paramsMap["projectIds"].([]any), "string")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't convert projectIds to array of strings: %s", err)
|
return nil, util.NewAgentError(fmt.Sprintf("can't convert projectIds to array of strings: %s", err), err)
|
||||||
}
|
}
|
||||||
projectIds := projectIdSlice.([]string)
|
projectIds := projectIdSlice.([]string)
|
||||||
|
|
||||||
datasetIdSlice, err := parameters.ConvertAnySliceToTyped(paramsMap["datasetIds"].([]any), "string")
|
datasetIdSlice, err := parameters.ConvertAnySliceToTyped(paramsMap["datasetIds"].([]any), "string")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't convert datasetIds to array of strings: %s", err)
|
return nil, util.NewAgentError(fmt.Sprintf("can't convert datasetIds to array of strings: %s", err), err)
|
||||||
}
|
}
|
||||||
datasetIds := datasetIdSlice.([]string)
|
datasetIds := datasetIdSlice.([]string)
|
||||||
|
|
||||||
typesSlice, err := parameters.ConvertAnySliceToTyped(paramsMap["types"].([]any), "string")
|
typesSlice, err := parameters.ConvertAnySliceToTyped(paramsMap["types"].([]any), "string")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't convert types to array of strings: %s", err)
|
return nil, util.NewAgentError(fmt.Sprintf("can't convert types to array of strings: %s", err), err)
|
||||||
}
|
}
|
||||||
types := typesSlice.([]string)
|
types := typesSlice.([]string)
|
||||||
|
|
||||||
@@ -223,17 +228,17 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err := accessToken.ParseBearerToken()
|
tokenStr, err := accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
catalogClient, err = dataplexClientCreator(tokenStr)
|
catalogClient, err = dataplexClientCreator(tokenStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error creating client from OAuth access token: %w", err)
|
return nil, util.NewClientServerError("error creating client from OAuth access token", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it := catalogClient.SearchEntries(ctx, req)
|
it := catalogClient.SearchEntries(ctx, req)
|
||||||
if it == nil {
|
if it == nil {
|
||||||
return nil, fmt.Errorf("failed to create search entries iterator for project %q", source.BigQueryProject())
|
return nil, util.NewClientServerError(fmt.Sprintf("failed to create search entries iterator for project %q", source.BigQueryProject()), http.StatusInternalServerError, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
var results []Response
|
var results []Response
|
||||||
@@ -243,7 +248,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
entrySource := entry.DataplexEntry.GetEntrySource()
|
entrySource := entry.DataplexEntry.GetEntrySource()
|
||||||
resp := Response{
|
resp := Response{
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package bigquerysql
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -27,6 +28,7 @@ import (
|
|||||||
bigqueryds "github.com/googleapis/genai-toolbox/internal/sources/bigquery"
|
bigqueryds "github.com/googleapis/genai-toolbox/internal/sources/bigquery"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
bqutil "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigquerycommon"
|
bqutil "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigquerycommon"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
bigqueryrestapi "google.golang.org/api/bigquery/v2"
|
bigqueryrestapi "google.golang.org/api/bigquery/v2"
|
||||||
)
|
)
|
||||||
@@ -103,11 +105,10 @@ type Tool struct {
|
|||||||
func (t Tool) ToConfig() tools.ToolConfig {
|
func (t Tool) ToConfig() tools.ToolConfig {
|
||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
highLevelParams := make([]bigqueryapi.QueryParameter, 0, len(t.Parameters))
|
highLevelParams := make([]bigqueryapi.QueryParameter, 0, len(t.Parameters))
|
||||||
@@ -116,7 +117,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
newStatement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, paramsMap)
|
newStatement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, paramsMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to extract template params %w", err)
|
return nil, util.NewAgentError("unable to extract template params", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range t.Parameters {
|
for _, p := range t.Parameters {
|
||||||
@@ -127,13 +128,13 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if arrayParam, ok := p.(*parameters.ArrayParameter); ok {
|
if arrayParam, ok := p.(*parameters.ArrayParameter); ok {
|
||||||
arrayParamValue, ok := value.([]any)
|
arrayParamValue, ok := value.([]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unable to convert parameter `%s` to []any", name)
|
return nil, util.NewAgentError(fmt.Sprintf("unable to convert parameter `%s` to []any", name), nil)
|
||||||
}
|
}
|
||||||
itemType := arrayParam.GetItems().GetType()
|
itemType := arrayParam.GetItems().GetType()
|
||||||
var err error
|
var err error
|
||||||
value, err = parameters.ConvertAnySliceToTyped(arrayParamValue, itemType)
|
value, err = parameters.ConvertAnySliceToTyped(arrayParamValue, itemType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to convert parameter `%s` from []any to typed slice: %w", name, err)
|
return nil, util.NewAgentError(fmt.Sprintf("unable to convert parameter `%s` from []any to typed slice", name), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +162,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
lowLevelParam.ParameterType.Type = "ARRAY"
|
lowLevelParam.ParameterType.Type = "ARRAY"
|
||||||
itemType, err := bqutil.BQTypeStringFromToolType(arrayParam.GetItems().GetType())
|
itemType, err := bqutil.BQTypeStringFromToolType(arrayParam.GetItems().GetType())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewAgentError("unable to get BigQuery type from tool parameter type", err)
|
||||||
}
|
}
|
||||||
lowLevelParam.ParameterType.ArrayType = &bigqueryrestapi.QueryParameterType{Type: itemType}
|
lowLevelParam.ParameterType.ArrayType = &bigqueryrestapi.QueryParameterType{Type: itemType}
|
||||||
|
|
||||||
@@ -178,7 +179,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
// Handle scalar types based on their defined type.
|
// Handle scalar types based on their defined type.
|
||||||
bqType, err := bqutil.BQTypeStringFromToolType(p.GetType())
|
bqType, err := bqutil.BQTypeStringFromToolType(p.GetType())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewAgentError("unable to get BigQuery type from tool parameter type", err)
|
||||||
}
|
}
|
||||||
lowLevelParam.ParameterType.Type = bqType
|
lowLevelParam.ParameterType.Type = bqType
|
||||||
lowLevelParam.ParameterValue.Value = fmt.Sprintf("%v", value)
|
lowLevelParam.ParameterValue.Value = fmt.Sprintf("%v", value)
|
||||||
@@ -190,7 +191,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if source.BigQuerySession() != nil {
|
if source.BigQuerySession() != nil {
|
||||||
session, err := source.BigQuerySession()(ctx)
|
session, err := source.BigQuerySession()(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get BigQuery session: %w", err)
|
return nil, util.NewClientServerError("failed to get BigQuery session", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
if session != nil {
|
if session != nil {
|
||||||
// Add session ID to the connection properties for subsequent calls.
|
// Add session ID to the connection properties for subsequent calls.
|
||||||
@@ -200,17 +201,20 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
|
|
||||||
bqClient, restService, err := source.RetrieveClientAndService(accessToken)
|
bqClient, restService, err := source.RetrieveClientAndService(accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dryRunJob, err := bqutil.DryRunQuery(ctx, restService, bqClient.Project(), bqClient.Location, newStatement, lowLevelParams, connProps)
|
dryRunJob, err := bqutil.DryRunQuery(ctx, restService, bqClient.Project(), bqClient.Location, newStatement, lowLevelParams, connProps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("query validation failed: %w", err)
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
statementType := dryRunJob.Statistics.Query.StatementType
|
statementType := dryRunJob.Statistics.Query.StatementType
|
||||||
|
resp, err := source.RunSQL(ctx, bqClient, newStatement, statementType, highLevelParams, connProps)
|
||||||
return source.RunSQL(ctx, bqClient, newStatement, statementType, highLevelParams, connProps)
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package bigtable
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"cloud.google.com/go/bigtable"
|
"cloud.google.com/go/bigtable"
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -96,24 +98,28 @@ type Tool struct {
|
|||||||
func (t Tool) ToConfig() tools.ToolConfig {
|
func (t Tool) ToConfig() tools.ToolConfig {
|
||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
newStatement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, paramsMap)
|
newStatement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, paramsMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to extract template params %w", err)
|
return nil, util.NewAgentError("unable to extract template params", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
newParams, err := parameters.GetParams(t.Parameters, paramsMap)
|
newParams, err := parameters.GetParams(t.Parameters, paramsMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to extract standard params %w", err)
|
return nil, util.NewAgentError("unable to extract standard params", err)
|
||||||
}
|
}
|
||||||
return source.RunSQL(ctx, newStatement, t.Parameters, newParams)
|
|
||||||
|
resp, err := source.RunSQL(ctx, newStatement, t.Parameters, newParams)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
// You may obtain a copy of the License at
|
// You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
//
|
//
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@@ -17,12 +17,14 @@ package cassandracql
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
gocql "github.com/apache/cassandra-gocql-driver/v2"
|
gocql "github.com/apache/cassandra-gocql-driver/v2"
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -107,23 +109,27 @@ func (t Tool) Authorized(verifiedAuthServices []string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke implements tools.Tool.
|
// Invoke implements tools.Tool.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
newStatement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, paramsMap)
|
newStatement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, paramsMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to extract template params %w", err)
|
return nil, util.NewAgentError("unable to extract template params", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
newParams, err := parameters.GetParams(t.Parameters, paramsMap)
|
newParams, err := parameters.GetParams(t.Parameters, paramsMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to extract standard params %w", err)
|
return nil, util.NewAgentError("unable to extract standard params", err)
|
||||||
}
|
}
|
||||||
return source.RunSQL(ctx, newStatement, newParams)
|
resp, err := source.RunSQL(ctx, newStatement, newParams)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGeneralError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manifest implements tools.Tool.
|
// Manifest implements tools.Tool.
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package clickhouse
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -87,18 +89,22 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
sql, ok := paramsMap["sql"].(string)
|
sql, ok := paramsMap["sql"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unable to cast sql parameter %s", paramsMap["sql"])
|
return nil, util.NewAgentError(fmt.Sprintf("unable to cast sql parameter %s", paramsMap["sql"]), nil)
|
||||||
}
|
}
|
||||||
return source.RunSQL(ctx, sql, nil)
|
resp, err := source.RunSQL(ctx, sql, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGeneralError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package clickhouse
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -86,10 +88,10 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query to list all databases
|
// Query to list all databases
|
||||||
@@ -97,7 +99,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
|
|
||||||
out, err := source.RunSQL(ctx, query, nil)
|
out, err := source.RunSQL(ctx, query, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.ProcessGeneralError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package clickhouse
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -90,34 +92,37 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mapParams := params.AsMap()
|
mapParams := params.AsMap()
|
||||||
database, ok := mapParams[databaseKey].(string)
|
database, ok := mapParams[databaseKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", databaseKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", databaseKey), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query to list all tables in the specified database
|
// Query to list all tables in the specified database
|
||||||
|
// Note: formatting identifier directly is risky if input is untrusted, but standard for this tool structure.
|
||||||
query := fmt.Sprintf("SHOW TABLES FROM %s", database)
|
query := fmt.Sprintf("SHOW TABLES FROM %s", database)
|
||||||
|
|
||||||
out, err := source.RunSQL(ctx, query, nil)
|
out, err := source.RunSQL(ctx, query, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.ProcessGeneralError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, ok := out.([]any)
|
res, ok := out.([]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unable to convert result to list")
|
return nil, util.NewClientServerError("unable to convert result to list", http.StatusInternalServerError, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
var tables []map[string]any
|
var tables []map[string]any
|
||||||
for _, item := range res {
|
for _, item := range res {
|
||||||
tableMap, ok := item.(map[string]any)
|
tableMap, ok := item.(map[string]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unexpected type in result: got %T, want map[string]any", item)
|
return nil, util.NewClientServerError(fmt.Sprintf("unexpected type in result: got %T, want map[string]any", item), http.StatusInternalServerError, nil)
|
||||||
}
|
}
|
||||||
tableMap["database"] = database
|
tableMap["database"] = database
|
||||||
tables = append(tables, tableMap)
|
tables = append(tables, tableMap)
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package clickhouse
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -88,24 +90,28 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, token tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
newStatement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, paramsMap)
|
newStatement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, paramsMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to extract template params: %w", err)
|
return nil, util.NewAgentError("unable to extract template params", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
newParams, err := parameters.GetParams(t.Parameters, paramsMap)
|
newParams, err := parameters.GetParams(t.Parameters, paramsMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to extract standard params: %w", err)
|
return nil, util.NewAgentError("unable to extract standard params", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return source.RunSQL(ctx, newStatement, newParams)
|
resp, err := source.RunSQL(ctx, newStatement, newParams)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGeneralError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -18,11 +18,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -119,17 +121,16 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool logic
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
query, ok := paramsMap["query"].(string)
|
query, ok := paramsMap["query"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("query parameter not found or not a string")
|
return nil, util.NewAgentError("query parameter not found or not a string", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the access token if provided
|
// Parse the access token if provided
|
||||||
@@ -138,7 +139,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
var err error
|
var err error
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,9 +155,14 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
|
|
||||||
bodyBytes, err := json.Marshal(payload)
|
bodyBytes, err := json.Marshal(payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to marshal request payload: %w", err)
|
return nil, util.NewClientServerError("failed to marshal request payload", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
return source.RunQuery(ctx, tokenStr, bodyBytes)
|
|
||||||
|
resp, err := source.RunQuery(ctx, tokenStr, bodyBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package fhirfetchpage
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -93,24 +95,31 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
url, ok := params.AsMap()[pageURLKey].(string)
|
url, ok := params.AsMap()[pageURLKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", pageURLKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", pageURLKey), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.FHIRFetchPage(ctx, url, tokenStr)
|
|
||||||
|
resp, err := source.FHIRFetchPage(ctx, url, tokenStr)
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package fhirpatienteverything
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
@@ -24,6 +25,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
)
|
)
|
||||||
@@ -116,26 +118,27 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedFHIRStores())
|
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedFHIRStores())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
// ValidateAndFetchStoreID usually returns input validation errors
|
||||||
|
return nil, util.NewAgentError("failed to validate store ID", err)
|
||||||
}
|
}
|
||||||
patientID, ok := params.AsMap()[patientIDKey].(string)
|
patientID, ok := params.AsMap()[patientIDKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", patientIDKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", patientIDKey), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,11 +146,11 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if val, ok := params.AsMap()[typeFilterKey]; ok {
|
if val, ok := params.AsMap()[typeFilterKey]; ok {
|
||||||
types, ok := val.([]any)
|
types, ok := val.([]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid '%s' parameter; expected a string array", typeFilterKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string array", typeFilterKey), nil)
|
||||||
}
|
}
|
||||||
typeFilterSlice, err := parameters.ConvertAnySliceToTyped(types, "string")
|
typeFilterSlice, err := parameters.ConvertAnySliceToTyped(types, "string")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't convert '%s' to array of strings: %s", typeFilterKey, err)
|
return nil, util.NewAgentError(fmt.Sprintf("can't convert '%s' to array of strings: %s", typeFilterKey, err), err)
|
||||||
}
|
}
|
||||||
if len(typeFilterSlice.([]string)) != 0 {
|
if len(typeFilterSlice.([]string)) != 0 {
|
||||||
opts = append(opts, googleapi.QueryParameter("_type", strings.Join(typeFilterSlice.([]string), ",")))
|
opts = append(opts, googleapi.QueryParameter("_type", strings.Join(typeFilterSlice.([]string), ",")))
|
||||||
@@ -156,13 +159,18 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if since, ok := params.AsMap()[sinceFilterKey]; ok {
|
if since, ok := params.AsMap()[sinceFilterKey]; ok {
|
||||||
sinceStr, ok := since.(string)
|
sinceStr, ok := since.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid '%s' parameter; expected a string", sinceFilterKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string", sinceFilterKey), nil)
|
||||||
}
|
}
|
||||||
if sinceStr != "" {
|
if sinceStr != "" {
|
||||||
opts = append(opts, googleapi.QueryParameter("_since", sinceStr))
|
opts = append(opts, googleapi.QueryParameter("_since", sinceStr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.FHIRPatientEverything(storeID, patientID, tokenStr, opts)
|
|
||||||
|
resp, err := source.FHIRPatientEverything(storeID, patientID, tokenStr, opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package fhirpatientsearch
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
@@ -24,6 +25,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
)
|
)
|
||||||
@@ -150,22 +152,22 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedFHIRStores())
|
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedFHIRStores())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewAgentError("failed to validate store ID", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,14 +181,14 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
var ok bool
|
var ok bool
|
||||||
summary, ok = v.(bool)
|
summary, ok = v.(bool)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid '%s' parameter; expected a boolean", summaryKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a boolean", summaryKey), nil)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
val, ok := v.(string)
|
val, ok := v.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid parameter '%s'; expected a string", k)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid parameter '%s'; expected a string", k), nil)
|
||||||
}
|
}
|
||||||
if val == "" {
|
if val == "" {
|
||||||
continue
|
continue
|
||||||
@@ -205,7 +207,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
}
|
}
|
||||||
parts := strings.Split(val, "/")
|
parts := strings.Split(val, "/")
|
||||||
if len(parts) != 2 {
|
if len(parts) != 2 {
|
||||||
return nil, fmt.Errorf("invalid '%s' format; expected YYYY-MM-DD/YYYY-MM-DD", k)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' format; expected YYYY-MM-DD/YYYY-MM-DD", k), nil)
|
||||||
}
|
}
|
||||||
var values []string
|
var values []string
|
||||||
if parts[0] != "" {
|
if parts[0] != "" {
|
||||||
@@ -229,13 +231,17 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
case familyNameKey:
|
case familyNameKey:
|
||||||
opts = append(opts, googleapi.QueryParameter("family", val))
|
opts = append(opts, googleapi.QueryParameter("family", val))
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unexpected parameter key %q", k)
|
return nil, util.NewAgentError(fmt.Sprintf("unexpected parameter key %q", k), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if summary {
|
if summary {
|
||||||
opts = append(opts, googleapi.QueryParameter("_summary", "text"))
|
opts = append(opts, googleapi.QueryParameter("_summary", "text"))
|
||||||
}
|
}
|
||||||
return source.FHIRPatientSearch(storeID, tokenStr, opts)
|
resp, err := source.FHIRPatientSearch(storeID, tokenStr, opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package gethealthcaredataset
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/healthcare/v1"
|
"google.golang.org/api/healthcare/v1"
|
||||||
)
|
)
|
||||||
@@ -90,19 +92,23 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.GetDataset(tokenStr)
|
resp, err := source.GetDataset(tokenStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package getdicomstore
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/healthcare/v1"
|
"google.golang.org/api/healthcare/v1"
|
||||||
)
|
)
|
||||||
@@ -107,23 +109,27 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
|
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewAgentError("failed to validate store ID", err)
|
||||||
}
|
}
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.GetDICOMStore(storeID, tokenStr)
|
resp, err := source.GetDICOMStore(storeID, tokenStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package getdicomstoremetrics
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/healthcare/v1"
|
"google.golang.org/api/healthcare/v1"
|
||||||
)
|
)
|
||||||
@@ -107,23 +109,27 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
|
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewAgentError("failed to validate store ID", err)
|
||||||
}
|
}
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.GetDICOMStoreMetrics(storeID, tokenStr)
|
resp, err := source.GetDICOMStoreMetrics(storeID, tokenStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package getfhirresource
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -112,32 +114,36 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedFHIRStores())
|
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedFHIRStores())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewAgentError("failed to validate store ID", err)
|
||||||
}
|
}
|
||||||
resType, ok := params.AsMap()[typeKey].(string)
|
resType, ok := params.AsMap()[typeKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", typeKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", typeKey), nil)
|
||||||
}
|
}
|
||||||
resID, ok := params.AsMap()[idKey].(string)
|
resID, ok := params.AsMap()[idKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", idKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", idKey), nil)
|
||||||
}
|
}
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.GetFHIRResource(storeID, resType, resID, tokenStr)
|
resp, err := source.GetFHIRResource(storeID, resType, resID, tokenStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package getfhirstore
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/healthcare/v1"
|
"google.golang.org/api/healthcare/v1"
|
||||||
)
|
)
|
||||||
@@ -107,23 +109,27 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedFHIRStores())
|
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedFHIRStores())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewAgentError("failed to validate store ID", err)
|
||||||
}
|
}
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.GetFHIRStore(storeID, tokenStr)
|
resp, err := source.GetFHIRStore(storeID, tokenStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package getfhirstoremetrics
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/healthcare/v1"
|
"google.golang.org/api/healthcare/v1"
|
||||||
)
|
)
|
||||||
@@ -107,23 +109,27 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedFHIRStores())
|
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedFHIRStores())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewAgentError("failed to validate store ID", err)
|
||||||
}
|
}
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.GetFHIRStoreMetrics(storeID, tokenStr)
|
resp, err := source.GetFHIRStoreMetrics(storeID, tokenStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package listdicomstores
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/healthcare/v1"
|
"google.golang.org/api/healthcare/v1"
|
||||||
)
|
)
|
||||||
@@ -90,19 +92,23 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.ListDICOMStores(tokenStr)
|
resp, err := source.ListDICOMStores(tokenStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package listfhirstores
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/healthcare/v1"
|
"google.golang.org/api/healthcare/v1"
|
||||||
)
|
)
|
||||||
@@ -90,19 +92,23 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.ListFHIRStores(tokenStr)
|
resp, err := source.ListFHIRStores(tokenStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package retrieverendereddicominstance
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -117,40 +119,44 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
|
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewAgentError("failed to validate store ID", err)
|
||||||
}
|
}
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
study, ok := params.AsMap()[studyInstanceUIDKey].(string)
|
study, ok := params.AsMap()[studyInstanceUIDKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid '%s' parameter; expected a string", studyInstanceUIDKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string", studyInstanceUIDKey), nil)
|
||||||
}
|
}
|
||||||
series, ok := params.AsMap()[seriesInstanceUIDKey].(string)
|
series, ok := params.AsMap()[seriesInstanceUIDKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid '%s' parameter; expected a string", seriesInstanceUIDKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string", seriesInstanceUIDKey), nil)
|
||||||
}
|
}
|
||||||
sop, ok := params.AsMap()[sopInstanceUIDKey].(string)
|
sop, ok := params.AsMap()[sopInstanceUIDKey].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid '%s' parameter; expected a string", sopInstanceUIDKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string", sopInstanceUIDKey), nil)
|
||||||
}
|
}
|
||||||
frame, ok := params.AsMap()[frameNumberKey].(int)
|
frame, ok := params.AsMap()[frameNumberKey].(int)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid '%s' parameter; expected an integer", frameNumberKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected an integer", frameNumberKey), nil)
|
||||||
}
|
}
|
||||||
return source.RetrieveRenderedDICOMInstance(storeID, study, series, sop, frame, tokenStr)
|
resp, err := source.RetrieveRenderedDICOMInstance(storeID, study, series, sop, frame, tokenStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package searchdicominstances
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
@@ -24,6 +25,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
)
|
)
|
||||||
@@ -131,33 +133,33 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
|
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewAgentError("failed to validate store ID", err)
|
||||||
}
|
}
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
opts, err := common.ParseDICOMSearchParameters(params, []string{sopInstanceUIDKey, patientNameKey, patientIDKey, accessionNumberKey, referringPhysicianNameKey, studyDateKey, modalityKey})
|
opts, err := common.ParseDICOMSearchParameters(params, []string{sopInstanceUIDKey, patientNameKey, patientIDKey, accessionNumberKey, referringPhysicianNameKey, studyDateKey, modalityKey})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewAgentError("failed to parse DICOM search parameters", err)
|
||||||
}
|
}
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
dicomWebPath := "instances"
|
dicomWebPath := "instances"
|
||||||
if studyInstanceUID, ok := paramsMap[studyInstanceUIDKey]; ok {
|
if studyInstanceUID, ok := paramsMap[studyInstanceUIDKey]; ok {
|
||||||
id, ok := studyInstanceUID.(string)
|
id, ok := studyInstanceUID.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid '%s' parameter; expected a string", studyInstanceUIDKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string", studyInstanceUIDKey), nil)
|
||||||
}
|
}
|
||||||
if id != "" {
|
if id != "" {
|
||||||
dicomWebPath = fmt.Sprintf("studies/%s/instances", id)
|
dicomWebPath = fmt.Sprintf("studies/%s/instances", id)
|
||||||
@@ -166,7 +168,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if seriesInstanceUID, ok := paramsMap[seriesInstanceUIDKey]; ok {
|
if seriesInstanceUID, ok := paramsMap[seriesInstanceUIDKey]; ok {
|
||||||
id, ok := seriesInstanceUID.(string)
|
id, ok := seriesInstanceUID.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid '%s' parameter; expected a string", seriesInstanceUIDKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string", seriesInstanceUIDKey), nil)
|
||||||
}
|
}
|
||||||
if id != "" {
|
if id != "" {
|
||||||
if dicomWebPath != "instances" {
|
if dicomWebPath != "instances" {
|
||||||
@@ -176,7 +178,11 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.SearchDICOM(t.Type, storeID, dicomWebPath, tokenStr, opts)
|
resp, err := source.SearchDICOM(t.Type, storeID, dicomWebPath, tokenStr, opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package searchdicomseries
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
)
|
)
|
||||||
@@ -128,40 +130,44 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
|
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewAgentError("failed to validate store ID", err)
|
||||||
}
|
}
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
opts, err := common.ParseDICOMSearchParameters(params, []string{seriesInstanceUIDKey, patientNameKey, patientIDKey, accessionNumberKey, referringPhysicianNameKey, studyDateKey, modalityKey})
|
opts, err := common.ParseDICOMSearchParameters(params, []string{seriesInstanceUIDKey, patientNameKey, patientIDKey, accessionNumberKey, referringPhysicianNameKey, studyDateKey, modalityKey})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewAgentError("failed to parse DICOM search parameters", err)
|
||||||
}
|
}
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
dicomWebPath := "series"
|
dicomWebPath := "series"
|
||||||
if studyInstanceUID, ok := paramsMap[studyInstanceUIDKey]; ok {
|
if studyInstanceUID, ok := paramsMap[studyInstanceUIDKey]; ok {
|
||||||
id, ok := studyInstanceUID.(string)
|
id, ok := studyInstanceUID.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid '%s' parameter; expected a string", studyInstanceUIDKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string", studyInstanceUIDKey), nil)
|
||||||
}
|
}
|
||||||
if id != "" {
|
if id != "" {
|
||||||
dicomWebPath = fmt.Sprintf("studies/%s/series", id)
|
dicomWebPath = fmt.Sprintf("studies/%s/series", id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.SearchDICOM(t.Type, storeID, dicomWebPath, tokenStr, opts)
|
resp, err := source.SearchDICOM(t.Type, storeID, dicomWebPath, tokenStr, opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package searchdicomstudies
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
)
|
)
|
||||||
@@ -124,28 +126,32 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
|
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewAgentError("failed to validate store ID", err)
|
||||||
}
|
}
|
||||||
var tokenStr string
|
var tokenStr string
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenStr, err = accessToken.ParseBearerToken()
|
tokenStr, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
opts, err := common.ParseDICOMSearchParameters(params, []string{studyInstanceUIDKey, patientNameKey, patientIDKey, accessionNumberKey, referringPhysicianNameKey, studyDateKey})
|
opts, err := common.ParseDICOMSearchParameters(params, []string{studyInstanceUIDKey, patientNameKey, patientIDKey, accessionNumberKey, referringPhysicianNameKey, studyDateKey})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewAgentError("failed to parse DICOM search parameters", err)
|
||||||
}
|
}
|
||||||
dicomWebPath := "studies"
|
dicomWebPath := "studies"
|
||||||
return source.SearchDICOM(t.Type, storeID, dicomWebPath, tokenStr, opts)
|
resp, err := source.SearchDICOM(t.Type, storeID, dicomWebPath, tokenStr, opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -16,11 +16,13 @@ package cloudloggingadminlistlognames
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -89,10 +91,10 @@ type Tool struct {
|
|||||||
Parameters parameters.Parameters `yaml:"parameters"`
|
Parameters parameters.Parameters `yaml:"parameters"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
limit := defaultLimit
|
limit := defaultLimit
|
||||||
@@ -100,18 +102,22 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if val, ok := paramsMap["limit"].(int); ok && val > 0 {
|
if val, ok := paramsMap["limit"].(int); ok && val > 0 {
|
||||||
limit = val
|
limit = val
|
||||||
} else if ok && val < 0 {
|
} else if ok && val < 0 {
|
||||||
return nil, fmt.Errorf("limit must be greater than or equal to 1")
|
return nil, util.NewAgentError("limit must be greater than or equal to 1", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenString := ""
|
tokenString := ""
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenString, err = accessToken.ParseBearerToken()
|
tokenString, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse access token: %w", err)
|
return nil, util.NewClientServerError("failed to parse access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return source.ListLogNames(ctx, limit, tokenString)
|
resp, err := source.ListLogNames(ctx, limit, tokenString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) ParseParams(data map[string]any, claimsMap map[string]map[string]any) (parameters.ParamValues, error) {
|
func (t Tool) ParseParams(data map[string]any, claimsMap map[string]map[string]any) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -16,11 +16,13 @@ package cloudloggingadminlistresourcetypes
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -84,21 +86,25 @@ type Tool struct {
|
|||||||
mcpManifest tools.McpManifest
|
mcpManifest tools.McpManifest
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenString := ""
|
tokenString := ""
|
||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenString, err = accessToken.ParseBearerToken()
|
tokenString, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse access token: %w", err)
|
return nil, util.NewClientServerError("failed to parse access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return source.ListResourceTypes(ctx, tokenString)
|
resp, err := source.ListResourceTypes(ctx, tokenString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) ParseParams(data map[string]any, claimsMap map[string]map[string]any) (parameters.ParamValues, error) {
|
func (t Tool) ParseParams(data map[string]any, claimsMap map[string]map[string]any) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ package cloudloggingadminquerylogs
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
@@ -23,6 +24,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
cla "github.com/googleapis/genai-toolbox/internal/sources/cloudloggingadmin"
|
cla "github.com/googleapis/genai-toolbox/internal/sources/cloudloggingadmin"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -104,10 +106,10 @@ type Tool struct {
|
|||||||
mcpManifest tools.McpManifest
|
mcpManifest tools.McpManifest
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse parameters
|
// Parse parameters
|
||||||
@@ -119,7 +121,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if val, ok := paramsMap["limit"].(int); ok && val > 0 {
|
if val, ok := paramsMap["limit"].(int); ok && val > 0 {
|
||||||
limit = val
|
limit = val
|
||||||
} else if ok && val < 0 {
|
} else if ok && val < 0 {
|
||||||
return nil, fmt.Errorf("limit must be greater than or equal to 1")
|
return nil, util.NewAgentError("limit must be greater than or equal to 1", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for verbosity of output
|
// Check for verbosity of output
|
||||||
@@ -129,7 +131,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
var filter string
|
var filter string
|
||||||
if f, ok := paramsMap["filter"].(string); ok {
|
if f, ok := paramsMap["filter"].(string); ok {
|
||||||
if len(f) == 0 {
|
if len(f) == 0 {
|
||||||
return nil, fmt.Errorf("filter cannot be empty if provided")
|
return nil, util.NewAgentError("filter cannot be empty if provided", nil)
|
||||||
}
|
}
|
||||||
filter = f
|
filter = f
|
||||||
}
|
}
|
||||||
@@ -138,7 +140,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
var startTime string
|
var startTime string
|
||||||
if val, ok := paramsMap["startTime"].(string); ok && val != "" {
|
if val, ok := paramsMap["startTime"].(string); ok && val != "" {
|
||||||
if _, err := time.Parse(time.RFC3339, val); err != nil {
|
if _, err := time.Parse(time.RFC3339, val); err != nil {
|
||||||
return nil, fmt.Errorf("startTime must be in RFC3339 format (e.g., 2025-12-09T00:00:00Z): %w", err)
|
return nil, util.NewAgentError(fmt.Sprintf("startTime must be in RFC3339 format (e.g., 2025-12-09T00:00:00Z): %v", err), err)
|
||||||
}
|
}
|
||||||
startTime = val
|
startTime = val
|
||||||
} else {
|
} else {
|
||||||
@@ -149,7 +151,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
var endTime string
|
var endTime string
|
||||||
if val, ok := paramsMap["endTime"].(string); ok && val != "" {
|
if val, ok := paramsMap["endTime"].(string); ok && val != "" {
|
||||||
if _, err := time.Parse(time.RFC3339, val); err != nil {
|
if _, err := time.Parse(time.RFC3339, val); err != nil {
|
||||||
return nil, fmt.Errorf("endTime must be in RFC3339 format (e.g., 2025-12-09T23:59:59Z): %w", err)
|
return nil, util.NewAgentError(fmt.Sprintf("endTime must be in RFC3339 format (e.g., 2025-12-09T23:59:59Z): %v", err), err)
|
||||||
}
|
}
|
||||||
endTime = val
|
endTime = val
|
||||||
}
|
}
|
||||||
@@ -158,7 +160,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if source.UseClientAuthorization() {
|
if source.UseClientAuthorization() {
|
||||||
tokenString, err = accessToken.ParseBearerToken()
|
tokenString, err = accessToken.ParseBearerToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to parse access token: %w", err)
|
return nil, util.NewClientServerError("failed to parse access token", http.StatusUnauthorized, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +173,11 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
Limit: limit,
|
Limit: limit,
|
||||||
}
|
}
|
||||||
|
|
||||||
return source.QueryLogs(ctx, queryParams, tokenString)
|
resp, err := source.QueryLogs(ctx, queryParams, tokenString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) ParseParams(data map[string]any, claimsMap map[string]map[string]any) (parameters.ParamValues, error) {
|
func (t Tool) ParseParams(data map[string]any, claimsMap map[string]map[string]any) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -93,22 +94,26 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
projectID, ok := paramsMap["projectId"].(string)
|
projectID, ok := paramsMap["projectId"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("projectId parameter not found or not a string")
|
return nil, util.NewAgentError("projectId parameter not found or not a string", nil)
|
||||||
}
|
}
|
||||||
query, ok := paramsMap["query"].(string)
|
query, ok := paramsMap["query"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("query parameter not found or not a string")
|
return nil, util.NewAgentError("query parameter not found or not a string", nil)
|
||||||
}
|
}
|
||||||
return source.RunQuery(projectID, query)
|
resp, err := source.RunQuery(projectID, query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package cloudsqlcloneinstance
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
sqladmin "google.golang.org/api/sqladmin/v1"
|
sqladmin "google.golang.org/api/sqladmin/v1"
|
||||||
)
|
)
|
||||||
@@ -124,31 +126,35 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error casting 'project' parameter: %v", paramsMap["project"])
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'project' parameter: %v", paramsMap["project"]), nil)
|
||||||
}
|
}
|
||||||
sourceInstanceName, ok := paramsMap["sourceInstanceName"].(string)
|
sourceInstanceName, ok := paramsMap["sourceInstanceName"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error casting 'sourceInstanceName' parameter: %v", paramsMap["sourceInstanceName"])
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'sourceInstanceName' parameter: %v", paramsMap["sourceInstanceName"]), nil)
|
||||||
}
|
}
|
||||||
destinationInstanceName, ok := paramsMap["destinationInstanceName"].(string)
|
destinationInstanceName, ok := paramsMap["destinationInstanceName"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error casting 'destinationInstanceName' parameter: %v", paramsMap["destinationInstanceName"])
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'destinationInstanceName' parameter: %v", paramsMap["destinationInstanceName"]), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
pointInTime, _ := paramsMap["pointInTime"].(string)
|
pointInTime, _ := paramsMap["pointInTime"].(string)
|
||||||
preferredZone, _ := paramsMap["preferredZone"].(string)
|
preferredZone, _ := paramsMap["preferredZone"].(string)
|
||||||
preferredSecondaryZone, _ := paramsMap["preferredSecondaryZone"].(string)
|
preferredSecondaryZone, _ := paramsMap["preferredSecondaryZone"].(string)
|
||||||
|
|
||||||
return source.CloneInstance(ctx, project, sourceInstanceName, destinationInstanceName, pointInTime, preferredZone, preferredSecondaryZone, string(accessToken))
|
resp, err := source.CloneInstance(ctx, project, sourceInstanceName, destinationInstanceName, pointInTime, preferredZone, preferredSecondaryZone, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package cloudsqlcreatebackup
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/sqladmin/v1"
|
"google.golang.org/api/sqladmin/v1"
|
||||||
)
|
)
|
||||||
@@ -120,26 +122,30 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error casting 'project' parameter: %v", paramsMap["project"])
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'project' parameter: %v", paramsMap["project"]), nil)
|
||||||
}
|
}
|
||||||
instance, ok := paramsMap["instance"].(string)
|
instance, ok := paramsMap["instance"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error casting 'instance' parameter: %v", paramsMap["instance"])
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'instance' parameter: %v", paramsMap["instance"]), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
location, _ := paramsMap["location"].(string)
|
location, _ := paramsMap["location"].(string)
|
||||||
description, _ := paramsMap["backup_description"].(string)
|
description, _ := paramsMap["backup_description"].(string)
|
||||||
|
|
||||||
return source.InsertBackupRun(ctx, project, instance, location, description, string(accessToken))
|
resp, err := source.InsertBackupRun(ctx, project, instance, location, description, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package cloudsqlcreatedatabase
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -117,27 +119,31 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'project' parameter")
|
return nil, util.NewAgentError("missing 'project' parameter", nil)
|
||||||
}
|
}
|
||||||
instance, ok := paramsMap["instance"].(string)
|
instance, ok := paramsMap["instance"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'instance' parameter")
|
return nil, util.NewAgentError("missing 'instance' parameter", nil)
|
||||||
}
|
}
|
||||||
name, ok := paramsMap["name"].(string)
|
name, ok := paramsMap["name"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'name' parameter")
|
return nil, util.NewAgentError("missing 'name' parameter", nil)
|
||||||
}
|
}
|
||||||
return source.CreateDatabase(ctx, name, project, instance, string(accessToken))
|
resp, err := source.CreateDatabase(ctx, name, project, instance, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package cloudsqlcreateusers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -119,30 +121,34 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'project' parameter")
|
return nil, util.NewAgentError("missing 'project' parameter", nil)
|
||||||
}
|
}
|
||||||
instance, ok := paramsMap["instance"].(string)
|
instance, ok := paramsMap["instance"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'instance' parameter")
|
return nil, util.NewAgentError("missing 'instance' parameter", nil)
|
||||||
}
|
}
|
||||||
name, ok := paramsMap["name"].(string)
|
name, ok := paramsMap["name"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'name' parameter")
|
return nil, util.NewAgentError("missing 'name' parameter", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
iamUser, _ := paramsMap["iamUser"].(bool)
|
iamUser, _ := paramsMap["iamUser"].(bool)
|
||||||
password, _ := paramsMap["password"].(string)
|
password, _ := paramsMap["password"].(string)
|
||||||
return source.CreateUsers(ctx, project, instance, name, password, iamUser, string(accessToken))
|
resp, err := source.CreateUsers(ctx, project, instance, name, password, iamUser, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package cloudsqlgetinstances
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -117,23 +119,27 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
projectId, ok := paramsMap["projectId"].(string)
|
projectId, ok := paramsMap["projectId"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'projectId' parameter")
|
return nil, util.NewAgentError("missing 'projectId' parameter", nil)
|
||||||
}
|
}
|
||||||
instanceId, ok := paramsMap["instanceId"].(string)
|
instanceId, ok := paramsMap["instanceId"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'instanceId' parameter")
|
return nil, util.NewAgentError("missing 'instanceId' parameter", nil)
|
||||||
}
|
}
|
||||||
return source.GetInstance(ctx, projectId, instanceId, string(accessToken))
|
resp, err := source.GetInstance(ctx, projectId, instanceId, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package cloudsqllistdatabases
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -116,23 +118,27 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'project' parameter")
|
return nil, util.NewAgentError("missing 'project' parameter", nil)
|
||||||
}
|
}
|
||||||
instance, ok := paramsMap["instance"].(string)
|
instance, ok := paramsMap["instance"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'instance' parameter")
|
return nil, util.NewAgentError("missing 'instance' parameter", nil)
|
||||||
}
|
}
|
||||||
return source.ListDatabase(ctx, project, instance, string(accessToken))
|
resp, err := source.ListDatabase(ctx, project, instance, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package cloudsqllistinstances
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -115,19 +117,23 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'project' parameter")
|
return nil, util.NewAgentError("missing 'project' parameter", nil)
|
||||||
}
|
}
|
||||||
return source.ListInstance(ctx, project, string(accessToken))
|
resp, err := source.ListInstance(ctx, project, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package cloudsqlrestorebackup
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/sqladmin/v1"
|
"google.golang.org/api/sqladmin/v1"
|
||||||
)
|
)
|
||||||
@@ -120,29 +122,33 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
targetProject, ok := paramsMap["target_project"].(string)
|
targetProject, ok := paramsMap["target_project"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error casting 'target_project' parameter: %v", paramsMap["target_project"])
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'target_project' parameter: %v", paramsMap["target_project"]), nil)
|
||||||
}
|
}
|
||||||
targetInstance, ok := paramsMap["target_instance"].(string)
|
targetInstance, ok := paramsMap["target_instance"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error casting 'target_instance' parameter: %v", paramsMap["target_instance"])
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'target_instance' parameter: %v", paramsMap["target_instance"]), nil)
|
||||||
}
|
}
|
||||||
backupID, ok := paramsMap["backup_id"].(string)
|
backupID, ok := paramsMap["backup_id"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error casting 'backup_id' parameter: %v", paramsMap["backup_id"])
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'backup_id' parameter: %v", paramsMap["backup_id"]), nil)
|
||||||
}
|
}
|
||||||
sourceProject, _ := paramsMap["source_project"].(string)
|
sourceProject, _ := paramsMap["source_project"].(string)
|
||||||
sourceInstance, _ := paramsMap["source_instance"].(string)
|
sourceInstance, _ := paramsMap["source_instance"].(string)
|
||||||
|
|
||||||
return source.RestoreBackup(ctx, targetProject, targetInstance, sourceProject, sourceInstance, backupID, string(accessToken))
|
resp, err := source.RestoreBackup(ctx, targetProject, targetInstance, sourceProject, sourceInstance, backupID, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package cloudsqlwaitforoperation
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/sqladmin/v1"
|
"google.golang.org/api/sqladmin/v1"
|
||||||
)
|
)
|
||||||
@@ -210,21 +212,21 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'project' parameter")
|
return nil, util.NewAgentError("missing 'project' parameter", nil)
|
||||||
}
|
}
|
||||||
operationID, ok := paramsMap["operation"].(string)
|
operationID, ok := paramsMap["operation"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'operation' parameter")
|
return nil, util.NewAgentError("missing 'operation' parameter", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(ctx, 30*time.Minute)
|
ctx, cancel := context.WithTimeout(ctx, 30*time.Minute)
|
||||||
@@ -232,7 +234,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
|
|
||||||
service, err := source.GetService(ctx, string(accessToken))
|
service, err := source.GetService(ctx, string(accessToken))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
delay := t.Delay
|
delay := t.Delay
|
||||||
@@ -244,13 +246,13 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
for retries < maxRetries {
|
for retries < maxRetries {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return nil, fmt.Errorf("timed out waiting for operation: %w", ctx.Err())
|
return nil, util.NewClientServerError("timed out waiting for operation", http.StatusRequestTimeout, ctx.Err())
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
op, err := source.GetWaitForOperations(ctx, service, project, operationID, cloudSQLConnectionMessageTemplate, delay)
|
op, err := source.GetWaitForOperations(ctx, service, project, operationID, cloudSQLConnectionMessageTemplate, delay)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.ProcessGcpError(err)
|
||||||
} else if op != nil {
|
} else if op != nil {
|
||||||
return op, nil
|
return op, nil
|
||||||
}
|
}
|
||||||
@@ -262,7 +264,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
}
|
}
|
||||||
retries++
|
retries++
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("exceeded max retries waiting for operation")
|
return nil, util.NewClientServerError("exceeded max retries waiting for operation", http.StatusGatewayTimeout, fmt.Errorf("exceeded max retries"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package cloudsqlmssqlcreateinstance
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/sqladmin/v1"
|
"google.golang.org/api/sqladmin/v1"
|
||||||
)
|
)
|
||||||
@@ -121,33 +123,33 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error casting 'project' parameter: %s", paramsMap["project"])
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'project' parameter: %s", paramsMap["project"]), nil)
|
||||||
}
|
}
|
||||||
name, ok := paramsMap["name"].(string)
|
name, ok := paramsMap["name"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error casting 'name' parameter: %s", paramsMap["name"])
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'name' parameter: %s", paramsMap["name"]), nil)
|
||||||
}
|
}
|
||||||
dbVersion, ok := paramsMap["databaseVersion"].(string)
|
dbVersion, ok := paramsMap["databaseVersion"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error casting 'databaseVersion' parameter: %s", paramsMap["databaseVersion"])
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'databaseVersion' parameter: %s", paramsMap["databaseVersion"]), nil)
|
||||||
}
|
}
|
||||||
rootPassword, ok := paramsMap["rootPassword"].(string)
|
rootPassword, ok := paramsMap["rootPassword"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error casting 'rootPassword' parameter: %s", paramsMap["rootPassword"])
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'rootPassword' parameter: %s", paramsMap["rootPassword"]), nil)
|
||||||
}
|
}
|
||||||
editionPreset, ok := paramsMap["editionPreset"].(string)
|
editionPreset, ok := paramsMap["editionPreset"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error casting 'editionPreset' parameter: %s", paramsMap["editionPreset"])
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'editionPreset' parameter: %s", paramsMap["editionPreset"]), nil)
|
||||||
}
|
}
|
||||||
settings := sqladmin.Settings{}
|
settings := sqladmin.Settings{}
|
||||||
switch strings.ToLower(editionPreset) {
|
switch strings.ToLower(editionPreset) {
|
||||||
@@ -164,9 +166,13 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
settings.DataDiskSizeGb = 100
|
settings.DataDiskSizeGb = 100
|
||||||
settings.DataDiskType = "PD_SSD"
|
settings.DataDiskType = "PD_SSD"
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("invalid 'editionPreset': %q. Must be either 'Production' or 'Development'", editionPreset)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid 'editionPreset': %q. Must be either 'Production' or 'Development'", editionPreset), nil)
|
||||||
}
|
}
|
||||||
return source.CreateInstance(ctx, project, name, dbVersion, rootPassword, settings, string(accessToken))
|
resp, err := source.CreateInstance(ctx, project, name, dbVersion, rootPassword, settings, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package cloudsqlmysqlcreateinstance
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
sqladmin "google.golang.org/api/sqladmin/v1"
|
sqladmin "google.golang.org/api/sqladmin/v1"
|
||||||
)
|
)
|
||||||
@@ -121,33 +123,33 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'project' parameter")
|
return nil, util.NewAgentError("missing 'project' parameter", nil)
|
||||||
}
|
}
|
||||||
name, ok := paramsMap["name"].(string)
|
name, ok := paramsMap["name"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'name' parameter")
|
return nil, util.NewAgentError("missing 'name' parameter", nil)
|
||||||
}
|
}
|
||||||
dbVersion, ok := paramsMap["databaseVersion"].(string)
|
dbVersion, ok := paramsMap["databaseVersion"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'databaseVersion' parameter")
|
return nil, util.NewAgentError("missing 'databaseVersion' parameter", nil)
|
||||||
}
|
}
|
||||||
rootPassword, ok := paramsMap["rootPassword"].(string)
|
rootPassword, ok := paramsMap["rootPassword"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'rootPassword' parameter")
|
return nil, util.NewAgentError("missing 'rootPassword' parameter", nil)
|
||||||
}
|
}
|
||||||
editionPreset, ok := paramsMap["editionPreset"].(string)
|
editionPreset, ok := paramsMap["editionPreset"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'editionPreset' parameter")
|
return nil, util.NewAgentError("missing 'editionPreset' parameter", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
settings := sqladmin.Settings{}
|
settings := sqladmin.Settings{}
|
||||||
@@ -165,10 +167,14 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
settings.DataDiskSizeGb = 100
|
settings.DataDiskSizeGb = 100
|
||||||
settings.DataDiskType = "PD_SSD"
|
settings.DataDiskType = "PD_SSD"
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("invalid 'editionPreset': %q. Must be either 'Production' or 'Development'", editionPreset)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid 'editionPreset': %q. Must be either 'Production' or 'Development'", editionPreset), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return source.CreateInstance(ctx, project, name, dbVersion, rootPassword, settings, string(accessToken))
|
resp, err := source.CreateInstance(ctx, project, name, dbVersion, rootPassword, settings, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package cloudsqlpgcreateinstances
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
sqladmin "google.golang.org/api/sqladmin/v1"
|
sqladmin "google.golang.org/api/sqladmin/v1"
|
||||||
)
|
)
|
||||||
@@ -121,33 +123,33 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'project' parameter")
|
return nil, util.NewAgentError("missing 'project' parameter", nil)
|
||||||
}
|
}
|
||||||
name, ok := paramsMap["name"].(string)
|
name, ok := paramsMap["name"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'name' parameter")
|
return nil, util.NewAgentError("missing 'name' parameter", nil)
|
||||||
}
|
}
|
||||||
dbVersion, ok := paramsMap["databaseVersion"].(string)
|
dbVersion, ok := paramsMap["databaseVersion"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'databaseVersion' parameter")
|
return nil, util.NewAgentError("missing 'databaseVersion' parameter", nil)
|
||||||
}
|
}
|
||||||
rootPassword, ok := paramsMap["rootPassword"].(string)
|
rootPassword, ok := paramsMap["rootPassword"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'rootPassword' parameter")
|
return nil, util.NewAgentError("missing 'rootPassword' parameter", nil)
|
||||||
}
|
}
|
||||||
editionPreset, ok := paramsMap["editionPreset"].(string)
|
editionPreset, ok := paramsMap["editionPreset"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("missing 'editionPreset' parameter")
|
return nil, util.NewAgentError("missing 'editionPreset' parameter", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
settings := sqladmin.Settings{}
|
settings := sqladmin.Settings{}
|
||||||
@@ -165,9 +167,13 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
settings.DataDiskSizeGb = 100
|
settings.DataDiskSizeGb = 100
|
||||||
settings.DataDiskType = "PD_SSD"
|
settings.DataDiskType = "PD_SSD"
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("invalid 'editionPreset': %q. Must be either 'Production' or 'Development'", editionPreset)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid 'editionPreset': %q. Must be either 'Production' or 'Development'", editionPreset), nil)
|
||||||
}
|
}
|
||||||
return source.CreateInstance(ctx, project, name, dbVersion, rootPassword, settings, string(accessToken))
|
resp, err := source.CreateInstance(ctx, project, name, dbVersion, rootPassword, settings, string(accessToken))
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package cloudsqlpgupgradeprecheck
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
sqladmin "google.golang.org/api/sqladmin/v1"
|
sqladmin "google.golang.org/api/sqladmin/v1"
|
||||||
)
|
)
|
||||||
@@ -132,31 +134,31 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke executes the tool's logic.
|
// Invoke executes the tool's logic.
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
project, ok := paramsMap["project"].(string)
|
project, ok := paramsMap["project"].(string)
|
||||||
if !ok || project == "" {
|
if !ok || project == "" {
|
||||||
return nil, fmt.Errorf("missing or empty 'project' parameter")
|
return nil, util.NewAgentError("missing or empty 'project' parameter", nil)
|
||||||
}
|
}
|
||||||
instanceName, ok := paramsMap["instance"].(string)
|
instanceName, ok := paramsMap["instance"].(string)
|
||||||
if !ok || instanceName == "" {
|
if !ok || instanceName == "" {
|
||||||
return nil, fmt.Errorf("missing or empty 'instance' parameter")
|
return nil, util.NewAgentError("missing or empty 'instance' parameter", nil)
|
||||||
}
|
}
|
||||||
targetVersion, ok := paramsMap["targetDatabaseVersion"].(string)
|
targetVersion, ok := paramsMap["targetDatabaseVersion"].(string)
|
||||||
if !ok || targetVersion == "" {
|
if !ok || targetVersion == "" {
|
||||||
// This should not happen due to the default value
|
// This should not happen due to the default value
|
||||||
return nil, fmt.Errorf("missing or empty 'targetDatabaseVersion' parameter")
|
return nil, util.NewAgentError("missing or empty 'targetDatabaseVersion' parameter", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
service, err := source.GetService(ctx, string(accessToken))
|
service, err := source.GetService(ctx, string(accessToken))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get HTTP client from source: %w", err)
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
reqBody := &sqladmin.InstancesPreCheckMajorVersionUpgradeRequest{
|
reqBody := &sqladmin.InstancesPreCheckMajorVersionUpgradeRequest{
|
||||||
@@ -168,7 +170,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
call := service.Instances.PreCheckMajorVersionUpgrade(project, instanceName, reqBody).Context(ctx)
|
call := service.Instances.PreCheckMajorVersionUpgrade(project, instanceName, reqBody).Context(ctx)
|
||||||
op, err := call.Do()
|
op, err := call.Do()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to start pre-check operation: %w", err)
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
const pollTimeout = 20 * time.Second
|
const pollTimeout = 20 * time.Second
|
||||||
@@ -177,7 +179,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
for time.Now().Before(cutoffTime) {
|
for time.Now().Before(cutoffTime) {
|
||||||
currentOp, err := service.Operations.Get(project, op.Name).Context(ctx).Do()
|
currentOp, err := service.Operations.Get(project, op.Name).Context(ctx).Do()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get operation status: %w", err)
|
return nil, util.ProcessGcpError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if currentOp.Status == "DONE" {
|
if currentOp.Status == "DONE" {
|
||||||
@@ -186,7 +188,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if currentOp.Error.Errors[0].Code != "" {
|
if currentOp.Error.Errors[0].Code != "" {
|
||||||
errMsg = fmt.Sprintf("%s (Code: %s)", errMsg, currentOp.Error.Errors[0].Code)
|
errMsg = fmt.Sprintf("%s (Code: %s)", errMsg, currentOp.Error.Errors[0].Code)
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("%s", errMsg)
|
return nil, util.NewClientServerError(errMsg, http.StatusInternalServerError, fmt.Errorf("pre-check operation failed with error: %s", errMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
var preCheckItems []*sqladmin.PreCheckResponse
|
var preCheckItems []*sqladmin.PreCheckResponse
|
||||||
@@ -199,7 +201,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return nil, ctx.Err()
|
return nil, util.NewClientServerError("timed out waiting for operation", http.StatusRequestTimeout, ctx.Err())
|
||||||
case <-time.After(5 * time.Second):
|
case <-time.After(5 * time.Second):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package couchbase
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/couchbase/gocb/v2"
|
"github.com/couchbase/gocb/v2"
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -58,7 +60,6 @@ type Config struct {
|
|||||||
TemplateParameters parameters.Parameters `yaml:"templateParameters"`
|
TemplateParameters parameters.Parameters `yaml:"templateParameters"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate interface
|
|
||||||
var _ tools.ToolConfig = Config{}
|
var _ tools.ToolConfig = Config{}
|
||||||
|
|
||||||
func (cfg Config) ToolConfigType() string {
|
func (cfg Config) ToolConfigType() string {
|
||||||
@@ -72,7 +73,6 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mcpManifest := tools.GetMcpManifest(cfg.Name, cfg.Description, cfg.AuthRequired, allParameters, nil)
|
mcpManifest := tools.GetMcpManifest(cfg.Name, cfg.Description, cfg.AuthRequired, allParameters, nil)
|
||||||
// finish tool setup
|
|
||||||
t := Tool{
|
t := Tool{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
AllParams: allParameters,
|
AllParams: allParameters,
|
||||||
@@ -82,7 +82,6 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error)
|
|||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate interface
|
|
||||||
var _ tools.Tool = Tool{}
|
var _ tools.Tool = Tool{}
|
||||||
|
|
||||||
type Tool struct {
|
type Tool struct {
|
||||||
@@ -96,23 +95,28 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
namedParamsMap := params.AsMap()
|
namedParamsMap := params.AsMap()
|
||||||
newStatement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, namedParamsMap)
|
newStatement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, namedParamsMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to extract template params %w", err)
|
return nil, util.NewAgentError("unable to extract template params", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
newParams, err := parameters.GetParams(t.Parameters, namedParamsMap)
|
newParams, err := parameters.GetParams(t.Parameters, namedParamsMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to extract standard params %w", err)
|
return nil, util.NewAgentError("unable to extract standard params", err)
|
||||||
}
|
}
|
||||||
return source.RunSQL(newStatement, newParams)
|
|
||||||
|
resp, err := source.RunSQL(newStatement, newParams)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGeneralError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import (
|
|||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -86,18 +87,19 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
|
|
||||||
projectDir, ok := paramsMap["project_dir"].(string)
|
projectDir, ok := paramsMap["project_dir"].(string)
|
||||||
if !ok || projectDir == "" {
|
if !ok || projectDir == "" {
|
||||||
return nil, fmt.Errorf("error casting 'project_dir' to string or invalid value")
|
return nil, util.NewAgentError("error casting 'project_dir' to string or invalid value", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.CommandContext(ctx, "dataform", "compile", projectDir, "--json")
|
cmd := exec.CommandContext(ctx, "dataform", "compile", projectDir, "--json")
|
||||||
output, err := cmd.CombinedOutput()
|
output, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error executing dataform compile: %w\nOutput: %s", err, string(output))
|
// Compilation failures are considered AgentErrors (invalid user code/project)
|
||||||
|
return nil, util.NewAgentError(fmt.Sprintf("error executing dataform compile: %v\nOutput: %s", err, string(output)), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.TrimSpace(string(output)), nil
|
return strings.TrimSpace(string(output)), nil
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package dataplexlookupentry
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
dataplexpb "cloud.google.com/go/dataplex/apiv1/dataplexpb"
|
dataplexpb "cloud.google.com/go/dataplex/apiv1/dataplexpb"
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -110,10 +112,10 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
@@ -122,10 +124,14 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
view, _ := paramsMap["view"].(int)
|
view, _ := paramsMap["view"].(int)
|
||||||
aspectTypeSlice, err := parameters.ConvertAnySliceToTyped(paramsMap["aspectTypes"].([]any), "string")
|
aspectTypeSlice, err := parameters.ConvertAnySliceToTyped(paramsMap["aspectTypes"].([]any), "string")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't convert aspectTypes to array of strings: %s", err)
|
return nil, util.NewAgentError(fmt.Sprintf("can't convert aspectTypes to array of strings: %s", err), err)
|
||||||
}
|
}
|
||||||
aspectTypes := aspectTypeSlice.([]string)
|
aspectTypes := aspectTypeSlice.([]string)
|
||||||
return source.LookupEntry(ctx, name, view, aspectTypes, entry)
|
resp, err := source.LookupEntry(ctx, name, view, aspectTypes, entry)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package dataplexsearchaspecttypes
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"cloud.google.com/go/dataplex/apiv1/dataplexpb"
|
"cloud.google.com/go/dataplex/apiv1/dataplexpb"
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -93,16 +95,29 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
query, _ := paramsMap["query"].(string)
|
query, ok := paramsMap["query"].(string)
|
||||||
pageSize, _ := paramsMap["pageSize"].(int)
|
if !ok {
|
||||||
orderBy, _ := paramsMap["orderBy"].(string)
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'query' parameter: %v", paramsMap["query"]), nil)
|
||||||
return source.SearchAspectTypes(ctx, query, pageSize, orderBy)
|
}
|
||||||
|
pageSize, ok := paramsMap["pageSize"].(int)
|
||||||
|
if !ok {
|
||||||
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'pageSize' parameter: %v", paramsMap["pageSize"]), nil)
|
||||||
|
}
|
||||||
|
orderBy, ok := paramsMap["orderBy"].(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'orderBy' parameter: %v", paramsMap["orderBy"]), nil)
|
||||||
|
}
|
||||||
|
resp, err := source.SearchAspectTypes(ctx, query, pageSize, orderBy)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package dataplexsearchentries
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"cloud.google.com/go/dataplex/apiv1/dataplexpb"
|
"cloud.google.com/go/dataplex/apiv1/dataplexpb"
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -93,16 +95,29 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
query, _ := paramsMap["query"].(string)
|
query, ok := paramsMap["query"].(string)
|
||||||
pageSize, _ := paramsMap["pageSize"].(int)
|
if !ok {
|
||||||
orderBy, _ := paramsMap["orderBy"].(string)
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'query' parameter: %v", paramsMap["query"]), nil)
|
||||||
return source.SearchEntries(ctx, query, pageSize, orderBy)
|
}
|
||||||
|
pageSize, ok := paramsMap["pageSize"].(int)
|
||||||
|
if !ok {
|
||||||
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'pageSize' parameter: %v", paramsMap["pageSize"]), nil)
|
||||||
|
}
|
||||||
|
orderBy, ok := paramsMap["orderBy"].(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, util.NewAgentError(fmt.Sprintf("error casting 'orderBy' parameter: %v", paramsMap["orderBy"]), nil)
|
||||||
|
}
|
||||||
|
resp, err := source.SearchEntries(ctx, query, pageSize, orderBy)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ package dgraph
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources/dgraph"
|
"github.com/googleapis/genai-toolbox/internal/sources/dgraph"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -91,12 +93,16 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
return source.RunSQL(t.Statement, params, t.IsQuery, t.Timeout)
|
resp, err := source.RunSQL(t.Statement, params, t.IsQuery, t.Timeout)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGeneralError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,9 +17,11 @@ package elasticsearchesql
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
@@ -89,10 +91,10 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
@@ -119,11 +121,15 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
|
|
||||||
for _, param := range t.Parameters {
|
for _, param := range t.Parameters {
|
||||||
if param.GetType() == "array" {
|
if param.GetType() == "array" {
|
||||||
return nil, fmt.Errorf("array parameters are not supported yet")
|
return nil, util.NewAgentError("array parameters are not supported yet", nil)
|
||||||
}
|
}
|
||||||
sqlParams = append(sqlParams, map[string]any{param.GetName(): paramMap[param.GetName()]})
|
sqlParams = append(sqlParams, map[string]any{param.GetName(): paramMap[param.GetName()]})
|
||||||
}
|
}
|
||||||
return source.RunSQL(ctx, t.Format, query, sqlParams)
|
resp, err := source.RunSQL(ctx, t.Format, query, sqlParams)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGeneralError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
@@ -90,25 +91,30 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
sql, ok := paramsMap["sql"].(string)
|
sqlStr, ok := paramsMap["sql"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unable to get cast %s", paramsMap["sql"])
|
return nil, util.NewAgentError(fmt.Sprintf("unable to cast parameter 'sql' to string: %v", paramsMap["sql"]), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log the query executed for debugging.
|
// Log the query executed for debugging.
|
||||||
logger, err := util.LoggerFromContext(ctx)
|
logger, err := util.LoggerFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error getting logger: %s", err)
|
return nil, util.NewClientServerError("error getting logger", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql))
|
logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sqlStr))
|
||||||
return source.RunSQL(ctx, sql, nil)
|
|
||||||
|
resp, err := source.RunSQL(ctx, sqlStr, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGeneralError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -18,12 +18,14 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -98,21 +100,21 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
paramsMap := params.AsMap()
|
paramsMap := params.AsMap()
|
||||||
statement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, paramsMap)
|
statement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, paramsMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to extract template params: %w", err)
|
return nil, util.NewAgentError("unable to extract template params", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
newParams, err := parameters.GetParams(t.Parameters, paramsMap)
|
newParams, err := parameters.GetParams(t.Parameters, paramsMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to extract standard params: %w", err)
|
return nil, util.NewAgentError("unable to extract standard params", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
namedArgs := make([]any, 0, len(newParams))
|
namedArgs := make([]any, 0, len(newParams))
|
||||||
@@ -127,7 +129,12 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
namedArgs = append(namedArgs, value)
|
namedArgs = append(namedArgs, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.RunSQL(ctx, statement, namedArgs)
|
|
||||||
|
resp, err := source.RunSQL(ctx, statement, namedArgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGeneralError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,13 +17,15 @@ package firestoreadddocuments
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
firestoreapi "cloud.google.com/go/firestore"
|
firestoreapi "cloud.google.com/go/firestore"
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools/firestore/util"
|
fsUtil "github.com/googleapis/genai-toolbox/internal/tools/firestore/util"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -128,32 +130,32 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mapParams := params.AsMap()
|
mapParams := params.AsMap()
|
||||||
// Get collection path
|
// Get collection path
|
||||||
collectionPath, ok := mapParams[collectionPathKey].(string)
|
collectionPath, ok := mapParams[collectionPathKey].(string)
|
||||||
if !ok || collectionPath == "" {
|
if !ok || collectionPath == "" {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter", collectionPathKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter", collectionPathKey), nil)
|
||||||
}
|
}
|
||||||
// Validate collection path
|
// Validate collection path
|
||||||
if err := util.ValidateCollectionPath(collectionPath); err != nil {
|
if err := fsUtil.ValidateCollectionPath(collectionPath); err != nil {
|
||||||
return nil, fmt.Errorf("invalid collection path: %w", err)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid collection path: %v", err), err)
|
||||||
}
|
}
|
||||||
// Get document data
|
// Get document data
|
||||||
documentDataRaw, ok := mapParams[documentDataKey]
|
documentDataRaw, ok := mapParams[documentDataKey]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter", documentDataKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter", documentDataKey), nil)
|
||||||
}
|
}
|
||||||
// Convert the document data from JSON format to Firestore format
|
// Convert the document data from JSON format to Firestore format
|
||||||
// The client is passed to handle referenceValue types
|
// The client is passed to handle referenceValue types
|
||||||
documentData, err := util.JSONToFirestoreValue(documentDataRaw, source.FirestoreClient())
|
documentData, err := fsUtil.JSONToFirestoreValue(documentDataRaw, source.FirestoreClient())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to convert document data: %w", err)
|
return nil, util.NewAgentError(fmt.Sprintf("failed to convert document data: %v", err), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get return document data flag
|
// Get return document data flag
|
||||||
@@ -161,7 +163,11 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
if val, ok := mapParams[returnDocumentDataKey].(bool); ok {
|
if val, ok := mapParams[returnDocumentDataKey].(bool); ok {
|
||||||
returnData = val
|
returnData = val
|
||||||
}
|
}
|
||||||
return source.AddDocuments(ctx, collectionPath, documentData, returnData)
|
resp, err := source.AddDocuments(ctx, collectionPath, documentData, returnData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,13 +17,15 @@ package firestoredeletedocuments
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
firestoreapi "cloud.google.com/go/firestore"
|
firestoreapi "cloud.google.com/go/firestore"
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools/firestore/util"
|
fsUtil "github.com/googleapis/genai-toolbox/internal/tools/firestore/util"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -94,39 +96,43 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mapParams := params.AsMap()
|
mapParams := params.AsMap()
|
||||||
documentPathsRaw, ok := mapParams[documentPathsKey].([]any)
|
documentPathsRaw, ok := mapParams[documentPathsKey].([]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected an array", documentPathsKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected an array", documentPathsKey), nil)
|
||||||
}
|
}
|
||||||
if len(documentPathsRaw) == 0 {
|
if len(documentPathsRaw) == 0 {
|
||||||
return nil, fmt.Errorf("'%s' parameter cannot be empty", documentPathsKey)
|
return nil, util.NewAgentError(fmt.Sprintf("'%s' parameter cannot be empty", documentPathsKey), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use ConvertAnySliceToTyped to convert the slice
|
// Use ConvertAnySliceToTyped to convert the slice
|
||||||
typedSlice, err := parameters.ConvertAnySliceToTyped(documentPathsRaw, "string")
|
typedSlice, err := parameters.ConvertAnySliceToTyped(documentPathsRaw, "string")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to convert document paths: %w", err)
|
return nil, util.NewAgentError(fmt.Sprintf("failed to convert document paths: %v", err), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
documentPaths, ok := typedSlice.([]string)
|
documentPaths, ok := typedSlice.([]string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unexpected type conversion error for document paths")
|
return nil, util.NewAgentError("unexpected type conversion error for document paths", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate each document path
|
// Validate each document path
|
||||||
for i, path := range documentPaths {
|
for i, path := range documentPaths {
|
||||||
if err := util.ValidateDocumentPath(path); err != nil {
|
if err := fsUtil.ValidateDocumentPath(path); err != nil {
|
||||||
return nil, fmt.Errorf("invalid document path at index %d: %w", i, err)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid document path at index %d: %v", i, err), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.DeleteDocuments(ctx, documentPaths)
|
resp, err := source.DeleteDocuments(ctx, documentPaths)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,13 +17,15 @@ package firestoregetdocuments
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
firestoreapi "cloud.google.com/go/firestore"
|
firestoreapi "cloud.google.com/go/firestore"
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools/firestore/util"
|
fsUtil "github.com/googleapis/genai-toolbox/internal/tools/firestore/util"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -94,40 +96,44 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mapParams := params.AsMap()
|
mapParams := params.AsMap()
|
||||||
documentPathsRaw, ok := mapParams[documentPathsKey].([]any)
|
documentPathsRaw, ok := mapParams[documentPathsKey].([]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected an array", documentPathsKey)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected an array", documentPathsKey), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(documentPathsRaw) == 0 {
|
if len(documentPathsRaw) == 0 {
|
||||||
return nil, fmt.Errorf("'%s' parameter cannot be empty", documentPathsKey)
|
return nil, util.NewAgentError(fmt.Sprintf("'%s' parameter cannot be empty", documentPathsKey), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use ConvertAnySliceToTyped to convert the slice
|
// Use ConvertAnySliceToTyped to convert the slice
|
||||||
typedSlice, err := parameters.ConvertAnySliceToTyped(documentPathsRaw, "string")
|
typedSlice, err := parameters.ConvertAnySliceToTyped(documentPathsRaw, "string")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to convert document paths: %w", err)
|
return nil, util.NewAgentError(fmt.Sprintf("failed to convert document paths: %v", err), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
documentPaths, ok := typedSlice.([]string)
|
documentPaths, ok := typedSlice.([]string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unexpected type conversion error for document paths")
|
return nil, util.NewAgentError("unexpected type conversion error for document paths", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate each document path
|
// Validate each document path
|
||||||
for i, path := range documentPaths {
|
for i, path := range documentPaths {
|
||||||
if err := util.ValidateDocumentPath(path); err != nil {
|
if err := fsUtil.ValidateDocumentPath(path); err != nil {
|
||||||
return nil, fmt.Errorf("invalid document path at index %d: %w", i, err)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid document path at index %d: %v", i, err), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.GetDocuments(ctx, documentPaths)
|
resp, err := source.GetDocuments(ctx, documentPaths)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ package firestoregetrules
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
"google.golang.org/api/firebaserules/v1"
|
"google.golang.org/api/firebaserules/v1"
|
||||||
)
|
)
|
||||||
@@ -92,12 +94,16 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
return source.GetRules(ctx)
|
resp, err := source.GetRules(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
@@ -17,13 +17,15 @@ package firestorelistcollections
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
firestoreapi "cloud.google.com/go/firestore"
|
firestoreapi "cloud.google.com/go/firestore"
|
||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||||
"github.com/googleapis/genai-toolbox/internal/tools/firestore/util"
|
fsUtil "github.com/googleapis/genai-toolbox/internal/tools/firestore/util"
|
||||||
|
"github.com/googleapis/genai-toolbox/internal/util"
|
||||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -95,10 +97,10 @@ func (t Tool) ToConfig() tools.ToolConfig {
|
|||||||
return t.Config
|
return t.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
|
||||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mapParams := params.AsMap()
|
mapParams := params.AsMap()
|
||||||
@@ -107,11 +109,15 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
|
|||||||
parentPath, _ := mapParams[parentPathKey].(string)
|
parentPath, _ := mapParams[parentPathKey].(string)
|
||||||
if parentPath != "" {
|
if parentPath != "" {
|
||||||
// Validate parent document path
|
// Validate parent document path
|
||||||
if err := util.ValidateDocumentPath(parentPath); err != nil {
|
if err := fsUtil.ValidateDocumentPath(parentPath); err != nil {
|
||||||
return nil, fmt.Errorf("invalid parent document path: %w", err)
|
return nil, util.NewAgentError(fmt.Sprintf("invalid parent document path: %v", err), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return source.ListCollections(ctx, parentPath)
|
resp, err := source.ListCollections(ctx, parentPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.ProcessGcpError(err)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user