Files
extension/test/mock/ai-mock-server.ts
T
Hanzo Dev a12d455b02 feat: Add Dev CLI with multi-agent orchestration and comprehensive testing
- Implement multi-agent orchestration system for parallel AI tasks
- Add role-based AI assignment (coder, reviewer, critic, architect, etc)
- Create predefined workflows (code-review, implement-feature, optimize, debug)
- Add local LLM support with auto-detection (Ollama, LocalAI, etc)
- Implement async job management with idle timeout
- Add authentication system with OAuth2 PKCE flow
- Create comprehensive test suite with integration tests
- Add headless Chrome testing for auth flows
- Create mock AI server for testing all endpoints
- Add visual test runners and demo scripts
- Update CI/CD pipeline for all services
- Rename CLI from 'hanzo-dev' to 'dev' for simplicity
- Update repository references to github.com/hanzoai/dev

Key features:
- Parallel execution of multiple AI agents
- Git worktree support for isolated development
- Universal context sync across tools
- Secure API key management
- Comprehensive workflow system
2025-07-08 18:33:08 -04:00

217 lines
6.8 KiB
TypeScript

import express from 'express';
import bodyParser from 'body-parser';
import chalk from 'chalk';
// Mock responses for different AI tools
const MOCK_RESPONSES = {
claude: {
'/v1/messages': {
content: [
{
type: 'text',
text: 'This is a mock Claude response. The code appears to implement a simple calculator with sum and product functions.'
}
],
model: 'claude-3-opus',
usage: { input_tokens: 10, output_tokens: 20 }
}
},
openai: {
'/v1/chat/completions': {
choices: [
{
message: {
role: 'assistant',
content: 'This is a mock Codex response. The functions are well-structured and follow JavaScript best practices.'
}
}
],
model: 'gpt-4',
usage: { prompt_tokens: 10, completion_tokens: 20 }
}
},
gemini: {
'/v1beta/models/gemini-pro:generateContent': {
candidates: [
{
content: {
parts: [
{
text: 'This is a mock Gemini response. Consider adding input validation and error handling to make the code more robust.'
}
]
}
}
]
}
},
ollama: {
'/api/generate': {
response: 'This is a mock local LLM response from Ollama. The code is efficient and straightforward.'
},
'/api/tags': {
models: [
{ name: 'llama3:latest', size: '4.5GB' },
{ name: 'codellama:latest', size: '3.8GB' },
{ name: 'mistral:latest', size: '4.1GB' }
]
}
}
};
export class AIMockServer {
private app: express.Application;
private server: any;
private requestLog: any[] = [];
constructor(private port: number = 0) {
this.app = express();
this.setupMiddleware();
this.setupRoutes();
}
private setupMiddleware() {
this.app.use(bodyParser.json());
// Log all requests
this.app.use((req, res, next) => {
const logEntry = {
timestamp: new Date(),
method: req.method,
url: req.url,
headers: req.headers,
body: req.body
};
this.requestLog.push(logEntry);
console.log(chalk.gray(`[Mock] ${req.method} ${req.url}`));
next();
});
}
private setupRoutes() {
// Claude API
this.app.post('/v1/messages', (req, res) => {
res.json(MOCK_RESPONSES.claude['/v1/messages']);
});
// OpenAI API
this.app.post('/v1/chat/completions', (req, res) => {
res.json(MOCK_RESPONSES.openai['/v1/chat/completions']);
});
// Gemini API
this.app.post('/v1beta/models/:model/generateContent', (req, res) => {
res.json(MOCK_RESPONSES.gemini['/v1beta/models/gemini-pro:generateContent']);
});
// Ollama API
this.app.post('/api/generate', (req, res) => {
res.json(MOCK_RESPONSES.ollama['/api/generate']);
});
this.app.get('/api/tags', (req, res) => {
res.json(MOCK_RESPONSES.ollama['/api/tags']);
});
// Health check
this.app.get('/health', (req, res) => {
res.json({ status: 'ok', mock: true });
});
// OAuth mock for auth testing
this.app.get('/oauth/authorize', (req, res) => {
const { redirect_uri, state } = req.query;
// Simulate immediate redirect with code
const code = 'mock-auth-code-' + Date.now();
res.redirect(`${redirect_uri}?code=${code}&state=${state}`);
});
this.app.post('/oauth/token', (req, res) => {
res.json({
access_token: 'mock-access-token-' + Date.now(),
refresh_token: 'mock-refresh-token-' + Date.now(),
expires_in: 3600,
token_type: 'Bearer'
});
});
this.app.get('/api/user', (req, res) => {
res.json({
id: 'mock-user-123',
email: 'test@hanzo.ai',
name: 'Test User'
});
});
this.app.get('/v1/api-keys', (req, res) => {
res.json([
{
name: 'Claude API',
provider: 'anthropic',
key: 'sk-ant-mock-key',
enabled: true
},
{
name: 'OpenAI API',
provider: 'openai',
key: 'sk-mock-openai-key',
enabled: true
},
{
name: 'Gemini API',
provider: 'google',
key: 'mock-gemini-key',
enabled: true
}
]);
});
}
async start(): Promise<number> {
return new Promise((resolve) => {
this.server = this.app.listen(this.port, () => {
const actualPort = this.server.address().port;
console.log(chalk.green(`🎭 Mock AI Server running on port ${actualPort}`));
resolve(actualPort);
});
});
}
stop() {
if (this.server) {
this.server.close();
}
}
getRequestLog() {
return this.requestLog;
}
clearRequestLog() {
this.requestLog = [];
}
}
// Run standalone if called directly
if (require.main === module) {
const port = parseInt(process.env.PORT || '8888');
const server = new AIMockServer(port);
server.start().then((actualPort) => {
console.log(chalk.cyan('\nMock endpoints available:'));
console.log(chalk.gray(' POST http://localhost:' + actualPort + '/v1/messages (Claude)'));
console.log(chalk.gray(' POST http://localhost:' + actualPort + '/v1/chat/completions (OpenAI)'));
console.log(chalk.gray(' POST http://localhost:' + actualPort + '/v1beta/models/gemini-pro:generateContent (Gemini)'));
console.log(chalk.gray(' POST http://localhost:' + actualPort + '/api/generate (Ollama)'));
console.log(chalk.gray(' GET http://localhost:' + actualPort + '/health'));
console.log();
process.on('SIGINT', () => {
console.log(chalk.yellow('\nShutting down mock server...'));
server.stop();
process.exit(0);
});
});
}