import { StateGraph } from '@langchain/langgraph'; import { BaseWorkflow, type WorkflowConfig } from '../base-workflow.js'; import { StrategyValidationState, type StrategyValidationStateType } from './state.js'; import { createCodeReviewNode, createFixCodeNode, createBacktestNode, createRiskAssessmentNode, createHumanApprovalNode, createRecommendationNode, } from './nodes.js'; import type { FastifyBaseLogger } from 'fastify'; import type { BaseChatModel } from '@langchain/core/language_models/chat_models'; import type { CodeReviewerSubagent } from '../../subagents/code-reviewer/index.js'; /** * Strategy Validation Workflow * * Multi-step workflow with validation loop: * 1. Code Review (using CodeReviewerSubagent) * 2. If issues found → Fix Code → Loop back to Code Review * 3. Backtest (using user's MCP server) * 4. If backtest fails → Fix Code → Loop back to Code Review * 5. Risk Assessment * 6. Human Approval (pause for user input) * 7. Final Recommendation * * Features: * - Validation loop with max retries * - Human-in-the-loop approval gate * - Multi-file memory from CodeReviewerSubagent * - Comprehensive state tracking */ export class StrategyValidationWorkflow extends BaseWorkflow { constructor( config: WorkflowConfig, private model: BaseChatModel, private codeReviewer: CodeReviewerSubagent, private mcpBacktestFn: (code: string, ticker: string, timeframe: string) => Promise>, logger: FastifyBaseLogger ) { super(config, logger); } buildGraph(): any { const graph = new StateGraph(StrategyValidationState); // Create nodes const codeReviewNode = createCodeReviewNode(this.codeReviewer, this.logger); const fixCodeNode = createFixCodeNode(this.model, this.logger); const backtestNode = createBacktestNode(this.mcpBacktestFn, this.logger); const riskAssessmentNode = createRiskAssessmentNode(this.model, this.logger); const humanApprovalNode = createHumanApprovalNode(this.logger); const recommendationNode = createRecommendationNode(this.model, this.logger); // Add nodes to graph graph .addNode('code_review', codeReviewNode) .addNode('fix_code', fixCodeNode) .addNode('backtest', backtestNode) .addNode('risk_assessment', riskAssessmentNode) .addNode('human_approval', humanApprovalNode) .addNode('recommendation', recommendationNode); // Define edges (graph as any).addEdge('__start__', 'code_review'); // Conditional: After code review, fix if needed or proceed to backtest (graph as any).addConditionalEdges('code_review', (state: any) => { if (state.needsFixing && state.validationRetryCount < 3) { return 'fix_code'; } if (state.needsFixing && state.validationRetryCount >= 3) { return 'recommendation'; // Give up, generate rejection } return 'backtest'; }); // After fixing code, loop back to code review (graph as any).addEdge('fix_code', 'code_review'); // Conditional: After backtest, fix if failed or proceed to risk assessment (graph as any).addConditionalEdges('backtest', (state: any) => { if (!state.backtestPassed && state.validationRetryCount < 3) { return 'fix_code'; } if (!state.backtestPassed && state.validationRetryCount >= 3) { return 'recommendation'; // Give up } return 'risk_assessment'; }); // After risk assessment, go to human approval (graph as any).addEdge('risk_assessment', 'human_approval'); // Conditional: After human approval, proceed to recommendation or reject (graph as any).addConditionalEdges('human_approval', (state: any) => { return state.humanApproved ? 'recommendation' : '__end__'; }); // Final recommendation is terminal (graph as any).addEdge('recommendation', '__end__'); return graph; } } /** * Factory function to create and compile workflow */ export async function createStrategyValidationWorkflow( model: BaseChatModel, codeReviewer: CodeReviewerSubagent, mcpBacktestFn: (code: string, ticker: string, timeframe: string) => Promise>, logger: FastifyBaseLogger, configPath: string ): Promise { const { readFile } = await import('fs/promises'); const yaml = await import('js-yaml'); // Load config const configContent = await readFile(configPath, 'utf-8'); const config = yaml.load(configContent) as WorkflowConfig; // Create workflow const workflow = new StrategyValidationWorkflow( config, model, codeReviewer, mcpBacktestFn, logger ); // Compile graph workflow.compile(); return workflow; }