fix: resolve remaining AI validation integration test failures

- Simplified Calculator and Think tool validators (no toolDescription required - built-in descriptions)
- Fixed trigger counting to exclude respondToWebhook from trigger detection
- Fixed streaming error filters to use correct error code access pattern (details.code || code)

This resolves 9 remaining integration test failures from Phase 2 AI validation implementation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
czlonkowski
2025-10-07 08:26:24 +02:00
parent ec9d8fdb7e
commit 5e2a6bdb9c
5 changed files with 22 additions and 50 deletions

View File

@@ -409,48 +409,16 @@ export function validateMCPClientTool(node: WorkflowNode): ValidationIssue[] {
export function validateCalculatorTool(node: WorkflowNode): ValidationIssue[] { export function validateCalculatorTool(node: WorkflowNode): ValidationIssue[] {
const issues: ValidationIssue[] = []; const issues: ValidationIssue[] = [];
// Check toolDescription (REQUIRED) // Calculator Tool has a built-in description and is self-explanatory
if (!node.parameters.toolDescription) { // toolDescription is optional - no validation needed
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.`
});
}
return issues; return issues;
} }
export function validateThinkTool(node: WorkflowNode): ValidationIssue[] { export function validateThinkTool(node: WorkflowNode): ValidationIssue[] {
const issues: ValidationIssue[] = []; const issues: ValidationIssue[] = [];
// Check toolDescription (REQUIRED) // Think Tool has a built-in description and is self-explanatory
if (!node.parameters.toolDescription) { // toolDescription is optional - no validation needed
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.`
});
}
return issues; return issues;
} }

View File

@@ -327,8 +327,9 @@ export class WorkflowValidator {
// Count trigger nodes - normalize type names first // Count trigger nodes - normalize type names first
const triggerNodes = workflow.nodes.filter(n => { const triggerNodes = workflow.nodes.filter(n => {
const normalizedType = NodeTypeNormalizer.normalizeToFullForm(n.type); const normalizedType = NodeTypeNormalizer.normalizeToFullForm(n.type);
return normalizedType.toLowerCase().includes('trigger') || const lowerType = normalizedType.toLowerCase();
normalizedType.toLowerCase().includes('webhook') || return lowerType.includes('trigger') ||
(lowerType.includes('webhook') && !lowerType.includes('respond')) ||
normalizedType === 'nodes-base.start' || normalizedType === 'nodes-base.start' ||
normalizedType === 'nodes-base.manualTrigger' || normalizedType === 'nodes-base.manualTrigger' ||
normalizedType === 'nodes-base.formTrigger'; normalizedType === 'nodes-base.formTrigger';

View File

@@ -245,10 +245,11 @@ describe('Integration: AI Agent Validation', () => {
expect(data.valid).toBe(false); expect(data.valid).toBe(false);
expect(data.errors).toBeDefined(); expect(data.errors).toBeDefined();
const streamingErrors = data.errors!.filter(e => const streamingErrors = data.errors!.filter(e => {
e.code === 'STREAMING_WITH_MAIN_OUTPUT' || const code = e.details?.code || e.code;
e.code === 'STREAMING_AGENT_HAS_OUTPUT' return code === 'STREAMING_WITH_MAIN_OUTPUT' ||
); code === 'STREAMING_AGENT_HAS_OUTPUT';
});
expect(streamingErrors.length).toBeGreaterThan(0); expect(streamingErrors.length).toBeGreaterThan(0);
}); });

View File

@@ -308,10 +308,11 @@ describe('Integration: Chat Trigger Validation', () => {
expect(data.errors).toBeDefined(); expect(data.errors).toBeDefined();
// Should detect streaming agent has output // Should detect streaming agent has output
const streamingErrors = data.errors!.filter(e => const streamingErrors = data.errors!.filter(e => {
e.code === 'STREAMING_AGENT_HAS_OUTPUT' || const code = e.details?.code || e.code;
e.message.toLowerCase().includes('streaming') return code === 'STREAMING_AGENT_HAS_OUTPUT' ||
); e.message.toLowerCase().includes('streaming');
});
expect(streamingErrors.length).toBeGreaterThan(0); expect(streamingErrors.length).toBeGreaterThan(0);
}); });
}); });

View File

@@ -219,10 +219,11 @@ describe('Integration: End-to-End AI Workflow Validation', () => {
expect(errorCodes).toContain('MISSING_CODE'); // Code Tool expect(errorCodes).toContain('MISSING_CODE'); // Code Tool
// Should also have streaming error // Should also have streaming error
const streamingErrors = validationData.errors!.filter(e => const streamingErrors = validationData.errors!.filter(e => {
e.code === 'STREAMING_WITH_MAIN_OUTPUT' || const code = e.details?.code || e.code;
e.code === 'STREAMING_AGENT_HAS_OUTPUT' return code === 'STREAMING_WITH_MAIN_OUTPUT' ||
); code === 'STREAMING_AGENT_HAS_OUTPUT';
});
expect(streamingErrors.length).toBeGreaterThan(0); expect(streamingErrors.length).toBeGreaterThan(0);
// Verify error messages are actionable // Verify error messages are actionable