From bb2ab0c4993f8815a89aa0bd6c02f9ef487f502a Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 2 Oct 2026 06:38:49 +0000 Subject: [PATCH] fix(insights): resolve room model for RunAgent tools in GetInsightActiveRoomModel GetInsightActiveRoomModel only read options.modelId from the stored ROOM row. The playground writes that key, but RunAgent resolves the model from engine=, ROOM.MODEL_ID, legacy option keys or the workspace config and only sets it on the cached Room, so MCP tools in an agent run got "No model associated with the room". Keep options.modelId first so playground behaviour is unchanged, then fall back to the cached room's model id, the stored MODEL_ID column and the legacy engine/model/engineId option keys. A missing room now gives a clear error instead of a NullPointerException. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01AEekNvT8xFqvVam2ADu1Hu --- .../GetInsightActiveRoomModelReactor.java | 52 ++++++++++++++++--- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/src/prerna/reactor/insights/GetInsightActiveRoomModelReactor.java b/src/prerna/reactor/insights/GetInsightActiveRoomModelReactor.java index b7286e1246e..b631965ed53 100644 --- a/src/prerna/reactor/insights/GetInsightActiveRoomModelReactor.java +++ b/src/prerna/reactor/insights/GetInsightActiveRoomModelReactor.java @@ -29,6 +29,9 @@ import java.util.Map; +import org.apache.commons.lang3.StringUtils; + +import prerna.auth.User; import prerna.engine.impl.model.Room; import prerna.engine.impl.model.inferencetracking.ModelInferenceLogsUtils; import prerna.reactor.AbstractReactor; @@ -37,19 +40,40 @@ public class GetInsightActiveRoomModelReactor extends AbstractReactor { + private static final String MODEL_ID_OPTION_KEY = "modelId"; + /** Older rooms stored the model under these option keys. Same keys AgentRunner reads. */ + private static final String[] LEGACY_MODEL_ID_OPTION_KEYS = { "engine", "model", "engineId" }; + @Override public NounMetadata execute() { String roomId = this.insight.getRoomId(); if (roomId == null) { throw new IllegalArgumentException("Insight is not associated with any room"); } - String userId = this.insight.getUser().getPrimaryLoginToken().getId(); - Room room = ModelInferenceLogsUtils.getRoomById(roomId, userId); + User user = this.insight.getUser(); + String userId = user.getPrimaryLoginToken().getId(); - String modelId = null; - Map optionsMap = room.getOptionsMap(); - if (optionsMap.containsKey("modelId")) { - modelId = (String) optionsMap.get("modelId"); + // The cached room is the one RunAgent works on, so it carries the model the + // run resolved even when that never reached the stored row. + Room cachedRoom = user.getRoomHash().get(roomId); + Room storedRoom = ModelInferenceLogsUtils.getRoomById(roomId, userId); + if (cachedRoom == null && storedRoom == null) { + throw new IllegalArgumentException("Room " + roomId + " does not exist"); + } + + // The playground writes the selected model to options.modelId, so it wins + String modelId = getOption(storedRoom, MODEL_ID_OPTION_KEY); + if (modelId == null) { + modelId = getOption(cachedRoom, MODEL_ID_OPTION_KEY); + } + if (modelId == null) { + modelId = getModelId(cachedRoom); + } + if (modelId == null) { + modelId = getModelId(storedRoom); + } + for (int i = 0; modelId == null && i < LEGACY_MODEL_ID_OPTION_KEYS.length; i++) { + modelId = getOption(storedRoom, LEGACY_MODEL_ID_OPTION_KEYS[i]); } if (modelId == null) { throw new IllegalArgumentException("No model associated with the room"); @@ -58,6 +82,22 @@ public NounMetadata execute() { return new NounMetadata(modelId, PixelDataType.CONST_STRING); } + private static String getOption(Room room, String key) { + if (room == null) { + return null; + } + Map optionsMap = room.getOptionsMap(); + if (optionsMap == null) { + return null; + } + Object value = optionsMap.get(key); + return value instanceof String ? StringUtils.trimToNull((String) value) : null; + } + + private static String getModelId(Room room) { + return room == null ? null : StringUtils.trimToNull(room.getModelId()); + } + @Override public String getReactorDescription() { return "Get the active model for the room set in the current insight";