Compare commits

..

4 Commits

Author SHA1 Message Date
Twisha Bansal
57b8de818b Update integration.cloudbuild.yaml 2026-02-03 14:03:08 +05:30
Twisha Bansal
9b4d59aed8 refactor: consolidate quickstart tests into universal runner 2026-02-03 13:59:59 +05:30
Twisha Bansal
3f1908a822 docs: fix JS quickstart (#2406)
## Description

Response is being re-assigned

## PR Checklist

> Thank you for opening a Pull Request! Before submitting your PR, there
are a
> few things you can do to make sure it goes smoothly:

- [ ] Make sure you reviewed

[CONTRIBUTING.md](https://github.com/googleapis/genai-toolbox/blob/main/CONTRIBUTING.md)
- [ ] Make sure to open an issue as a

[bug/issue](https://github.com/googleapis/genai-toolbox/issues/new/choose)
  before writing your code! That way we can discuss the change, evaluate
  designs, and agree on the general idea
- [ ] Ensure the tests and linter pass
- [ ] Code coverage does not decrease (if any source code was changed)
- [ ] Appropriate docs were updated (if necessary)
- [ ] Make sure to add `!` if this involve a breaking change

🛠️ Fixes #<issue_number_goes_here>
2026-02-03 11:36:16 +05:30
Yuan Teoh
eef7a94977 docs: close notice shortcode (#2404)
fix notice shortcode closing brackets.
2026-02-02 17:38:15 -08:00
84 changed files with 847 additions and 1691 deletions

View File

@@ -1,47 +0,0 @@
# 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.
steps:
- name: 'golang:1.25.1'
id: 'go-quickstart-test'
entrypoint: 'bash'
args:
# The '-c' flag tells bash to execute the following string as a command.
# The 'set -ex' enables debug output and exits on error for easier troubleshooting.
- -c
- |
set -ex
export VERSION=$(cat ./cmd/version.txt)
chmod +x .ci/quickstart_test/run_go_tests.sh
.ci/quickstart_test/run_go_tests.sh
env:
- 'CLOUD_SQL_INSTANCE=${_CLOUD_SQL_INSTANCE}'
- 'GCP_PROJECT=${_GCP_PROJECT}'
- 'DATABASE_NAME=${_DATABASE_NAME}'
- 'DB_USER=${_DB_USER}'
secretEnv: ['TOOLS_YAML_CONTENT', 'GOOGLE_API_KEY', 'DB_PASSWORD']
availableSecrets:
secretManager:
- versionName: projects/${_GCP_PROJECT}/secrets/${_TOOLS_YAML_SECRET}/versions/7
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: 1000s
options:
logging: CLOUD_LOGGING_ONLY

View File

@@ -1,47 +0,0 @@
# 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.
steps:
- name: 'node:22'
id: 'js-quickstart-test'
entrypoint: 'bash'
args:
# The '-c' flag tells bash to execute the following string as a command.
# The 'set -ex' enables debug output and exits on error for easier troubleshooting.
- -c
- |
set -ex
export VERSION=$(cat ./cmd/version.txt)
chmod +x .ci/quickstart_test/run_js_tests.sh
.ci/quickstart_test/run_js_tests.sh
env:
- 'CLOUD_SQL_INSTANCE=${_CLOUD_SQL_INSTANCE}'
- 'GCP_PROJECT=${_GCP_PROJECT}'
- 'DATABASE_NAME=${_DATABASE_NAME}'
- 'DB_USER=${_DB_USER}'
secretEnv: ['TOOLS_YAML_CONTENT', 'GOOGLE_API_KEY', 'DB_PASSWORD']
availableSecrets:
secretManager:
- versionName: projects/${_GCP_PROJECT}/secrets/${_TOOLS_YAML_SECRET}/versions/6
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: 1000s
options:
logging: CLOUD_LOGGING_ONLY

View File

@@ -1,47 +0,0 @@
# 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.
steps:
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:537.0.0'
id: 'python-quickstart-test'
entrypoint: 'bash'
args:
# The '-c' flag tells bash to execute the following string as a command.
# The 'set -ex' enables debug output and exits on error for easier troubleshooting.
- -c
- |
set -ex
export VERSION=$(cat ./cmd/version.txt)
chmod +x .ci/quickstart_test/run_py_tests.sh
.ci/quickstart_test/run_py_tests.sh
env:
- 'CLOUD_SQL_INSTANCE=${_CLOUD_SQL_INSTANCE}'
- 'GCP_PROJECT=${_GCP_PROJECT}'
- 'DATABASE_NAME=${_DATABASE_NAME}'
- 'DB_USER=${_DB_USER}'
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: 1000s
options:
logging: CLOUD_LOGGING_ONLY

View File

@@ -1,125 +0,0 @@
# 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

View File

@@ -1,125 +0,0 @@
# 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

View File

@@ -1,115 +0,0 @@
# 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

View File

@@ -0,0 +1,59 @@
# 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: "universal-test"
entrypoint: "bash"
args:
- -c
- |
set -ex
chmod +x .ci/universal/run_tests.sh
.ci/universal/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: "python:3.11"
_TARGET_ROOT: "docs/en/getting-started/quickstart/python"
_TABLE_NAME: "hotels_python"
_SQL_FILE: ".ci/universal/setup_hotels.sql"
_AGENT_FILE_PATTERN: "quickstart.py"
_LOG_BUCKET: "toolbox-test-logs"
options:
logging: CLOUD_LOGGING_ONLY

173
.ci/universal/run_tests.sh Normal file
View File

@@ -0,0 +1,173 @@
#!/bin/bash
# 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 ..
# If there is a pytest file in the parent directory (like agent_test.py or quickstart_test.py)
# we use it. Otherwise we just run the agent.
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"
)
}
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"
fi
done

View File

@@ -53,7 +53,7 @@ export async function main() {
for (const query of queries) {
conversationHistory.push({ role: "user", content: [{ text: query }] });
const response = await ai.generate({
let response = await ai.generate({
messages: conversationHistory,
tools: tools,
});

View File

@@ -13,12 +13,12 @@ The `invoke` command allows you to invoke tools defined in your configuration di
{{< 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.
{{< notice tip >}}
{{< /notice >}}
## Prerequisites
## Before you begin
- You have the `toolbox` binary installed or built.
- You have a valid tool configuration file (e.g., `tools.yaml`).
1. Make sure you have the `toolbox` binary installed or built.
2. Make sure you have a valid tool configuration file (e.g., `tools.yaml`).
## Basic Usage

View File

@@ -19,6 +19,7 @@ import (
"errors"
"fmt"
"net/http"
"strings"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
@@ -234,10 +235,8 @@ func toolInvokeHandler(s *Server, w http.ResponseWriter, r *http.Request) {
params, err := parameters.ParseParams(tool.GetParameters(), data, claimsFromAuth)
if err != nil {
// If auth error, return 401
errMsg := fmt.Sprintf("error parsing authenticated parameters from ID token: %w", err)
var clientServerErr *util.ClientServerError
if errors.As(err, &clientServerErr) && clientServerErr.Code == http.StatusUnauthorized {
s.logger.DebugContext(ctx, errMsg)
if errors.Is(err, util.ErrUnauthorized) {
s.logger.DebugContext(ctx, fmt.Sprintf("error parsing authenticated parameters from ID token: %s", err))
_ = render.Render(w, r, newErrResponse(err, http.StatusUnauthorized))
return
}
@@ -260,49 +259,34 @@ func toolInvokeHandler(s *Server, w http.ResponseWriter, r *http.Request) {
// Determine what error to return to the users.
if err != nil {
var tbErr util.ToolboxError
errStr := err.Error()
var statusCode int
if errors.As(err, &tbErr) {
switch tbErr.Category() {
case util.CategoryAgent:
// Agent Errors -> 200 OK
s.logger.DebugContext(ctx, fmt.Sprintf("Tool invocation agent error: %v", err))
_ = render.Render(w, r, newErrResponse(err, http.StatusOK))
return
// Upstream API auth error propagation
switch {
case strings.Contains(errStr, "Error 401"):
statusCode = http.StatusUnauthorized
case strings.Contains(errStr, "Error 403"):
statusCode = http.StatusForbidden
}
case util.CategoryServer:
// Server Errors -> Check the specific code inside
var clientServerErr *util.ClientServerError
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))
if statusCode == http.StatusUnauthorized || statusCode == http.StatusForbidden {
if clientAuth {
// Propagate the original 401/403 error.
s.logger.DebugContext(ctx, fmt.Sprintf("error invoking tool. Client credentials lack authorization to the source: %v", err))
_ = render.Render(w, r, newErrResponse(err, statusCode))
return
}
} else {
// Unknown error -> 500
s.logger.ErrorContext(ctx, fmt.Sprintf("Tool invocation unknown error: %v", err))
_ = render.Render(w, r, newErrResponse(err, http.StatusInternalServerError))
// ADC lacking permission or credentials configuration error.
internalErr := fmt.Errorf("unexpected auth error occured during Tool invocation: %w", err)
s.logger.ErrorContext(ctx, internalErr.Error())
_ = render.Render(w, r, newErrResponse(internalErr, http.StatusInternalServerError))
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)

View File

@@ -30,7 +30,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/server/resources"
"github.com/googleapis/genai-toolbox/internal/telemetry"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -52,7 +51,7 @@ type MockTool struct {
requiresClientAuthrorization bool
}
func (t MockTool) Invoke(context.Context, tools.SourceProvider, parameters.ParamValues, tools.AccessToken) (any, util.ToolboxError) {
func (t MockTool) Invoke(context.Context, tools.SourceProvider, parameters.ParamValues, tools.AccessToken) (any, error) {
mock := []any{t.Name}
return mock, nil
}

View File

@@ -23,6 +23,7 @@ import (
"fmt"
"io"
"net/http"
"strings"
"sync"
"time"
@@ -443,17 +444,15 @@ func httpHandler(s *Server, w http.ResponseWriter, r *http.Request) {
code := rpcResponse.Error.Code
switch code {
case jsonrpc.INTERNAL_ERROR:
// Map Internal RPC Error (-32603) to HTTP 500
w.WriteHeader(http.StatusInternalServerError)
case jsonrpc.INVALID_REQUEST:
var clientServerErr *util.ClientServerError
if errors.As(err, &clientServerErr) {
switch clientServerErr.Code {
case http.StatusUnauthorized:
w.WriteHeader(http.StatusUnauthorized)
case http.StatusForbidden:
w.WriteHeader(http.StatusForbidden)
}
errStr := err.Error()
if errors.Is(err, util.ErrUnauthorized) {
w.WriteHeader(http.StatusUnauthorized)
} else if strings.Contains(errStr, "Error 401") {
w.WriteHeader(http.StatusUnauthorized)
} else if strings.Contains(errStr, "Error 403") {
w.WriteHeader(http.StatusForbidden)
}
}
}

View File

@@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"net/http"
"strings"
"github.com/googleapis/genai-toolbox/internal/prompts"
"github.com/googleapis/genai-toolbox/internal/server/mcp/jsonrpc"
@@ -123,11 +124,7 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
}
if clientAuth {
if accessToken == "" {
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,
)
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, "missing access token in the 'Authorization' header", nil), util.ErrUnauthorized
}
}
@@ -175,11 +172,7 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
// Check if any of the specified auth services is verified
isAuthorized := tool.Authorized(verifiedAuthServices)
if !isAuthorized {
err = util.NewClientServerError(
"unauthorized Tool call: Please make sure you specify correct auth headers",
http.StatusUnauthorized,
nil,
)
err = fmt.Errorf("unauthorized Tool call: Please make sure your specify correct auth headers: %w", util.ErrUnauthorized)
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
}
logger.DebugContext(ctx, "tool invocation authorized")
@@ -201,44 +194,30 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
// run tool invocation and generate response.
results, err := tool.Invoke(ctx, resourceMgr, params, accessToken)
if err != nil {
var tbErr util.ToolboxError
if errors.As(err, &tbErr) {
switch tbErr.Category() {
case util.CategoryAgent:
// MCP - Tool execution error
// Return SUCCESS but with IsError: true
text := TextContent{
Type: "text",
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
errStr := err.Error()
// Missing authService tokens.
if errors.Is(err, util.ErrUnauthorized) {
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
}
// Upstream auth error
if strings.Contains(errStr, "Error 401") || strings.Contains(errStr, "Error 403") {
if clientAuth {
// Error with client credentials should pass down to the client
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
}
} else {
// Unknown error -> 500
// Auth error with ADC should raise internal 500 error
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)

View File

@@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"net/http"
"strings"
"github.com/googleapis/genai-toolbox/internal/prompts"
"github.com/googleapis/genai-toolbox/internal/server/mcp/jsonrpc"
@@ -123,11 +124,7 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
}
if clientAuth {
if accessToken == "" {
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,
)
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, "missing access token in the 'Authorization' header", nil), util.ErrUnauthorized
}
}
@@ -175,11 +172,7 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
// Check if any of the specified auth services is verified
isAuthorized := tool.Authorized(verifiedAuthServices)
if !isAuthorized {
err = util.NewClientServerError(
"unauthorized Tool call: Please make sure you specify correct auth headers",
http.StatusUnauthorized,
nil,
)
err = fmt.Errorf("unauthorized Tool call: Please make sure your specify correct auth headers: %w", util.ErrUnauthorized)
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
}
logger.DebugContext(ctx, "tool invocation authorized")
@@ -201,45 +194,31 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
// run tool invocation and generate response.
results, err := tool.Invoke(ctx, resourceMgr, params, accessToken)
if err != nil {
var tbErr util.ToolboxError
if errors.As(err, &tbErr) {
switch tbErr.Category() {
case util.CategoryAgent:
// MCP - Tool execution error
// Return SUCCESS but with IsError: true
text := TextContent{
Type: "text",
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
errStr := err.Error()
// Missing authService tokens.
if errors.Is(err, util.ErrUnauthorized) {
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
}
// Upstream auth error
if strings.Contains(errStr, "Error 401") || strings.Contains(errStr, "Error 403") {
if clientAuth {
// Error with client credentials should pass down to the client
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
}
} else {
// Unknown error -> 500
// Auth error with ADC should raise internal 500 error
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)
sliceRes, ok := results.([]any)

View File

@@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"net/http"
"strings"
"github.com/googleapis/genai-toolbox/internal/prompts"
"github.com/googleapis/genai-toolbox/internal/server/mcp/jsonrpc"
@@ -116,12 +117,7 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
}
if clientAuth {
if accessToken == "" {
errMsg := "missing access token in the 'Authorization' header"
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, errMsg, nil), util.NewClientServerError(
errMsg,
http.StatusUnauthorized,
nil,
)
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, "missing access token in the 'Authorization' header", nil), util.ErrUnauthorized
}
}
@@ -169,11 +165,7 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
// Check if any of the specified auth services is verified
isAuthorized := tool.Authorized(verifiedAuthServices)
if !isAuthorized {
err = util.NewClientServerError(
"unauthorized Tool call: Please make sure you specify correct auth headers",
http.StatusUnauthorized,
nil,
)
err = fmt.Errorf("unauthorized Tool call: Please make sure your specify correct auth headers: %w", util.ErrUnauthorized)
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
}
logger.DebugContext(ctx, "tool invocation authorized")
@@ -195,44 +187,29 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
// run tool invocation and generate response.
results, err := tool.Invoke(ctx, resourceMgr, params, accessToken)
if err != nil {
var tbErr util.ToolboxError
if errors.As(err, &tbErr) {
switch tbErr.Category() {
case util.CategoryAgent:
// MCP - Tool execution error
// Return SUCCESS but with IsError: true
text := TextContent{
Type: "text",
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
errStr := err.Error()
// Missing authService tokens.
if errors.Is(err, util.ErrUnauthorized) {
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
}
// Upstream auth error
if strings.Contains(errStr, "Error 401") || strings.Contains(errStr, "Error 403") {
if clientAuth {
// Error with client credentials should pass down to the client
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
}
} else {
// Unknown error -> 500
// Auth error with ADC should raise internal 500 error
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)

View File

@@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"net/http"
"strings"
"github.com/googleapis/genai-toolbox/internal/prompts"
"github.com/googleapis/genai-toolbox/internal/server/mcp/jsonrpc"
@@ -116,11 +117,7 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
}
if clientAuth {
if accessToken == "" {
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,
)
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, "missing access token in the 'Authorization' header", nil), util.ErrUnauthorized
}
}
@@ -168,11 +165,7 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
// Check if any of the specified auth services is verified
isAuthorized := tool.Authorized(verifiedAuthServices)
if !isAuthorized {
err = util.NewClientServerError(
"unauthorized Tool call: Please make sure you specify correct auth headers",
http.StatusUnauthorized,
nil,
)
err = fmt.Errorf("unauthorized Tool call: Please make sure your specify correct auth headers: %w", util.ErrUnauthorized)
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
}
logger.DebugContext(ctx, "tool invocation authorized")
@@ -194,44 +187,29 @@ func toolsCallHandler(ctx context.Context, id jsonrpc.RequestId, resourceMgr *re
// run tool invocation and generate response.
results, err := tool.Invoke(ctx, resourceMgr, params, accessToken)
if err != nil {
var tbErr util.ToolboxError
if errors.As(err, &tbErr) {
switch tbErr.Category() {
case util.CategoryAgent:
// MCP - Tool execution error
// Return SUCCESS but with IsError: true
text := TextContent{
Type: "text",
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
errStr := err.Error()
// Missing authService tokens.
if errors.Is(err, util.ErrUnauthorized) {
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
}
// Upstream auth error
if strings.Contains(errStr, "Error 401") || strings.Contains(errStr, "Error 403") {
if clientAuth {
// Error with client credentials should pass down to the client
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), err
}
} else {
// Unknown error -> 500
// Auth error with ADC should raise internal 500 error
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)

View File

@@ -22,7 +22,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -123,49 +122,44 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok || project == "" {
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a non-empty string", nil)
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a non-empty string")
}
location, ok := paramsMap["location"].(string)
if !ok {
return nil, util.NewAgentError("invalid 'location' parameter; expected a string", nil)
return nil, fmt.Errorf("invalid 'location' parameter; expected a string")
}
clusterID, ok := paramsMap["cluster"].(string)
if !ok || clusterID == "" {
return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a non-empty string", nil)
return nil, fmt.Errorf("invalid or missing 'cluster' parameter; expected a non-empty string")
}
password, ok := paramsMap["password"].(string)
if !ok || password == "" {
return nil, util.NewAgentError("invalid or missing 'password' parameter; expected a non-empty string", nil)
return nil, fmt.Errorf("invalid or missing 'password' parameter; expected a non-empty string")
}
network, ok := paramsMap["network"].(string)
if !ok {
return nil, util.NewAgentError("invalid 'network' parameter; expected a string", nil)
return nil, fmt.Errorf("invalid 'network' parameter; expected a string")
}
user, ok := paramsMap["user"].(string)
if !ok {
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.ProecessGcpError(err)
return nil, fmt.Errorf("invalid 'user' parameter; expected a string")
}
return resp, nil
return source.CreateCluster(ctx, project, location, network, user, password, clusterID, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -22,7 +22,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -124,36 +123,36 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok || project == "" {
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a non-empty string", nil)
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a non-empty string")
}
location, ok := paramsMap["location"].(string)
if !ok || location == "" {
return nil, util.NewAgentError("invalid or missing 'location' parameter; expected a non-empty string", nil)
return nil, fmt.Errorf("invalid or missing 'location' parameter; expected a non-empty string")
}
cluster, ok := paramsMap["cluster"].(string)
if !ok || cluster == "" {
return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a non-empty string", nil)
return nil, fmt.Errorf("invalid or missing 'cluster' parameter; expected a non-empty string")
}
instanceID, ok := paramsMap["instance"].(string)
if !ok || instanceID == "" {
return nil, util.NewAgentError("invalid or missing 'instance' parameter; expected a non-empty string", nil)
return nil, fmt.Errorf("invalid or missing 'instance' parameter; expected a non-empty string")
}
instanceType, ok := paramsMap["instanceType"].(string)
if !ok || (instanceType != "READ_POOL" && instanceType != "PRIMARY") {
return nil, util.NewAgentError("invalid 'instanceType' parameter; expected 'PRIMARY' or 'READ_POOL'", nil)
return nil, fmt.Errorf("invalid 'instanceType' parameter; expected 'PRIMARY' or 'READ_POOL'")
}
displayName, _ := paramsMap["displayName"].(string)
@@ -162,15 +161,11 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if instanceType == "READ_POOL" {
nodeCount, ok = paramsMap["nodeCount"].(int)
if !ok {
return nil, util.NewAgentError("invalid 'nodeCount' parameter; expected an integer for READ_POOL", nil)
return nil, fmt.Errorf("invalid 'nodeCount' parameter; expected an integer for READ_POOL")
}
}
resp, err := source.CreateInstance(ctx, project, location, cluster, instanceID, instanceType, displayName, nodeCount, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.CreateInstance(ctx, project, location, cluster, instanceID, instanceType, displayName, nodeCount, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -22,7 +22,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -123,43 +122,43 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok || project == "" {
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a non-empty string", nil)
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a non-empty string")
}
location, ok := paramsMap["location"].(string)
if !ok || location == "" {
return nil, util.NewAgentError("invalid or missing'location' parameter; expected a non-empty string", nil)
return nil, fmt.Errorf("invalid or missing'location' parameter; expected a non-empty string")
}
cluster, ok := paramsMap["cluster"].(string)
if !ok || cluster == "" {
return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a non-empty string", nil)
return nil, fmt.Errorf("invalid or missing 'cluster' parameter; expected a non-empty string")
}
userID, ok := paramsMap["user"].(string)
if !ok || userID == "" {
return nil, util.NewAgentError("invalid or missing 'user' parameter; expected a non-empty string", nil)
return nil, fmt.Errorf("invalid or missing 'user' parameter; expected a non-empty string")
}
userType, ok := paramsMap["userType"].(string)
if !ok || (userType != "ALLOYDB_BUILT_IN" && userType != "ALLOYDB_IAM_USER") {
return nil, util.NewAgentError("invalid or missing 'userType' parameter; expected 'ALLOYDB_BUILT_IN' or 'ALLOYDB_IAM_USER'", nil)
return nil, fmt.Errorf("invalid or missing 'userType' parameter; expected 'ALLOYDB_BUILT_IN' or 'ALLOYDB_IAM_USER'")
}
var password string
if userType == "ALLOYDB_BUILT_IN" {
password, ok = paramsMap["password"].(string)
if !ok || password == "" {
return nil, util.NewAgentError("password is required when userType is ALLOYDB_BUILT_IN", nil)
return nil, fmt.Errorf("password is required when userType is ALLOYDB_BUILT_IN")
}
}
@@ -171,11 +170,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
}
}
}
resp, err := source.CreateUser(ctx, userType, password, roles, string(accessToken), project, location, cluster, userID)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.CreateUser(ctx, userType, password, roles, string(accessToken), project, location, cluster, userID)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -22,7 +22,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -121,32 +120,28 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok || project == "" {
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string")
}
location, ok := paramsMap["location"].(string)
if !ok || location == "" {
return nil, util.NewAgentError("invalid or missing 'location' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid 'location' parameter; expected a string")
}
cluster, ok := paramsMap["cluster"].(string)
if !ok || cluster == "" {
return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid 'cluster' parameter; expected a string")
}
resp, err := source.GetCluster(ctx, project, location, cluster, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.GetCluster(ctx, project, location, cluster, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -22,7 +22,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -121,36 +120,32 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok || project == "" {
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string")
}
location, ok := paramsMap["location"].(string)
if !ok || location == "" {
return nil, util.NewAgentError("invalid or missing 'location' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid 'location' parameter; expected a string")
}
cluster, ok := paramsMap["cluster"].(string)
if !ok || cluster == "" {
return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid 'cluster' parameter; expected a string")
}
instance, ok := paramsMap["instance"].(string)
if !ok || instance == "" {
return nil, util.NewAgentError("invalid or missing 'instance' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid 'instance' parameter; expected a string")
}
resp, err := source.GetInstance(ctx, project, location, cluster, instance, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.GetInstance(ctx, project, location, cluster, instance, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -22,7 +22,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -121,36 +120,32 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok || project == "" {
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string")
}
location, ok := paramsMap["location"].(string)
if !ok || location == "" {
return nil, util.NewAgentError("invalid or missing 'location' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid 'location' parameter; expected a string")
}
cluster, ok := paramsMap["cluster"].(string)
if !ok || cluster == "" {
return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid 'cluster' parameter; expected a string")
}
user, ok := paramsMap["user"].(string)
if !ok || user == "" {
return nil, util.NewAgentError("invalid or missing 'user' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid 'user' parameter; expected a string")
}
resp, err := source.GetUsers(ctx, project, location, cluster, user, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.GetUsers(ctx, project, location, cluster, user, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -22,7 +22,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -119,28 +118,24 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok || project == "" {
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string")
}
location, ok := paramsMap["location"].(string)
if !ok {
return nil, util.NewAgentError("invalid 'location' parameter; expected a string", nil)
return nil, fmt.Errorf("invalid 'location' parameter; expected a string")
}
resp, err := source.ListCluster(ctx, project, location, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.ListCluster(ctx, project, location, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -22,7 +22,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -120,32 +119,28 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok || project == "" {
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string")
}
location, ok := paramsMap["location"].(string)
if !ok {
return nil, util.NewAgentError("invalid 'location' parameter; expected a string", nil)
return nil, fmt.Errorf("invalid 'location' parameter; expected a string")
}
cluster, ok := paramsMap["cluster"].(string)
if !ok {
return nil, util.NewAgentError("invalid 'cluster' parameter; expected a string", nil)
return nil, fmt.Errorf("invalid 'cluster' parameter; expected a string")
}
resp, err := source.ListInstance(ctx, project, location, cluster, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.ListInstance(ctx, project, location, cluster, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -22,7 +22,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -120,32 +119,28 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok || project == "" {
return nil, util.NewAgentError("invalid or missing 'project' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid or missing 'project' parameter; expected a string")
}
location, ok := paramsMap["location"].(string)
if !ok || location == "" {
return nil, util.NewAgentError("invalid or missing 'location' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid 'location' parameter; expected a string")
}
cluster, ok := paramsMap["cluster"].(string)
if !ok || cluster == "" {
return nil, util.NewAgentError("invalid or missing 'cluster' parameter; expected a string", nil)
if !ok {
return nil, fmt.Errorf("invalid 'cluster' parameter; expected a string")
}
resp, err := source.ListUsers(ctx, project, location, cluster, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.ListUsers(ctx, project, location, cluster, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -24,7 +24,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -214,25 +213,25 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", 500, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok {
return nil, util.NewAgentError("missing 'project' parameter", nil)
return nil, fmt.Errorf("missing 'project' parameter")
}
location, ok := paramsMap["location"].(string)
if !ok {
return nil, util.NewAgentError("missing 'location' parameter", nil)
return nil, fmt.Errorf("missing 'location' parameter")
}
operation, ok := paramsMap["operation"].(string)
if !ok {
return nil, util.NewAgentError("missing 'operation' parameter", nil)
return nil, fmt.Errorf("missing 'operation' parameter")
}
ctx, cancel := context.WithTimeout(ctx, 30*time.Minute)
@@ -247,15 +246,14 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
for retries < maxRetries {
select {
case <-ctx.Done():
return nil, util.NewAgentError("timed out waiting for operation %s", ctx.Err())
return nil, fmt.Errorf("timed out waiting for operation: %w", ctx.Err())
default:
}
op, err := source.GetOperations(ctx, project, location, operation, alloyDBConnectionMessageTemplate, delay, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
if op != nil {
return nil, err
} else if op != nil {
return op, nil
}
@@ -266,7 +264,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
}
retries++
}
return nil, util.NewAgentError("exceeded max retries waiting for operation", nil)
return nil, fmt.Errorf("exceeded max retries waiting for operation")
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package alloydbainl
import (
"context"
"fmt"
"net/http"
"strings"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"github.com/jackc/pgx/v5/pgxpool"
)
@@ -129,10 +127,10 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
sliceParams := params.AsSlice()
@@ -145,7 +143,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
resp, err := source.RunSQL(ctx, t.Statement, allParamValues)
if err != nil {
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 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 resp, nil
}

View File

@@ -17,7 +17,6 @@ package bigqueryanalyzecontribution
import (
"context"
"fmt"
"net/http"
"strings"
bigqueryapi "cloud.google.com/go/bigquery"
@@ -28,7 +27,6 @@ import (
bigqueryds "github.com/googleapis/genai-toolbox/internal/sources/bigquery"
"github.com/googleapis/genai-toolbox/internal/tools"
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"
bigqueryrestapi "google.golang.org/api/bigquery/v2"
)
@@ -156,21 +154,21 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke runs the contribution analysis.
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
inputData, ok := paramsMap["input_data"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("unable to cast input_data parameter %s", paramsMap["input_data"]), nil)
return nil, fmt.Errorf("unable to cast input_data parameter %s", paramsMap["input_data"])
}
bqClient, restService, err := source.RetrieveClientAndService(accessToken)
if err != nil {
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
return nil, err
}
modelID := fmt.Sprintf("contribution_analysis_model_%s", strings.ReplaceAll(uuid.New().String(), "-", ""))
@@ -188,7 +186,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
}
options = append(options, fmt.Sprintf("DIMENSION_ID_COLS = [%s]", strings.Join(strCols, ", ")))
} else {
return nil, util.NewAgentError(fmt.Sprintf("unable to cast dimension_id_cols parameter %s", paramsMap["dimension_id_cols"]), nil)
return nil, fmt.Errorf("unable to cast dimension_id_cols parameter %s", paramsMap["dimension_id_cols"])
}
}
if val, ok := paramsMap["top_k_insights_by_apriori_support"]; ok {
@@ -197,7 +195,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if val, ok := paramsMap["pruning_method"].(string); ok {
upperVal := strings.ToUpper(val)
if upperVal != "NO_PRUNING" && upperVal != "PRUNE_REDUNDANT_INSIGHTS" {
return nil, util.NewAgentError(fmt.Sprintf("invalid pruning_method: %s", val), nil)
return nil, fmt.Errorf("invalid pruning_method: %s", val)
}
options = append(options, fmt.Sprintf("PRUNING_METHOD = '%s'", upperVal))
}
@@ -209,7 +207,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
var connProps []*bigqueryapi.ConnectionProperty
session, err := source.BigQuerySession()(ctx)
if err != nil {
return nil, util.NewClientServerError("failed to get BigQuery session", http.StatusInternalServerError, err)
return nil, fmt.Errorf("failed to get BigQuery session: %w", err)
}
if session != nil {
connProps = []*bigqueryapi.ConnectionProperty{
@@ -218,22 +216,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)
if err != nil {
return nil, util.ProecessGcpError(err)
return nil, fmt.Errorf("query validation failed: %w", err)
}
statementType := dryRunJob.Statistics.Query.StatementType
if statementType != "SELECT" {
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)
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)
}
queryStats := dryRunJob.Statistics.Query
if queryStats != nil {
for _, tableRef := range queryStats.ReferencedTables {
if !source.IsDatasetAllowed(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)
return nil, fmt.Errorf("query in input_data accesses dataset '%s.%s', which is not in the allowed list", tableRef.ProjectId, tableRef.DatasetId)
}
}
} else {
return nil, util.NewAgentError("could not analyze query in input_data to validate against allowed datasets", nil)
return nil, fmt.Errorf("could not analyze query in input_data to validate against allowed datasets")
}
}
inputDataSource = fmt.Sprintf("(%s)", inputData)
@@ -247,10 +245,10 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
case 2: // dataset.table
projectID, datasetID = source.BigQueryClient().Project(), parts[0]
default:
return nil, util.NewAgentError(fmt.Sprintf("invalid table ID format for 'input_data': %q. Expected 'dataset.table' or 'project.dataset.table'", inputData), nil)
return nil, fmt.Errorf("invalid table ID format for 'input_data': %q. Expected 'dataset.table' or 'project.dataset.table'", inputData)
}
if !source.IsDatasetAllowed(projectID, datasetID) {
return nil, util.NewAgentError(fmt.Sprintf("access to dataset '%s.%s' (from table '%s') is not allowed", projectID, datasetID, inputData), nil)
return nil, fmt.Errorf("access to dataset '%s.%s' (from table '%s') is not allowed", projectID, datasetID, inputData)
}
}
inputDataSource = fmt.Sprintf("SELECT * FROM `%s`", inputData)
@@ -270,7 +268,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
// Otherwise, a new session will be created by the first query.
session, err := source.BigQuerySession()(ctx)
if err != nil {
return nil, util.NewClientServerError("failed to get BigQuery session", http.StatusInternalServerError, err)
return nil, fmt.Errorf("failed to get BigQuery session: %w", err)
}
if session != nil {
@@ -283,15 +281,15 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
}
createModelJob, err := createModelQuery.Run(ctx)
if err != nil {
return nil, util.ProecessGcpError(err)
return nil, fmt.Errorf("failed to start create model job: %w", err)
}
status, err := createModelJob.Wait(ctx)
if err != nil {
return nil, util.ProecessGcpError(err)
return nil, fmt.Errorf("failed to wait for create model job: %w", err)
}
if err := status.Err(); err != nil {
return nil, util.ProecessGcpError(err)
return nil, fmt.Errorf("create model job failed: %w", err)
}
// Determine the session ID to use for subsequent queries.
@@ -302,17 +300,12 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
} else if status.Statistics != nil && status.Statistics.SessionInfo != nil {
sessionID = status.Statistics.SessionInfo.SessionID
} else {
return nil, util.NewClientServerError("failed to get or create a BigQuery session ID", http.StatusInternalServerError, nil)
return nil, fmt.Errorf("failed to get or create a BigQuery session ID")
}
getInsightsSQL := fmt.Sprintf("SELECT * FROM ML.GET_INSIGHTS(MODEL %s)", modelID)
connProps := []*bigqueryapi.ConnectionProperty{{Key: "session_id", Value: sessionID}}
resp, err := source.RunSQL(ctx, bqClient, getInsightsSQL, "SELECT", nil, connProps)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.RunSQL(ctx, bqClient, getInsightsSQL, "SELECT", nil, connProps)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -172,10 +172,10 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
var tokenStr string
@@ -184,26 +184,26 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if source.UseClientAuthorization() {
// Use client-side access token
if accessToken == "" {
return nil, util.NewClientServerError("tool is configured for client OAuth but no token was provided in the request header", http.StatusUnauthorized, nil)
return nil, fmt.Errorf("tool is configured for client OAuth but no token was provided in the request header: %w", util.ErrUnauthorized)
}
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
} else {
// Get a token source for the Gemini Data Analytics API.
tokenSource, err := source.BigQueryTokenSourceWithScope(ctx, nil)
if err != nil {
return nil, util.NewClientServerError("failed to get token source", http.StatusInternalServerError, err)
return nil, fmt.Errorf("failed to get token source: %w", err)
}
// Use cloud-platform token source for Gemini Data Analytics API
if tokenSource == nil {
return nil, util.NewClientServerError("cloud-platform token source is missing", http.StatusInternalServerError, nil)
return nil, fmt.Errorf("cloud-platform token source is missing")
}
token, err := tokenSource.Token()
if err != nil {
return nil, util.NewClientServerError("failed to get token from cloud-platform token source", http.StatusInternalServerError, err)
return nil, fmt.Errorf("failed to get token from cloud-platform token source: %w", err)
}
tokenStr = token.AccessToken
}
@@ -218,14 +218,14 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
var tableRefs []BQTableReference
if tableRefsJSON != "" {
if err := json.Unmarshal([]byte(tableRefsJSON), &tableRefs); err != nil {
return nil, util.NewAgentError("failed to parse 'table_references' JSON string", err)
return nil, fmt.Errorf("failed to parse 'table_references' JSON string: %w", err)
}
}
if len(source.BigQueryAllowedDatasets()) > 0 {
for _, tableRef := range tableRefs {
if !source.IsDatasetAllowed(tableRef.ProjectID, tableRef.DatasetID) {
return nil, util.NewAgentError(fmt.Sprintf("access to dataset '%s.%s' (from table '%s') is not allowed", tableRef.ProjectID, tableRef.DatasetID, tableRef.TableID), nil)
return nil, fmt.Errorf("access to dataset '%s.%s' (from table '%s') is not allowed", tableRef.ProjectID, tableRef.DatasetID, tableRef.TableID)
}
}
}
@@ -258,8 +258,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
// Call the streaming API
response, err := getStream(caURL, payload, headers, source.GetMaxQueryResultRows())
if err != nil {
// getStream wraps network errors or non-200 responses
return nil, util.NewClientServerError("failed to get response from conversational analytics API", http.StatusInternalServerError, err)
return nil, fmt.Errorf("failed to get response from conversational analytics API: %w", err)
}
return response, nil

View File

@@ -18,7 +18,6 @@ import (
"context"
"encoding/json"
"fmt"
"net/http"
"strings"
bigqueryapi "cloud.google.com/go/bigquery"
@@ -153,25 +152,25 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
sql, ok := paramsMap["sql"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("unable to cast sql parameter %s", paramsMap["sql"]), nil)
return nil, fmt.Errorf("unable to cast sql parameter %s", paramsMap["sql"])
}
dryRun, ok := paramsMap["dry_run"].(bool)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("unable to cast dry_run parameter %s", paramsMap["dry_run"]), nil)
return nil, fmt.Errorf("unable to cast dry_run parameter %s", paramsMap["dry_run"])
}
bqClient, restService, err := source.RetrieveClientAndService(accessToken)
if err != nil {
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
return nil, err
}
var connProps []*bigqueryapi.ConnectionProperty
@@ -179,7 +178,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if source.BigQueryWriteMode() == bigqueryds.WriteModeProtected {
session, err = source.BigQuerySession()(ctx)
if err != nil {
return nil, util.NewClientServerError("failed to get BigQuery session for protected mode", http.StatusInternalServerError, err)
return nil, fmt.Errorf("failed to get BigQuery session for protected mode: %w", err)
}
connProps = []*bigqueryapi.ConnectionProperty{
{Key: "session_id", Value: session.ID},
@@ -188,7 +187,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)
if err != nil {
return nil, util.NewClientServerError("query validation failed", http.StatusInternalServerError, err)
return nil, fmt.Errorf("query validation failed: %w", err)
}
statementType := dryRunJob.Statistics.Query.StatementType
@@ -196,13 +195,13 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
switch source.BigQueryWriteMode() {
case bigqueryds.WriteModeBlocked:
if statementType != "SELECT" {
return nil, util.NewAgentError("write mode is 'blocked', only SELECT statements are allowed", nil)
return nil, fmt.Errorf("write mode is 'blocked', only SELECT statements are allowed")
}
case bigqueryds.WriteModeProtected:
if dryRunJob.Configuration != nil && dryRunJob.Configuration.Query != nil {
if dest := dryRunJob.Configuration.Query.DestinationTable; dest != nil && dest.DatasetId != session.DatasetID {
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), nil)
return nil, fmt.Errorf("protected write mode only supports SELECT statements, or write operations in the anonymous "+
"dataset of a BigQuery session, but destination was %q", dest.DatasetId)
}
}
}
@@ -210,11 +209,11 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if len(source.BigQueryAllowedDatasets()) > 0 {
switch statementType {
case "CREATE_SCHEMA", "DROP_SCHEMA", "ALTER_SCHEMA":
return nil, util.NewAgentError(fmt.Sprintf("dataset-level operations like '%s' are not allowed when dataset restrictions are in place", statementType), nil)
return nil, fmt.Errorf("dataset-level operations like '%s' are not allowed when dataset restrictions are in place", statementType)
case "CREATE_FUNCTION", "CREATE_TABLE_FUNCTION", "CREATE_PROCEDURE":
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)
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)
case "CALL":
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)
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)
}
// Use a map to avoid duplicate table names.
@@ -245,7 +244,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
parsedTables, parseErr := bqutil.TableParser(sql, source.BigQueryClient().Project())
if parseErr != nil {
// If parsing fails (e.g., EXECUTE IMMEDIATE), we cannot guarantee safety, so we must fail.
return nil, util.NewAgentError("could not parse tables from query to validate against allowed datasets", parseErr)
return nil, fmt.Errorf("could not parse tables from query to validate against allowed datasets: %w", parseErr)
}
tableNames = parsedTables
}
@@ -255,7 +254,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if len(parts) == 3 {
projectID, datasetID := parts[0], parts[1]
if !source.IsDatasetAllowed(projectID, datasetID) {
return nil, util.NewAgentError(fmt.Sprintf("query accesses dataset '%s.%s', which is not in the allowed list", projectID, datasetID), nil)
return nil, fmt.Errorf("query accesses dataset '%s.%s', which is not in the allowed list", projectID, datasetID)
}
}
}
@@ -265,7 +264,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if dryRunJob != nil {
jobJSON, err := json.MarshalIndent(dryRunJob, "", " ")
if err != nil {
return nil, util.NewClientServerError("failed to marshal dry run job to JSON", http.StatusInternalServerError, err)
return nil, fmt.Errorf("failed to marshal dry run job to JSON: %w", err)
}
return string(jobJSON), nil
}
@@ -276,14 +275,10 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
// Log the query executed for debugging.
logger, err := util.LoggerFromContext(ctx)
if err != nil {
return nil, util.NewClientServerError("error getting logger", http.StatusInternalServerError, err)
return nil, fmt.Errorf("error getting logger: %s", err)
}
logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql))
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
return source.RunSQL(ctx, bqClient, sql, statementType, nil, connProps)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,7 +17,6 @@ package bigqueryforecast
import (
"context"
"fmt"
"net/http"
"strings"
bigqueryapi "cloud.google.com/go/bigquery"
@@ -134,34 +133,34 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
historyData, ok := paramsMap["history_data"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("unable to cast history_data parameter %v", paramsMap["history_data"]), nil)
return nil, fmt.Errorf("unable to cast history_data parameter %v", paramsMap["history_data"])
}
timestampCol, ok := paramsMap["timestamp_col"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("unable to cast timestamp_col parameter %v", paramsMap["timestamp_col"]), nil)
return nil, fmt.Errorf("unable to cast timestamp_col parameter %v", paramsMap["timestamp_col"])
}
dataCol, ok := paramsMap["data_col"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("unable to cast data_col parameter %v", paramsMap["data_col"]), nil)
return nil, fmt.Errorf("unable to cast data_col parameter %v", paramsMap["data_col"])
}
idColsRaw, ok := paramsMap["id_cols"].([]any)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("unable to cast id_cols parameter %v", paramsMap["id_cols"]), nil)
return nil, fmt.Errorf("unable to cast id_cols parameter %v", paramsMap["id_cols"])
}
var idCols []string
for _, v := range idColsRaw {
s, ok := v.(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("id_cols contains non-string value: %v", v), nil)
return nil, fmt.Errorf("id_cols contains non-string value: %v", v)
}
idCols = append(idCols, s)
}
@@ -170,13 +169,13 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if h, ok := paramsMap["horizon"].(float64); ok {
horizon = int(h)
} else {
return nil, util.NewAgentError(fmt.Sprintf("unable to cast horizon parameter %v", paramsMap["horizon"]), nil)
return nil, fmt.Errorf("unable to cast horizon parameter %v", paramsMap["horizon"])
}
}
bqClient, restService, err := source.RetrieveClientAndService(accessToken)
if err != nil {
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
return nil, err
}
var historyDataSource string
@@ -186,7 +185,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
var connProps []*bigqueryapi.ConnectionProperty
session, err := source.BigQuerySession()(ctx)
if err != nil {
return nil, util.NewClientServerError("failed to get BigQuery session", http.StatusInternalServerError, err)
return nil, fmt.Errorf("failed to get BigQuery session: %w", err)
}
if session != nil {
connProps = []*bigqueryapi.ConnectionProperty{
@@ -195,22 +194,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)
if err != nil {
return nil, util.ProecessGcpError(err)
return nil, fmt.Errorf("query validation failed: %w", err)
}
statementType := dryRunJob.Statistics.Query.StatementType
if statementType != "SELECT" {
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)
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)
}
queryStats := dryRunJob.Statistics.Query
if queryStats != nil {
for _, tableRef := range queryStats.ReferencedTables {
if !source.IsDatasetAllowed(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)
return nil, fmt.Errorf("query in history_data accesses dataset '%s.%s', which is not in the allowed list", tableRef.ProjectId, tableRef.DatasetId)
}
}
} else {
return nil, util.NewAgentError("could not analyze query in history_data to validate against allowed datasets", nil)
return nil, fmt.Errorf("could not analyze query in history_data to validate against allowed datasets")
}
}
historyDataSource = fmt.Sprintf("(%s)", historyData)
@@ -227,11 +226,11 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
projectID = source.BigQueryClient().Project()
datasetID = parts[0]
default:
return nil, util.NewAgentError(fmt.Sprintf("invalid table ID format for 'history_data': %q. Expected 'dataset.table' or 'project.dataset.table'", historyData), nil)
return nil, fmt.Errorf("invalid table ID format for 'history_data': %q. Expected 'dataset.table' or 'project.dataset.table'", historyData)
}
if !source.IsDatasetAllowed(projectID, datasetID) {
return nil, util.NewAgentError(fmt.Sprintf("access to dataset '%s.%s' (from table '%s') is not allowed", projectID, datasetID, historyData), nil)
return nil, fmt.Errorf("access to dataset '%s.%s' (from table '%s') is not allowed", projectID, datasetID, historyData)
}
}
historyDataSource = fmt.Sprintf("TABLE `%s`", historyData)
@@ -244,15 +243,15 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
}
sql := fmt.Sprintf(`SELECT *
FROM AI.FORECAST(
%s,
data_col => '%s',
timestamp_col => '%s',
horizon => %d%s)`,
%s,
data_col => '%s',
timestamp_col => '%s',
horizon => %d%s)`,
historyDataSource, dataCol, timestampCol, horizon, idColsArg)
session, err := source.BigQuerySession()(ctx)
if err != nil {
return nil, util.NewClientServerError("failed to get BigQuery session", http.StatusInternalServerError, err)
return nil, fmt.Errorf("failed to get BigQuery session: %w", err)
}
var connProps []*bigqueryapi.ConnectionProperty
if session != nil {
@@ -265,15 +264,11 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
// Log the query executed for debugging.
logger, err := util.LoggerFromContext(ctx)
if err != nil {
return nil, util.NewClientServerError("error getting logger", http.StatusInternalServerError, err)
return nil, fmt.Errorf("error getting logger: %s", err)
}
logger.DebugContext(ctx, fmt.Sprintf("executing `%s` tool query: %s", resourceType, sql))
resp, err := source.RunSQL(ctx, bqClient, sql, "SELECT", nil, connProps)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.RunSQL(ctx, bqClient, sql, "SELECT", nil, connProps)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,7 +17,6 @@ package bigquerygetdatasetinfo
import (
"context"
"fmt"
"net/http"
bigqueryapi "cloud.google.com/go/bigquery"
yaml "github.com/goccy/go-yaml"
@@ -25,7 +24,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
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"
bigqueryrestapi "google.golang.org/api/bigquery/v2"
)
@@ -122,38 +120,38 @@ type Tool struct {
func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
mapParams := params.AsMap()
projectId, ok := mapParams[projectKey].(string)
if !ok {
// 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)
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", projectKey)
}
datasetId, ok := mapParams[datasetKey].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", datasetKey), nil)
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", datasetKey)
}
bqClient, _, err := source.RetrieveClientAndService(accessToken)
if err != nil {
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
return nil, err
}
if !source.IsDatasetAllowed(projectId, datasetId) {
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)
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)
}
dsHandle := bqClient.DatasetInProject(projectId, datasetId)
metadata, err := dsHandle.Metadata(ctx)
if err != nil {
return nil, util.ProecessGcpError(err)
return nil, fmt.Errorf("failed to get metadata for dataset %s (in project %s): %w", datasetId, projectId, err)
}
return metadata, nil

View File

@@ -17,7 +17,6 @@ package bigquerygettableinfo
import (
"context"
"fmt"
"net/http"
bigqueryapi "cloud.google.com/go/bigquery"
yaml "github.com/goccy/go-yaml"
@@ -25,7 +24,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
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"
bigqueryrestapi "google.golang.org/api/bigquery/v2"
)
@@ -127,35 +125,35 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
mapParams := params.AsMap()
projectId, ok := mapParams[projectKey].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", projectKey), nil)
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", projectKey)
}
datasetId, ok := mapParams[datasetKey].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", datasetKey), nil)
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", datasetKey)
}
tableId, ok := mapParams[tableKey].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", tableKey), nil)
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", tableKey)
}
if !source.IsDatasetAllowed(projectId, datasetId) {
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)
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)
}
bqClient, _, err := source.RetrieveClientAndService(accessToken)
if err != nil {
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
return nil, err
}
dsHandle := bqClient.DatasetInProject(projectId, datasetId)
@@ -163,7 +161,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
metadata, err := tableHandle.Metadata(ctx)
if err != nil {
return nil, util.ProecessGcpError(err)
return nil, fmt.Errorf("failed to get metadata for table %s.%s.%s: %w", projectId, datasetId, tableId, err)
}
return metadata, nil

View File

@@ -17,14 +17,12 @@ package bigquerylistdatasetids
import (
"context"
"fmt"
"net/http"
bigqueryapi "cloud.google.com/go/bigquery"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
bigqueryrestapi "google.golang.org/api/bigquery/v2"
"google.golang.org/api/iterator"
@@ -122,10 +120,10 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
if len(source.BigQueryAllowedDatasets()) > 0 {
@@ -134,12 +132,12 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
mapParams := params.AsMap()
projectId, ok := mapParams[projectKey].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", projectKey), nil)
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", projectKey)
}
bqClient, _, err := source.RetrieveClientAndService(accessToken)
if err != nil {
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
return nil, err
}
datasetIterator := bqClient.Datasets(ctx)
datasetIterator.ProjectID = projectId
@@ -151,7 +149,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
break
}
if err != nil {
return nil, util.ProecessGcpError(err)
return nil, fmt.Errorf("unable to iterate through datasets: %w", err)
}
// Remove leading and trailing quotes

View File

@@ -17,7 +17,6 @@ package bigquerylisttableids
import (
"context"
"fmt"
"net/http"
bigqueryapi "cloud.google.com/go/bigquery"
yaml "github.com/goccy/go-yaml"
@@ -25,7 +24,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
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"
bigqueryrestapi "google.golang.org/api/bigquery/v2"
"google.golang.org/api/iterator"
@@ -125,30 +123,31 @@ type Tool struct {
func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
mapParams := params.AsMap()
projectId, ok := mapParams[projectKey].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", projectKey), nil)
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", projectKey)
}
datasetId, ok := mapParams[datasetKey].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", datasetKey), nil)
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", datasetKey)
}
if !source.IsDatasetAllowed(projectId, datasetId) {
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)
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)
}
bqClient, _, err := source.RetrieveClientAndService(accessToken)
if err != nil {
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
return nil, err
}
dsHandle := bqClient.DatasetInProject(projectId, datasetId)
@@ -161,7 +160,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
break
}
if err != nil {
return nil, util.ProecessGcpError(err)
return nil, fmt.Errorf("failed to iterate through tables in dataset %s.%s: %w", projectId, datasetId, err)
}
// Remove leading and trailing quotes

View File

@@ -17,7 +17,6 @@ package bigquerysearchcatalog
import (
"context"
"fmt"
"net/http"
"strings"
dataplexapi "cloud.google.com/go/dataplex/apiv1"
@@ -27,7 +26,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/sources"
bigqueryds "github.com/googleapis/genai-toolbox/internal/sources/bigquery"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/iterator"
)
@@ -188,31 +186,28 @@ func ExtractType(resourceString string) string {
return typeMap[resourceString[lastIndex+1:]]
}
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
pageSize := int32(paramsMap["pageSize"].(int))
prompt, _ := paramsMap["prompt"].(string)
projectIdSlice, err := parameters.ConvertAnySliceToTyped(paramsMap["projectIds"].([]any), "string")
if err != nil {
return nil, util.NewAgentError(fmt.Sprintf("can't convert projectIds to array of strings: %s", err), err)
return nil, fmt.Errorf("can't convert projectIds to array of strings: %s", err)
}
projectIds := projectIdSlice.([]string)
datasetIdSlice, err := parameters.ConvertAnySliceToTyped(paramsMap["datasetIds"].([]any), "string")
if err != nil {
return nil, util.NewAgentError(fmt.Sprintf("can't convert datasetIds to array of strings: %s", err), err)
return nil, fmt.Errorf("can't convert datasetIds to array of strings: %s", err)
}
datasetIds := datasetIdSlice.([]string)
typesSlice, err := parameters.ConvertAnySliceToTyped(paramsMap["types"].([]any), "string")
if err != nil {
return nil, util.NewAgentError(fmt.Sprintf("can't convert types to array of strings: %s", err), err)
return nil, fmt.Errorf("can't convert types to array of strings: %s", err)
}
types := typesSlice.([]string)
@@ -228,17 +223,17 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if source.UseClientAuthorization() {
tokenStr, err := accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
catalogClient, err = dataplexClientCreator(tokenStr)
if err != nil {
return nil, util.NewClientServerError("error creating client from OAuth access token", http.StatusInternalServerError, err)
return nil, fmt.Errorf("error creating client from OAuth access token: %w", err)
}
}
it := catalogClient.SearchEntries(ctx, req)
if it == nil {
return nil, util.NewClientServerError(fmt.Sprintf("failed to create search entries iterator for project %q", source.BigQueryProject()), http.StatusInternalServerError, nil)
return nil, fmt.Errorf("failed to create search entries iterator for project %q", source.BigQueryProject())
}
var results []Response
@@ -248,7 +243,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
break
}
if err != nil {
return nil, util.ProecessGcpError(err)
break
}
entrySource := entry.DataplexEntry.GetEntrySource()
resp := Response{

View File

@@ -17,7 +17,6 @@ package bigquerysql
import (
"context"
"fmt"
"net/http"
"reflect"
"strings"
@@ -28,7 +27,6 @@ import (
bigqueryds "github.com/googleapis/genai-toolbox/internal/sources/bigquery"
"github.com/googleapis/genai-toolbox/internal/tools"
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"
bigqueryrestapi "google.golang.org/api/bigquery/v2"
)
@@ -105,10 +103,11 @@ type Tool struct {
func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
highLevelParams := make([]bigqueryapi.QueryParameter, 0, len(t.Parameters))
@@ -117,7 +116,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
paramsMap := params.AsMap()
newStatement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, paramsMap)
if err != nil {
return nil, util.NewAgentError("unable to extract template params", err)
return nil, fmt.Errorf("unable to extract template params %w", err)
}
for _, p := range t.Parameters {
@@ -128,13 +127,13 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if arrayParam, ok := p.(*parameters.ArrayParameter); ok {
arrayParamValue, ok := value.([]any)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("unable to convert parameter `%s` to []any", name), nil)
return nil, fmt.Errorf("unable to convert parameter `%s` to []any", name)
}
itemType := arrayParam.GetItems().GetType()
var err error
value, err = parameters.ConvertAnySliceToTyped(arrayParamValue, itemType)
if err != nil {
return nil, util.NewAgentError(fmt.Sprintf("unable to convert parameter `%s` from []any to typed slice", name), err)
return nil, fmt.Errorf("unable to convert parameter `%s` from []any to typed slice: %w", name, err)
}
}
@@ -162,7 +161,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
lowLevelParam.ParameterType.Type = "ARRAY"
itemType, err := bqutil.BQTypeStringFromToolType(arrayParam.GetItems().GetType())
if err != nil {
return nil, util.NewAgentError("unable to get BigQuery type from tool parameter type", err)
return nil, err
}
lowLevelParam.ParameterType.ArrayType = &bigqueryrestapi.QueryParameterType{Type: itemType}
@@ -179,7 +178,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
// Handle scalar types based on their defined type.
bqType, err := bqutil.BQTypeStringFromToolType(p.GetType())
if err != nil {
return nil, util.NewAgentError("unable to get BigQuery type from tool parameter type", err)
return nil, err
}
lowLevelParam.ParameterType.Type = bqType
lowLevelParam.ParameterValue.Value = fmt.Sprintf("%v", value)
@@ -191,7 +190,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if source.BigQuerySession() != nil {
session, err := source.BigQuerySession()(ctx)
if err != nil {
return nil, util.NewClientServerError("failed to get BigQuery session", http.StatusInternalServerError, err)
return nil, fmt.Errorf("failed to get BigQuery session: %w", err)
}
if session != nil {
// Add session ID to the connection properties for subsequent calls.
@@ -201,20 +200,17 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
bqClient, restService, err := source.RetrieveClientAndService(accessToken)
if err != nil {
return nil, util.NewClientServerError("failed to retrieve BigQuery client", http.StatusInternalServerError, err)
return nil, err
}
dryRunJob, err := bqutil.DryRunQuery(ctx, restService, bqClient.Project(), bqClient.Location, newStatement, lowLevelParams, connProps)
if err != nil {
return nil, util.ProecessGcpError(err)
return nil, fmt.Errorf("query validation failed: %w", err)
}
statementType := dryRunJob.Statistics.Query.StatementType
resp, err := source.RunSQL(ctx, bqClient, newStatement, statementType, highLevelParams, connProps)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.RunSQL(ctx, bqClient, newStatement, statementType, highLevelParams, connProps)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package bigtable
import (
"context"
"fmt"
"net/http"
"cloud.google.com/go/bigtable"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -98,28 +96,24 @@ type Tool struct {
func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
newStatement, err := parameters.ResolveTemplateParams(t.TemplateParameters, t.Statement, paramsMap)
if err != nil {
return nil, util.NewAgentError("unable to extract template params", err)
return nil, fmt.Errorf("unable to extract template params %w", err)
}
newParams, err := parameters.GetParams(t.Parameters, paramsMap)
if err != nil {
return nil, util.NewAgentError("unable to extract standard params", err)
return nil, fmt.Errorf("unable to extract standard params %w", err)
}
resp, err := source.RunSQL(ctx, newStatement, t.Parameters, newParams)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.RunSQL(ctx, newStatement, t.Parameters, newParams)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -18,13 +18,11 @@ import (
"context"
"encoding/json"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -121,16 +119,17 @@ func (t Tool) ToConfig() tools.ToolConfig {
return t.Config
}
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
// Invoke executes the tool logic
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
query, ok := paramsMap["query"].(string)
if !ok {
return nil, util.NewAgentError("query parameter not found or not a string", nil)
return nil, fmt.Errorf("query parameter not found or not a string")
}
// Parse the access token if provided
@@ -139,7 +138,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
var err error
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
@@ -155,14 +154,9 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
bodyBytes, err := json.Marshal(payload)
if err != nil {
return nil, util.NewClientServerError("failed to marshal request payload", http.StatusInternalServerError, err)
return nil, fmt.Errorf("failed to marshal request payload: %w", err)
}
resp, err := source.RunQuery(ctx, tokenStr, bodyBytes)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.RunQuery(ctx, tokenStr, bodyBytes)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,13 +17,11 @@ package fhirfetchpage
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -95,31 +93,24 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
url, ok := params.AsMap()[pageURLKey].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", pageURLKey), nil)
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", pageURLKey)
}
var tokenStr string
if source.UseClientAuthorization() {
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
resp, err := source.FHIRFetchPage(ctx, url, tokenStr)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.FHIRFetchPage(ctx, url, tokenStr)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,7 +17,6 @@ package fhirpatienteverything
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/goccy/go-yaml"
@@ -25,7 +24,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/googleapi"
)
@@ -118,27 +116,26 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedFHIRStores())
if err != nil {
// ValidateAndFetchStoreID usually returns input validation errors
return nil, util.NewAgentError("failed to validate store ID", err)
return nil, err
}
patientID, ok := params.AsMap()[patientIDKey].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", patientIDKey), nil)
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", patientIDKey)
}
var tokenStr string
if source.UseClientAuthorization() {
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
@@ -146,11 +143,11 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if val, ok := params.AsMap()[typeFilterKey]; ok {
types, ok := val.([]any)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string array", typeFilterKey), nil)
return nil, fmt.Errorf("invalid '%s' parameter; expected a string array", typeFilterKey)
}
typeFilterSlice, err := parameters.ConvertAnySliceToTyped(types, "string")
if err != nil {
return nil, util.NewAgentError(fmt.Sprintf("can't convert '%s' to array of strings: %s", typeFilterKey, err), err)
return nil, fmt.Errorf("can't convert '%s' to array of strings: %s", typeFilterKey, err)
}
if len(typeFilterSlice.([]string)) != 0 {
opts = append(opts, googleapi.QueryParameter("_type", strings.Join(typeFilterSlice.([]string), ",")))
@@ -159,18 +156,13 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if since, ok := params.AsMap()[sinceFilterKey]; ok {
sinceStr, ok := since.(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string", sinceFilterKey), nil)
return nil, fmt.Errorf("invalid '%s' parameter; expected a string", sinceFilterKey)
}
if sinceStr != "" {
opts = append(opts, googleapi.QueryParameter("_since", sinceStr))
}
}
resp, err := source.FHIRPatientEverything(storeID, patientID, tokenStr, opts)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.FHIRPatientEverything(storeID, patientID, tokenStr, opts)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,7 +17,6 @@ package fhirpatientsearch
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/goccy/go-yaml"
@@ -25,7 +24,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/googleapi"
)
@@ -152,22 +150,22 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedFHIRStores())
if err != nil {
return nil, util.NewAgentError("failed to validate store ID", err)
return nil, err
}
var tokenStr string
if source.UseClientAuthorization() {
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
@@ -181,14 +179,14 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
var ok bool
summary, ok = v.(bool)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a boolean", summaryKey), nil)
return nil, fmt.Errorf("invalid '%s' parameter; expected a boolean", summaryKey)
}
continue
}
val, ok := v.(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid parameter '%s'; expected a string", k), nil)
return nil, fmt.Errorf("invalid parameter '%s'; expected a string", k)
}
if val == "" {
continue
@@ -207,7 +205,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
}
parts := strings.Split(val, "/")
if len(parts) != 2 {
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' format; expected YYYY-MM-DD/YYYY-MM-DD", k), nil)
return nil, fmt.Errorf("invalid '%s' format; expected YYYY-MM-DD/YYYY-MM-DD", k)
}
var values []string
if parts[0] != "" {
@@ -231,17 +229,13 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
case familyNameKey:
opts = append(opts, googleapi.QueryParameter("family", val))
default:
return nil, util.NewAgentError(fmt.Sprintf("unexpected parameter key %q", k), nil)
return nil, fmt.Errorf("unexpected parameter key %q", k)
}
}
if summary {
opts = append(opts, googleapi.QueryParameter("_summary", "text"))
}
resp, err := source.FHIRPatientSearch(storeID, tokenStr, opts)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.FHIRPatientSearch(storeID, tokenStr, opts)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,13 +17,11 @@ package gethealthcaredataset
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/healthcare/v1"
)
@@ -92,23 +90,19 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
var tokenStr string
if source.UseClientAuthorization() {
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
resp, err := source.GetDataset(tokenStr)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.GetDataset(tokenStr)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package getdicomstore
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/healthcare/v1"
)
@@ -109,27 +107,23 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
if err != nil {
return nil, util.NewAgentError("failed to validate store ID", err)
return nil, err
}
var tokenStr string
if source.UseClientAuthorization() {
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
resp, err := source.GetDICOMStore(storeID, tokenStr)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.GetDICOMStore(storeID, tokenStr)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package getdicomstoremetrics
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/healthcare/v1"
)
@@ -109,27 +107,23 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
if err != nil {
return nil, util.NewAgentError("failed to validate store ID", err)
return nil, err
}
var tokenStr string
if source.UseClientAuthorization() {
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
resp, err := source.GetDICOMStoreMetrics(storeID, tokenStr)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.GetDICOMStoreMetrics(storeID, tokenStr)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package getfhirresource
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -114,36 +112,32 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedFHIRStores())
if err != nil {
return nil, util.NewAgentError("failed to validate store ID", err)
return nil, err
}
resType, ok := params.AsMap()[typeKey].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", typeKey), nil)
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", typeKey)
}
resID, ok := params.AsMap()[idKey].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected a string", idKey), nil)
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected a string", idKey)
}
var tokenStr string
if source.UseClientAuthorization() {
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
resp, err := source.GetFHIRResource(storeID, resType, resID, tokenStr)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.GetFHIRResource(storeID, resType, resID, tokenStr)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package getfhirstore
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/healthcare/v1"
)
@@ -109,27 +107,23 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedFHIRStores())
if err != nil {
return nil, util.NewAgentError("failed to validate store ID", err)
return nil, err
}
var tokenStr string
if source.UseClientAuthorization() {
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
resp, err := source.GetFHIRStore(storeID, tokenStr)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.GetFHIRStore(storeID, tokenStr)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package getfhirstoremetrics
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/healthcare/v1"
)
@@ -109,27 +107,23 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedFHIRStores())
if err != nil {
return nil, util.NewAgentError("failed to validate store ID", err)
return nil, err
}
var tokenStr string
if source.UseClientAuthorization() {
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
resp, err := source.GetFHIRStoreMetrics(storeID, tokenStr)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.GetFHIRStoreMetrics(storeID, tokenStr)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,13 +17,11 @@ package listdicomstores
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/healthcare/v1"
)
@@ -92,23 +90,19 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
var tokenStr string
if source.UseClientAuthorization() {
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
resp, err := source.ListDICOMStores(tokenStr)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.ListDICOMStores(tokenStr)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,13 +17,11 @@ package listfhirstores
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/healthcare/v1"
)
@@ -92,23 +90,19 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
var tokenStr string
if source.UseClientAuthorization() {
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
resp, err := source.ListFHIRStores(tokenStr)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.ListFHIRStores(tokenStr)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package retrieverendereddicominstance
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -119,44 +117,40 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
if err != nil {
return nil, util.NewAgentError("failed to validate store ID", err)
return nil, err
}
var tokenStr string
if source.UseClientAuthorization() {
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
study, ok := params.AsMap()[studyInstanceUIDKey].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string", studyInstanceUIDKey), nil)
return nil, fmt.Errorf("invalid '%s' parameter; expected a string", studyInstanceUIDKey)
}
series, ok := params.AsMap()[seriesInstanceUIDKey].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string", seriesInstanceUIDKey), nil)
return nil, fmt.Errorf("invalid '%s' parameter; expected a string", seriesInstanceUIDKey)
}
sop, ok := params.AsMap()[sopInstanceUIDKey].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string", sopInstanceUIDKey), nil)
return nil, fmt.Errorf("invalid '%s' parameter; expected a string", sopInstanceUIDKey)
}
frame, ok := params.AsMap()[frameNumberKey].(int)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected an integer", frameNumberKey), nil)
return nil, fmt.Errorf("invalid '%s' parameter; expected an integer", frameNumberKey)
}
resp, err := source.RetrieveRenderedDICOMInstance(storeID, study, series, sop, frame, tokenStr)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.RetrieveRenderedDICOMInstance(storeID, study, series, sop, frame, tokenStr)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,7 +17,6 @@ package searchdicominstances
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/goccy/go-yaml"
@@ -25,7 +24,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/googleapi"
)
@@ -133,33 +131,33 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
if err != nil {
return nil, util.NewAgentError("failed to validate store ID", err)
return nil, err
}
var tokenStr string
if source.UseClientAuthorization() {
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
opts, err := common.ParseDICOMSearchParameters(params, []string{sopInstanceUIDKey, patientNameKey, patientIDKey, accessionNumberKey, referringPhysicianNameKey, studyDateKey, modalityKey})
if err != nil {
return nil, util.NewAgentError("failed to parse DICOM search parameters", err)
return nil, err
}
paramsMap := params.AsMap()
dicomWebPath := "instances"
if studyInstanceUID, ok := paramsMap[studyInstanceUIDKey]; ok {
id, ok := studyInstanceUID.(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string", studyInstanceUIDKey), nil)
return nil, fmt.Errorf("invalid '%s' parameter; expected a string", studyInstanceUIDKey)
}
if id != "" {
dicomWebPath = fmt.Sprintf("studies/%s/instances", id)
@@ -168,7 +166,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if seriesInstanceUID, ok := paramsMap[seriesInstanceUIDKey]; ok {
id, ok := seriesInstanceUID.(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string", seriesInstanceUIDKey), nil)
return nil, fmt.Errorf("invalid '%s' parameter; expected a string", seriesInstanceUIDKey)
}
if id != "" {
if dicomWebPath != "instances" {
@@ -178,11 +176,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
}
}
}
resp, err := source.SearchDICOM(t.Type, storeID, dicomWebPath, tokenStr, opts)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.SearchDICOM(t.Type, storeID, dicomWebPath, tokenStr, opts)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package searchdicomseries
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/googleapi"
)
@@ -130,44 +128,40 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
if err != nil {
return nil, util.NewAgentError("failed to validate store ID", err)
return nil, err
}
var tokenStr string
if source.UseClientAuthorization() {
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
opts, err := common.ParseDICOMSearchParameters(params, []string{seriesInstanceUIDKey, patientNameKey, patientIDKey, accessionNumberKey, referringPhysicianNameKey, studyDateKey, modalityKey})
if err != nil {
return nil, util.NewAgentError("failed to parse DICOM search parameters", err)
return nil, err
}
paramsMap := params.AsMap()
dicomWebPath := "series"
if studyInstanceUID, ok := paramsMap[studyInstanceUIDKey]; ok {
id, ok := studyInstanceUID.(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid '%s' parameter; expected a string", studyInstanceUIDKey), nil)
return nil, fmt.Errorf("invalid '%s' parameter; expected a string", studyInstanceUIDKey)
}
if id != "" {
dicomWebPath = fmt.Sprintf("studies/%s/series", id)
}
}
resp, err := source.SearchDICOM(t.Type, storeID, dicomWebPath, tokenStr, opts)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.SearchDICOM(t.Type, storeID, dicomWebPath, tokenStr, opts)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package searchdicomstudies
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/tools/cloudhealthcare/common"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/googleapi"
)
@@ -126,32 +124,28 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
storeID, err := common.ValidateAndFetchStoreID(params, source.AllowedDICOMStores())
if err != nil {
return nil, util.NewAgentError("failed to validate store ID", err)
return nil, err
}
var tokenStr string
if source.UseClientAuthorization() {
tokenStr, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("error parsing access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("error parsing access token: %w", err)
}
}
opts, err := common.ParseDICOMSearchParameters(params, []string{studyInstanceUIDKey, patientNameKey, patientIDKey, accessionNumberKey, referringPhysicianNameKey, studyDateKey})
if err != nil {
return nil, util.NewAgentError("failed to parse DICOM search parameters", err)
return nil, err
}
dicomWebPath := "studies"
resp, err := source.SearchDICOM(t.Type, storeID, dicomWebPath, tokenStr, opts)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.SearchDICOM(t.Type, storeID, dicomWebPath, tokenStr, opts)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -16,13 +16,11 @@ package cloudloggingadminlistlognames
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -91,10 +89,10 @@ type Tool struct {
Parameters parameters.Parameters `yaml:"parameters"`
}
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
limit := defaultLimit
@@ -102,22 +100,18 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if val, ok := paramsMap["limit"].(int); ok && val > 0 {
limit = val
} else if ok && val < 0 {
return nil, util.NewAgentError("limit must be greater than or equal to 1", nil)
return nil, fmt.Errorf("limit must be greater than or equal to 1")
}
tokenString := ""
if source.UseClientAuthorization() {
tokenString, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("failed to parse access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("failed to parse access token: %w", err)
}
}
resp, err := source.ListLogNames(ctx, limit, tokenString)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.ListLogNames(ctx, limit, tokenString)
}
func (t Tool) ParseParams(data map[string]any, claimsMap map[string]map[string]any) (parameters.ParamValues, error) {

View File

@@ -16,13 +16,11 @@ package cloudloggingadminlistresourcetypes
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -86,25 +84,21 @@ type Tool struct {
mcpManifest tools.McpManifest
}
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
tokenString := ""
if source.UseClientAuthorization() {
tokenString, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("failed to parse access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("failed to parse access token: %w", err)
}
}
resp, err := source.ListResourceTypes(ctx, tokenString)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.ListResourceTypes(ctx, tokenString)
}
func (t Tool) ParseParams(data map[string]any, claimsMap map[string]map[string]any) (parameters.ParamValues, error) {

View File

@@ -16,7 +16,6 @@ package cloudloggingadminquerylogs
import (
"context"
"fmt"
"net/http"
"time"
"github.com/goccy/go-yaml"
@@ -24,7 +23,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/sources"
cla "github.com/googleapis/genai-toolbox/internal/sources/cloudloggingadmin"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -106,10 +104,10 @@ type Tool struct {
mcpManifest tools.McpManifest
}
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
// Parse parameters
@@ -121,7 +119,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if val, ok := paramsMap["limit"].(int); ok && val > 0 {
limit = val
} else if ok && val < 0 {
return nil, util.NewAgentError("limit must be greater than or equal to 1", nil)
return nil, fmt.Errorf("limit must be greater than or equal to 1")
}
// Check for verbosity of output
@@ -131,7 +129,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
var filter string
if f, ok := paramsMap["filter"].(string); ok {
if len(f) == 0 {
return nil, util.NewAgentError("filter cannot be empty if provided", nil)
return nil, fmt.Errorf("filter cannot be empty if provided")
}
filter = f
}
@@ -140,7 +138,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
var startTime string
if val, ok := paramsMap["startTime"].(string); ok && val != "" {
if _, err := time.Parse(time.RFC3339, val); err != nil {
return nil, util.NewAgentError(fmt.Sprintf("startTime must be in RFC3339 format (e.g., 2025-12-09T00:00:00Z): %v", err), err)
return nil, fmt.Errorf("startTime must be in RFC3339 format (e.g., 2025-12-09T00:00:00Z): %w", err)
}
startTime = val
} else {
@@ -151,7 +149,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
var endTime string
if val, ok := paramsMap["endTime"].(string); ok && val != "" {
if _, err := time.Parse(time.RFC3339, val); err != nil {
return nil, util.NewAgentError(fmt.Sprintf("endTime must be in RFC3339 format (e.g., 2025-12-09T23:59:59Z): %v", err), err)
return nil, fmt.Errorf("endTime must be in RFC3339 format (e.g., 2025-12-09T23:59:59Z): %w", err)
}
endTime = val
}
@@ -160,7 +158,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if source.UseClientAuthorization() {
tokenString, err = accessToken.ParseBearerToken()
if err != nil {
return nil, util.NewClientServerError("failed to parse access token", http.StatusUnauthorized, err)
return nil, fmt.Errorf("failed to parse access token: %w", err)
}
}
@@ -173,11 +171,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
Limit: limit,
}
resp, err := source.QueryLogs(ctx, queryParams, tokenString)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.QueryLogs(ctx, queryParams, tokenString)
}
func (t Tool) ParseParams(data map[string]any, claimsMap map[string]map[string]any) (parameters.ParamValues, error) {

View File

@@ -23,7 +23,6 @@ import (
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -94,26 +93,22 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
projectID, ok := paramsMap["projectId"].(string)
if !ok {
return nil, util.NewAgentError("projectId parameter not found or not a string", nil)
return nil, fmt.Errorf("projectId parameter not found or not a string")
}
query, ok := paramsMap["query"].(string)
if !ok {
return nil, util.NewAgentError("query parameter not found or not a string", nil)
return nil, fmt.Errorf("query parameter not found or not a string")
}
resp, err := source.RunQuery(projectID, query)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.RunQuery(projectID, query)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,13 +17,11 @@ package cloudsqlcloneinstance
import (
"context"
"fmt"
"net/http"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
sqladmin "google.golang.org/api/sqladmin/v1"
)
@@ -126,35 +124,31 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("error casting 'project' parameter: %v", paramsMap["project"]), nil)
return nil, fmt.Errorf("error casting 'project' parameter: %v", paramsMap["project"])
}
sourceInstanceName, ok := paramsMap["sourceInstanceName"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("error casting 'sourceInstanceName' parameter: %v", paramsMap["sourceInstanceName"]), nil)
return nil, fmt.Errorf("error casting 'sourceInstanceName' parameter: %v", paramsMap["sourceInstanceName"])
}
destinationInstanceName, ok := paramsMap["destinationInstanceName"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("error casting 'destinationInstanceName' parameter: %v", paramsMap["destinationInstanceName"]), nil)
return nil, fmt.Errorf("error casting 'destinationInstanceName' parameter: %v", paramsMap["destinationInstanceName"])
}
pointInTime, _ := paramsMap["pointInTime"].(string)
preferredZone, _ := paramsMap["preferredZone"].(string)
preferredSecondaryZone, _ := paramsMap["preferredSecondaryZone"].(string)
resp, err := source.CloneInstance(ctx, project, sourceInstanceName, destinationInstanceName, pointInTime, preferredZone, preferredSecondaryZone, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.CloneInstance(ctx, project, sourceInstanceName, destinationInstanceName, pointInTime, preferredZone, preferredSecondaryZone, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,13 +17,11 @@ package cloudsqlcreatebackup
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/sqladmin/v1"
)
@@ -122,30 +120,26 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("error casting 'project' parameter: %v", paramsMap["project"]), nil)
return nil, fmt.Errorf("error casting 'project' parameter: %v", paramsMap["project"])
}
instance, ok := paramsMap["instance"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("error casting 'instance' parameter: %v", paramsMap["instance"]), nil)
return nil, fmt.Errorf("error casting 'instance' parameter: %v", paramsMap["instance"])
}
location, _ := paramsMap["location"].(string)
description, _ := paramsMap["backup_description"].(string)
resp, err := source.InsertBackupRun(ctx, project, instance, location, description, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.InsertBackupRun(ctx, project, instance, location, description, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,13 +17,11 @@ package cloudsqlcreatedatabase
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -119,31 +117,27 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok {
return nil, util.NewAgentError("missing 'project' parameter", nil)
return nil, fmt.Errorf("missing 'project' parameter")
}
instance, ok := paramsMap["instance"].(string)
if !ok {
return nil, util.NewAgentError("missing 'instance' parameter", nil)
return nil, fmt.Errorf("missing 'instance' parameter")
}
name, ok := paramsMap["name"].(string)
if !ok {
return nil, util.NewAgentError("missing 'name' parameter", nil)
return nil, fmt.Errorf("missing 'name' parameter")
}
resp, err := source.CreateDatabase(ctx, name, project, instance, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.CreateDatabase(ctx, name, project, instance, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,13 +17,11 @@ package cloudsqlcreateusers
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -121,34 +119,30 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok {
return nil, util.NewAgentError("missing 'project' parameter", nil)
return nil, fmt.Errorf("missing 'project' parameter")
}
instance, ok := paramsMap["instance"].(string)
if !ok {
return nil, util.NewAgentError("missing 'instance' parameter", nil)
return nil, fmt.Errorf("missing 'instance' parameter")
}
name, ok := paramsMap["name"].(string)
if !ok {
return nil, util.NewAgentError("missing 'name' parameter", nil)
return nil, fmt.Errorf("missing 'name' parameter")
}
iamUser, _ := paramsMap["iamUser"].(bool)
password, _ := paramsMap["password"].(string)
resp, err := source.CreateUsers(ctx, project, instance, name, password, iamUser, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.CreateUsers(ctx, project, instance, name, password, iamUser, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,13 +17,11 @@ package cloudsqlgetinstances
import (
"context"
"fmt"
"net/http"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -119,27 +117,23 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
projectId, ok := paramsMap["projectId"].(string)
if !ok {
return nil, util.NewAgentError("missing 'projectId' parameter", nil)
return nil, fmt.Errorf("missing 'projectId' parameter")
}
instanceId, ok := paramsMap["instanceId"].(string)
if !ok {
return nil, util.NewAgentError("missing 'instanceId' parameter", nil)
return nil, fmt.Errorf("missing 'instanceId' parameter")
}
resp, err := source.GetInstance(ctx, projectId, instanceId, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.GetInstance(ctx, projectId, instanceId, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,13 +17,11 @@ package cloudsqllistdatabases
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -118,27 +116,23 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok {
return nil, util.NewAgentError("missing 'project' parameter", nil)
return nil, fmt.Errorf("missing 'project' parameter")
}
instance, ok := paramsMap["instance"].(string)
if !ok {
return nil, util.NewAgentError("missing 'instance' parameter", nil)
return nil, fmt.Errorf("missing 'instance' parameter")
}
resp, err := source.ListDatabase(ctx, project, instance, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.ListDatabase(ctx, project, instance, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,13 +17,11 @@ package cloudsqllistinstances
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -117,23 +115,19 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok {
return nil, util.NewAgentError("missing 'project' parameter", nil)
return nil, fmt.Errorf("missing 'project' parameter")
}
resp, err := source.ListInstance(ctx, project, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.ListInstance(ctx, project, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,13 +17,11 @@ package cloudsqlrestorebackup
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/sqladmin/v1"
)
@@ -122,33 +120,29 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
targetProject, ok := paramsMap["target_project"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("error casting 'target_project' parameter: %v", paramsMap["target_project"]), nil)
return nil, fmt.Errorf("error casting 'target_project' parameter: %v", paramsMap["target_project"])
}
targetInstance, ok := paramsMap["target_instance"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("error casting 'target_instance' parameter: %v", paramsMap["target_instance"]), nil)
return nil, fmt.Errorf("error casting 'target_instance' parameter: %v", paramsMap["target_instance"])
}
backupID, ok := paramsMap["backup_id"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("error casting 'backup_id' parameter: %v", paramsMap["backup_id"]), nil)
return nil, fmt.Errorf("error casting 'backup_id' parameter: %v", paramsMap["backup_id"])
}
sourceProject, _ := paramsMap["source_project"].(string)
sourceInstance, _ := paramsMap["source_instance"].(string)
resp, err := source.RestoreBackup(ctx, targetProject, targetInstance, sourceProject, sourceInstance, backupID, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.RestoreBackup(ctx, targetProject, targetInstance, sourceProject, sourceInstance, backupID, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package cloudsqlwaitforoperation
import (
"context"
"fmt"
"net/http"
"time"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/sqladmin/v1"
)
@@ -212,21 +210,21 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok {
return nil, util.NewAgentError("missing 'project' parameter", nil)
return nil, fmt.Errorf("missing 'project' parameter")
}
operationID, ok := paramsMap["operation"].(string)
if !ok {
return nil, util.NewAgentError("missing 'operation' parameter", nil)
return nil, fmt.Errorf("missing 'operation' parameter")
}
ctx, cancel := context.WithTimeout(ctx, 30*time.Minute)
@@ -234,7 +232,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
service, err := source.GetService(ctx, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
return nil, err
}
delay := t.Delay
@@ -246,13 +244,13 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
for retries < maxRetries {
select {
case <-ctx.Done():
return nil, util.NewClientServerError("timed out waiting for operation", http.StatusRequestTimeout, ctx.Err())
return nil, fmt.Errorf("timed out waiting for operation: %w", ctx.Err())
default:
}
op, err := source.GetWaitForOperations(ctx, service, project, operationID, cloudSQLConnectionMessageTemplate, delay)
if err != nil {
return nil, util.ProecessGcpError(err)
return nil, err
} else if op != nil {
return op, nil
}
@@ -264,7 +262,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
}
retries++
}
return nil, util.NewClientServerError("exceeded max retries waiting for operation", http.StatusGatewayTimeout, fmt.Errorf("exceeded max retries"))
return nil, fmt.Errorf("exceeded max retries waiting for operation")
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package cloudsqlmssqlcreateinstance
import (
"context"
"fmt"
"net/http" // Added for http.StatusInternalServerError
"strings"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util" // Added for util.ToolboxError
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/sqladmin/v1"
)
@@ -123,33 +121,33 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("error casting 'project' parameter: %s", paramsMap["project"]), nil)
return nil, fmt.Errorf("error casting 'project' parameter: %s", paramsMap["project"])
}
name, ok := paramsMap["name"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("error casting 'name' parameter: %s", paramsMap["name"]), nil)
return nil, fmt.Errorf("error casting 'name' parameter: %s", paramsMap["name"])
}
dbVersion, ok := paramsMap["databaseVersion"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("error casting 'databaseVersion' parameter: %s", paramsMap["databaseVersion"]), nil)
return nil, fmt.Errorf("error casting 'databaseVersion' parameter: %s", paramsMap["databaseVersion"])
}
rootPassword, ok := paramsMap["rootPassword"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("error casting 'rootPassword' parameter: %s", paramsMap["rootPassword"]), nil)
return nil, fmt.Errorf("error casting 'rootPassword' parameter: %s", paramsMap["rootPassword"])
}
editionPreset, ok := paramsMap["editionPreset"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("error casting 'editionPreset' parameter: %s", paramsMap["editionPreset"]), nil)
return nil, fmt.Errorf("error casting 'editionPreset' parameter: %s", paramsMap["editionPreset"])
}
settings := sqladmin.Settings{}
switch strings.ToLower(editionPreset) {
@@ -166,13 +164,9 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
settings.DataDiskSizeGb = 100
settings.DataDiskType = "PD_SSD"
default:
return nil, util.NewAgentError(fmt.Sprintf("invalid 'editionPreset': %q. Must be either 'Production' or 'Development'", editionPreset), nil)
return nil, fmt.Errorf("invalid 'editionPreset': %q. Must be either 'Production' or 'Development'", editionPreset)
}
resp, err := source.CreateInstance(ctx, project, name, dbVersion, rootPassword, settings, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.CreateInstance(ctx, project, name, dbVersion, rootPassword, settings, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package cloudsqlmysqlcreateinstance
import (
"context"
"fmt"
"net/http" // Added for http.StatusInternalServerError
"strings"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util" // Added for util.ToolboxError
"github.com/googleapis/genai-toolbox/internal/util/parameters"
sqladmin "google.golang.org/api/sqladmin/v1"
)
@@ -123,33 +121,33 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok {
return nil, util.NewAgentError("missing 'project' parameter", nil)
return nil, fmt.Errorf("missing 'project' parameter")
}
name, ok := paramsMap["name"].(string)
if !ok {
return nil, util.NewAgentError("missing 'name' parameter", nil)
return nil, fmt.Errorf("missing 'name' parameter")
}
dbVersion, ok := paramsMap["databaseVersion"].(string)
if !ok {
return nil, util.NewAgentError("missing 'databaseVersion' parameter", nil)
return nil, fmt.Errorf("missing 'databaseVersion' parameter")
}
rootPassword, ok := paramsMap["rootPassword"].(string)
if !ok {
return nil, util.NewAgentError("missing 'rootPassword' parameter", nil)
return nil, fmt.Errorf("missing 'rootPassword' parameter")
}
editionPreset, ok := paramsMap["editionPreset"].(string)
if !ok {
return nil, util.NewAgentError("missing 'editionPreset' parameter", nil)
return nil, fmt.Errorf("missing 'editionPreset' parameter")
}
settings := sqladmin.Settings{}
@@ -167,14 +165,10 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
settings.DataDiskSizeGb = 100
settings.DataDiskType = "PD_SSD"
default:
return nil, util.NewAgentError(fmt.Sprintf("invalid 'editionPreset': %q. Must be either 'Production' or 'Development'", editionPreset), nil)
return nil, fmt.Errorf("invalid 'editionPreset': %q. Must be either 'Production' or 'Development'", editionPreset)
}
resp, err := source.CreateInstance(ctx, project, name, dbVersion, rootPassword, settings, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.CreateInstance(ctx, project, name, dbVersion, rootPassword, settings, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package cloudsqlpgcreateinstances
import (
"context"
"fmt"
"net/http" // Added for http.StatusInternalServerError
"strings"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util" // Added for util.ToolboxError
"github.com/googleapis/genai-toolbox/internal/util/parameters"
sqladmin "google.golang.org/api/sqladmin/v1"
)
@@ -123,33 +121,33 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok {
return nil, util.NewAgentError("missing 'project' parameter", nil)
return nil, fmt.Errorf("missing 'project' parameter")
}
name, ok := paramsMap["name"].(string)
if !ok {
return nil, util.NewAgentError("missing 'name' parameter", nil)
return nil, fmt.Errorf("missing 'name' parameter")
}
dbVersion, ok := paramsMap["databaseVersion"].(string)
if !ok {
return nil, util.NewAgentError("missing 'databaseVersion' parameter", nil)
return nil, fmt.Errorf("missing 'databaseVersion' parameter")
}
rootPassword, ok := paramsMap["rootPassword"].(string)
if !ok {
return nil, util.NewAgentError("missing 'rootPassword' parameter", nil)
return nil, fmt.Errorf("missing 'rootPassword' parameter")
}
editionPreset, ok := paramsMap["editionPreset"].(string)
if !ok {
return nil, util.NewAgentError("missing 'editionPreset' parameter", nil)
return nil, fmt.Errorf("missing 'editionPreset' parameter")
}
settings := sqladmin.Settings{}
@@ -167,13 +165,9 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
settings.DataDiskSizeGb = 100
settings.DataDiskType = "PD_SSD"
default:
return nil, util.NewAgentError(fmt.Sprintf("invalid 'editionPreset': %q. Must be either 'Production' or 'Development'", editionPreset), nil)
return nil, fmt.Errorf("invalid 'editionPreset': %q. Must be either 'Production' or 'Development'", editionPreset)
}
resp, err := source.CreateInstance(ctx, project, name, dbVersion, rootPassword, settings, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.CreateInstance(ctx, project, name, dbVersion, rootPassword, settings, string(accessToken))
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package cloudsqlpgupgradeprecheck
import (
"context"
"fmt"
"net/http" // Added for http.StatusInternalServerError
"time"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util" // Added for util.ToolboxError
"github.com/googleapis/genai-toolbox/internal/util/parameters"
sqladmin "google.golang.org/api/sqladmin/v1"
)
@@ -134,31 +132,31 @@ func (t Tool) ToConfig() tools.ToolConfig {
}
// Invoke executes the tool's 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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
project, ok := paramsMap["project"].(string)
if !ok || project == "" {
return nil, util.NewAgentError("missing or empty 'project' parameter", nil)
return nil, fmt.Errorf("missing or empty 'project' parameter")
}
instanceName, ok := paramsMap["instance"].(string)
if !ok || instanceName == "" {
return nil, util.NewAgentError("missing or empty 'instance' parameter", nil)
return nil, fmt.Errorf("missing or empty 'instance' parameter")
}
targetVersion, ok := paramsMap["targetDatabaseVersion"].(string)
if !ok || targetVersion == "" {
// This should not happen due to the default value
return nil, util.NewAgentError("missing or empty 'targetDatabaseVersion' parameter", nil)
return nil, fmt.Errorf("missing or empty 'targetDatabaseVersion' parameter")
}
service, err := source.GetService(ctx, string(accessToken))
if err != nil {
return nil, util.ProecessGcpError(err)
return nil, fmt.Errorf("failed to get HTTP client from source: %w", err)
}
reqBody := &sqladmin.InstancesPreCheckMajorVersionUpgradeRequest{
@@ -170,7 +168,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
call := service.Instances.PreCheckMajorVersionUpgrade(project, instanceName, reqBody).Context(ctx)
op, err := call.Do()
if err != nil {
return nil, util.ProecessGcpError(err)
return nil, fmt.Errorf("failed to start pre-check operation: %w", err)
}
const pollTimeout = 20 * time.Second
@@ -179,7 +177,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
for time.Now().Before(cutoffTime) {
currentOp, err := service.Operations.Get(project, op.Name).Context(ctx).Do()
if err != nil {
return nil, util.ProecessGcpError(err)
return nil, fmt.Errorf("failed to get operation status: %w", err)
}
if currentOp.Status == "DONE" {
@@ -188,7 +186,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if currentOp.Error.Errors[0].Code != "" {
errMsg = fmt.Sprintf("%s (Code: %s)", errMsg, currentOp.Error.Errors[0].Code)
}
return nil, util.NewClientServerError(errMsg, http.StatusInternalServerError, fmt.Errorf("pre-check operation failed with error: %s", errMsg))
return nil, fmt.Errorf("%s", errMsg)
}
var preCheckItems []*sqladmin.PreCheckResponse
@@ -201,7 +199,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
select {
case <-ctx.Done():
return nil, util.NewClientServerError("timed out waiting for operation", http.StatusRequestTimeout, ctx.Err())
return nil, ctx.Err()
case <-time.After(5 * time.Second):
}
}

View File

@@ -17,14 +17,12 @@ package dataplexlookupentry
import (
"context"
"fmt"
"net/http" // Added for http.StatusInternalServerError
dataplexpb "cloud.google.com/go/dataplex/apiv1/dataplexpb"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util" // Added for util.ToolboxError
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -112,10 +110,10 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
@@ -124,14 +122,10 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
view, _ := paramsMap["view"].(int)
aspectTypeSlice, err := parameters.ConvertAnySliceToTyped(paramsMap["aspectTypes"].([]any), "string")
if err != nil {
return nil, util.NewAgentError(fmt.Sprintf("can't convert aspectTypes to array of strings: %s", err), err)
return nil, fmt.Errorf("can't convert aspectTypes to array of strings: %s", err)
}
aspectTypes := aspectTypeSlice.([]string)
resp, err := source.LookupEntry(ctx, name, view, aspectTypes, entry)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.LookupEntry(ctx, name, view, aspectTypes, entry)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package dataplexsearchaspecttypes
import (
"context"
"fmt"
"net/http" // Added for http.StatusInternalServerError
"cloud.google.com/go/dataplex/apiv1/dataplexpb"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util" // Added for util.ToolboxError
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -95,29 +93,16 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
query, ok := paramsMap["query"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("error casting 'query' parameter: %v", paramsMap["query"]), nil)
}
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.ProecessGcpError(err)
}
return resp, nil
query, _ := paramsMap["query"].(string)
pageSize, _ := paramsMap["pageSize"].(int)
orderBy, _ := paramsMap["orderBy"].(string)
return source.SearchAspectTypes(ctx, query, pageSize, orderBy)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,14 +17,12 @@ package dataplexsearchentries
import (
"context"
"fmt"
"net/http" // Added for http.StatusInternalServerError
"cloud.google.com/go/dataplex/apiv1/dataplexpb"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util" // Added for util.ToolboxError
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -95,29 +93,16 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
paramsMap := params.AsMap()
query, ok := paramsMap["query"].(string)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("error casting 'query' parameter: %v", paramsMap["query"]), nil)
}
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.ProecessGcpError(err)
}
return resp, nil
query, _ := paramsMap["query"].(string)
pageSize, _ := paramsMap["pageSize"].(int)
orderBy, _ := paramsMap["orderBy"].(string)
return source.SearchEntries(ctx, query, pageSize, orderBy)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,15 +17,13 @@ package firestoreadddocuments
import (
"context"
"fmt"
"net/http" // Added for http.StatusInternalServerError
firestoreapi "cloud.google.com/go/firestore"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
fsUtil "github.com/googleapis/genai-toolbox/internal/tools/firestore/util"
"github.com/googleapis/genai-toolbox/internal/util" // Added for util.ToolboxError
"github.com/googleapis/genai-toolbox/internal/tools/firestore/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -130,32 +128,32 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
mapParams := params.AsMap()
// Get collection path
collectionPath, ok := mapParams[collectionPathKey].(string)
if !ok || collectionPath == "" {
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter", collectionPathKey), nil)
return nil, fmt.Errorf("invalid or missing '%s' parameter", collectionPathKey)
}
// Validate collection path
if err := fsUtil.ValidateCollectionPath(collectionPath); err != nil {
return nil, util.NewAgentError(fmt.Sprintf("invalid collection path: %v", err), err)
if err := util.ValidateCollectionPath(collectionPath); err != nil {
return nil, fmt.Errorf("invalid collection path: %w", err)
}
// Get document data
documentDataRaw, ok := mapParams[documentDataKey]
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter", documentDataKey), nil)
return nil, fmt.Errorf("invalid or missing '%s' parameter", documentDataKey)
}
// Convert the document data from JSON format to Firestore format
// The client is passed to handle referenceValue types
documentData, err := fsUtil.JSONToFirestoreValue(documentDataRaw, source.FirestoreClient())
documentData, err := util.JSONToFirestoreValue(documentDataRaw, source.FirestoreClient())
if err != nil {
return nil, util.NewAgentError(fmt.Sprintf("failed to convert document data: %v", err), err)
return nil, fmt.Errorf("failed to convert document data: %w", err)
}
// Get return document data flag
@@ -163,11 +161,7 @@ func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, para
if val, ok := mapParams[returnDocumentDataKey].(bool); ok {
returnData = val
}
resp, err := source.AddDocuments(ctx, collectionPath, documentData, returnData)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.AddDocuments(ctx, collectionPath, documentData, returnData)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,15 +17,13 @@ package firestoredeletedocuments
import (
"context"
"fmt"
"net/http" // Added for http.StatusInternalServerError
firestoreapi "cloud.google.com/go/firestore"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
fsUtil "github.com/googleapis/genai-toolbox/internal/tools/firestore/util"
"github.com/googleapis/genai-toolbox/internal/util" // Added for util.ToolboxError
"github.com/googleapis/genai-toolbox/internal/tools/firestore/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -96,43 +94,39 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
mapParams := params.AsMap()
documentPathsRaw, ok := mapParams[documentPathsKey].([]any)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected an array", documentPathsKey), nil)
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected an array", documentPathsKey)
}
if len(documentPathsRaw) == 0 {
return nil, util.NewAgentError(fmt.Sprintf("'%s' parameter cannot be empty", documentPathsKey), nil)
return nil, fmt.Errorf("'%s' parameter cannot be empty", documentPathsKey)
}
// Use ConvertAnySliceToTyped to convert the slice
typedSlice, err := parameters.ConvertAnySliceToTyped(documentPathsRaw, "string")
if err != nil {
return nil, util.NewAgentError(fmt.Sprintf("failed to convert document paths: %v", err), err)
return nil, fmt.Errorf("failed to convert document paths: %w", err)
}
documentPaths, ok := typedSlice.([]string)
if !ok {
return nil, util.NewAgentError("unexpected type conversion error for document paths", nil)
return nil, fmt.Errorf("unexpected type conversion error for document paths")
}
// Validate each document path
for i, path := range documentPaths {
if err := fsUtil.ValidateDocumentPath(path); err != nil {
return nil, util.NewAgentError(fmt.Sprintf("invalid document path at index %d: %v", i, err), err)
if err := util.ValidateDocumentPath(path); err != nil {
return nil, fmt.Errorf("invalid document path at index %d: %w", i, err)
}
}
resp, err := source.DeleteDocuments(ctx, documentPaths)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.DeleteDocuments(ctx, documentPaths)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,15 +17,13 @@ package firestoregetdocuments
import (
"context"
"fmt"
"net/http" // Added for http.StatusInternalServerError
firestoreapi "cloud.google.com/go/firestore"
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
fsUtil "github.com/googleapis/genai-toolbox/internal/tools/firestore/util"
"github.com/googleapis/genai-toolbox/internal/util" // Added for util.ToolboxError
"github.com/googleapis/genai-toolbox/internal/tools/firestore/util"
"github.com/googleapis/genai-toolbox/internal/util/parameters"
)
@@ -96,44 +94,40 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
mapParams := params.AsMap()
documentPathsRaw, ok := mapParams[documentPathsKey].([]any)
if !ok {
return nil, util.NewAgentError(fmt.Sprintf("invalid or missing '%s' parameter; expected an array", documentPathsKey), nil)
return nil, fmt.Errorf("invalid or missing '%s' parameter; expected an array", documentPathsKey)
}
if len(documentPathsRaw) == 0 {
return nil, util.NewAgentError(fmt.Sprintf("'%s' parameter cannot be empty", documentPathsKey), nil)
return nil, fmt.Errorf("'%s' parameter cannot be empty", documentPathsKey)
}
// Use ConvertAnySliceToTyped to convert the slice
typedSlice, err := parameters.ConvertAnySliceToTyped(documentPathsRaw, "string")
if err != nil {
return nil, util.NewAgentError(fmt.Sprintf("failed to convert document paths: %v", err), err)
return nil, fmt.Errorf("failed to convert document paths: %w", err)
}
documentPaths, ok := typedSlice.([]string)
if !ok {
return nil, util.NewAgentError("unexpected type conversion error for document paths", nil)
return nil, fmt.Errorf("unexpected type conversion error for document paths")
}
// Validate each document path
for i, path := range documentPaths {
if err := fsUtil.ValidateDocumentPath(path); err != nil {
return nil, util.NewAgentError(fmt.Sprintf("invalid document path at index %d: %v", i, err), err)
if err := util.ValidateDocumentPath(path); err != nil {
return nil, fmt.Errorf("invalid document path at index %d: %w", i, err)
}
}
resp, err := source.GetDocuments(ctx, documentPaths)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.GetDocuments(ctx, documentPaths)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,13 +17,11 @@ package firestoregetrules
import (
"context"
"fmt"
"net/http" // Added for http.StatusInternalServerError
yaml "github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
"github.com/googleapis/genai-toolbox/internal/sources"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/util" // Added for util.ToolboxError
"github.com/googleapis/genai-toolbox/internal/util/parameters"
"google.golang.org/api/firebaserules/v1"
)
@@ -94,16 +92,12 @@ func (t Tool) ToConfig() tools.ToolConfig {
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)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
return nil, err
}
resp, err := source.GetRules(ctx)
if err != nil {
return nil, util.ProecessGcpError(err)
}
return resp, nil
return source.GetRules(ctx)
}
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {

View File

@@ -17,7 +17,6 @@ package tools
import (
"context"
"fmt"
"net/http"
"slices"
"strings"
@@ -81,13 +80,13 @@ type AccessToken string
func (token AccessToken) ParseBearerToken() (string, error) {
headerParts := strings.Split(string(token), " ")
if len(headerParts) != 2 || strings.ToLower(headerParts[0]) != "bearer" {
return "", util.NewClientServerError("authorization header must be in the format 'Bearer <token>'", http.StatusUnauthorized, nil)
return "", fmt.Errorf("authorization header must be in the format 'Bearer <token>': %w", util.ErrUnauthorized)
}
return headerParts[1], nil
}
type Tool interface {
Invoke(context.Context, SourceProvider, parameters.ParamValues, AccessToken) (any, util.ToolboxError)
Invoke(context.Context, SourceProvider, parameters.ParamValues, AccessToken) (any, error)
EmbedParams(context.Context, parameters.ParamValues, map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error)
Manifest() Manifest
McpManifest() McpManifest

View File

@@ -1,122 +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.
package util
import (
"errors"
"fmt"
"net/http"
"strings"
"google.golang.org/api/googleapi"
)
type ErrorCategory string
const (
CategoryAgent ErrorCategory = "AGENT_ERROR"
CategoryServer ErrorCategory = "SERVER_ERROR"
)
// ToolboxError is the interface all custom errors must satisfy
type ToolboxError interface {
error
Category() ErrorCategory
}
// Agent Errors return 200 to the sender
type AgentError struct {
Msg string
Cause error
}
func (e *AgentError) Error() string { return e.Msg }
func (e *AgentError) Category() ErrorCategory { return CategoryAgent }
func (e *AgentError) Unwrap() error { return e.Cause }
func NewAgentError(msg string, cause error) *AgentError {
return &AgentError{Msg: msg, Cause: cause}
}
// ClientServerError returns 4XX/5XX error code
type ClientServerError struct {
Msg string
Code int
Cause error
}
func (e *ClientServerError) Error() string { return fmt.Sprintf("%s: %v", e.Msg, e.Cause) }
func (e *ClientServerError) Category() ErrorCategory { return CategoryServer }
func (e *ClientServerError) Unwrap() error { return e.Cause }
func NewClientServerError(msg string, code int, cause error) *ClientServerError {
return &ClientServerError{Msg: msg, Code: code, Cause: cause}
}
// ProecessGcpError catches auth related errors and return 401/403 error codes
// Returns AgentError for all other errors
func ProecessGcpError(err error) ToolboxError {
var gErr *googleapi.Error
if errors.As(err, &gErr) {
if gErr.Code == 401 {
return NewClientServerError(
"failed to access GCP resource",
http.StatusUnauthorized,
err,
)
}
if gErr.Code == 403 {
return NewClientServerError(
"failed to access GCP resource",
http.StatusForbidden,
err,
)
}
}
return NewAgentError("error processing GCP request", err)
}
// ProcessGeneralError handles generic errors by inspecting the error string
// for common status code patterns.
func ProcessGeneralError(err error) ToolboxError {
if err == nil {
return nil
}
errStr := err.Error()
// Check for Unauthorized
if strings.Contains(errStr, "Error 401") || strings.Contains(errStr, "status 401") {
return NewClientServerError(
"failed to access resource",
http.StatusUnauthorized,
err,
)
}
// Check for Forbidden
if strings.Contains(errStr, "Error 403") || strings.Contains(errStr, "status 403") {
return NewClientServerError(
"failed to access resource",
http.StatusForbidden,
err,
)
}
// Default to AgentError for logical failures (task execution failed)
return NewAgentError("error processing request", err)
}

View File

@@ -19,7 +19,6 @@ import (
"context"
"encoding/json"
"fmt"
"net/http"
"reflect"
"regexp"
"slices"
@@ -119,7 +118,7 @@ func parseFromAuthService(paramAuthServices []ParamAuthService, claimsMap map[st
}
return v, nil
}
return nil, util.NewClientServerError("missing or invalid authentication header", http.StatusUnauthorized, nil)
return nil, fmt.Errorf("missing or invalid authentication header: %w", util.ErrUnauthorized)
}
// CheckParamRequired checks if a parameter is required based on the required and default field.

View File

@@ -17,6 +17,7 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
@@ -187,3 +188,5 @@ func InstrumentationFromContext(ctx context.Context) (*telemetry.Instrumentation
}
return nil, fmt.Errorf("unable to retrieve instrumentation")
}
var ErrUnauthorized = errors.New("unauthorized")