478df063 by Ean Schuessler

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.
1 parent 36e96772
...@@ -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
......