""" Dynamic Mode Prompt Generation Handles prompt templates for dynamic mode action handling. """ import json 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, extractWorkflowHistory, ) from modules.workflows.processing.shared.methodDiscovery import methods, getActionParameterList def generateDynamicPlanSelectionPrompt(services, context: Any, learningEngine=None) -> PromptBundle: """Define placeholders first, then the template; return PromptBundle.""" placeholders: List[PromptPlaceholder] = [ PromptPlaceholder(label="OVERALL_TASK_CONTEXT", content=services.currentUserPromptNormalized, summaryAllowed=False), PromptPlaceholder(label="TASK_OBJECTIVE", content=context.taskStep.objective, summaryAllowed=False), PromptPlaceholder(label="USER_PROMPT", content=extractUserPrompt(context), summaryAllowed=False), PromptPlaceholder(label="USER_LANGUAGE", content=extractUserLanguage(services), summaryAllowed=False), PromptPlaceholder(label="AVAILABLE_DOCUMENTS_SUMMARY", content=extractAvailableDocumentsSummary(services, context), summaryAllowed=True), PromptPlaceholder(label="AVAILABLE_METHODS", content=extractAvailableMethods(services), summaryAllowed=False), # Provide enriched history context for Stage 1 to craft parametersContext PromptPlaceholder(label="WORKFLOW_HISTORY", content=extractWorkflowHistory(services), summaryAllowed=True), # Provide deterministic indexes so the planner can choose exact labels PromptPlaceholder(label="AVAILABLE_DOCUMENTS_INDEX", content=extractAvailableDocumentsIndex(services, context), summaryAllowed=True), PromptPlaceholder(label="AVAILABLE_CONNECTIONS_INDEX", content=extractAvailableConnectionsIndex(services), summaryAllowed=False), ] # Add adaptive learning context if available adaptiveContext = {} if learningEngine: workflowId = getattr(context, 'workflow_id', 'unknown') userPrompt = extractUserPrompt(context) adaptiveContext = learningEngine.getAdaptiveContextForActionSelection(workflowId, userPrompt) if adaptiveContext: # Add learning-aware placeholders placeholders.extend([ PromptPlaceholder(label="ADAPTIVE_GUIDANCE", content=adaptiveContext.get('adaptiveGuidance', ''), summaryAllowed=True), PromptPlaceholder(label="FAILURE_ANALYSIS", content=json.dumps(adaptiveContext.get('failureAnalysis', {}), indent=2), summaryAllowed=True), PromptPlaceholder(label="ESCALATION_LEVEL", content=adaptiveContext.get('escalationLevel', 'low'), summaryAllowed=False), ]) template = """Select exactly one next action to advance the task incrementally. === TASK === CONTEXT: {{KEY:OVERALL_TASK_CONTEXT}} OBJECTIVE: {{KEY:TASK_OBJECTIVE}} === AVAILABLE RESOURCES === AVAILABLE_DOCUMENTS_INDEX: {{KEY:AVAILABLE_DOCUMENTS_SUMMARY}} {{KEY:AVAILABLE_DOCUMENTS_INDEX}} AVAILABLE_CONNECTIONS_INDEX: {{KEY:AVAILABLE_CONNECTIONS_INDEX}} === AVAILABLE ACTIONS === {{KEY:AVAILABLE_METHODS}} === CONTEXT === HISTORY: {{KEY:WORKFLOW_HISTORY}} GUIDANCE: {{KEY:ADAPTIVE_GUIDANCE}} FAILURES: {{KEY:FAILURE_ANALYSIS}} ESCALATION: {{KEY:ESCALATION_LEVEL}} === SELECTION RULE === 1. Read OBJECTIVE and identify what it requires 2. Check AVAILABLE_METHODS to find action whose PURPOSE matches that requirement 3. Select action that can DO what objective needs - do not select actions that do something different === OUTPUT FORMAT === Return ONLY JSON (no markdown, no explanations). The chosen action MUST: - Match the objective's requirement (verify action's purpose in AVAILABLE_METHODS) - Be the next logical incremental step (not complete entire objective in one step) - Target exactly one output format if producing files - Use ONLY exact references from AVAILABLE_DOCUMENTS_INDEX (docList:... or docItem:...) - ALWAYS use FULL document references with filename: docItem:: (filename is required) - Learn from previous validation feedback and avoid repeated mistakes - Include intent analysis fields (dataType, expectedFormats, qualityRequirements, successCriteria) {{ "action": "method.action_name", "actionObjective": "...", "dataType": "numbers|text|documents|analysis|code|unknown", "expectedFormats": ["pdf", "docx", "xlsx", "txt", "json", "csv", "html", "md"], "qualityRequirements": {{ "accuracyThreshold": 0.0-1.0, "completenessThreshold": 0.0-1.0 }}, "successCriteria": ["specific criterion 1", "specific criterion 2"], "userMessage": "User-friendly message in language '{{KEY:USER_LANGUAGE}}' explaining what this action will do (1 sentence, first person, friendly tone)", "learnings": ["..."], "requiredInputDocuments": ["docItem::", "docList: