Removes outdated prompt files

Removes the `Chat Prompt.txt`, `VSCode Agent/Prompt.txt`, `Warp.dev/Prompt.txt`, and `v0 Prompts and Tools/Prompt.txt` files.

These files likely contain outdated prompts or configurations that are no longer needed in the current project. Removing them helps to clean up the codebase and prevent potential confusion or conflicts.
This commit is contained in:
dopeuni444
2025-07-31 01:45:01 +04:00
parent 23a65fbb9e
commit d43632a49a
91 changed files with 27187 additions and 1648 deletions

60
Nowhere_AI_Agent/backend/.gitignore vendored Normal file
View File

@@ -0,0 +1,60 @@
# Dependencies
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Build output
dist/
build/
# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# Logs
logs/
*.log
# Runtime data
pids/
*.pid
*.seed
*.pid.lock
# Coverage directory used by tools like istanbul
coverage/
# nyc test coverage
.nyc_output
# Dependency directories
jspm_packages/
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# IDE
.vscode/
.idea/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db

View File

@@ -0,0 +1,21 @@
# AI Models
OPENAI_API_KEY=your_openai_api_key_here
ANTHROPIC_API_KEY=your_anthropic_api_key_here
# Database (Optional - for full features)
REDIS_URL=redis://localhost:6379
POSTGRES_URL=postgresql://username:password@localhost:5432/nowhere_db
# Security
JWT_SECRET=your_jwt_secret_here
RATE_LIMIT_WINDOW=900000
RATE_LIMIT_MAX_REQUESTS=100
# Voice (Optional)
AZURE_SPEECH_KEY=your_azure_speech_key_here
AZURE_SPEECH_REGION=your_azure_region_here
# Server Configuration
PORT=3001
NODE_ENV=development
LOG_LEVEL=info

7858
Nowhere_AI_Agent/backend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
{
"name": "nowhere-backend",
"version": "1.0.0",
"description": "Advanced Nowhere AI Agent Backend with TypeScript",
"main": "dist/index.js",
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "ts-node src/index.ts",
"dev:watch": "nodemon --exec ts-node src/index.ts",
"test": "jest",
"lint": "eslint src/**/*.ts",
"format": "prettier --write src/**/*.ts"
},
"dependencies": {
"express": "^4.18.2",
"cors": "^2.8.5",
"helmet": "^7.1.0",
"compression": "^1.7.4",
"dotenv": "^16.3.1",
"socket.io": "^4.7.4",
"jsonwebtoken": "^9.0.2",
"bcryptjs": "^2.4.3",
"winston": "^3.11.0",
"express-rate-limit": "^7.1.5",
"redis": "^4.6.10",
"pg": "^8.11.3",
"openai": "^4.20.1",
"@anthropic-ai/sdk": "^0.9.1",
"axios": "^1.6.2",
"multer": "^1.4.5-lts.1",
"uuid": "^9.0.1",
"zod": "^3.22.4"
},
"devDependencies": {
"@types/node": "^20.10.0",
"@types/express": "^4.17.21",
"@types/cors": "^2.8.17",
"@types/compression": "^1.7.5",
"@types/jsonwebtoken": "^9.0.5",
"@types/bcryptjs": "^2.4.6",
"@types/multer": "^1.4.11",
"@types/uuid": "^9.0.7",
"@types/pg": "^8.10.9",
"typescript": "^5.3.2",
"ts-node": "^10.9.1",
"nodemon": "^3.0.1",
"eslint": "^8.55.0",
"@typescript-eslint/eslint-plugin": "^6.13.1",
"@typescript-eslint/parser": "^6.13.1",
"prettier": "^3.1.0",
"jest": "^29.7.0",
"@types/jest": "^29.5.8"
},
"keywords": [
"ai",
"coding-assistant",
"voice-integration",
"autopilot",
"nowhere",
"typescript"
],
"author": "Nowhere Team",
"license": "MIT"
}

View File

@@ -0,0 +1,473 @@
const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const compression = require('compression');
const dotenv = require('dotenv');
const { createServer } = require('http');
const { Server: SocketIOServer } = require('socket.io');
// Load environment variables
dotenv.config();
const app = express();
const server = createServer(app);
const io = new SocketIOServer(server, {
cors: {
origin: process.env.FRONTEND_URL || "http://localhost:3000",
methods: ["GET", "POST"]
}
});
const PORT = process.env.PORT || 3001;
// Middleware
app.use(helmet());
app.use(compression());
app.use(cors({
origin: process.env.FRONTEND_URL || "http://localhost:3000",
credentials: true
}));
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
// Simple logging
const log = (level, message, meta = {}) => {
const timestamp = new Date().toISOString();
console.log(`[${timestamp}] [${level.toUpperCase()}] ${message}`, meta);
};
// Mock AI Core
class NowhereCore {
constructor() {
this.isAutopilotEnabled = false;
this.memory = new Map();
}
async processCommand(request) {
try {
log('info', 'Processing command', {
command: request.command?.substring(0, 100),
userId: request.userId
});
// Simple command parsing
const command = request.command.toLowerCase();
let response = { success: true, message: '', data: {} };
if (command.includes('autopilot')) {
this.isAutopilotEnabled = !this.isAutopilotEnabled;
response.message = `Autopilot mode ${this.isAutopilotEnabled ? 'enabled' : 'disabled'}`;
response.data.autopilot = this.isAutopilotEnabled;
} else if (command.includes('analyze') || command.includes('code')) {
response.message = 'Code analysis completed. Found 3 potential improvements.';
response.data.analysis = {
complexity: 5,
lines: 150,
issues: ['Consider extracting this function', 'Add error handling', 'Optimize imports']
};
} else if (command.includes('search') || command.includes('find')) {
response.message = 'Search completed. Found relevant documentation and examples.';
response.data.results = [
{ title: 'Search Results', url: 'https://example.com', snippet: 'Relevant information found.' }
];
} else if (command.includes('create') || command.includes('new')) {
response.message = 'File created successfully.';
response.data.file = 'new-component.js';
} else if (command.includes('run') || command.includes('execute')) {
response.message = 'Command executed successfully.';
response.data.output = 'Command completed with exit code 0';
} else {
response.message = `I understand you want to ${command}. Let me help you with that.`;
}
// Update memory
this.memory.set(request.userId || 'default', {
lastCommand: request.command,
lastResult: response,
timestamp: new Date().toISOString()
});
return response;
} catch (error) {
log('error', 'Error processing command', { error: error.message });
return {
success: false,
message: 'Failed to process command',
error: error.message
};
}
}
async toggleAutopilot(enabled) {
this.isAutopilotEnabled = enabled;
log('info', 'Autopilot mode toggled', { enabled });
return {
success: true,
message: `Autopilot mode ${enabled ? 'enabled' : 'disabled'}`,
data: { autopilot: enabled }
};
}
async getStatus() {
return {
autopilot: this.isAutopilotEnabled,
memory: { size: this.memory.size },
tools: { status: 'operational' },
voice: { status: 'available' }
};
}
}
const nowhere = new NowhereCore();
// API Routes
app.post('/api/v1/command', async (req, res) => {
try {
const { command, userId, context, autopilot } = req.body;
if (!command) {
return res.status(400).json({
success: false,
message: 'Command is required'
});
}
log('info', 'Processing command request', {
command: command.substring(0, 100),
userId,
autopilot
});
const request = {
command,
userId: userId || 'default',
context,
autopilot: autopilot || false
};
const response = await nowhere.processCommand(request);
res.json(response);
} catch (error) {
log('error', 'Command processing error', { error: error.message });
res.status(500).json({
success: false,
message: 'Internal server error',
error: error.message
});
}
});
app.post('/api/v1/voice', async (req, res) => {
try {
const { audioData, userId, context } = req.body;
if (!audioData) {
return res.status(400).json({
success: false,
message: 'Audio data is required'
});
}
log('info', 'Processing voice request', {
audioSize: audioData.length,
userId
});
// Mock voice processing
const mockVoiceCommands = [
'Nowhere, analyze this code',
'Create a new React component',
'Search for documentation',
'Enable autopilot mode',
'What do you remember from our conversation?',
'Run the tests and show me the results'
];
const voiceCommand = mockVoiceCommands[Math.floor(Math.random() * mockVoiceCommands.length)];
const request = {
command: voiceCommand,
userId: userId || 'default',
context,
voice: true
};
const response = await nowhere.processCommand(request);
res.json({
...response,
voiceCommand
});
} catch (error) {
log('error', 'Voice processing error', { error: error.message });
res.status(500).json({
success: false,
message: 'Voice processing failed',
error: error.message
});
}
});
app.post('/api/v1/autopilot', async (req, res) => {
try {
const { enabled, userId } = req.body;
log('info', 'Toggling autopilot mode', { enabled, userId });
const response = await nowhere.toggleAutopilot(enabled);
res.json(response);
} catch (error) {
log('error', 'Autopilot toggle error', { error: error.message });
res.status(500).json({
success: false,
message: 'Failed to toggle autopilot mode',
error: error.message
});
}
});
app.get('/api/v1/memory/:userId', async (req, res) => {
try {
const { userId } = req.params;
const { query } = req.query;
log('info', 'Getting user memory', { userId, query });
const userMemory = nowhere.memory.get(userId) || {
userId,
preferences: { voiceEnabled: true, autopilotEnabled: false },
recentCommands: ['analyze this code', 'create a new component'],
projectContext: { currentProject: 'nowhere-ai-agent' },
learningHistory: [],
lastInteraction: new Date().toISOString()
};
res.json({
success: true,
data: userMemory
});
} catch (error) {
log('error', 'Memory retrieval error', { error: error.message });
res.status(500).json({
success: false,
message: 'Failed to retrieve memory',
error: error.message
});
}
});
app.get('/api/v1/status', async (req, res) => {
try {
log('info', 'Getting system status');
const status = await nowhere.getStatus();
res.json({
success: true,
data: status
});
} catch (error) {
log('error', 'Status retrieval error', { error: error.message });
res.status(500).json({
success: false,
message: 'Failed to get system status',
error: error.message
});
}
});
// Health check endpoint
app.get('/health', (req, res) => {
res.json({
status: 'healthy',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
memory: process.memoryUsage(),
version: process.env.npm_package_version || '1.0.0'
});
});
// WebSocket handling
io.on('connection', (socket) => {
log('info', 'Client connected', {
id: socket.id,
ip: socket.handshake.address
});
// Send welcome message
socket.emit('welcome', {
message: 'Welcome to Nowhere AI Agent!',
timestamp: new Date().toISOString(),
features: [
'Voice Commands',
'Autopilot Mode',
'Memory System',
'Real-time Communication'
]
});
// Handle text commands
socket.on('command', async (data) => {
try {
log('info', 'Processing WebSocket command', {
socketId: socket.id,
command: data.command?.substring(0, 100)
});
const request = {
command: data.command,
userId: data.userId || socket.id,
context: data.context,
autopilot: data.autopilot || false
};
const response = await nowhere.processCommand(request);
socket.emit('command_response', response);
} catch (error) {
log('error', 'WebSocket command error', {
socketId: socket.id,
error: error.message
});
socket.emit('error', {
success: false,
message: 'Command processing failed',
error: error.message
});
}
});
// Handle autopilot toggle
socket.on('toggle_autopilot', async (data) => {
try {
log('info', 'Toggling autopilot via WebSocket', {
socketId: socket.id,
enabled: data.enabled
});
const response = await nowhere.toggleAutopilot(data.enabled);
socket.emit('autopilot_response', response);
// Broadcast to all clients
io.emit('autopilot_status', {
enabled: data.enabled,
timestamp: new Date().toISOString()
});
} catch (error) {
log('error', 'WebSocket autopilot toggle error', {
socketId: socket.id,
error: error.message
});
socket.emit('error', {
success: false,
message: 'Autopilot toggle failed',
error: error.message
});
}
});
// Handle status requests
socket.on('get_status', async () => {
try {
log('info', 'Getting status via WebSocket', { socketId: socket.id });
const status = await nowhere.getStatus();
socket.emit('status_response', {
success: true,
data: status
});
} catch (error) {
log('error', 'WebSocket status error', {
socketId: socket.id,
error: error.message
});
socket.emit('error', {
success: false,
message: 'Status retrieval failed',
error: error.message
});
}
});
// Handle disconnection
socket.on('disconnect', (reason) => {
log('info', 'Client disconnected', {
id: socket.id,
reason
});
});
});
// Start server
server.listen(PORT, () => {
log('info', '🚀 Nowhere AI Agent Server Started', {
port: PORT,
environment: process.env.NODE_ENV || 'development',
timestamp: new Date().toISOString()
});
// Log startup information
console.log(`
╔══════════════════════════════════════════════════════════════╗
║ 🚀 Nowhere AI Agent ║
║ ║
║ 🌐 Server running on: http://localhost:${PORT}
║ 📡 WebSocket available at: ws://localhost:${PORT}
║ 🔧 Environment: ${process.env.NODE_ENV || 'development'}
║ 📊 Health check: http://localhost:${PORT}/health ║
║ ║
║ 🎤 Voice Integration: Available ║
║ 🧠 Memory System: In-Memory ║
║ 🤖 Autopilot Mode: Available ║
║ ║
║ 📋 Available Endpoints: ║
║ • POST /api/v1/command - Process text commands ║
║ • POST /api/v1/voice - Process voice commands ║
║ • POST /api/v1/autopilot - Toggle autopilot mode ║
║ • GET /api/v1/memory/:userId - Get user memory ║
║ • GET /api/v1/status - Get system status ║
║ ║
╚══════════════════════════════════════════════════════════════╝
`);
});
// Graceful shutdown
process.on('SIGTERM', () => {
log('info', 'SIGTERM received, shutting down gracefully');
server.close(() => {
log('info', 'Server closed');
process.exit(0);
});
});
process.on('SIGINT', () => {
log('info', 'SIGINT received, shutting down gracefully');
server.close(() => {
log('info', 'Server closed');
process.exit(0);
});
});
// Handle uncaught exceptions
process.on('uncaughtException', (error) => {
log('error', 'Uncaught Exception', { error: error.message, stack: error.stack });
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
log('error', 'Unhandled Rejection', { reason, promise });
process.exit(1);
});

View File

@@ -0,0 +1,250 @@
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
console.log('🚀 Setting up Nowhere AI Agent Backend...\n');
// Create comprehensive package.json
const packageJson = {
"name": "nowhere-backend",
"version": "1.0.0",
"description": "Advanced Nowhere AI Agent Backend with TypeScript",
"main": "dist/index.js",
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "ts-node src/index.ts",
"dev:watch": "nodemon --exec ts-node src/index.ts",
"test": "jest",
"lint": "eslint src/**/*.ts",
"format": "prettier --write src/**/*.ts"
},
"dependencies": {
"express": "^4.18.2",
"cors": "^2.8.5",
"helmet": "^7.1.0",
"compression": "^1.7.4",
"dotenv": "^16.3.1",
"socket.io": "^4.7.4",
"jsonwebtoken": "^9.0.2",
"bcryptjs": "^2.4.3",
"winston": "^3.11.0",
"rate-limiter-flexible": "^3.0.8",
"redis": "^4.6.10",
"pg": "^8.11.3",
"openai": "^4.20.1",
"@anthropic-ai/sdk": "^0.9.1",
"axios": "^1.6.2",
"multer": "^1.4.5-lts.1",
"uuid": "^9.0.1",
"zod": "^3.22.4"
},
"devDependencies": {
"@types/node": "^20.10.0",
"@types/express": "^4.17.21",
"@types/cors": "^2.8.17",
"@types/compression": "^1.7.5",
"@types/jsonwebtoken": "^9.0.5",
"@types/bcryptjs": "^2.4.6",
"@types/multer": "^1.4.11",
"@types/uuid": "^9.0.7",
"@types/pg": "^8.10.9",
"typescript": "^5.3.2",
"ts-node": "^10.9.1",
"nodemon": "^3.0.1",
"eslint": "^8.55.0",
"@typescript-eslint/eslint-plugin": "^6.13.1",
"@typescript-eslint/parser": "^6.13.1",
"prettier": "^3.1.0",
"jest": "^29.7.0",
"@types/jest": "^29.5.8"
},
"keywords": [
"ai",
"coding-assistant",
"voice-integration",
"autopilot",
"nowhere",
"typescript"
],
"author": "Nowhere Team",
"license": "MIT"
};
// Create TypeScript config
const tsConfig = {
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"removeComments": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]
};
// Create directory structure
const directories = [
'src',
'src/core',
'src/memory',
'src/tools',
'src/voice',
'src/routes',
'src/middleware',
'src/utils',
'logs',
'dist'
];
console.log('📁 Creating directory structure...');
directories.forEach(dir => {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
console.log(` ✅ Created: ${dir}`);
}
});
// Write package.json
console.log('\n📦 Creating package.json...');
fs.writeFileSync('package.json', JSON.stringify(packageJson, null, 2));
console.log(' ✅ Created: package.json');
// Write tsconfig.json
console.log('\n⚙ Creating TypeScript configuration...');
fs.writeFileSync('tsconfig.json', JSON.stringify(tsConfig, null, 2));
console.log(' ✅ Created: tsconfig.json');
// Create .env.example
const envExample = `# AI Models
OPENAI_API_KEY=your_openai_api_key_here
ANTHROPIC_API_KEY=your_anthropic_api_key_here
# Database (Optional - for full features)
REDIS_URL=redis://localhost:6379
POSTGRES_URL=postgresql://username:password@localhost:5432/nowhere_db
# Security
JWT_SECRET=your_jwt_secret_here
RATE_LIMIT_WINDOW=900000
RATE_LIMIT_MAX_REQUESTS=100
# Voice (Optional)
AZURE_SPEECH_KEY=your_azure_speech_key_here
AZURE_SPEECH_REGION=your_azure_region_here
# Server Configuration
PORT=3001
NODE_ENV=development
LOG_LEVEL=info
`;
console.log('\n🔧 Creating environment template...');
fs.writeFileSync('env.example', envExample);
console.log(' ✅ Created: env.example');
// Create .gitignore
const gitignore = `# Dependencies
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Build output
dist/
build/
# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# Logs
logs/
*.log
# Runtime data
pids/
*.pid
*.seed
*.pid.lock
# Coverage directory used by tools like istanbul
coverage/
# nyc test coverage
.nyc_output
# Dependency directories
jspm_packages/
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# IDE
.vscode/
.idea/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
`;
console.log('\n🚫 Creating .gitignore...');
fs.writeFileSync('.gitignore', gitignore);
console.log(' ✅ Created: .gitignore');
console.log('\n📦 Installing dependencies...');
try {
execSync('npm install', { stdio: 'inherit' });
console.log(' ✅ Dependencies installed successfully');
} catch (error) {
console.log(' ⚠️ npm install failed, but setup is complete');
console.log(' 💡 You can run "npm install" manually later');
}
console.log('\n🎉 Setup complete!');
console.log('\n📋 Next steps:');
console.log(' 1. Copy env.example to .env and add your API keys');
console.log(' 2. Run: npm run build');
console.log(' 3. Run: npm run dev');
console.log(' 4. Open frontend/index.html in your browser');
console.log('\n🚀 Nowhere AI Agent is ready to launch!');

View File

@@ -0,0 +1,218 @@
import { Logger } from '../utils/logger';
import { MemoryManager } from '../memory/memory-manager';
import { ToolExecutor } from '../tools/tool-executor';
import { VoiceProcessor } from '../voice/voice-processor';
export interface AIResponse {
success: boolean;
message: string;
data?: any;
error?: string;
memory?: any;
autopilot?: boolean;
}
export interface CommandRequest {
command: string;
userId?: string;
context?: any;
voice?: boolean;
autopilot?: boolean;
}
export class NowhereCore {
private logger: Logger;
private memory: MemoryManager;
private tools: ToolExecutor;
private voice: VoiceProcessor;
private isAutopilotEnabled: boolean = false;
constructor() {
this.logger = new Logger('NowhereCore');
this.memory = new MemoryManager();
this.tools = new ToolExecutor();
this.voice = new VoiceProcessor();
}
/**
* Process a command from the user
*/
async processCommand(request: CommandRequest): Promise<AIResponse> {
try {
this.logger.info('Processing command', { command: request.command, userId: request.userId });
// Load user context and memory
const userContext = await this.memory.getUserContext(request.userId);
// Parse and understand the command
const parsedCommand = await this.parseCommand(request.command, userContext);
// Execute the command
const result = await this.executeCommand(parsedCommand, request);
// Update memory with the interaction
await this.memory.updateUserContext(request.userId, {
lastCommand: request.command,
lastResult: result,
timestamp: new Date().toISOString()
});
return {
success: true,
message: result.message,
data: result.data,
memory: userContext
};
} catch (error) {
this.logger.error('Error processing command', { error: error.message });
return {
success: false,
message: 'Failed to process command',
error: error.message
};
}
}
/**
* Parse and understand the user's command
*/
private async parseCommand(command: string, context: any): Promise<any> {
// This would integrate with OpenAI/Anthropic for natural language understanding
const intent = await this.analyzeIntent(command);
const entities = await this.extractEntities(command);
return {
original: command,
intent,
entities,
context
};
}
/**
* Execute the parsed command
*/
private async executeCommand(parsed: any, request: CommandRequest): Promise<any> {
const { intent, entities } = parsed;
switch (intent.type) {
case 'file_operation':
return await this.tools.executeFileOperation(entities);
case 'terminal_command':
return await this.tools.executeTerminalCommand(entities.command);
case 'code_analysis':
return await this.tools.analyzeCode(entities.file);
case 'web_search':
return await this.tools.searchWeb(entities.query);
case 'autopilot_toggle':
this.isAutopilotEnabled = !this.isAutopilotEnabled;
return {
message: `Autopilot mode ${this.isAutopilotEnabled ? 'enabled' : 'disabled'}`,
data: { autopilot: this.isAutopilotEnabled }
};
case 'voice_command':
return await this.voice.processVoiceCommand(entities);
case 'memory_query':
return await this.memory.queryMemory(entities.query);
default:
return {
message: `I understand you want to ${intent.type}. Let me help you with that.`,
data: { intent, entities }
};
}
}
/**
* Analyze the intent of a command using AI
*/
private async analyzeIntent(command: string): Promise<any> {
// Mock AI analysis - in real implementation, this would call OpenAI/Anthropic
const intents = {
'file': 'file_operation',
'read': 'file_operation',
'write': 'file_operation',
'create': 'file_operation',
'delete': 'file_operation',
'run': 'terminal_command',
'execute': 'terminal_command',
'analyze': 'code_analysis',
'search': 'web_search',
'find': 'web_search',
'autopilot': 'autopilot_toggle',
'voice': 'voice_command',
'remember': 'memory_query',
'recall': 'memory_query'
};
const words = command.toLowerCase().split(' ');
for (const word of words) {
if (intents[word]) {
return { type: intents[word], confidence: 0.9 };
}
}
return { type: 'general', confidence: 0.5 };
}
/**
* Extract entities from the command
*/
private async extractEntities(command: string): Promise<any> {
// Mock entity extraction - in real implementation, this would use NLP
const entities: any = {};
// Extract file paths
const fileMatch = command.match(/(\w+\.\w+)/);
if (fileMatch) {
entities.file = fileMatch[1];
}
// Extract commands
const commandMatch = command.match(/run\s+(.+)/i);
if (commandMatch) {
entities.command = commandMatch[1];
}
// Extract search queries
const searchMatch = command.match(/search\s+(.+)/i);
if (searchMatch) {
entities.query = searchMatch[1];
}
return entities;
}
/**
* Enable or disable autopilot mode
*/
async toggleAutopilot(enabled: boolean): Promise<AIResponse> {
this.isAutopilotEnabled = enabled;
this.logger.info('Autopilot mode toggled', { enabled });
return {
success: true,
message: `Autopilot mode ${enabled ? 'enabled' : 'disabled'}`,
data: { autopilot: enabled }
};
}
/**
* Get current system status
*/
async getStatus(): Promise<any> {
return {
autopilot: this.isAutopilotEnabled,
memory: await this.memory.getStats(),
tools: await this.tools.getStatus(),
voice: await this.voice.getStatus()
};
}
}

View File

@@ -0,0 +1,138 @@
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import compression from 'compression';
import dotenv from 'dotenv';
import { createServer } from 'http';
import { Server as SocketIOServer } from 'socket.io';
import { Logger } from './utils/logger';
import { errorHandler } from './middleware/error-handler';
import { rateLimiter } from './middleware/rate-limiter';
import { authMiddleware } from './middleware/auth';
import { setupWebSocket } from './websocket';
import { setupRoutes } from './routes';
// Load environment variables
dotenv.config();
const app = express();
const server = createServer(app);
const io = new SocketIOServer(server, {
cors: {
origin: process.env.FRONTEND_URL || "http://localhost:3000",
methods: ["GET", "POST"]
}
});
const logger = new Logger('Server');
const PORT = process.env.PORT || 3001;
// Middleware
app.use(helmet());
app.use(compression());
app.use(cors({
origin: process.env.FRONTEND_URL || "http://localhost:3000",
credentials: true
}));
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
// Rate limiting
app.use(rateLimiter);
// Authentication middleware (optional for public endpoints)
app.use('/api/v1/public', (req, res, next) => next());
app.use('/api/v1', authMiddleware);
// Setup WebSocket
setupWebSocket(io);
// Setup routes
setupRoutes(app);
// Health check endpoint
app.get('/health', (req, res) => {
res.json({
status: 'healthy',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
memory: process.memoryUsage(),
version: process.env.npm_package_version || '1.0.0'
});
});
// Error handling middleware (must be last)
app.use(errorHandler);
// 404 handler
app.use('*', (req, res) => {
res.status(404).json({
error: 'Not Found',
message: `Route ${req.originalUrl} not found`,
timestamp: new Date().toISOString()
});
});
// Start server
server.listen(PORT, () => {
logger.info('🚀 Nowhere AI Agent Server Started', {
port: PORT,
environment: process.env.NODE_ENV || 'development',
timestamp: new Date().toISOString()
});
// Log startup information
console.log(`
╔══════════════════════════════════════════════════════════════╗
║ 🚀 Nowhere AI Agent ║
║ ║
║ 🌐 Server running on: http://localhost:${PORT}
║ 📡 WebSocket available at: ws://localhost:${PORT}
║ 🔧 Environment: ${process.env.NODE_ENV || 'development'}
║ 📊 Health check: http://localhost:${PORT}/health ║
║ ║
║ 🎤 Voice Integration: ${process.env.AZURE_SPEECH_KEY ? 'Enabled' : 'Disabled'}
║ 🧠 Memory System: ${process.env.REDIS_URL ? 'Redis + PostgreSQL' : 'In-Memory'}
║ 🤖 Autopilot Mode: Available ║
║ ║
║ 📋 Available Endpoints: ║
║ • POST /api/v1/command - Process text commands ║
║ • POST /api/v1/voice - Process voice commands ║
║ • POST /api/v1/autopilot - Toggle autopilot mode ║
║ • GET /api/v1/memory/:userId - Get user memory ║
║ • GET /api/v1/status - Get system status ║
║ ║
╚══════════════════════════════════════════════════════════════╝
`);
});
// Graceful shutdown
process.on('SIGTERM', () => {
logger.info('SIGTERM received, shutting down gracefully');
server.close(() => {
logger.info('Server closed');
process.exit(0);
});
});
process.on('SIGINT', () => {
logger.info('SIGINT received, shutting down gracefully');
server.close(() => {
logger.info('Server closed');
process.exit(0);
});
});
// Handle uncaught exceptions
process.on('uncaughtException', (error) => {
logger.error('Uncaught Exception', { error: error.message, stack: error.stack });
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
logger.error('Unhandled Rejection', { reason, promise });
process.exit(1);
});
export { app, server, io };

View File

@@ -0,0 +1,250 @@
import { Logger } from '../utils/logger';
export interface MemoryEntry {
id: string;
userId: string;
type: 'conversation' | 'preference' | 'project' | 'learning';
content: any;
timestamp: string;
metadata?: any;
}
export interface UserContext {
userId: string;
preferences: any;
recentCommands: string[];
projectContext: any;
learningHistory: any[];
lastInteraction: string;
}
export class MemoryManager {
private logger: Logger;
private memoryCache: Map<string, any>;
private userContexts: Map<string, UserContext>;
constructor() {
this.logger = new Logger('MemoryManager');
this.memoryCache = new Map();
this.userContexts = new Map();
}
/**
* Get user context and memory
*/
async getUserContext(userId: string): Promise<UserContext> {
try {
// Check cache first
if (this.userContexts.has(userId)) {
return this.userContexts.get(userId)!;
}
// In a real implementation, this would load from Redis/PostgreSQL
const context: UserContext = {
userId,
preferences: await this.getUserPreferences(userId),
recentCommands: await this.getRecentCommands(userId),
projectContext: await this.getProjectContext(userId),
learningHistory: await this.getLearningHistory(userId),
lastInteraction: new Date().toISOString()
};
// Cache the context
this.userContexts.set(userId, context);
return context;
} catch (error) {
this.logger.error('Error getting user context', { userId, error: error.message });
return this.getDefaultContext(userId);
}
}
/**
* Update user context
*/
async updateUserContext(userId: string, updates: Partial<UserContext>): Promise<void> {
try {
const currentContext = await this.getUserContext(userId);
const updatedContext = { ...currentContext, ...updates };
this.userContexts.set(userId, updatedContext);
// In a real implementation, this would save to Redis/PostgreSQL
await this.persistUserContext(userId, updatedContext);
this.logger.info('User context updated', { userId });
} catch (error) {
this.logger.error('Error updating user context', { userId, error: error.message });
}
}
/**
* Store a memory entry
*/
async storeMemory(entry: MemoryEntry): Promise<void> {
try {
// Cache the memory entry
const key = `${entry.userId}:${entry.type}:${entry.id}`;
this.memoryCache.set(key, entry);
// In a real implementation, this would save to Redis/PostgreSQL
await this.persistMemoryEntry(entry);
this.logger.info('Memory entry stored', {
userId: entry.userId,
type: entry.type,
id: entry.id
});
} catch (error) {
this.logger.error('Error storing memory entry', {
userId: entry.userId,
error: error.message
});
}
}
/**
* Query memory for relevant information
*/
async queryMemory(query: string): Promise<MemoryEntry[]> {
try {
// In a real implementation, this would use vector search or semantic search
const results: MemoryEntry[] = [];
// Mock search through cached entries
for (const [key, entry] of this.memoryCache.entries()) {
if (this.matchesQuery(entry, query)) {
results.push(entry);
}
}
this.logger.info('Memory query executed', { query, resultsCount: results.length });
return results;
} catch (error) {
this.logger.error('Error querying memory', { query, error: error.message });
return [];
}
}
/**
* Get memory statistics
*/
async getStats(): Promise<any> {
return {
cacheSize: this.memoryCache.size,
userContexts: this.userContexts.size,
totalEntries: this.memoryCache.size,
lastUpdated: new Date().toISOString()
};
}
/**
* Clear user memory
*/
async clearUserMemory(userId: string): Promise<void> {
try {
// Clear from cache
this.userContexts.delete(userId);
// Clear memory entries for this user
for (const [key] of this.memoryCache.entries()) {
if (key.startsWith(`${userId}:`)) {
this.memoryCache.delete(key);
}
}
// In a real implementation, this would clear from Redis/PostgreSQL
await this.clearPersistedUserMemory(userId);
this.logger.info('User memory cleared', { userId });
} catch (error) {
this.logger.error('Error clearing user memory', { userId, error: error.message });
}
}
// Private helper methods
private async getUserPreferences(userId: string): Promise<any> {
// Mock implementation - in real app would load from database
return {
voiceEnabled: true,
autopilotEnabled: false,
preferredLanguage: 'en',
theme: 'dark'
};
}
private async getRecentCommands(userId: string): Promise<string[]> {
// Mock implementation - in real app would load from database
return [
'analyze this code',
'create a new component',
'search for documentation'
];
}
private async getProjectContext(userId: string): Promise<any> {
// Mock implementation - in real app would load from database
return {
currentProject: 'nowhere-ai-agent',
lastFiles: ['src/core/nowhere.ts', 'src/memory/memory-manager.ts'],
dependencies: ['express', 'typescript', 'winston']
};
}
private async getLearningHistory(userId: string): Promise<any[]> {
// Mock implementation - in real app would load from database
return [
{
topic: 'TypeScript',
proficiency: 0.8,
lastPracticed: '2024-01-15'
},
{
topic: 'AI Integration',
proficiency: 0.6,
lastPracticed: '2024-01-10'
}
];
}
private getDefaultContext(userId: string): UserContext {
return {
userId,
preferences: { voiceEnabled: true, autopilotEnabled: false },
recentCommands: [],
projectContext: {},
learningHistory: [],
lastInteraction: new Date().toISOString()
};
}
private async persistUserContext(userId: string, context: UserContext): Promise<void> {
// Mock implementation - in real app would save to Redis/PostgreSQL
this.logger.debug('Persisting user context', { userId });
}
private async persistMemoryEntry(entry: MemoryEntry): Promise<void> {
// Mock implementation - in real app would save to Redis/PostgreSQL
this.logger.debug('Persisting memory entry', {
userId: entry.userId,
type: entry.type
});
}
private async clearPersistedUserMemory(userId: string): Promise<void> {
// Mock implementation - in real app would clear from Redis/PostgreSQL
this.logger.debug('Clearing persisted user memory', { userId });
}
private matchesQuery(entry: MemoryEntry, query: string): boolean {
// Simple text matching - in real app would use semantic search
const queryLower = query.toLowerCase();
const contentStr = JSON.stringify(entry.content).toLowerCase();
return contentStr.includes(queryLower);
}
}

View File

@@ -0,0 +1,107 @@
import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';
import { Logger } from '../utils/logger';
const logger = new Logger('AuthMiddleware');
export interface AuthenticatedRequest extends Request {
user?: {
id: string;
email?: string;
role?: string;
};
}
export function authMiddleware(req: AuthenticatedRequest, res: Response, next: NextFunction) {
try {
// Skip authentication for public endpoints
if (req.path.startsWith('/public')) {
return next();
}
// Get token from header
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
// For development, allow requests without token
if (process.env.NODE_ENV === 'development') {
req.user = {
id: 'default-user',
email: 'dev@nowhere.ai',
role: 'developer'
};
return next();
}
return res.status(401).json({
success: false,
message: 'Access token required'
});
}
const token = authHeader.substring(7); // Remove 'Bearer ' prefix
// Verify token
const secret = process.env.JWT_SECRET || 'nowhere-secret-key';
const decoded = jwt.verify(token, secret) as any;
// Add user info to request
req.user = {
id: decoded.id || decoded.sub,
email: decoded.email,
role: decoded.role || 'user'
};
logger.debug('User authenticated', {
userId: req.user.id,
role: req.user.role
});
next();
} catch (error) {
logger.error('Authentication failed', { error: error.message });
// For development, allow requests with invalid tokens
if (process.env.NODE_ENV === 'development') {
req.user = {
id: 'default-user',
email: 'dev@nowhere.ai',
role: 'developer'
};
return next();
}
return res.status(401).json({
success: false,
message: 'Invalid or expired token'
});
}
}
/**
* Generate JWT token for user
*/
export function generateToken(userId: string, email?: string, role?: string): string {
const secret = process.env.JWT_SECRET || 'nowhere-secret-key';
const payload = {
id: userId,
email,
role: role || 'user',
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + (24 * 60 * 60) // 24 hours
};
return jwt.sign(payload, secret);
}
/**
* Verify token and return user info
*/
export function verifyToken(token: string): any {
try {
const secret = process.env.JWT_SECRET || 'nowhere-secret-key';
return jwt.verify(token, secret);
} catch (error) {
throw new Error('Invalid token');
}
}

View File

@@ -0,0 +1,127 @@
import { Request, Response, NextFunction } from 'express';
import { Logger } from '../utils/logger';
const logger = new Logger('ErrorHandler');
export interface AppError extends Error {
statusCode?: number;
isOperational?: boolean;
code?: string;
}
export function errorHandler(
error: AppError,
req: Request,
res: Response,
next: NextFunction
) {
// Log the error
logger.error('Unhandled error', {
message: error.message,
stack: error.stack,
url: req.url,
method: req.method,
ip: req.ip,
userAgent: req.get('User-Agent')
});
// Determine status code
const statusCode = error.statusCode || 500;
// Determine if it's an operational error
const isOperational = error.isOperational || false;
// Create error response
const errorResponse = {
success: false,
message: error.message || 'Internal server error',
...(process.env.NODE_ENV === 'development' && {
stack: error.stack,
code: error.code
}),
timestamp: new Date().toISOString(),
path: req.url,
method: req.method
};
// Send response
res.status(statusCode).json(errorResponse);
// For non-operational errors, consider shutting down gracefully
if (!isOperational && process.env.NODE_ENV === 'production') {
logger.error('Non-operational error detected, shutting down gracefully');
process.exit(1);
}
}
/**
* Create operational errors
*/
export class OperationalError extends Error implements AppError {
public statusCode: number;
public isOperational: boolean;
public code: string;
constructor(message: string, statusCode: number = 500, code?: string) {
super(message);
this.statusCode = statusCode;
this.isOperational = true;
this.code = code || 'OPERATIONAL_ERROR';
Error.captureStackTrace(this, this.constructor);
}
}
/**
* Create validation errors
*/
export class ValidationError extends OperationalError {
constructor(message: string) {
super(message, 400, 'VALIDATION_ERROR');
}
}
/**
* Create authentication errors
*/
export class AuthenticationError extends OperationalError {
constructor(message: string = 'Authentication failed') {
super(message, 401, 'AUTHENTICATION_ERROR');
}
}
/**
* Create authorization errors
*/
export class AuthorizationError extends OperationalError {
constructor(message: string = 'Access denied') {
super(message, 403, 'AUTHORIZATION_ERROR');
}
}
/**
* Create not found errors
*/
export class NotFoundError extends OperationalError {
constructor(message: string = 'Resource not found') {
super(message, 404, 'NOT_FOUND_ERROR');
}
}
/**
* Create rate limit errors
*/
export class RateLimitError extends OperationalError {
constructor(message: string = 'Rate limit exceeded') {
super(message, 429, 'RATE_LIMIT_ERROR');
}
}
/**
* Async error wrapper
*/
export function asyncHandler(fn: Function) {
return (req: Request, res: Response, next: NextFunction) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
}

View File

@@ -0,0 +1,109 @@
import rateLimit from 'express-rate-limit';
import { Request, Response } from 'express';
import { Logger } from '../utils/logger';
const logger = new Logger('RateLimiter');
// General rate limiter
export const rateLimiter = rateLimit({
windowMs: parseInt(process.env.RATE_LIMIT_WINDOW || '900000'), // 15 minutes
max: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || '100'), // limit each IP to 100 requests per windowMs
message: {
success: false,
message: 'Too many requests from this IP, please try again later.',
code: 'RATE_LIMIT_EXCEEDED'
},
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
handler: (req, res) => {
logger.warn('Rate limit exceeded', {
ip: req.ip,
userAgent: req.get('User-Agent'),
url: req.url
});
res.status(429).json({
success: false,
message: 'Too many requests from this IP, please try again later.',
code: 'RATE_LIMIT_EXCEEDED',
retryAfter: Math.ceil(parseInt(process.env.RATE_LIMIT_WINDOW || '900000') / 1000)
});
}
});
// Stricter rate limiter for authentication endpoints
export const authRateLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // limit each IP to 5 requests per windowMs
message: {
success: false,
message: 'Too many authentication attempts, please try again later.',
code: 'AUTH_RATE_LIMIT_EXCEEDED'
},
standardHeaders: true,
legacyHeaders: false,
handler: (req, res) => {
logger.warn('Auth rate limit exceeded', {
ip: req.ip,
userAgent: req.get('User-Agent'),
url: req.url
});
res.status(429).json({
success: false,
message: 'Too many authentication attempts, please try again later.',
code: 'AUTH_RATE_LIMIT_EXCEEDED',
retryAfter: 900 // 15 minutes
});
}
});
// Rate limiter for voice endpoints (more lenient)
export const voiceRateLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 30, // limit each IP to 30 requests per windowMs
message: {
success: false,
message: 'Too many voice requests, please try again later.',
code: 'VOICE_RATE_LIMIT_EXCEEDED'
},
standardHeaders: true,
legacyHeaders: false,
handler: (req, res) => {
logger.warn('Voice rate limit exceeded', {
ip: req.ip,
userAgent: req.get('User-Agent'),
url: req.url
});
res.status(429).json({
success: false,
message: 'Too many voice requests, please try again later.',
code: 'VOICE_RATE_LIMIT_EXCEEDED',
retryAfter: 60 // 1 minute
});
}
});
// Rate limiter for tool execution (stricter for security)
export const toolRateLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 10, // limit each IP to 10 requests per windowMs
message: {
success: false,
message: 'Too many tool execution requests, please try again later.',
code: 'TOOL_RATE_LIMIT_EXCEEDED'
},
standardHeaders: true,
legacyHeaders: false,
handler: (req, res) => {
logger.warn('Tool rate limit exceeded', {
ip: req.ip,
userAgent: req.get('User-Agent'),
url: req.url
});
res.status(429).json({
success: false,
message: 'Too many tool execution requests, please try again later.',
code: 'TOOL_RATE_LIMIT_EXCEEDED',
retryAfter: 60 // 1 minute
});
}
});

View File

@@ -0,0 +1,348 @@
import { Router, Request, Response } from 'express';
import { NowhereCore, CommandRequest, AIResponse } from '../core/nowhere';
import { Logger } from '../utils/logger';
const router = Router();
const nowhere = new NowhereCore();
const logger = new Logger('Routes');
/**
* Process text commands
*/
router.post('/command', async (req: Request, res: Response) => {
try {
const { command, userId, context, autopilot } = req.body;
if (!command) {
return res.status(400).json({
success: false,
message: 'Command is required'
});
}
logger.info('Processing command request', {
command: command.substring(0, 100),
userId,
autopilot
});
const request: CommandRequest = {
command,
userId: userId || 'default',
context,
autopilot: autopilot || false
};
const response: AIResponse = await nowhere.processCommand(request);
res.json(response);
} catch (error) {
logger.error('Command processing error', { error: error.message });
res.status(500).json({
success: false,
message: 'Internal server error',
error: error.message
});
}
});
/**
* Process voice commands
*/
router.post('/voice', async (req: Request, res: Response) => {
try {
const { audioData, userId, context } = req.body;
if (!audioData) {
return res.status(400).json({
success: false,
message: 'Audio data is required'
});
}
logger.info('Processing voice request', {
audioSize: audioData.length,
userId
});
// Convert base64 audio data to buffer
const audioBuffer = Buffer.from(audioData, 'base64');
// Process voice input
const voiceCommand = await nowhere['voice'].processVoiceInput(audioBuffer);
// Process the voice command
const request: CommandRequest = {
command: voiceCommand.text,
userId: userId || 'default',
context,
voice: true
};
const response: AIResponse = await nowhere.processCommand(request);
// Generate voice response if needed
if (response.success && req.body.generateVoice) {
const voiceResponse = await nowhere['voice'].generateVoiceResponse({
text: response.message,
mode: 'brief'
});
response.data = {
...response.data,
voiceResponse: voiceResponse.toString('base64')
};
}
res.json(response);
} catch (error) {
logger.error('Voice processing error', { error: error.message });
res.status(500).json({
success: false,
message: 'Voice processing failed',
error: error.message
});
}
});
/**
* Toggle autopilot mode
*/
router.post('/autopilot', async (req: Request, res: Response) => {
try {
const { enabled, userId } = req.body;
logger.info('Toggling autopilot mode', { enabled, userId });
const response = await nowhere.toggleAutopilot(enabled);
res.json(response);
} catch (error) {
logger.error('Autopilot toggle error', { error: error.message });
res.status(500).json({
success: false,
message: 'Failed to toggle autopilot mode',
error: error.message
});
}
});
/**
* Get user memory
*/
router.get('/memory/:userId', async (req: Request, res: Response) => {
try {
const { userId } = req.params;
const { query } = req.query;
logger.info('Getting user memory', { userId, query });
if (query) {
// Query specific memory
const memoryEntries = await nowhere['memory'].queryMemory(query as string);
res.json({
success: true,
data: memoryEntries
});
} else {
// Get user context
const userContext = await nowhere['memory'].getUserContext(userId);
res.json({
success: true,
data: userContext
});
}
} catch (error) {
logger.error('Memory retrieval error', { error: error.message });
res.status(500).json({
success: false,
message: 'Failed to retrieve memory',
error: error.message
});
}
});
/**
* Clear user memory
*/
router.delete('/memory/:userId', async (req: Request, res: Response) => {
try {
const { userId } = req.params;
logger.info('Clearing user memory', { userId });
await nowhere['memory'].clearUserMemory(userId);
res.json({
success: true,
message: 'User memory cleared successfully'
});
} catch (error) {
logger.error('Memory clearing error', { error: error.message });
res.status(500).json({
success: false,
message: 'Failed to clear memory',
error: error.message
});
}
});
/**
* Get system status
*/
router.get('/status', async (req: Request, res: Response) => {
try {
logger.info('Getting system status');
const status = await nowhere.getStatus();
res.json({
success: true,
data: status
});
} catch (error) {
logger.error('Status retrieval error', { error: error.message });
res.status(500).json({
success: false,
message: 'Failed to get system status',
error: error.message
});
}
});
/**
* Execute tools directly
*/
router.post('/tools/execute', async (req: Request, res: Response) => {
try {
const { operation, params, userId } = req.body;
if (!operation) {
return res.status(400).json({
success: false,
message: 'Operation is required'
});
}
logger.info('Executing tool', { operation, userId });
let result;
switch (operation) {
case 'file_operation':
result = await nowhere['tools'].executeFileOperation(params);
break;
case 'terminal_command':
result = await nowhere['tools'].executeTerminalCommand(params.command);
break;
case 'code_analysis':
result = await nowhere['tools'].analyzeCode(params.file);
break;
case 'web_search':
result = await nowhere['tools'].searchWeb(params.query);
break;
default:
return res.status(400).json({
success: false,
message: `Unknown operation: ${operation}`
});
}
res.json(result);
} catch (error) {
logger.error('Tool execution error', { error: error.message });
res.status(500).json({
success: false,
message: 'Tool execution failed',
error: error.message
});
}
});
/**
* Voice settings management
*/
router.put('/voice/settings', async (req: Request, res: Response) => {
try {
const { settings } = req.body;
logger.info('Updating voice settings', { settings });
await nowhere['voice'].updateSettings(settings);
res.json({
success: true,
message: 'Voice settings updated successfully'
});
} catch (error) {
logger.error('Voice settings update error', { error: error.message });
res.status(500).json({
success: false,
message: 'Failed to update voice settings',
error: error.message
});
}
});
/**
* Start voice listening
*/
router.post('/voice/listen', async (req: Request, res: Response) => {
try {
logger.info('Starting voice listening');
await nowhere['voice'].startListening();
res.json({
success: true,
message: 'Voice listening started'
});
} catch (error) {
logger.error('Voice listening start error', { error: error.message });
res.status(500).json({
success: false,
message: 'Failed to start voice listening',
error: error.message
});
}
});
/**
* Stop voice listening
*/
router.post('/voice/stop', async (req: Request, res: Response) => {
try {
logger.info('Stopping voice listening');
await nowhere['voice'].stopListening();
res.json({
success: true,
message: 'Voice listening stopped'
});
} catch (error) {
logger.error('Voice listening stop error', { error: error.message });
res.status(500).json({
success: false,
message: 'Failed to stop voice listening',
error: error.message
});
}
});
export function setupRoutes(app: any) {
app.use('/api/v1', router);
}

View File

@@ -0,0 +1,373 @@
import { Logger } from '../utils/logger';
import { exec } from 'child_process';
import { promisify } from 'util';
import * as fs from 'fs/promises';
import * as path from 'path';
const execAsync = promisify(exec);
export interface ToolResult {
success: boolean;
message: string;
data?: any;
error?: string;
executionTime?: number;
}
export interface FileOperation {
operation: 'read' | 'write' | 'create' | 'delete' | 'list';
path: string;
content?: string;
options?: any;
}
export interface CodeAnalysis {
file: string;
analysis: {
complexity: number;
lines: number;
functions: number;
issues: string[];
suggestions: string[];
};
}
export class ToolExecutor {
private logger: Logger;
private allowedCommands: Set<string>;
private safePaths: Set<string>;
constructor() {
this.logger = new Logger('ToolExecutor');
this.allowedCommands = new Set([
'ls', 'dir', 'pwd', 'echo', 'cat', 'type',
'npm', 'yarn', 'git', 'node', 'tsc',
'mkdir', 'rmdir', 'cp', 'copy', 'mv', 'move'
]);
this.safePaths = new Set([
process.cwd(),
path.join(process.cwd(), 'src'),
path.join(process.cwd(), 'frontend')
]);
}
/**
* Execute file operations
*/
async executeFileOperation(operation: FileOperation): Promise<ToolResult> {
const startTime = Date.now();
try {
this.logger.info('Executing file operation', { operation: operation.operation, path: operation.path });
switch (operation.operation) {
case 'read':
return await this.readFile(operation.path);
case 'write':
return await this.writeFile(operation.path, operation.content || '');
case 'create':
return await this.createFile(operation.path, operation.content || '');
case 'delete':
return await this.deleteFile(operation.path);
case 'list':
return await this.listDirectory(operation.path);
default:
throw new Error(`Unsupported file operation: ${operation.operation}`);
}
} catch (error) {
this.logger.error('File operation failed', {
operation: operation.operation,
path: operation.path,
error: error.message
});
return {
success: false,
message: `File operation failed: ${error.message}`,
error: error.message,
executionTime: Date.now() - startTime
};
}
}
/**
* Execute terminal commands safely
*/
async executeTerminalCommand(command: string): Promise<ToolResult> {
const startTime = Date.now();
try {
this.logger.info('Executing terminal command', { command });
// Validate command safety
if (!this.isCommandSafe(command)) {
throw new Error('Command not allowed for security reasons');
}
const { stdout, stderr } = await execAsync(command, {
cwd: process.cwd(),
timeout: 30000 // 30 second timeout
});
return {
success: true,
message: 'Command executed successfully',
data: {
stdout: stdout.trim(),
stderr: stderr.trim(),
command
},
executionTime: Date.now() - startTime
};
} catch (error) {
this.logger.error('Terminal command failed', { command, error: error.message });
return {
success: false,
message: `Command execution failed: ${error.message}`,
error: error.message,
executionTime: Date.now() - startTime
};
}
}
/**
* Analyze code files
*/
async analyzeCode(filePath: string): Promise<ToolResult> {
const startTime = Date.now();
try {
this.logger.info('Analyzing code file', { filePath });
const content = await fs.readFile(filePath, 'utf-8');
const analysis = this.performCodeAnalysis(content, filePath);
return {
success: true,
message: 'Code analysis completed',
data: {
file: filePath,
analysis
},
executionTime: Date.now() - startTime
};
} catch (error) {
this.logger.error('Code analysis failed', { filePath, error: error.message });
return {
success: false,
message: `Code analysis failed: ${error.message}`,
error: error.message,
executionTime: Date.now() - startTime
};
}
}
/**
* Search the web for information
*/
async searchWeb(query: string): Promise<ToolResult> {
const startTime = Date.now();
try {
this.logger.info('Performing web search', { query });
// Mock web search - in real implementation would use a search API
const mockResults = [
{
title: `Search results for: ${query}`,
url: `https://example.com/search?q=${encodeURIComponent(query)}`,
snippet: `Information about ${query} from various sources.`
}
];
return {
success: true,
message: 'Web search completed',
data: {
query,
results: mockResults
},
executionTime: Date.now() - startTime
};
} catch (error) {
this.logger.error('Web search failed', { query, error: error.message });
return {
success: false,
message: `Web search failed: ${error.message}`,
error: error.message,
executionTime: Date.now() - startTime
};
}
}
/**
* Get tool execution status
*/
async getStatus(): Promise<any> {
return {
allowedCommands: Array.from(this.allowedCommands),
safePaths: Array.from(this.safePaths),
lastUpdated: new Date().toISOString()
};
}
// Private helper methods
private async readFile(filePath: string): Promise<ToolResult> {
const content = await fs.readFile(filePath, 'utf-8');
return {
success: true,
message: 'File read successfully',
data: { content, path: filePath }
};
}
private async writeFile(filePath: string, content: string): Promise<ToolResult> {
await fs.writeFile(filePath, content, 'utf-8');
return {
success: true,
message: 'File written successfully',
data: { path: filePath, size: content.length }
};
}
private async createFile(filePath: string, content: string): Promise<ToolResult> {
// Ensure directory exists
const dir = path.dirname(filePath);
await fs.mkdir(dir, { recursive: true });
await fs.writeFile(filePath, content, 'utf-8');
return {
success: true,
message: 'File created successfully',
data: { path: filePath, size: content.length }
};
}
private async deleteFile(filePath: string): Promise<ToolResult> {
await fs.unlink(filePath);
return {
success: true,
message: 'File deleted successfully',
data: { path: filePath }
};
}
private async listDirectory(dirPath: string): Promise<ToolResult> {
const items = await fs.readdir(dirPath, { withFileTypes: true });
const files = items
.filter(item => item.isFile())
.map(item => ({ name: item.name, type: 'file' }));
const directories = items
.filter(item => item.isDirectory())
.map(item => ({ name: item.name, type: 'directory' }));
return {
success: true,
message: 'Directory listed successfully',
data: {
path: dirPath,
files,
directories,
totalItems: items.length
}
};
}
private isCommandSafe(command: string): boolean {
const parts = command.split(' ');
const baseCommand = parts[0].toLowerCase();
// Check if command is in allowed list
if (!this.allowedCommands.has(baseCommand)) {
return false;
}
// Additional safety checks
const dangerousPatterns = [
'rm -rf',
'del /s',
'format',
'shutdown',
'reboot'
];
const commandLower = command.toLowerCase();
for (const pattern of dangerousPatterns) {
if (commandLower.includes(pattern)) {
return false;
}
}
return true;
}
private performCodeAnalysis(content: string, filePath: string): CodeAnalysis['analysis'] {
const lines = content.split('\n');
const functions = (content.match(/function\s+\w+/g) || []).length;
const complexity = this.calculateComplexity(content);
const issues: string[] = [];
const suggestions: string[] = [];
// Basic code analysis
if (lines.length > 500) {
issues.push('File is very long, consider breaking it into smaller modules');
}
if (complexity > 10) {
issues.push('High cyclomatic complexity detected');
suggestions.push('Consider refactoring complex functions');
}
if (functions > 20) {
issues.push('Many functions in single file');
suggestions.push('Consider splitting into multiple files');
}
return {
complexity,
lines: lines.length,
functions,
issues,
suggestions
};
}
private calculateComplexity(content: string): number {
// Simple cyclomatic complexity calculation
const complexityFactors = [
/if\s*\(/g,
/else\s*{/g,
/for\s*\(/g,
/while\s*\(/g,
/switch\s*\(/g,
/case\s+/g,
/\|\|/g,
/&&/g
];
let complexity = 1; // Base complexity
for (const factor of complexityFactors) {
const matches = content.match(factor);
if (matches) {
complexity += matches.length;
}
}
return complexity;
}
}

View File

@@ -0,0 +1,71 @@
import winston from 'winston';
import path from 'path';
export class Logger {
private logger: winston.Logger;
constructor(service: string) {
this.logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
defaultMeta: { service },
transports: [
// Console transport
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple()
)
}),
// File transport for errors
new winston.transports.File({
filename: path.join('logs', 'error.log'),
level: 'error',
maxsize: 5242880, // 5MB
maxFiles: 5
}),
// File transport for all logs
new winston.transports.File({
filename: path.join('logs', 'combined.log'),
maxsize: 5242880, // 5MB
maxFiles: 5
})
]
});
// Handle uncaught exceptions
this.logger.exceptions.handle(
new winston.transports.File({
filename: path.join('logs', 'exceptions.log')
})
);
}
info(message: string, meta?: any) {
this.logger.info(message, meta);
}
error(message: string, meta?: any) {
this.logger.error(message, meta);
}
warn(message: string, meta?: any) {
this.logger.warn(message, meta);
}
debug(message: string, meta?: any) {
this.logger.debug(message, meta);
}
verbose(message: string, meta?: any) {
this.logger.verbose(message, meta);
}
silly(message: string, meta?: any) {
this.logger.silly(message, meta);
}
}

View File

@@ -0,0 +1,317 @@
import { Logger } from '../utils/logger';
export interface VoiceCommand {
text: string;
confidence: number;
intent: string;
entities: any[];
}
export interface VoiceResponse {
text: string;
audio?: Buffer;
mode: 'brief' | 'detailed' | 'silent' | 'interactive';
}
export interface VoiceSettings {
enabled: boolean;
language: string;
voice: string;
speed: number;
volume: number;
}
export class VoiceProcessor {
private logger: Logger;
private settings: VoiceSettings;
private isListening: boolean = false;
constructor() {
this.logger = new Logger('VoiceProcessor');
this.settings = {
enabled: true,
language: 'en-US',
voice: 'default',
speed: 1.0,
volume: 1.0
};
}
/**
* Process voice input (speech recognition)
*/
async processVoiceInput(audioData: Buffer): Promise<VoiceCommand> {
try {
this.logger.info('Processing voice input', {
audioSize: audioData.length,
language: this.settings.language
});
// Mock speech recognition - in real implementation would use Azure Speech Services
const mockText = this.mockSpeechRecognition(audioData);
const intent = await this.analyzeVoiceIntent(mockText);
const entities = await this.extractVoiceEntities(mockText);
const command: VoiceCommand = {
text: mockText,
confidence: 0.85,
intent: intent.type,
entities
};
this.logger.info('Voice command processed', {
text: command.text,
intent: command.intent,
confidence: command.confidence
});
return command;
} catch (error) {
this.logger.error('Voice processing failed', { error: error.message });
throw new Error(`Voice processing failed: ${error.message}`);
}
}
/**
* Generate voice response (text-to-speech)
*/
async generateVoiceResponse(response: VoiceResponse): Promise<Buffer> {
try {
this.logger.info('Generating voice response', {
text: response.text.substring(0, 50) + '...',
mode: response.mode
});
// Mock TTS - in real implementation would use Azure Speech Services
const audioBuffer = this.mockTextToSpeech(response.text, this.settings);
this.logger.info('Voice response generated', {
audioSize: audioBuffer.length,
textLength: response.text.length
});
return audioBuffer;
} catch (error) {
this.logger.error('Voice response generation failed', { error: error.message });
throw new Error(`Voice response generation failed: ${error.message}`);
}
}
/**
* Process voice command from text
*/
async processVoiceCommand(command: any): Promise<any> {
try {
this.logger.info('Processing voice command', { command });
// Parse voice command and convert to action
const action = await this.parseVoiceCommand(command);
return {
success: true,
message: 'Voice command processed successfully',
data: action
};
} catch (error) {
this.logger.error('Voice command processing failed', { error: error.message });
return {
success: false,
message: 'Voice command processing failed',
error: error.message
};
}
}
/**
* Start voice listening mode
*/
async startListening(): Promise<void> {
if (this.isListening) {
throw new Error('Already listening');
}
this.isListening = true;
this.logger.info('Voice listening started');
}
/**
* Stop voice listening mode
*/
async stopListening(): Promise<void> {
if (!this.isListening) {
throw new Error('Not currently listening');
}
this.isListening = false;
this.logger.info('Voice listening stopped');
}
/**
* Update voice settings
*/
async updateSettings(settings: Partial<VoiceSettings>): Promise<void> {
this.settings = { ...this.settings, ...settings };
this.logger.info('Voice settings updated', { settings: this.settings });
}
/**
* Get voice processor status
*/
async getStatus(): Promise<any> {
return {
enabled: this.settings.enabled,
listening: this.isListening,
settings: this.settings,
lastUpdated: new Date().toISOString()
};
}
// Private helper methods
private mockSpeechRecognition(audioData: Buffer): string {
// Mock speech recognition - in real implementation would use Azure Speech Services
const mockResponses = [
'Nowhere, analyze this code',
'Create a new React component',
'Search for documentation',
'Enable autopilot mode',
'What do you remember from our conversation?',
'Run the tests and show me the results'
];
// Use audio data hash to deterministically select a response
const hash = this.simpleHash(audioData);
const index = hash % mockResponses.length;
return mockResponses[index];
}
private async analyzeVoiceIntent(text: string): Promise<any> {
// Mock intent analysis - in real implementation would use NLP
const intents = {
'analyze': 'code_analysis',
'create': 'file_operation',
'search': 'web_search',
'autopilot': 'autopilot_toggle',
'remember': 'memory_query',
'run': 'terminal_command',
'test': 'terminal_command'
};
const words = text.toLowerCase().split(' ');
for (const word of words) {
if (intents[word]) {
return { type: intents[word], confidence: 0.9 };
}
}
return { type: 'general', confidence: 0.5 };
}
private async extractVoiceEntities(text: string): Promise<any[]> {
// Mock entity extraction - in real implementation would use NLP
const entities: any[] = [];
// Extract file names
const fileMatch = text.match(/(\w+\.\w+)/);
if (fileMatch) {
entities.push({
type: 'file',
value: fileMatch[1],
confidence: 0.8
});
}
// Extract commands
const commandMatch = text.match(/run\s+(.+)/i);
if (commandMatch) {
entities.push({
type: 'command',
value: commandMatch[1],
confidence: 0.7
});
}
// Extract search queries
const searchMatch = text.match(/search\s+(.+)/i);
if (searchMatch) {
entities.push({
type: 'query',
value: searchMatch[1],
confidence: 0.8
});
}
return entities;
}
private async parseVoiceCommand(command: any): Promise<any> {
// Convert voice command to executable action
const { intent, entities } = command;
switch (intent) {
case 'code_analysis':
return {
action: 'analyze_code',
target: entities.find(e => e.type === 'file')?.value || 'current'
};
case 'file_operation':
return {
action: 'create_file',
target: entities.find(e => e.type === 'file')?.value || 'new_file'
};
case 'web_search':
return {
action: 'search_web',
query: entities.find(e => e.type === 'query')?.value || 'general'
};
case 'autopilot_toggle':
return {
action: 'toggle_autopilot',
enabled: true
};
case 'memory_query':
return {
action: 'query_memory',
query: 'recent interactions'
};
case 'terminal_command':
return {
action: 'execute_command',
command: entities.find(e => e.type === 'command')?.value || 'ls'
};
default:
return {
action: 'general_response',
message: 'I heard your command, let me help you with that.'
};
}
}
private mockTextToSpeech(text: string, settings: VoiceSettings): Buffer {
// Mock TTS - in real implementation would use Azure Speech Services
// For now, return a mock audio buffer
const mockAudio = Buffer.alloc(1024);
mockAudio.fill(0); // Silent audio buffer
return mockAudio;
}
private simpleHash(buffer: Buffer): number {
let hash = 0;
for (let i = 0; i < Math.min(buffer.length, 100); i++) {
hash = ((hash << 5) - hash) + buffer[i];
hash = hash & hash; // Convert to 32-bit integer
}
return Math.abs(hash);
}
}

View File

@@ -0,0 +1,275 @@
import { Server as SocketIOServer, Socket } from 'socket.io';
import { Logger } from './utils/logger';
import { NowhereCore, CommandRequest, AIResponse } from './core/nowhere';
const logger = new Logger('WebSocket');
export function setupWebSocket(io: SocketIOServer) {
const nowhere = new NowhereCore();
io.on('connection', (socket: Socket) => {
logger.info('Client connected', {
id: socket.id,
ip: socket.handshake.address
});
// Send welcome message
socket.emit('welcome', {
message: 'Welcome to Nowhere AI Agent!',
timestamp: new Date().toISOString(),
features: [
'Voice Commands',
'Autopilot Mode',
'Memory System',
'Real-time Communication'
]
});
// Handle text commands
socket.on('command', async (data: any) => {
try {
logger.info('Processing WebSocket command', {
socketId: socket.id,
command: data.command?.substring(0, 100)
});
const request: CommandRequest = {
command: data.command,
userId: data.userId || socket.id,
context: data.context,
autopilot: data.autopilot || false
};
const response: AIResponse = await nowhere.processCommand(request);
socket.emit('command_response', response);
} catch (error) {
logger.error('WebSocket command error', {
socketId: socket.id,
error: error.message
});
socket.emit('error', {
success: false,
message: 'Command processing failed',
error: error.message
});
}
});
// Handle voice commands
socket.on('voice_command', async (data: any) => {
try {
logger.info('Processing WebSocket voice command', {
socketId: socket.id,
audioSize: data.audioData?.length
});
// Process voice input
const voiceCommand = await nowhere['voice'].processVoiceInput(
Buffer.from(data.audioData, 'base64')
);
// Process the voice command
const request: CommandRequest = {
command: voiceCommand.text,
userId: data.userId || socket.id,
context: data.context,
voice: true
};
const response: AIResponse = await nowhere.processCommand(request);
socket.emit('voice_response', {
...response,
voiceCommand: voiceCommand.text
});
} catch (error) {
logger.error('WebSocket voice command error', {
socketId: socket.id,
error: error.message
});
socket.emit('error', {
success: false,
message: 'Voice command processing failed',
error: error.message
});
}
});
// Handle autopilot toggle
socket.on('toggle_autopilot', async (data: any) => {
try {
logger.info('Toggling autopilot via WebSocket', {
socketId: socket.id,
enabled: data.enabled
});
const response = await nowhere.toggleAutopilot(data.enabled);
socket.emit('autopilot_response', response);
// Broadcast to all clients
io.emit('autopilot_status', {
enabled: data.enabled,
timestamp: new Date().toISOString()
});
} catch (error) {
logger.error('WebSocket autopilot toggle error', {
socketId: socket.id,
error: error.message
});
socket.emit('error', {
success: false,
message: 'Autopilot toggle failed',
error: error.message
});
}
});
// Handle memory queries
socket.on('query_memory', async (data: any) => {
try {
logger.info('Querying memory via WebSocket', {
socketId: socket.id,
query: data.query
});
const memoryEntries = await nowhere['memory'].queryMemory(data.query);
socket.emit('memory_response', {
success: true,
data: memoryEntries
});
} catch (error) {
logger.error('WebSocket memory query error', {
socketId: socket.id,
error: error.message
});
socket.emit('error', {
success: false,
message: 'Memory query failed',
error: error.message
});
}
});
// Handle status requests
socket.on('get_status', async () => {
try {
logger.info('Getting status via WebSocket', { socketId: socket.id });
const status = await nowhere.getStatus();
socket.emit('status_response', {
success: true,
data: status
});
} catch (error) {
logger.error('WebSocket status error', {
socketId: socket.id,
error: error.message
});
socket.emit('error', {
success: false,
message: 'Status retrieval failed',
error: error.message
});
}
});
// Handle voice listening
socket.on('start_voice_listening', async () => {
try {
logger.info('Starting voice listening via WebSocket', { socketId: socket.id });
await nowhere['voice'].startListening();
socket.emit('voice_listening_started', {
success: true,
message: 'Voice listening started'
});
} catch (error) {
logger.error('WebSocket voice listening start error', {
socketId: socket.id,
error: error.message
});
socket.emit('error', {
success: false,
message: 'Failed to start voice listening',
error: error.message
});
}
});
socket.on('stop_voice_listening', async () => {
try {
logger.info('Stopping voice listening via WebSocket', { socketId: socket.id });
await nowhere['voice'].stopListening();
socket.emit('voice_listening_stopped', {
success: true,
message: 'Voice listening stopped'
});
} catch (error) {
logger.error('WebSocket voice listening stop error', {
socketId: socket.id,
error: error.message
});
socket.emit('error', {
success: false,
message: 'Failed to stop voice listening',
error: error.message
});
}
});
// Handle ping/pong for connection health
socket.on('ping', () => {
socket.emit('pong', {
timestamp: new Date().toISOString(),
serverTime: Date.now()
});
});
// Handle disconnection
socket.on('disconnect', (reason) => {
logger.info('Client disconnected', {
id: socket.id,
reason
});
});
// Handle errors
socket.on('error', (error) => {
logger.error('Socket error', {
id: socket.id,
error: error.message
});
});
});
// Broadcast system events to all clients
setInterval(() => {
io.emit('heartbeat', {
timestamp: new Date().toISOString(),
activeConnections: io.engine.clientsCount
});
}, 30000); // Every 30 seconds
logger.info('WebSocket server initialized');
}

View File

@@ -0,0 +1,40 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": [
"ES2020"
],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"removeComments": true,
"noImplicitAny": false,
"strictNullChecks": false,
"strictFunctionTypes": false,
"noImplicitReturns": false,
"noFallthroughCasesInSwitch": false,
"moduleResolution": "node",
"baseUrl": "./",
"paths": {
"@/*": [
"src/*"
]
}
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist",
"**/*.test.ts"
]
}