- 05 Feb, 2026 7 commits
-
-
BREAKING: Introduces new LLM Request/Response pattern for CSR agents Major Changes: - Add new SystemMessage types: SmtyLlmRequest, SmtyLlmResponse - Extend SystemMessage entity with callback and audit fields: * parentSystemMessageId - Links Response → Request * callbackServiceName - Service to call when LLM completes * callbackParameters - JSON params for callback * sourceTypeEnumId/sourceId - Audit trail (Order, CommEvent, etc.) * llmResponse - Raw response stored for debugging New Services: - AgentServices.process#LLMRequest: General-purpose async LLM service * Any trigger (SECA, UI, Order, etc.) can call this * Creates SmtyLlmRequest SystemMessage * Triggers async processing via poller * Validates callback service exists before creating task Refactored Services: - AgentServices.run#AgentTaskTurn: Universal agent processor * Supports both SmtyAgentTask (legacy) and SmtyLlmRequest (new) * ALWAYS provides MCP tools to LLM (for CSR agent pattern) * Creates SmtyLlmResponse and calls callback for new pattern * Maintains backward compatibility with SmtyAgentTask - AgentServices.callback#CommunicationEvent: Saves LLM responses to conversation * Callback service for CommunicationEvent-triggered requests * Maintains conversation thread via rootCommEventId Updated SECA: - AgentTriggerOnCommunication now calls AgentServices.process#LLMRequest * Uses callback pattern instead of direct SystemMessage creation * Enables full audit trail via SystemMessage Request
Ean Schuessler committed
Response
Benefits:
- General-purpose: Any trigger can request LLM processing (orders, inventory, support, etc.)
- Traceability: Full audit trail via linked SystemMessages
- RBAC: Agent impersonates users, respects permissions
- Same UX: Agent uses same screens humans use (via MCP tools)
- Flexible: Different callbacks handle responses differently -
- AgentServices.xml: Added authenticate='false' to OpenAiChatCompletion, added logging to AgentQueue poller - Agent.secas.xml: Added extensive logging to trigger SECA - AgentData.xml: Fixed SmtyAgentTask to use run#AgentTaskTurn as consumeServiceName
Ean Schuessler committed -
- Update AgentServices.xml: Single-turn state machine (process one turn, re-queue if tool called) - Add Agent.secas.xml: Trigger Agent Turn on new CommunicationEvent to Agent Party - Update AgentEntities.xml: Add rootCommEventId to SystemMessage for thread tracking - Update AgentData.xml: Define Agent Party, Role, and default VLLM config
Ean Schuessler committed -
Prevent receive#IncomingSystemMessage from auto-consuming messages by setting receiveServiceName to empty string instead of null. This allows AgentQueuePoller to pick up SmtyAgentTask messages before they are consumed by the receive service.
Ean Schuessler committed -
The data file in runtime/component directory didn't have consumeServiceName, so adding it back. Needs rebuild to load properly.
Ean Schuessler committed -
This fixes race condition where receive#IncomingSystemMessage was immediately consuming the message instead of letting AgentQueuePoller pick it up. Now: - Message created with SmsgReceived status - AgentQueuePoller (calls poll#AgentQueue) finds and processes it
Ean Schuessler committed -
Remove duplicate/corrupted content at end of file - Lines were orphaned from previous edit - File now has proper structure with 3 services
Ean Schuessler committed
-
- 04 Feb, 2026 17 commits
-
-
- Remove response message creation and task status updates from run#AgentTask - Let poll#AgentQueue handle all status management - Pass noStatusUpdate=false to run#AgentTask to prevent auto status changes - run#AgentTask now just calls LLM and returns result This fixes NullPointerException issues and simplifies the agent flow
Ean Schuessler committed -
Add consumeServiceName='AgentServices.poll#AgentQueue' to SmtyAgentTask This fixes the 'no consumeServiceName, not consuming' error.
Ean Schuessler committed -
Remove consumeServiceName from SmtyAgentTask. This allows receive#IncomingSystemMessage to create SystemMessage (status=SmsgReceived) which poll#AgentQueue can then process.
Ean Schuessler committed -
Changes: 1. Add contentType='application/json' to SmtyAgentTask SystemMessageType 2. Update run#AgentTask to create response as child SystemMessage 3. Use parentMessageId to link response to original task 4. Use ackMessageId to correlate request/response 5. Update task status to SmsgConfirmed on completion This follows Moqui framework messaging patterns: - Queue response message (isOutgoing='Y', status='SmsgProduced') - Update original with ackMessageId linking to response - Use proper message flow: Request (SmsgReceived) → Response (SmsgSent) → Confirmed (SmsgConfirmed)
Ean Schuessler committed -
Set contentType='application/json' for proper JSON message handling This enables proper content-type headers when sending messages
Ean Schuessler committed -
- Set authenticate=false on poll#AgentQueue and run#AgentTask - Remove runAsUser from AgentQueuePoller (ServiceJob doesn't support it) - Keep ServiceJobUser record for AGENT_CLAUDE association This should allow the scheduled job to run without user authentication
Ean Schuessler committed -
- Add ServiceJob for AgentQueuePoller (polls every 30 seconds) - Add consumeServiceName="AgentServices.poll#AgentQueue" to SmtyAgentTask SystemMessageType
Ean Schuessler committed -
- Remove SmtyAgentTask and AI Product Store enum entries from AgentEntities.xml - Add SmtyAgentTask as SystemMessageType record in AgentData.xml - These follow the same pattern as demo data
Ean Schuessler committed -
Use SystemMessageType format: systemMessageTypeId instead of enumTypeId/enumTypeId
Ean Schuessler committed -
Create separate enum data file for agent runtime - AiServiceType enum type and values - SmtyAgentTask enum for SystemMessageType Update component.xml to load AgentEnumData.xml
Ean Schuessler committed -
Remove ProductStoreAiConfig and enumerations that have FK issues Keep only essential data: AGENT_CLAUDE user, AgentUsers group, permissions Will add AI config after verifying basic infrastructure loads
Ean Schuessler committed -
ScheduledJob cannot be loaded via seed data - needs to be created through service Will create AgentQueuePoller via service call after rebuild
Ean Schuessler committed -
Remove package prefixes from entity names to match data loader format - ScheduledJob instead of moqui.service.ScheduledJob - UserAccount instead of moqui.security.UserAccount - UserGroup instead of moqui.security.UserGroup - UserGroupMember instead of moqui.security.UserGroupMember - ArtifactGroup instead of moqui.security.ArtifactGroup - ArtifactGroupMember instead of moqui.security.ArtifactGroupMember - ArtifactAuthz instead of moqui.security.ArtifactAuthz - ProductStoreAiConfig instead of moqui.mcp.agent.ProductStoreAiConfig
Ean Schuessler committed -
- Use crunchy.private.brainfood.com:11434/v1 endpoint - Model: bf-ai - API key: brainfood
Ean Schuessler committed -
- AgentEntities.xml: Entity extensions for agent tasks - AgentServices.xml: Agent runner, client, and queue services - AgentData.xml: Scheduled job, user, and AI config seed data
Ean Schuessler committed
-
- 30 Jan, 2026 1 commit
-
-
Ean Schuessler committed
-
- 28 Jan, 2026 2 commits
-
-
Introduce clean adapter layer between Moqui infrastructure and MCP protocol: - transport/MoquiMcpTransport: Interface abstracting transport concerns - transport/SseTransport: SSE implementation with session management - adapter/McpSessionAdapter: Maps Moqui Visit to MCP sessions - adapter/McpToolAdapter: Maps MCP tools/methods to Moqui services - adapter/MoquiNotificationMcpBridge: Bridges Moqui notifications to MCP Simplify EnhancedMcpServlet to orchestrator role, removing inline session management, SSE logic, and tool dispatch. Remove redundant session validation in Initialize service (MoquiAuthFilter handles auth). Delete obsolete files: - VisitBasedMcpSession.groovy (replaced by McpSessionAdapter) - JsonRpcMessage.groovy (using plain Maps) - MoquiMcpTransport.groovy (replaced by new interface)
Ean Schuessler committed -
- Index business process workflows from BUSINESS_PROCESSES wiki space - Add workflow support to search and help tools - Improve documentation with better organized help content - Add type attributes to seed data files - Enhance error handling for workflow loading
Ean Schuessler committed
-
- 23 Jan, 2026 1 commit
-
-
- Fix column extraction to include fields with both search and display widgets - Add all ID fields to row ref as pipe-delimited key=value pairs for unambiguous LLM parsing - Show NULL values as '(none)' in grid cells for consistency - Add ARIA-compliant action result feedback (role=alert for errors, role=status for success) - Pass actionResult through BrowseScreens ARIA mode - Hide batch_operations tool until fixed - Default renderMode to 'aria' instead of 'compact'
Ean Schuessler committed
-
- 21 Jan, 2026 9 commits
-
-
When pseudoId differs from the internal productId (e.g., DEMO_VAR_GR_SM_COPY vs 100204), models were using the display ID for service calls causing FK errors. Now extracts the actual entity ID from the row's link URL and includes it in the row data: - compact: {id: 'DEMO_VAR_GR_SM_COPY', productId: '100204', link: '...'} - aria: {ref: 'DEMO_VAR_GR_SM_COPY', productId: '100204', ...} This is a generic solution that works for any entity type by parsing the primary key parameter from the Edit link URL. Fixes QA issue where models used pseudoId for applyProductFeatures causing 'record does not exist' referential integrity errors.Ean Schuessler committed -
- FTL: Capture Moqui pagination vars (pageIndex, pageSize, pageMaxIndex, listCount) - Compact mode: Add nextCursor object with pageIndex, pageSize, hasMore - ARIA mode: Add nextCursor to grid nodes - Add totalCount to show full result size Usage: Pass nextCursor values as parameters to get next page: parameters: {pageIndex: 1, pageSize: 20} Response format: nextCursor: {pageIndex: 1, pageSize: 20, hasMore: true} totalCount: 29Ean Schuessler committed -
- FTL: Detect header-field search widgets (text-find, date-find, etc.) - FTL: Add 'searchable' flag and search-specific types to field metadata - ARIA: Add role='search' landmark before grids with searchable fields - Compact: Add searchParams array listing filterable parameters - Filter out 'get*' transitions (autocomplete helpers) from transitions list This helps LLM clients understand how to filter form-list results by passing parameters, rather than trying to call autocomplete transitions.
Ean Schuessler committed -
XML mode renders nearly empty screen hierarchy (just path structure, no content or data), which isn't useful for MCP clients. Remaining render modes: - compact: structured actionable summary (default) - aria: accessibility tree for field discovery - text: plain text rendering - html: full HTML rendering
Ean Schuessler committed -
These modes render Vue.js wrapper templates for web frontends, not actual screen content. They only show outer container HTML with subscreen placeholders, which isn't useful for MCP clients. Remaining render modes: - compact: structured actionable summary (default) - aria: accessibility tree for field discovery - text: plain text rendering - html: full HTML rendering - xml: XML rendering
Ean Schuessler committed -
The mcp render mode exposed too much internal detail (service names, full metadata) which confused smaller models into trying to call services directly. Changes: - Remove 'mcp' from renderMode descriptions in tool definitions - Map renderMode='mcp' to 'compact' if explicitly requested - Update AGENTS.md to remove mcp mode documentation - Internal rendering still uses mcp mode, just not exposed to users Users should use: - compact (default): actionable summary - aria: accessibility tree for field discovery - text/html: rendered output
Ean Schuessler committed -
Adds clear instructions in root wiki doc explaining: - How to execute actions (use action parameter, NOT service calls) - How to get dropdown options (use moqui_get_screen_details) - How to get action documentation (use moqui_get_help with help URI) - Updated screen paths to use apps/PopcAdmin format - Added global navigation paths (Messages, Tasks, Calendar) This helps models understand how to use the system after we removed service names and dropdown examples from responses.
Ean Schuessler committed -
ARIA and compact modes now cleaner for smaller models: - Remove service names from actions (confuses models into trying to call services) - Rename 'describedby' to 'help' for clarity (points to moqui_get_help tool) - Remove wiki:screen references (not useful, wiki content already in response) - Fix grid row refs to use specific IDs (productFeatureId, toProductId) instead of repeating generic productId for all rows - Filter navigation links: remove cross-app links, remove action URLs with encoded timestamps (fromDate/thruDate parameters) - Remove dropdown options counts and random examples - just indicate type, use moqui_get_screen_details for actual options This significantly reduces context volume and eliminates patterns that caused smaller models to hallucinate service calls.
Ean Schuessler committed -
ARIA mode was truncating grid rows to 3, links to 10, and actions to 15. This caused models to miss important data (e.g., only seeing 3 of 8 features or 3 of 16 variant associations). Now ARIA mode shows complete data like text mode does.
Ean Schuessler committed
-
- 20 Jan, 2026 3 commits
-
-
Adds globalNav array to every browse_screens response with links to: - My Notifications (apps/my/User/Notifications) - My Messages (apps/my/User/Messages/FindMessage) - My Calendar (apps/my/User/Calendar/MyCalendar) - My Tasks (apps/my/User/Task/MyTasks) These mirror the MyAccountNav component in the web UI and are always available regardless of which app the user is currently browsing. Also adds a hint in uiNarrative.notes about globalNav and search.
Ean Schuessler committed -
The username parameter was being injected into screen render params, which conflicted with FindCustomer's 'username' search field. This caused the screen to filter results to only show customers with username matching the current user (john.sales*), returning 0 results. User context is already available via ec.user for authorization purposes, so injecting these params was redundant and harmful.
Ean Schuessler committed -
Critical fix: Errors now correctly captured and reported - Capture errors immediately after render() in CustomScreenTestImpl - Added saveMessagesToSession() to WebFacadeStub for framework compatibility - Actions that fail validation now report status:'error' instead of false success Documentation fix: Clarify two different feature services - applyProductFeatures: Apply EXISTING features to products (most common) - createProductFeature: Create NEW feature definitions (rare) - Updated EditProduct and ProductFeature wiki docs with correct examples
Ean Schuessler committed
-