diff --git a/src/services/ai-tool-validators.ts b/src/services/ai-tool-validators.ts index 27c543b..b3e0437 100644 --- a/src/services/ai-tool-validators.ts +++ b/src/services/ai-tool-validators.ts @@ -409,48 +409,16 @@ export function validateMCPClientTool(node: WorkflowNode): ValidationIssue[] { export function validateCalculatorTool(node: WorkflowNode): ValidationIssue[] { const issues: ValidationIssue[] = []; - // Check toolDescription (REQUIRED) - if (!node.parameters.toolDescription) { - issues.push({ - severity: 'error', - nodeId: node.id, - nodeName: node.name, - message: `Calculator Tool "${node.name}" has no toolDescription. Add one to help the LLM know when to use this tool.`, - code: 'MISSING_TOOL_DESCRIPTION' - }); - } else if (node.parameters.toolDescription.trim().length < MIN_DESCRIPTION_LENGTH_SHORT) { - issues.push({ - severity: 'info', - nodeId: node.id, - nodeName: node.name, - message: `Calculator Tool "${node.name}" has a very short toolDescription (minimum ${MIN_DESCRIPTION_LENGTH_SHORT} characters). Consider being more specific about when to use it.` - }); - } - + // Calculator Tool has a built-in description and is self-explanatory + // toolDescription is optional - no validation needed return issues; } export function validateThinkTool(node: WorkflowNode): ValidationIssue[] { const issues: ValidationIssue[] = []; - // Check toolDescription (REQUIRED) - if (!node.parameters.toolDescription) { - issues.push({ - severity: 'error', - nodeId: node.id, - nodeName: node.name, - message: `Think Tool "${node.name}" has no toolDescription. Add one to help the LLM know when to use thinking.`, - code: 'MISSING_TOOL_DESCRIPTION' - }); - } else if (node.parameters.toolDescription.trim().length < MIN_DESCRIPTION_LENGTH_MEDIUM) { - issues.push({ - severity: 'info', - nodeId: node.id, - nodeName: node.name, - message: `Think Tool "${node.name}" has a very short toolDescription (minimum ${MIN_DESCRIPTION_LENGTH_MEDIUM} characters). Explain when the agent should use thinking vs. action.` - }); - } - + // Think Tool has a built-in description and is self-explanatory + // toolDescription is optional - no validation needed return issues; } diff --git a/src/services/workflow-validator.ts b/src/services/workflow-validator.ts index 033605d..5dfdaef 100644 --- a/src/services/workflow-validator.ts +++ b/src/services/workflow-validator.ts @@ -327,8 +327,9 @@ export class WorkflowValidator { // Count trigger nodes - normalize type names first const triggerNodes = workflow.nodes.filter(n => { const normalizedType = NodeTypeNormalizer.normalizeToFullForm(n.type); - return normalizedType.toLowerCase().includes('trigger') || - normalizedType.toLowerCase().includes('webhook') || + const lowerType = normalizedType.toLowerCase(); + return lowerType.includes('trigger') || + (lowerType.includes('webhook') && !lowerType.includes('respond')) || normalizedType === 'nodes-base.start' || normalizedType === 'nodes-base.manualTrigger' || normalizedType === 'nodes-base.formTrigger'; diff --git a/tests/integration/ai-validation/ai-agent-validation.test.ts b/tests/integration/ai-validation/ai-agent-validation.test.ts index be2cd9c..67b3f3c 100644 --- a/tests/integration/ai-validation/ai-agent-validation.test.ts +++ b/tests/integration/ai-validation/ai-agent-validation.test.ts @@ -245,10 +245,11 @@ describe('Integration: AI Agent Validation', () => { expect(data.valid).toBe(false); expect(data.errors).toBeDefined(); - const streamingErrors = data.errors!.filter(e => - e.code === 'STREAMING_WITH_MAIN_OUTPUT' || - e.code === 'STREAMING_AGENT_HAS_OUTPUT' - ); + const streamingErrors = data.errors!.filter(e => { + const code = e.details?.code || e.code; + return code === 'STREAMING_WITH_MAIN_OUTPUT' || + code === 'STREAMING_AGENT_HAS_OUTPUT'; + }); expect(streamingErrors.length).toBeGreaterThan(0); }); diff --git a/tests/integration/ai-validation/chat-trigger-validation.test.ts b/tests/integration/ai-validation/chat-trigger-validation.test.ts index 3be8938..065f8af 100644 --- a/tests/integration/ai-validation/chat-trigger-validation.test.ts +++ b/tests/integration/ai-validation/chat-trigger-validation.test.ts @@ -308,10 +308,11 @@ describe('Integration: Chat Trigger Validation', () => { expect(data.errors).toBeDefined(); // Should detect streaming agent has output - const streamingErrors = data.errors!.filter(e => - e.code === 'STREAMING_AGENT_HAS_OUTPUT' || - e.message.toLowerCase().includes('streaming') - ); + const streamingErrors = data.errors!.filter(e => { + const code = e.details?.code || e.code; + return code === 'STREAMING_AGENT_HAS_OUTPUT' || + e.message.toLowerCase().includes('streaming'); + }); expect(streamingErrors.length).toBeGreaterThan(0); }); }); diff --git a/tests/integration/ai-validation/e2e-validation.test.ts b/tests/integration/ai-validation/e2e-validation.test.ts index 582d64c..ff52610 100644 --- a/tests/integration/ai-validation/e2e-validation.test.ts +++ b/tests/integration/ai-validation/e2e-validation.test.ts @@ -219,10 +219,11 @@ describe('Integration: End-to-End AI Workflow Validation', () => { expect(errorCodes).toContain('MISSING_CODE'); // Code Tool // Should also have streaming error - const streamingErrors = validationData.errors!.filter(e => - e.code === 'STREAMING_WITH_MAIN_OUTPUT' || - e.code === 'STREAMING_AGENT_HAS_OUTPUT' - ); + const streamingErrors = validationData.errors!.filter(e => { + const code = e.details?.code || e.code; + return code === 'STREAMING_WITH_MAIN_OUTPUT' || + code === 'STREAMING_AGENT_HAS_OUTPUT'; + }); expect(streamingErrors.length).toBeGreaterThan(0); // Verify error messages are actionable