feat: add CLI Command Node and Prompt Node components for orchestrator

- Implemented CliCommandNode component for executing CLI tools with AI models.
- Implemented PromptNode component for constructing AI prompts with context.
- Added styling for mode and tool badges in both components.
- Enhanced user experience with command and argument previews, execution status, and error handling.

test: add comprehensive tests for ask_question tool

- Created direct test for ask_question tool execution.
- Developed end-to-end tests to validate ask_question tool integration with WebSocket and A2UI surfaces.
- Implemented simple and integrated WebSocket tests to ensure proper message handling and surface reception.
- Added tool registration test to verify ask_question tool is correctly registered.

chore: add WebSocket listener and simulation tests

- Added WebSocket listener for A2UI surfaces to facilitate testing.
- Implemented frontend simulation test to validate complete flow from backend to frontend.
- Created various test scripts to ensure robust testing of ask_question tool functionality.
This commit is contained in:
catlog22
2026-02-03 23:10:36 +08:00
parent a806d70d9b
commit c6093ef741
134 changed files with 6392 additions and 634 deletions

114
test-e2e-ask-question.mjs Normal file
View File

@@ -0,0 +1,114 @@
/**
* End-to-end test for ask_question tool
* Connects WebSocket and calls tool via MCP API endpoint
*/
import { WebSocket } from 'ws';
async function testEndToEnd() {
console.log('=== E2E Test: ask_question Tool ===\n');
// Connect WebSocket client
console.log('1. Connecting WebSocket client...');
const ws = new WebSocket('ws://127.0.0.1:3456/ws');
await new Promise((resolve, reject) => {
ws.on('open', () => {
console.log('✓ WebSocket connected\n');
// Give the server a moment to register the client
setTimeout(resolve, 200);
});
ws.on('error', reject);
setTimeout(() => reject(new Error('Connection timeout')), 5000);
});
// Listen for A2UI surface messages
let surfaceResolve;
const surfaceReceived = new Promise((resolve) => {
surfaceResolve = resolve;
});
ws.on('message', (data) => {
try {
const message = JSON.parse(data.toString());
console.log(' [WS] Received message type:', message.type);
if (message.type === 'a2ui-surface') {
console.log('3. ✓ Frontend received A2UI surface:');
console.log(' Surface ID:', message.surfaceUpdate.surfaceId);
console.log(' Components:', message.surfaceUpdate.components.length);
console.log(' Question ID:', message.surfaceUpdate.initialState?.questionId);
surfaceResolve(message);
}
} catch (e) {
console.log(' [WS] Raw message:', data.toString().substring(0, 100));
}
});
// Execute tool via MCP API endpoint
console.log('2. Calling ask_question tool via MCP API...');
const toolCallPromise = fetch('http://127.0.0.1:3456/api/mcp/tool', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'ask_question',
arguments: {
question: {
id: 'e2e-test-1',
type: 'confirm',
title: 'Test E2E Question',
message: 'This tests the complete flow from backend to frontend',
description: 'If you see this on frontend, the integration works!'
},
timeout: 8000
}
})
});
// Wait for surface to be received (or timeout)
const surface = await Promise.race([
surfaceReceived,
new Promise((_, reject) => setTimeout(() => reject(new Error('Surface not received within 5s')), 5000))
]);
console.log('\n4. Simulating user answer via WebSocket...');
// Simulate user clicking "Confirm"
ws.send(JSON.stringify({
type: 'a2ui-answer',
questionId: 'e2e-test-1',
surfaceId: surface.surfaceUpdate.surfaceId,
value: true,
cancelled: false,
timestamp: new Date().toISOString()
}));
// Wait for tool result
console.log('5. Waiting for tool result...');
const response = await toolCallPromise;
const result = await response.json();
console.log('\n6. ✓ Tool result received:');
console.log(' HTTP Status:', response.status);
console.log(' Result:', JSON.stringify(result, null, 2));
ws.close();
if (result.result?.success && result.result?.answers?.[0]?.value === true) {
console.log('\n✅ E2E Test PASSED - Full integration working!');
console.log('\nSummary:');
console.log('- MCP tool API endpoint ✓');
console.log('- A2UI surface generation ✓');
console.log('- WebSocket distribution ✓');
console.log('- Frontend answer handling ✓');
console.log('- Backend answer processing ✓');
} else {
console.log('\n⚠ Test completed but answer may not have been received');
}
}
testEndToEnd()
.then(() => process.exit(0))
.catch((err) => {
console.error('\n❌ E2E Test FAILED:', err.message);
process.exit(1);
});