Allow the AI a set of magical presets
This is obviously the wrong solution but I want to explore what we need to do to make screens directly explorable. Browser use affords the model the DOM interface, which helps it understand the document. We need to simplify the responses so that the abstraction becomes unnecessary.
Showing
1 changed file
with
139 additions
and
28 deletions
| ... | @@ -413,6 +413,18 @@ | ... | @@ -413,6 +413,18 @@ |
| 413 | def screenPath | 413 | def screenPath |
| 414 | def subscreenName = null | 414 | def subscreenName = null |
| 415 | 415 | ||
| 416 | // Find the actual screen path from the tool definition | ||
| 417 | def actualScreenPath = null | ||
| 418 | def toolDefinition = tools.find { it.name == name } | ||
| 419 | if (toolDefinition?.description) { | ||
| 420 | // Extract actual screen path from description: "Moqui screen: ${screenPath}" | ||
| 421 | def descMatch = toolDefinition.description =~ /Moqui screen: (.+)/ | ||
| 422 | if (descMatch.find()) { | ||
| 423 | actualScreenPath = descMatch.group(1) | ||
| 424 | ec.logger.info("Found actual screen path from tool description: ${actualScreenPath}") | ||
| 425 | } | ||
| 426 | } | ||
| 427 | |||
| 416 | // Check if this is a subscreen (contains dot after the initial prefix) | 428 | // Check if this is a subscreen (contains dot after the initial prefix) |
| 417 | if (toolNameSuffix.contains('.')) { | 429 | if (toolNameSuffix.contains('.')) { |
| 418 | // Split on dot to separate parent screen path from subscreen name | 430 | // Split on dot to separate parent screen path from subscreen name |
| ... | @@ -420,13 +432,25 @@ | ... | @@ -420,13 +432,25 @@ |
| 420 | def parentPath = toolNameSuffix.substring(0, lastDotIndex) | 432 | def parentPath = toolNameSuffix.substring(0, lastDotIndex) |
| 421 | subscreenName = toolNameSuffix.substring(lastDotIndex + 1) | 433 | subscreenName = toolNameSuffix.substring(lastDotIndex + 1) |
| 422 | 434 | ||
| 423 | // Restore parent path: _ -> /, prepend component://, append .xml | 435 | // Use actual screen path if available, otherwise derive from tool name |
| 424 | screenPath = "component://" + parentPath.replace('_', '/') + ".xml" | 436 | if (actualScreenPath) { |
| 425 | ec.logger.info("Decoded subscreen path for tool ${name}: parent=${screenPath}, subscreen=${subscreenName}") | 437 | screenPath = actualScreenPath |
| 438 | ec.logger.info("Using actual screen path for subscreen tool ${name}: ${screenPath}, subscreen=${subscreenName}") | ||
| 439 | } else { | ||
| 440 | // Restore parent path: _ -> /, prepend component://, append .xml | ||
| 441 | screenPath = "component://" + parentPath.replace('_', '/') + ".xml" | ||
| 442 | ec.logger.info("Decoded subscreen path for tool ${name}: parent=${screenPath}, subscreen=${subscreenName}") | ||
| 443 | } | ||
| 426 | } else { | 444 | } else { |
| 427 | // Regular screen path: _ -> /, prepend component://, append .xml | 445 | // Use actual screen path if available, otherwise derive from tool name |
| 428 | screenPath = "component://" + toolNameSuffix.replace('_', '/') + ".xml" | 446 | if (actualScreenPath) { |
| 429 | ec.logger.info("Decoded screen path for tool ${name}: ${screenPath}") | 447 | screenPath = actualScreenPath |
| 448 | ec.logger.info("Using actual screen path for tool ${name}: ${screenPath}") | ||
| 449 | } else { | ||
| 450 | // Regular screen path: _ -> /, prepend component://, append .xml | ||
| 451 | screenPath = "component://" + toolNameSuffix.replace('_', '/') + ".xml" | ||
| 452 | ec.logger.info("Decoded screen path for tool ${name}: ${screenPath}") | ||
| 453 | } | ||
| 430 | } | 454 | } |
| 431 | 455 | ||
| 432 | // Now call the screen tool with proper user context | 456 | // Now call the screen tool with proper user context |
| ... | @@ -1117,7 +1141,7 @@ try { | ... | @@ -1117,7 +1141,7 @@ try { |
| 1117 | def subscreenName = screenPath.split("/")[-1] | 1141 | def subscreenName = screenPath.split("/")[-1] |
| 1118 | if (subscreenName.endsWith(".xml")) subscreenName = subscreenName.substring(0, subscreenName.length() - 4) | 1142 | if (subscreenName.endsWith(".xml")) subscreenName = subscreenName.substring(0, subscreenName.length() - 4) |
| 1119 | 1143 | ||
| 1120 | // Use dot only for first level subscreens, underscore for deeper levels | 1144 | // Use dot for first level subscreens (level 1), underscore for deeper levels (level 2+) |
| 1121 | def separator = (level == 1) ? "." : "_" | 1145 | def separator = (level == 1) ? "." : "_" |
| 1122 | toolName = parentToolName + separator + subscreenName | 1146 | toolName = parentToolName + separator + subscreenName |
| 1123 | ec.logger.info("MCP Screen Discovery: Creating subscreen tool ${toolName} for ${screenPath} (parentToolName: ${parentToolName}, level: ${level}, separator: ${separator})") | 1147 | ec.logger.info("MCP Screen Discovery: Creating subscreen tool ${toolName} for ${screenPath} (parentToolName: ${parentToolName}, level: ${level}, separator: ${separator})") |
| ... | @@ -1147,36 +1171,113 @@ try { | ... | @@ -1147,36 +1171,113 @@ try { |
| 1147 | try { | 1171 | try { |
| 1148 | def screenInfoList = ec.screen.getScreenInfoList(screenPath, 1) | 1172 | def screenInfoList = ec.screen.getScreenInfoList(screenPath, 1) |
| 1149 | def screenInfo = screenInfoList?.first() | 1173 | def screenInfo = screenInfoList?.first() |
| 1150 | ec.logger.info("MCP Screen Discovery: SCREENINFO ${screenInfo}") | 1174 | ec.logger.info("MCP Screen Discovery: SCREENINFO for ${screenPath}: ${screenInfo}") |
| 1151 | if (screenInfo?.subscreenInfoByName) { | 1175 | if (screenInfo?.subscreenInfoByName) { |
| 1152 | ec.logger.info("MCP Screen Discovery: Found ${screenInfo.subscreenInfoByName.size()} subscreens for ${screenPath}") | 1176 | ec.logger.info("MCP Screen Discovery: Found ${screenInfo.subscreenInfoByName.size()} subscreens for ${screenPath}: ${screenInfo.subscreenInfoByName.keySet()}") |
| 1153 | for (subScreenEntry in screenInfo.subscreenInfoByName) { | 1177 | for (subScreenEntry in screenInfo.subscreenInfoByName) { |
| 1154 | ec.logger.info("MCP Screen Discovery: Process subscreen ${subScreenEntry.key}") | 1178 | ec.logger.info("MCP Screen Discovery: ===== Processing subscreen ${subScreenEntry.key} from parent ${screenPath} =====") |
| 1155 | def subScreenInfo = subScreenEntry.value | 1179 | def subScreenInfo = subScreenEntry.value |
| 1156 | def subScreenPathList = subScreenInfo?.screenPath | 1180 | def subScreenPathList = subScreenInfo?.screenPath |
| 1157 | ec.logger.info("MCP Screen Discovery: Processing subscreen entry - key: ${subScreenEntry.key}, location: ${subScreenPathList}") | 1181 | ec.logger.info("MCP Screen Discovery: Processing subscreen entry - key: ${subScreenEntry.key}, location: ${subScreenPathList}, full info: ${subScreenInfo}") |
| 1182 | |||
| 1183 | // Special debug for Catalog.xml | ||
| 1184 | if (screenPath.contains("Catalog.xml")) { | ||
| 1185 | ec.logger.info("MCP Screen Discovery: *** CATALOG DEBUG *** Processing ${subScreenEntry.key} from Catalog.xml") | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | // Special handling for known Catalog.xml subscreens that point to SimpleScreens | ||
| 1189 | def knownLocations = [ | ||
| 1190 | "dashboard": "component://SimpleScreens/screen/SimpleScreens/Catalog/dashboard.xml", | ||
| 1191 | "Category": "component://SimpleScreens/screen/SimpleScreens/Catalog/Category.xml", | ||
| 1192 | "Feature": "component://SimpleScreens/screen/SimpleScreens/Catalog/Feature.xml", | ||
| 1193 | "FeatureGroup": "component://SimpleScreens/screen/SimpleScreens/Catalog/FeatureGroup.xml", | ||
| 1194 | "Product": "component://SimpleScreens/screen/SimpleScreens/Catalog/Product.xml", | ||
| 1195 | "Search": "component://SimpleScreens/screen/SimpleScreens/Catalog/Search.xml" | ||
| 1196 | ] | ||
| 1158 | 1197 | ||
| 1159 | // The screenPathList contains the actual subscreen location path | 1198 | // Try to get the actual subscreen location from multiple sources |
| 1160 | // We need to get the actual location from the subscreen-item definition | ||
| 1161 | def actualSubScreenPath = null | 1199 | def actualSubScreenPath = null |
| 1162 | 1200 | ||
| 1163 | // Try to get the subscreen location from the screen definition | 1201 | // First, try known locations for Catalog.xml subscreens |
| 1164 | try { | 1202 | if (screenPath.contains("Catalog.xml") && knownLocations[subScreenEntry.key]) { |
| 1165 | def parentScreenDef = ec.screen.getScreenDefinition(screenPath) | 1203 | actualSubScreenPath = knownLocations[subScreenEntry.key] |
| 1166 | if (parentScreenDef?.screenNode) { | 1204 | ec.logger.info("MCP Screen Discovery: Using known location for ${subScreenEntry.key}: ${actualSubScreenPath}") |
| 1167 | def subscreensNode = parentScreenDef.screenNode.first("subscreens") | 1205 | } |
| 1168 | if (subscreensNode) { | 1206 | |
| 1169 | def subscreenItem = subscreensNode.children().find { | 1207 | // Then try to get location from subScreenInfo object (most reliable) |
| 1170 | it.name() == "subscreens-item" && it.attribute('name') == subScreenEntry.key | 1208 | if (!actualSubScreenPath && subScreenInfo?.screenPath) { |
| 1209 | // subScreenInfo.screenPath might be a list or string | ||
| 1210 | if (subScreenInfo.screenPath instanceof List) { | ||
| 1211 | // For automatic discovery screens, the path might be constructed differently | ||
| 1212 | def pathList = subScreenInfo.screenPath | ||
| 1213 | ec.logger.info("MCP Screen Discovery: SubScreenInfo path list for ${subScreenEntry.key}: ${pathList}") | ||
| 1214 | |||
| 1215 | // Try to find a valid screen path from the list | ||
| 1216 | for (path in pathList) { | ||
| 1217 | if (path && path.toString().contains(".xml")) { | ||
| 1218 | actualSubScreenPath = path.toString() | ||
| 1219 | break | ||
| 1171 | } | 1220 | } |
| 1172 | if (subscreenItem?.attribute('location')) { | 1221 | } |
| 1173 | actualSubScreenPath = subscreenItem.attribute('location') | 1222 | } else { |
| 1174 | ec.logger.info("MCP Screen Discovery: Found actual subscreen location for ${subScreenEntry.key}: ${actualSubScreenPath}") | 1223 | actualSubScreenPath = subScreenInfo.screenPath.toString() |
| 1224 | } | ||
| 1225 | ec.logger.info("MCP Screen Discovery: SubScreenInfo location for ${subScreenEntry.key}: ${actualSubScreenPath}") | ||
| 1226 | } | ||
| 1227 | |||
| 1228 | // If that didn't work, try XML parsing | ||
| 1229 | if (!actualSubScreenPath) { | ||
| 1230 | try { | ||
| 1231 | def parentScreenDef = ec.screen.getScreenDefinition(screenPath) | ||
| 1232 | ec.logger.info("MCP Screen Discovery: Parent screen def for ${screenPath}: ${parentScreenDef?.screenName}") | ||
| 1233 | if (parentScreenDef?.screenNode) { | ||
| 1234 | def subscreensNode = parentScreenDef.screenNode.first("subscreens") | ||
| 1235 | ec.logger.info("MCP Screen Discovery: Subscreens node: ${subscreensNode}") | ||
| 1236 | if (subscreensNode) { | ||
| 1237 | def subscreenItems = [] | ||
| 1238 | try { | ||
| 1239 | // Try using Groovy's GPath syntax first (most reliable) | ||
| 1240 | subscreenItems = subscreensNode."subscreens-item" | ||
| 1241 | ec.logger.info("MCP Screen Discovery: GPath found ${subscreenItems.size()} subscreen-item elements") | ||
| 1242 | } catch (Exception gpathException) { | ||
| 1243 | ec.logger.info("MCP Screen Discovery: GPath approach failed: ${gpathException.message}") | ||
| 1244 | try { | ||
| 1245 | // Try children() with no parameters | ||
| 1246 | def allChildren = subscreensNode.children() | ||
| 1247 | ec.logger.info("MCP Screen Discovery: children() found: ${allChildren*.name()}") | ||
| 1248 | subscreenItems = allChildren.findAll { | ||
| 1249 | it.name() == "subscreens-item" | ||
| 1250 | } | ||
| 1251 | } catch (Exception childrenException) { | ||
| 1252 | ec.logger.info("MCP Screen Discovery: children() approach failed: ${childrenException.message}") | ||
| 1253 | // Fallback: iterate through node values | ||
| 1254 | subscreensNode.each { child -> | ||
| 1255 | if (child.name() == "subscreens-item") { | ||
| 1256 | subscreenItems << child | ||
| 1257 | } | ||
| 1258 | } | ||
| 1259 | } | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | ec.logger.info("MCP Screen Discovery: Found ${subscreenItems.size()} subscreen-item elements: ${subscreenItems*.attributes()}") | ||
| 1263 | def subscreenItem = subscreenItems.find { | ||
| 1264 | it.attribute('name') == subScreenEntry.key | ||
| 1265 | } | ||
| 1266 | ec.logger.info("MCP Screen Discovery: Looking for subscreen item with name '${subScreenEntry.key}', found: ${subscreenItem?.attributes()}") | ||
| 1267 | if (subscreenItem?.attribute('location')) { | ||
| 1268 | actualSubScreenPath = subscreenItem.attribute('location') | ||
| 1269 | ec.logger.info("MCP Screen Discovery: Found actual subscreen location for ${subScreenEntry.key}: ${actualSubScreenPath}") | ||
| 1270 | } else { | ||
| 1271 | ec.logger.info("MCP Screen Discovery: Subscreen item found but no location attribute") | ||
| 1272 | } | ||
| 1175 | } | 1273 | } |
| 1274 | } else { | ||
| 1275 | ec.logger.info("MCP Screen Discovery: Parent screen def has no screenNode") | ||
| 1176 | } | 1276 | } |
| 1277 | } catch (Exception e) { | ||
| 1278 | ec.logger.info("MCP Screen Discovery: Could not get subscreen location for ${subScreenEntry.key}: ${e.message}") | ||
| 1279 | e.printStackTrace() | ||
| 1177 | } | 1280 | } |
| 1178 | } catch (Exception e) { | ||
| 1179 | ec.logger.debug("MCP Screen Discovery: Could not get subscreen location for ${subScreenEntry.key}: ${e.message}") | ||
| 1180 | } | 1281 | } |
| 1181 | 1282 | ||
| 1182 | // Fallback: try to construct from screenPathList if we couldn't get the actual location | 1283 | // Fallback: try to construct from screenPathList if we couldn't get the actual location |
| ... | @@ -1199,7 +1300,17 @@ try { | ... | @@ -1199,7 +1300,17 @@ try { |
| 1199 | ec.logger.info("MCP Screen Discovery: Processing subscreen path: ${actualSubScreenPath} ${screenPath}") | 1300 | ec.logger.info("MCP Screen Discovery: Processing subscreen path: ${actualSubScreenPath} ${screenPath}") |
| 1200 | processScreenWithSubscreens(actualSubScreenPath, screenPath, processedScreens, toolsAccumulator, toolName, level + 1) | 1301 | processScreenWithSubscreens(actualSubScreenPath, screenPath, processedScreens, toolsAccumulator, toolName, level + 1) |
| 1201 | } else if (!actualSubScreenPath) { | 1302 | } else if (!actualSubScreenPath) { |
| 1202 | ec.logger.info("MCP Screen Discovery: Subscreen entry ${subScreenEntry.key} has no location, skipping") | 1303 | ec.logger.info("MCP Screen Discovery: Subscreen entry ${subScreenEntry.key} has no location, trying automatic discovery") |
| 1304 | // For screens without explicit location (like Product.xml), try automatic discovery | ||
| 1305 | // The subscreen location is typically based on parent screen location + subscreen name | ||
| 1306 | def lastSlash = screenPath.lastIndexOf('/') | ||
| 1307 | if (lastSlash > 0) { | ||
| 1308 | def basePath = screenPath.substring(0, lastSlash + 1) | ||
| 1309 | def autoSubScreenPath = basePath + subScreenEntry.key + ".xml" | ||
| 1310 | ec.logger.info("MCP Screen Discovery: Trying automatic subscreen discovery for ${subScreenEntry.key} at ${autoSubScreenPath}") | ||
| 1311 | |||
| 1312 | processScreenWithSubscreens(autoSubScreenPath, screenPath, processedScreens, toolsAccumulator, toolName, level + 1) | ||
| 1313 | } | ||
| 1203 | } else if (processedScreens.contains(actualSubScreenPath)) { | 1314 | } else if (processedScreens.contains(actualSubScreenPath)) { |
| 1204 | ec.logger.info("MCP Screen Discovery: Subscreen ${actualSubScreenPath} already processed, skipping") | 1315 | ec.logger.info("MCP Screen Discovery: Subscreen ${actualSubScreenPath} already processed, skipping") |
| 1205 | } | 1316 | } |
| ... | @@ -1222,7 +1333,7 @@ try { | ... | @@ -1222,7 +1333,7 @@ try { |
| 1222 | ec.logger.info("MCP Screen Discovery: Starting recursive processing from ${accessibleScreens.size()} base screens") | 1333 | ec.logger.info("MCP Screen Discovery: Starting recursive processing from ${accessibleScreens.size()} base screens") |
| 1223 | for (screenPath in accessibleScreens) { | 1334 | for (screenPath in accessibleScreens) { |
| 1224 | ec.logger.info("MCP Screen Discovery: SCREEN PATH ${screenPath}") | 1335 | ec.logger.info("MCP Screen Discovery: SCREEN PATH ${screenPath}") |
| 1225 | processScreenWithSubscreens(screenPath, null, processedScreens, tools, null, 1) | 1336 | processScreenWithSubscreens(screenPath, null, processedScreens, tools, null, 0) |
| 1226 | } | 1337 | } |
| 1227 | ec.logger.info("MCP Screen Discovery: Recursive processing found ${tools.size()} total tools") | 1338 | ec.logger.info("MCP Screen Discovery: Recursive processing found ${tools.size()} total tools") |
| 1228 | 1339 | ... | ... |
-
Please register or sign in to post a comment