""" React Mode Prompt Generation Handles prompt templates for react mode action handling. """ from typing import Any, List from modules.datamodels.datamodelChat import PromptBundle, PromptPlaceholder from modules.workflows.processing.shared.placeholderFactory import ( extractUserPrompt, extractUserLanguage, extractAvailableMethods, extractAvailableDocumentsSummary, extractAvailableDocumentsIndex, extractAvailableConnectionsIndex, extractPreviousActionResults, extractLearningsAndImprovements, extractLatestRefinementFeedback, ) from modules.workflows.processing.shared.methodDiscovery import methods, getActionParameterSignature def generateReactPlanSelectionPrompt(services, context: Any) -> PromptBundle: """Define placeholders first, then the template; return PromptBundle.""" placeholders: List[PromptPlaceholder] = [ PromptPlaceholder(label="USER_PROMPT", content=extractUserPrompt(context), summaryAllowed=False), PromptPlaceholder(label="AVAILABLE_DOCUMENTS_SUMMARY", content=extractAvailableDocumentsSummary(services, context), summaryAllowed=True), PromptPlaceholder(label="AVAILABLE_METHODS", content=extractAvailableMethods(services), summaryAllowed=False), ] template = """Select one action to advance the task. OBJECTIVE: {{KEY:USER_PROMPT}} AVAILABLE_DOCUMENTS_SUMMARY: {{KEY:AVAILABLE_DOCUMENTS_SUMMARY}} AVAILABLE_METHODS: {{KEY:AVAILABLE_METHODS}} REPLY: Return only a JSON object with the selected action: {{ "action": "method.action_name" }} RULES: 1. Use EXACT action names from AVAILABLE_METHODS 2. Return ONLY JSON - no other text 3. Do NOT use markdown code blocks 4. Do NOT add explanations """ return PromptBundle(prompt=template, placeholders=placeholders) def generateReactParametersPrompt(services, context: Any, compoundActionName: str) -> PromptBundle: """Define placeholders first, then the template; return PromptBundle.""" # derive method/action and signature methodName, actionName = (compoundActionName.split('.', 1) if '.' in compoundActionName else (compoundActionName, '')) actionSignature = getActionParameterSignature(methodName, actionName, methods) # determine action objective if available, else fall back to user prompt actionObjective = None if hasattr(context, 'action_objective') and context.action_objective: actionObjective = context.action_objective elif hasattr(context, 'task_step') and context.task_step and getattr(context.task_step, 'objective', None): actionObjective = context.task_step.objective else: actionObjective = extractUserPrompt(context) placeholders: List[PromptPlaceholder] = [ PromptPlaceholder(label="ACTION_OBJECTIVE", content=actionObjective, summaryAllowed=False), PromptPlaceholder(label="ACTION_SIGNATURE", content=actionSignature, summaryAllowed=False), PromptPlaceholder(label="AVAILABLE_DOCUMENTS_INDEX", content=extractAvailableDocumentsIndex(services, context), summaryAllowed=True), PromptPlaceholder(label="AVAILABLE_CONNECTIONS_INDEX", content=extractAvailableConnectionsIndex(services), summaryAllowed=False), PromptPlaceholder(label="USER_PROMPT", content=extractUserPrompt(context), summaryAllowed=False), PromptPlaceholder(label="USER_LANGUAGE", content=extractUserLanguage(services), summaryAllowed=False), PromptPlaceholder(label="PREVIOUS_ACTION_RESULTS", content=extractPreviousActionResults(context), summaryAllowed=True), PromptPlaceholder(label="LEARNINGS_AND_IMPROVEMENTS", content=extractLearningsAndImprovements(context), summaryAllowed=True), PromptPlaceholder(label="LATEST_REFINEMENT_FEEDBACK", content=extractLatestRefinementFeedback(context), summaryAllowed=True), PromptPlaceholder(label="SELECTED_ACTION", content=compoundActionName, summaryAllowed=False), ] template = """Generate parameters for this action. ACTION_OBJECTIVE (the objective for this action to fulfill): {{KEY:ACTION_OBJECTIVE}} ACTION_SIGNATURE (the signature of the action to generate parameters for): {{KEY:ACTION_SIGNATURE}} AVAILABLE_DOCUMENTS_INDEX: {{KEY:AVAILABLE_DOCUMENTS_INDEX}} AVAILABLE_CONNECTIONS_INDEX: {{KEY:AVAILABLE_CONNECTIONS_INDEX}} USER_REQUEST (final user prompt to deliver): {{KEY:USER_PROMPT}} USER_LANGUAGE: {{KEY:USER_LANGUAGE}} PREVIOUS_ACTION_RESULTS: {{KEY:PREVIOUS_ACTION_RESULTS}} LEARNINGS_AND_IMPROVEMENTS: {{KEY:LEARNINGS_AND_IMPROVEMENTS}} LATEST_REFINEMENT_FEEDBACK: {{KEY:LATEST_REFINEMENT_FEEDBACK}} SELECTED_ACTION: {{KEY:SELECTED_ACTION}} REPLY: Return only a JSON object with the parameters according to the ACTION_SIGNATURE without any comments in the structure below: {{ "parameters": {{ "parameter": "value", }}, "signature": [List of all signatures, you see in the ACTION_SIGNATURE] }} RULES: 1. Use ONLY parameter names from ACTION_SIGNATURE 2. Use exact connection references from AVAILABLE_CONNECTIONS_INDEX for connectionReference parameters 3. Use exact document references from AVAILABLE_DOCUMENTS_INDEX for documentList parameters 4. Learn from PREVIOUS_ACTION_RESULTS and LEARNINGS_AND_IMPROVEMENTS to avoid repeating mistakes 5. Consider LATEST_REFINEMENT_FEEDBACK when generating parameters 6. Use the ACTION_OBJECTIVE to understand the specific goal for this action 7. Generate parameters that align with the USER_LANGUAGE when applicable 8. Return ONLY JSON - no other text 9. Do NOT use markdown code blocks 10. Do NOT add explanations """ return PromptBundle(prompt=template, placeholders=placeholders) def generateReactRefinementPrompt(services, context: Any, reviewContent: str) -> PromptBundle: """Define placeholders first, then the template; return PromptBundle.""" placeholders: List[PromptPlaceholder] = [ PromptPlaceholder(label="USER_PROMPT", content=extractUserPrompt(context), summaryAllowed=False), PromptPlaceholder(label="REVIEW_CONTENT", content=reviewContent, summaryAllowed=True), ] template = """Decide the next step based on the observation. OBJECTIVE: {{KEY:USER_PROMPT}} OBSERVATION: {{KEY:REVIEW_CONTENT}} REPLY: Return only a JSON object with your decision: {{ "decision": "continue|stop", "reason": "brief explanation" }} RULES: 1. Use "continue" if objective NOT fulfilled 2. Use "stop" if objective fulfilled 3. Return ONLY JSON - no other text 4. Do NOT use markdown code blocks 5. Do NOT add explanations """ return PromptBundle(prompt=template, placeholders=placeholders)