b844cc47 by Ean Schuessler

Refactor wiki system - remove McpScreenDoc entity

- Remove McpScreenDoc entity and mapping layer
- Use screen paths directly as WikiPage.pagePath
- Fix historySeqId from string "01" to numeric "1"
- Fix DbResourceFile fileData to use CDATA for complex content
- Add wiki descriptions to BrowseScreens subscreens
- Update BrowseScreens to query WikiPage directly by screenPath
- Remove duplicate/corrupt data entries from McpScreenDocsData.xml
1 parent 3f89e412
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
52 <!-- WikiPageHistory for version tracking --> 52 <!-- WikiPageHistory for version tracking -->
53 <moqui.resource.wiki.WikiPageHistory 53 <moqui.resource.wiki.WikiPageHistory
54 wikiPageId="MCP_PROMPTS/get-started" 54 wikiPageId="MCP_PROMPTS/get-started"
55 historySeqId="01" 55 historySeqId="1"
56 versionName="v1" 56 versionName="v1"
57 userId="EX_JOHN_DOE" 57 userId="EX_JOHN_DOE"
58 changeDateTime="2025-12-29 00:00:00.000"/> 58 changeDateTime="2025-12-29 00:00:00.000"/>
......
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!--
3 This software is in the public domain under CC0 1.0 Universal plus a
4 Grant of Patent License.
5
6 To the extent possible under law, the author(s) have dedicated all
7 copyright and related and neighboring rights to this software to the
8 public domain worldwide. This software is distributed without any warranty.
9
10 You should have received a copy of the CC0 Public Domain Dedication
11 along with this software. If not, see
12 <http://creativecommons.org/publicdomain/zero/1.0/>.
13 -->
14 <entity-facade-xml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
15 xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/entity-facade-3.xsd">
16
17 <!-- MCP Screen Documentation Wiki Space -->
18 <moqui.resource.wiki.WikiSpace wikiSpaceId="MCP_SCREEN_DOCS"
19 description="MCP Screen Documentation - LLM instructions for specific screens"
20 restrictView="N"
21 restrictUpdate="Y"
22 rootPageLocation="dbresource://WikiSpace/MCP_SCREEN_DOCS.md"/>
23
24 <!-- WikiSpace Root Page -->
25 <moqui.resource.DbResource
26 resourceId="WIKI_MCP_SCREEN_DOCS"
27 parentResourceId=""
28 filename="MCP_SCREEN_DOCS.md"
29 isFile="Y"/>
30 <moqui.resource.DbResourceFile
31 resourceId="WIKI_MCP_SCREEN_DOCS"
32 mimeType="text/markdown"
33 versionName="v1"><![CDATA[# Moqui MCP Server
34
35 This server provides access to Moqui ERP through MCP.
36
37 ## Getting Started
38
39 Use the following discovery tools to explore available functionality:
40 - `moqui_browse_screens`: Browse Moqui screen hierarchy
41 - `moqui_search_screens`: Search for screens by name to find their paths
42 - `moqui_get_screen_details`: Get input parameters for specific screens
43
44 ## Common Screen Paths
45
46 ### Catalog Operations
47 - `PopCommerce.PopCommerceAdmin.Catalog.Product.FindProduct`: Search and browse products
48 - `PopCommerce.PopCommerceAdmin.Catalog.Feature.FindFeature`: Search by features like color or size
49 - `PopCommerce.PopCommerceAdmin.Catalog.Product.EditPrices`: View and update product prices
50
51 ### Order Management
52 - `PopCommerce.PopCommerceAdmin.Order.FindOrder`: Lookup order status and details
53 - `PopCommerce.PopCommerceAdmin.QuickSearch`: General order and customer search
54
55 ### Customer Management
56 - `PopCommerce.PopCommerceRoot.Customer`: Manage customer accounts
57 - `PopCommerce.PopCommerceAdmin.QuickSearch`: Customer lookup
58
59 ## Tips for LLM Clients
60
61 - All screens support parameterized queries for filtering results
62 - Use `moqui_render_screen` with the screen path to execute screens
63 - Screen paths use dot notation (e.g., `PopCommerce.Catalog.Product`)
64 - Check `moqui_get_screen_details` for required parameters before rendering
65 - Use `renderMode: "mcp"` for structured JSON output or `"text"` for human-readable format]]></moqui.resource.DbResourceFile>
66
67 <!-- Root Wiki Page -->
68 <moqui.resource.wiki.WikiPage
69 wikiPageId="MCP_SCREEN_DOCS/root"
70 wikiSpaceId="MCP_SCREEN_DOCS"
71 pagePath="root"
72 publishedVersionName="v1"
73 restrictView="N">
74 </moqui.resource.wiki.WikiPage>
75
76 <moqui.resource.wiki.WikiPageHistory
77 wikiPageId="MCP_SCREEN_DOCS/root"
78 historySeqId="1"
79 versionName="v1"
80 userId="EX_JOHN_DOE"
81 changeDateTime="2025-01-02 00:00:00.000"/>
82
83 <!-- Root Screen Documentation -->
84 <moqui.resource.DbResource
85 resourceId="WIKI_MCP_DOCS_ROOT"
86 parentResourceId="WIKI_MCP_SCREEN_DOCS"
87 filename="root.md"
88 isFile="Y"/>
89 <moqui.resource.DbResourceFile
90 resourceId="WIKI_MCP_DOCS_ROOT"
91 mimeType="text/markdown"
92 versionName="v1"><![CDATA[# Moqui MCP Server
93
94 This server provides access to Moqui ERP through MCP.
95
96 ## Getting Started
97
98 Use the following discovery tools to explore available functionality:
99 - `moqui_browse_screens`: Browse Moqui screen hierarchy
100 - `moqui_search_screens`: Search for screens by name to find their paths
101 - `moqui_get_screen_details`: Get input parameters for specific screens
102
103 ## Common Screen Paths
104
105 ### Catalog Operations
106 - `PopCommerce.PopCommerceAdmin.Catalog.Product.FindProduct`: Search and browse products
107 - `PopCommerce.PopCommerceAdmin.Catalog.Feature.FindFeature`: Search by features like color or size
108 - `PopCommerce.PopCommerceAdmin.Catalog.Product.EditPrices`: View and update product prices
109
110 ### Order Management
111 - `PopCommerce.PopCommerceAdmin.Order.FindOrder`: Lookup order status and details
112 - `PopCommerce.PopCommerceAdmin.QuickSearch`: General order and customer search
113
114 ### Customer Management
115 - `PopCommerce.PopCommerceRoot.Customer`: Manage customer accounts
116 - `PopCommerce.PopCommerceAdmin.QuickSearch`: Customer lookup
117
118 ## Tips for LLM Clients
119
120 - All screens support parameterized queries for filtering results
121 - Use `moqui_render_screen` with the screen path to execute screens
122 - Screen paths use dot notation (e.g., `PopCommerce.Catalog.Product`)
123 - Check `moqui_get_screen_details` for required parameters before rendering
124 - Use `renderMode: "mcp"` for structured JSON output or `"text"` for human-readable format]]></moqui.resource.DbResourceFile>
125
126 <!-- PopCommerce Root Screen Documentation -->
127 <moqui.resource.DbResource
128 resourceId="WIKI_MCP_DOCS_POPCOMM_ROOT"
129 parentResourceId="WIKI_MCP_SCREEN_DOCS"
130 filename="PopCommerce.PopCommerceRoot.md"
131 isFile="Y"/>
132 <moqui.resource.DbResourceFile
133 resourceId="WIKI_MCP_DOCS_POPCOMM_ROOT"
134 mimeType="text/markdown"
135 versionName="v1"><![CDATA[# PopCommerce Root
136
137 Main storefront and customer-facing screens for PopCommerce e-commerce component.
138
139 ## Key Screens
140
141 - **Customer Management**: Browse and manage customer accounts
142 - **Order Status**: View order history and track shipments
143 - **Product Catalog**: Browse products and categories
144 - **Shopping Cart**: Review and checkout items
145
146 ## Navigation
147
148 Use browse tools to explore the full catalog of PopCommerce screens starting from this root screen.]]></moqui.resource.DbResourceFile>
149
150 <!-- PopCommerce Root Wiki Page -->
151 <moqui.resource.wiki.WikiPage
152 wikiPageId="MCP_SCREEN_DOCS/PopCommerceRoot"
153 wikiSpaceId="MCP_SCREEN_DOCS"
154 pagePath="PopCommerce.PopCommerceRoot"
155 publishedVersionName="v1"
156 restrictView="N">
157 </moqui.resource.wiki.WikiPage>
158
159 <moqui.resource.wiki.WikiPageHistory
160 wikiPageId="MCP_SCREEN_DOCS/PopCommerceRoot"
161 historySeqId="1"
162 versionName="v1"
163 userId="EX_JOHN_DOE"
164 changeDateTime="2025-01-02 00:00:00.000"/>
165
166 <!-- SimpleScreens Root Documentation -->
167 <moqui.resource.DbResource
168 resourceId="WIKI_MCP_DOCS_SIMPLE_ROOT"
169 parentResourceId="WIKI_MCP_SCREEN_DOCS"
170 filename="SimpleScreens.Root.md"
171 isFile="Y"/>
172 <moqui.resource.DbResourceFile
173 resourceId="WIKI_MCP_DOCS_SIMPLE_ROOT"
174 mimeType="text/markdown"
175 versionName="v1"><![CDATA[# Simple Screens Root
176
177 Basic Moqui framework demonstration screens showing common patterns and examples.
178
179 ## Screens
180
181 - **Hello World**: Simple text rendering example
182 - **Examples**: Various framework demonstration screens
183 - **Forms**: Form input and validation examples
184 - **Lists**: Data list and table examples
185
186 ## Usage
187
188 These screens are primarily for learning Moqui screen development patterns.]]></moqui.resource.DbResourceFile>
189
190 <!-- SimpleScreens Root Wiki Page -->
191 <moqui.resource.wiki.WikiPage
192 wikiPageId="MCP_SCREEN_DOCS/SimpleRoot"
193 wikiSpaceId="MCP_SCREEN_DOCS"
194 pagePath="SimpleScreens.Root"
195 publishedVersionName="v1"
196 restrictView="N">
197 </moqui.resource.wiki.WikiPage>
198
199 <moqui.resource.wiki.WikiPageHistory
200 wikiPageId="MCP_SCREEN_DOCS/SimpleRoot"
201 historySeqId="1"
202 versionName="v1"
203 userId="EX_JOHN_DOE"
204 changeDateTime="2025-01-02 00:00:00.000"/>
205
206 </entity-facade-xml>
...@@ -83,10 +83,46 @@ ...@@ -83,10 +83,46 @@
83 if (!supportedVersions.contains(protocolVersion)) { 83 if (!supportedVersions.contains(protocolVersion)) {
84 throw new Exception("Unsupported protocol version: ${protocolVersion}. Supported versions: ${supportedVersions.join(', ')}") 84 throw new Exception("Unsupported protocol version: ${protocolVersion}. Supported versions: ${supportedVersions.join(', ')}")
85 } 85 }
86 86
87 // Get current user context (if authenticated) 87 // Get current user context (if authenticated)
88 def userId = ec.user.userId 88 def userId = ec.user.userId
89 def userAccountId = userId ? userId : null 89 def userAccountId = userId ? userId : null
90
91 // Try to load root instructions from wiki
92 def instructions = null
93 try {
94 def wikiPage = ec.entity.find("moqui.resource.wiki.WikiPage")
95 .condition("wikiSpaceId", "MCP_SCREEN_DOCS")
96 .condition("pagePath", "root")
97 .useCache(true)
98 .one()
99
100 if (wikiPage) {
101 def wikiSpace = ec.entity.find("moqui.resource.wiki.WikiSpace")
102 .condition("wikiSpaceId", wikiPage.wikiSpaceId)
103 .one()
104
105 if (wikiSpace) {
106 def pageLocation = wikiSpace.rootPageLocation
107 if (!pageLocation.endsWith('/')) pageLocation += '/'
108 pageLocation += wikiPage.pagePath + '.md'
109
110 def pageRef = ec.resource.getLocationReference(pageLocation)
111 def wikiText = pageRef?.getText()
112 if (wikiText) {
113 instructions = wikiText
114 ec.logger.info("MCP Initialize: Loaded root instructions from wiki")
115 }
116 }
117 }
118 } catch (Exception e) {
119 ec.logger.debug("Could not load root instructions from wiki: ${e.message}")
120 }
121
122 // Fallback to hardcoded instructions if wiki not available
123 if (!instructions) {
124 instructions = "This server provides access to Moqui ERP through MCP. For common business queries: Use PopCommerce.PopCommerceAdmin.Catalog.Feature.FindFeature to search by features like color or size. Use PopCommerce.PopCommerceAdmin.Catalog.Product.FindProduct for product catalog, PopCommerce.PopCommerceAdmin.Order.FindOrder for order status, PopCommerce.PopCommerceRoot.Customer for customer management, PopCommerce.PopCommerceAdmin.Catalog.Product.EditPrices to check prices and PopCommerce.PopCommerceAdmin.QuickSearch for general searches. All screens support parameterized queries for filtering results."
125 }
90 126
91 // Build server capabilities - don't fetch actual tools/resources during init 127 // Build server capabilities - don't fetch actual tools/resources during init
92 // Tools and resources will be discovered via separate list requests per MCP spec 128 // Tools and resources will be discovered via separate list requests per MCP spec
...@@ -107,7 +143,7 @@ ...@@ -107,7 +143,7 @@
107 capabilities: serverCapabilities, 143 capabilities: serverCapabilities,
108 serverInfo: serverInfo, 144 serverInfo: serverInfo,
109 sessionId: sessionId, 145 sessionId: sessionId,
110 instructions: "This server provides access to Moqui ERP through MCP. For common business queries: Use PopCommerce.PopCommerceAdmin.Catalog.Feature.FindFeature to search by features like color or size. Use PopCommerce.PopCommerceAdmin.Catalog.Product.FindProduct for product catalog, PopCommerce.PopCommerceAdmin.Order.FindOrder for order status, PopCommerce.PopCommerceRoot.Customer for customer management, PopCommerce.PopCommerceAdmin.Catalog.Product.EditPrices to check prices and PopCommerce.PopCommerceAdmin.QuickSearch for general searches. All screens support parameterized queries for filtering results." 146 instructions: instructions
111 ] 147 ]
112 148
113 ec.logger.info("MCP Initialize for user ${userId} (session ${sessionId}): capabilities negotiated") 149 ec.logger.info("MCP Initialize for user ${userId} (session ${sessionId}): capabilities negotiated")
...@@ -353,11 +389,43 @@ ...@@ -353,11 +389,43 @@
353 389
354 // Handle special moqui://mcp/instructions resource 390 // Handle special moqui://mcp/instructions resource
355 if (uri == "moqui://mcp/instructions") { 391 if (uri == "moqui://mcp/instructions") {
392 // Try to load from wiki
393 def instructionsText = null
394 try {
395 def wikiPage = ec.entity.find("moqui.resource.wiki.WikiPage")
396 .condition("wikiSpaceId", "MCP_SCREEN_DOCS")
397 .condition("pagePath", "root")
398 .useCache(true)
399 .one()
400
401 if (wikiPage) {
402 def wikiSpace = ec.entity.find("moqui.resource.wiki.WikiSpace")
403 .condition("wikiSpaceId", wikiPage.wikiSpaceId)
404 .one()
405
406 if (wikiSpace) {
407 def pageLocation = wikiSpace.rootPageLocation
408 if (!pageLocation.endsWith('/')) pageLocation += '/'
409 pageLocation += wikiPage.pagePath + '.md'
410
411 def pageRef = ec.resource.getLocationReference(pageLocation)
412 instructionsText = pageRef?.getText()
413 }
414 }
415 } catch (Exception e) {
416 ec.logger.debug("Could not load instructions from wiki: ${e.message}")
417 }
418
419 // Fallback to hardcoded instructions
420 if (!instructionsText) {
421 instructionsText = "This server provides access to Moqui ERP through MCP. For common business queries: Use PopCommerce.PopCommerceAdmin.Catalog.Feature.FindFeature to search by features like color or size. Use PopCommerce.PopCommerceAdmin.Catalog.Product.FindProduct for product catalog, PopCommerce.PopCommerceAdmin.Order.FindOrder for order status, PopCommerce.PopCommerceRoot.Customer for customer management, PopCommerce.PopCommerceAdmin.Catalog.Product.EditPrices to check prices and PopCommerce.PopCommerceAdmin.QuickSearch for general searches. All screens support parameterized queries for filtering results."
422 }
423
356 result = [ 424 result = [
357 content: [[ 425 content: [[
358 uri: "moqui://mcp/instructions", 426 uri: "moqui://mcp/instructions",
359 mimeType: "text/plain", 427 mimeType: "text/plain",
360 text: "This server provides access to Moqui ERP through MCP. For common business queries: Use PopCommerce.PopCommerceAdmin.Catalog.Feature.FindFeature to search by features like color or size. Use PopCommerce.PopCommerceAdmin.Catalog.Product.FindProduct for product catalog, PopCommerce.PopCommerceAdmin.Order.FindOrder for order status, PopCommerce.PopCommerceRoot.Customer for customer management, PopCommerce.PopCommerceAdmin.Catalog.Product.EditPrices to check prices and PopCommerce.PopCommerceAdmin.QuickSearch for general searches. All screens support parameterized queries for filtering results." 428 text: instructionsText
361 ]], 429 ]],
362 isError: false 430 isError: false
363 ] 431 ]
...@@ -652,11 +720,69 @@ import groovy.json.JsonBuilder ...@@ -652,11 +720,69 @@ import groovy.json.JsonBuilder
652 ExecutionContext ec = context.ec 720 ExecutionContext ec = context.ec
653 721
654 def startTime = System.currentTimeMillis() 722 def startTime = System.currentTimeMillis()
655 723
656 // Set parameters in context 724 // Set parameters in context
657 if (parameters) { 725 if (parameters) {
658 ec.context.putAll(parameters) 726 ec.context.putAll(parameters)
727 }
728
729 // Helper function to get simple path from component path
730 def getSimplePath = { fullPath ->
731 if (!fullPath || fullPath == "root") return "root"
732 String cleanPath = fullPath
733 if (cleanPath.startsWith("component://")) cleanPath = cleanPath.substring(12)
734 if (cleanPath.endsWith(".xml")) cleanPath = cleanPath.substring(0, cleanPath.length() - 4)
735 List<String> parts = cleanPath.split('/').toList()
736 if (parts.size() > 1 && parts[1] == "screen") parts.remove(1)
737 return parts.join('.')
738 }
739
740 // Helper function to load wiki instructions for a screen
741 def getWikiInstructions = { screenPath ->
742 try {
743 def wikiPage = ec.entity.find("moqui.resource.wiki.WikiPage")
744 .condition("wikiSpaceId", "MCP_SCREEN_DOCS")
745 .condition("pagePath", screenPath)
746 .useCache(true)
747 .one()
748
749 if (!wikiPage) return null
750
751 def wikiSpace = ec.entity.find("moqui.resource.wiki.WikiSpace")
752 .condition("wikiSpaceId", wikiPage.wikiSpaceId)
753 .one()
754
755 if (!wikiSpace) return null
756
757 // Build the resource location for the page
758 def pageLocation = wikiSpace.rootPageLocation
759 if (!pageLocation.endsWith('/')) {
760 pageLocation += '/'
659 } 761 }
762 pageLocation += wikiPage.pagePath + '.md'
763
764 // Get the resource reference and text content
765 def pageRef = ec.resource.getLocationReference(pageLocation)
766 def wikiText = pageRef?.getText()
767
768 if (wikiText) {
769 return wikiText
770 }
771 } catch (Exception e) {
772 ec.logger.debug("Could not load wiki instructions for ${screenPath}: ${e.message}")
773 }
774 return null
775 }
776
777 // Resolve input screen path to simple path for lookup
778 def inputScreenPath = screenPath
779 if (screenPath.startsWith("component://")) {
780 inputScreenPath = getSimplePath(screenPath)
781 }
782 ec.logger.info("MCP Screen Execution: Looking up wiki docs for ${inputScreenPath}")
783
784 // Try to get wiki instructions
785 def wikiInstructions = getWikiInstructions(inputScreenPath)
660 786
661 // Check if action is being processed - use real screen rendering if so 787 // Check if action is being processed - use real screen rendering if so
662 def isActionExecution = parameters?.action != null 788 def isActionExecution = parameters?.action != null
...@@ -833,6 +959,7 @@ def startTime = System.currentTimeMillis() ...@@ -833,6 +959,7 @@ def startTime = System.currentTimeMillis()
833 if (mcpData.forms) mcpResult.forms = mcpData.forms 959 if (mcpData.forms) mcpResult.forms = mcpData.forms
834 if (mcpData.actions) mcpResult.actions = mcpData.actions 960 if (mcpData.actions) mcpResult.actions = mcpData.actions
835 if (output) mcpResult.htmlPreview = output.take(2000) + (output.length() > 2000 ? "..." : "") 961 if (output) mcpResult.htmlPreview = output.take(2000) + (output.length() > 2000 ? "..." : "")
962 if (wikiInstructions) mcpResult.wikiInstructions = wikiInstructions
836 963
837 content << [ 964 content << [
838 type: "text", 965 type: "text",
...@@ -840,9 +967,13 @@ def startTime = System.currentTimeMillis() ...@@ -840,9 +967,13 @@ def startTime = System.currentTimeMillis()
840 ] 967 ]
841 } else { 968 } else {
842 // Return raw output for other modes 969 // Return raw output for other modes
970 def textOutput = output
971 if (wikiInstructions) {
972 textOutput = "--- Wiki Instructions ---\n\n${wikiInstructions}\n\n--- Screen Output ---\n\n${output}"
973 }
843 content << [ 974 content << [
844 type: "text", 975 type: "text",
845 text: output, 976 text: textOutput,
846 screenPath: screenPath, 977 screenPath: screenPath,
847 screenUrl: screenUrl, 978 screenUrl: screenUrl,
848 executionTime: executionTime, 979 executionTime: executionTime,
...@@ -1155,6 +1286,73 @@ def startTime = System.currentTimeMillis() ...@@ -1155,6 +1286,73 @@ def startTime = System.currentTimeMillis()
1155 currentPath = currentPath.split("\\?")[0] 1286 currentPath = currentPath.split("\\?")[0]
1156 } 1287 }
1157 1288
1289 // Helper function to load wiki content
1290 def loadWikiContent = { path ->
1291 ec.logger.info("BrowseScreens: loadWikiContent CALLED for ${path}")
1292 try {
1293 def simplePath = (path == "root") ? "root" : path
1294 if (simplePath.contains("?")) {
1295 simplePath = simplePath.split("\\?")[0]
1296 }
1297
1298 ec.logger.info("BrowseScreens: Looking up wiki instructions for ${simplePath}")
1299
1300 def wikiPage = ec.entity.find("moqui.resource.wiki.WikiPage")
1301 .condition("wikiSpaceId", "MCP_SCREEN_DOCS")
1302 .condition("pagePath", simplePath)
1303 .useCache(true)
1304 .one()
1305
1306 if (wikiPage) {
1307 ec.logger.info("BrowseScreens: Found wikiPage: ${wikiPage.pagePath}")
1308 def wikiSpace = ec.entity.find("moqui.resource.wiki.WikiSpace")
1309 .condition("wikiSpaceId", wikiPage.wikiSpaceId)
1310 .one()
1311
1312 if (wikiSpace) {
1313 ec.logger.info("BrowseScreens: Found wikiSpace: ${wikiSpace.wikiSpaceId}")
1314
1315 def dbResource = ec.entity.find("moqui.resource.DbResource")
1316 .condition("parentResourceId", "WIKI_MCP_SCREEN_DOCS")
1317 .condition("filename", wikiPage.pagePath + ".md")
1318 .one()
1319
1320 if (dbResource) {
1321 ec.logger.info("BrowseScreens: Found dbResource: ${dbResource.resourceId}")
1322 def dbResourceFile = ec.entity.find("moqui.resource.DbResourceFile")
1323 .condition("resourceId", dbResource.resourceId)
1324 .condition("versionName", wikiPage.publishedVersionName)
1325 .one()
1326
1327 ec.logger.info("BrowseScreens: dbResourceFile query result: ${dbResourceFile ? 'found' : 'null'}")
1328
1329 if (!dbResourceFile) {
1330 dbResourceFile = ec.entity.find("moqui.resource.DbResourceFile")
1331 .condition("resourceId", dbResource.resourceId)
1332 .one()
1333 ec.logger.info("BrowseScreens: dbResourceFile fallback query result: ${dbResourceFile ? 'found' : 'null'}")
1334 }
1335
1336 if (dbResourceFile) {
1337 ec.logger.info("BrowseScreens: dbResourceFile.fileData: ${dbResourceFile.fileData ? 'exists, size=' + dbResourceFile.fileData.length : 'null'}")
1338 }
1339
1340 if (dbResourceFile && dbResourceFile.fileData) {
1341 def content = new String(dbResourceFile.fileData, "UTF-8")
1342 ec.logger.info("BrowseScreens: Found wiki instructions for ${simplePath}, length: ${content?.length()}")
1343 return content
1344 }
1345 } else {
1346 ec.logger.warn("BrowseScreens: No dbResource found for ${wikiPage.pagePath}.md")
1347 }
1348 }
1349 }
1350 } catch (Exception e) {
1351 ec.logger.warn("BrowseScreens: Error getting wiki instructions: ${e.message}")
1352 }
1353 return null
1354 }
1355
1158 // Helper to convert full component path to simple path (PopCommerce/screen/Root.xml -> PopCommerce.Root) 1356 // Helper to convert full component path to simple path (PopCommerce/screen/Root.xml -> PopCommerce.Root)
1159 def convertToSimplePath = { fullPath -> 1357 def convertToSimplePath = { fullPath ->
1160 if (!fullPath) return null 1358 if (!fullPath) return null
...@@ -1166,6 +1364,18 @@ def startTime = System.currentTimeMillis() ...@@ -1166,6 +1364,18 @@ def startTime = System.currentTimeMillis()
1166 return parts.join('.') 1364 return parts.join('.')
1167 } 1365 }
1168 1366
1367 // Helper to extract short description from wiki content
1368 def getShortDescription = { wikiText ->
1369 if (!wikiText) return null
1370 def lines = wikiText.split('\n')
1371 for (def line : lines) {
1372 if (line.trim() && !line.trim().startsWith('#')) {
1373 return line.trim().take(200)
1374 }
1375 }
1376 return null
1377 }
1378
1169 if (currentPath == "root") { 1379 if (currentPath == "root") {
1170 // Discover top-level applications 1380 // Discover top-level applications
1171 def aacvList = ec.entity.find("moqui.security.ArtifactAuthzCheckView") 1381 def aacvList = ec.entity.find("moqui.security.ArtifactAuthzCheckView")
...@@ -1194,9 +1404,11 @@ def startTime = System.currentTimeMillis() ...@@ -1194,9 +1404,11 @@ def startTime = System.currentTimeMillis()
1194 1404
1195 for (def screenPath in rootScreens) { 1405 for (def screenPath in rootScreens) {
1196 def simplePath = convertToSimplePath(screenPath) 1406 def simplePath = convertToSimplePath(screenPath)
1407 def wikiContent = loadWikiContent(simplePath)
1408 def description = wikiContent ? getShortDescription(wikiContent) : "Application: ${simplePath}"
1197 subscreens << [ 1409 subscreens << [
1198 path: simplePath, 1410 path: simplePath,
1199 description: "Application: ${simplePath}" 1411 description: description
1200 ] 1412 ]
1201 } 1413 }
1202 } else { 1414 } else {
...@@ -1238,9 +1450,11 @@ def startTime = System.currentTimeMillis() ...@@ -1238,9 +1450,11 @@ def startTime = System.currentTimeMillis()
1238 for (subItem in subItems) { 1450 for (subItem in subItems) {
1239 def subName = subItem.getName() 1451 def subName = subItem.getName()
1240 def subPath = currentPath + "." + subName 1452 def subPath = currentPath + "." + subName
1453 def wikiContent = loadWikiContent(subPath)
1454 def description = wikiContent ? getShortDescription(wikiContent) : "Subscreen: ${subName}"
1241 subscreens << [ 1455 subscreens << [
1242 path: subPath, 1456 path: subPath,
1243 description: "Subscreen: ${subName}" 1457 description: description
1244 ] 1458 ]
1245 } 1459 }
1246 } 1460 }
...@@ -1375,11 +1589,18 @@ def startTime = System.currentTimeMillis() ...@@ -1375,11 +1589,18 @@ def startTime = System.currentTimeMillis()
1375 } 1589 }
1376 } 1590 }
1377 1591
1592 // Try to get wiki instructions for screen
1593 def wikiInstructions = null
1594
1595 ec.logger.info("BrowseScreens: About to check wiki instructions, currentPath='${currentPath}', isRoot=${currentPath == 'root'}")
1596
1597 wikiInstructions = loadWikiContent(currentPath)
1598
1378 // Render current screen if not root browsing 1599 // Render current screen if not root browsing
1379 def renderedContent = null 1600 def renderedContent = null
1380 def renderError = null 1601 def renderError = null
1381 def actualRenderMode = renderMode ?: "mcp" 1602 def actualRenderMode = renderMode ?: "mcp"
1382 1603
1383 if (currentPath != "root") { 1604 if (currentPath != "root") {
1384 try { 1605 try {
1385 ec.logger.info("BrowseScreens: Rendering screen ${currentPath} with mode=${actualRenderMode}") 1606 ec.logger.info("BrowseScreens: Rendering screen ${currentPath} with mode=${actualRenderMode}")
...@@ -1467,7 +1688,11 @@ def startTime = System.currentTimeMillis() ...@@ -1467,7 +1688,11 @@ def startTime = System.currentTimeMillis()
1467 if (renderedContent) { 1688 if (renderedContent) {
1468 resultMap.renderedContent = renderedContent 1689 resultMap.renderedContent = renderedContent
1469 } 1690 }
1470 1691
1692 if (wikiInstructions) {
1693 resultMap.wikiInstructions = wikiInstructions
1694 }
1695
1471 if (renderError) { 1696 if (renderError) {
1472 resultMap.renderError = renderError 1697 resultMap.renderError = renderError
1473 } 1698 }
......