From 6bc35c24a3878fa3f23b5201bef2b2cdaad119f8 Mon Sep 17 00:00:00 2001 From: labkey-matthewb Date: Wed, 12 Aug 2026 16:14:45 -0700 Subject: [PATCH 1/2] WIP BedRockProvider, GuardRail, ChatException move dependencies to professional/build.gradle --- api/build.gradle | 52 ------------------- .../labkey/api/mcp/AbstractAgentAction.java | 8 +-- .../ExpressionAssistantAgentAction.java | 7 ++- .../query/controllers/QueryController.java | 7 ++- 4 files changed, 7 insertions(+), 67 deletions(-) diff --git a/api/build.gradle b/api/build.gradle index 4631e046e6e..2be9f4fd3da 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -1077,45 +1077,6 @@ dependencies { ) ) - BuildUtils.addExternalDependency( - project, - new ExternalDependency( - "org.springframework.ai:spring-ai-starter-model-google-genai:${springAiVersion}", - "spring-ai-starter-google-genai", - "spring-ai", - "https://github.com/spring-projects/spring-ai", - ExternalDependency.APACHE_2_LICENSE_NAME, - ExternalDependency.APACHE_2_LICENSE_URL, - "LLM Chat Client integration for Gemini" - ) - ) - - BuildUtils.addExternalDependency( - project, - new ExternalDependency( - "org.springframework.ai:spring-ai-anthropic:${springAiVersion}", - "spring-ai-anthropic", - "spring-ai", - "https://github.com/spring-projects/spring-ai", - ExternalDependency.APACHE_2_LICENSE_NAME, - ExternalDependency.APACHE_2_LICENSE_URL, - "LLM Chat Client integration for Claude" - ) - ) - - BuildUtils.addExternalDependency( - project, - new ExternalDependency( - "org.springframework.ai:spring-ai-openai:${springAiVersion}", - "spring-ai-openai", - "spring-ai", - "https://github.com/spring-projects/spring-ai", - ExternalDependency.APACHE_2_LICENSE_NAME, - ExternalDependency.APACHE_2_LICENSE_URL, - "LLM Chat Client integration for ChatGPT" - ) - ) - BuildUtils.addExternalDependency( project, new ExternalDependency( @@ -1142,19 +1103,6 @@ dependencies { ) ) - BuildUtils.addExternalDependency( - project, - new ExternalDependency( - "org.springframework.ai:spring-ai-starter-model-google-genai-embedding:${springAiVersion}", - "spring-ai-starter-model-google-genai-embedding", - "spring-ai", - "https://github.com/spring-projects/spring-ai", - ExternalDependency.APACHE_2_LICENSE_NAME, - ExternalDependency.APACHE_2_LICENSE_URL, - "Vector store integration" - ) - ) - jspImplementation files(project.tasks.jar) jspImplementation apache, jackson, spring } diff --git a/api/src/org/labkey/api/mcp/AbstractAgentAction.java b/api/src/org/labkey/api/mcp/AbstractAgentAction.java index a8bb158aab1..102982a6963 100644 --- a/api/src/org/labkey/api/mcp/AbstractAgentAction.java +++ b/api/src/org/labkey/api/mcp/AbstractAgentAction.java @@ -15,8 +15,6 @@ */ package org.labkey.api.mcp; -import com.google.genai.errors.ClientException; -import com.google.genai.errors.ServerException; import jakarta.servlet.http.HttpSession; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; @@ -167,17 +165,13 @@ else if (isNotBlank(response.text())) } return ret; } - catch (ServerException x) + catch (ChatException x) { return new JSONObject(Map.of( "error", x.getMessage(), "text", "ERROR: " + x.getMessage(), "success", Boolean.FALSE)); } - catch (ClientException ex) - { - return errorResponse(ex); - } } protected @NotNull JSONObject errorResponse(Exception ex) diff --git a/query/src/org/labkey/query/controllers/ExpressionAssistantAgentAction.java b/query/src/org/labkey/query/controllers/ExpressionAssistantAgentAction.java index 297fbb80825..c10cebb0c3d 100644 --- a/query/src/org/labkey/query/controllers/ExpressionAssistantAgentAction.java +++ b/query/src/org/labkey/query/controllers/ExpressionAssistantAgentAction.java @@ -15,8 +15,6 @@ */ package org.labkey.query.controllers; -import com.google.genai.errors.ClientException; -import com.google.genai.errors.ServerException; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -26,6 +24,7 @@ import org.junit.Test; import org.labkey.api.markdown.MarkdownService; import org.labkey.api.mcp.AbstractAgentAction; +import org.labkey.api.mcp.ChatException; import org.labkey.api.mcp.McpContext; import org.labkey.api.mcp.McpService; import org.labkey.api.query.RuntimeValidationException; @@ -96,7 +95,7 @@ public Object execute(ParseForm form, BindException errors) throws Exception LOG.info("Expression assistant prompt: {}", prompt); responses = McpService.get().sendMessageEx(chatSession, composedPrompt); } - catch (ServerException x) + catch (ChatException x) { return new JSONObject(Map.of( "error", x.getMessage(), @@ -110,7 +109,7 @@ public Object execute(ParseForm form, BindException errors) throws Exception "conversationId", getConversationId(), "segments", segments)); } - catch (ClientException x) + catch (ChatException x) { return errorResponse(x); } diff --git a/query/src/org/labkey/query/controllers/QueryController.java b/query/src/org/labkey/query/controllers/QueryController.java index 64743343c08..571cbdbdc7f 100644 --- a/query/src/org/labkey/query/controllers/QueryController.java +++ b/query/src/org/labkey/query/controllers/QueryController.java @@ -19,8 +19,6 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.genai.errors.ClientException; -import com.google.genai.errors.ServerException; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -153,6 +151,7 @@ import org.labkey.api.files.FileContentService; import org.labkey.api.gwt.client.AuditBehaviorType; import org.labkey.api.mcp.AbstractAgentAction; +import org.labkey.api.mcp.ChatException; import org.labkey.api.mcp.McpContext; import org.labkey.api.mcp.McpService; import org.labkey.api.mcp.PromptForm; @@ -8684,7 +8683,7 @@ public Object execute(SqlPromptForm form, BindException errors) throws Exception responses = McpService.get().sendMessageEx(chatSession, prompt); sqlResponse = extractSql(responses); } - catch (ServerException x) + catch (ChatException x) { return new JSONObject(Map.of( "error", x.getMessage(), @@ -8733,7 +8732,7 @@ public Object execute(SqlPromptForm form, BindException errors) throws Exception ret.put("html", sqlResponse.html()); return ret; } - catch (ClientException ex) + catch (ChatException ex) { return errorResponse(ex); } From 85ac235e1c478f906c0cf54d6fb1a381bd1974cd Mon Sep 17 00:00:00 2001 From: labkey-matthewb Date: Thu, 13 Aug 2026 12:07:04 -0700 Subject: [PATCH 2/2] ChatException --- api/src/org/labkey/api/mcp/ChatException.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 api/src/org/labkey/api/mcp/ChatException.java diff --git a/api/src/org/labkey/api/mcp/ChatException.java b/api/src/org/labkey/api/mcp/ChatException.java new file mode 100644 index 00000000000..f304ff1a8ed --- /dev/null +++ b/api/src/org/labkey/api/mcp/ChatException.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026 LabKey Corporation + * + * 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 org.labkey.api.mcp; + +// Provider-agnostic wrapper for exceptions thrown by the active _ModelProvider's ChatModel, so callers can handle +// chat failures without depending on any specific vendor SDK (Anthropic/OpenAI/Gemini/Bedrock/Ollama, etc.). +public class ChatException extends RuntimeException +{ + public ChatException(String message, Throwable cause) + { + super(message, cause); + } +} \ No newline at end of file