mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2026-02-03 21:40:53 +00:00
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:
38
.github/Advanced_AI_Agent/examples/implementation/backend/.env
vendored
Normal file
38
.github/Advanced_AI_Agent/examples/implementation/backend/.env
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
# Nowhere AI Agent Backend Configuration
|
||||
|
||||
# Server Configuration
|
||||
NODE_ENV=development
|
||||
PORT=3001
|
||||
FRONTEND_URL=http://localhost:3000
|
||||
|
||||
# AI Model API Keys
|
||||
OPENAI_API_KEY=your_openai_api_key_here
|
||||
ANTHROPIC_API_KEY=your_anthropic_api_key_here
|
||||
|
||||
# Database Configuration
|
||||
REDIS_URL=redis://localhost:6379
|
||||
POSTGRES_URL=postgresql://username:password@localhost:5432/nowhere_db
|
||||
|
||||
# Authentication (Optional for development)
|
||||
JWT_SECRET=your_jwt_secret_here
|
||||
JWT_EXPIRES_IN=7d
|
||||
|
||||
# Logging
|
||||
LOG_LEVEL=info
|
||||
|
||||
# Rate Limiting
|
||||
RATE_LIMIT_POINTS=100
|
||||
RATE_LIMIT_DURATION=60
|
||||
VOICE_RATE_LIMIT_POINTS=50
|
||||
|
||||
# Voice Processing (Optional)
|
||||
AZURE_SPEECH_KEY=your_azure_speech_key_here
|
||||
AZURE_SPEECH_REGION=your_azure_region_here
|
||||
|
||||
# Security
|
||||
CORS_ORIGIN=http://localhost:3000
|
||||
HELMET_ENABLED=true
|
||||
|
||||
# Development
|
||||
DEBUG=true
|
||||
ENABLE_SWAGGER=true
|
||||
333
.github/Advanced_AI_Agent/examples/implementation/backend/README.md
vendored
Normal file
333
.github/Advanced_AI_Agent/examples/implementation/backend/README.md
vendored
Normal file
@@ -0,0 +1,333 @@
|
||||
# 🚀 Nowhere AI Agent Backend
|
||||
|
||||
Advanced AI coding assistant backend with voice integration, autopilot mode, and adaptive learning capabilities.
|
||||
|
||||
## 🎯 Features
|
||||
|
||||
- **Voice Command Processing** - Natural language voice commands
|
||||
- **Autopilot Mode** - Autonomous task execution
|
||||
- **Adaptive Learning** - Memory system with persistent context
|
||||
- **Multi-Model Support** - OpenAI GPT-4.1+ and Anthropic Claude 3.5 Sonnet
|
||||
- **Real-time Communication** - WebSocket support for live collaboration
|
||||
- **Rate Limiting** - Protection against abuse
|
||||
- **Comprehensive Logging** - Structured logging with Winston
|
||||
|
||||
## 🏗️ Architecture
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Frontend │◄──►│ Nowhere API │◄──►│ AI Models │
|
||||
│ (React/Web) │ │ (Express) │ │ (OpenAI/Claude)│
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Voice APIs │ │ Memory System │ │ Tool Executor │
|
||||
│ (Speech/Text) │ │ (Redis/DB) │ │ (File/Code) │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js 18+
|
||||
- Redis (for memory and rate limiting)
|
||||
- PostgreSQL (optional, for persistent storage)
|
||||
- OpenAI API key
|
||||
- Anthropic API key
|
||||
|
||||
### Installation
|
||||
|
||||
1. **Clone and install dependencies:**
|
||||
```bash
|
||||
cd Advanced_AI_Agent/implementation/backend
|
||||
npm install
|
||||
```
|
||||
|
||||
2. **Set up environment variables:**
|
||||
```bash
|
||||
cp env.example .env
|
||||
# Edit .env with your API keys and configuration
|
||||
```
|
||||
|
||||
3. **Start the development server:**
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
The server will start on `http://localhost:3001`
|
||||
|
||||
## 📋 API Endpoints
|
||||
|
||||
### Core Commands
|
||||
|
||||
#### Process Command
|
||||
```http
|
||||
POST /api/v1/command
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"command": "Create a React component for user authentication",
|
||||
"context": {
|
||||
"userId": "user123",
|
||||
"projectId": "project456",
|
||||
"currentFile": "src/components/Auth.jsx",
|
||||
"codebase": {...},
|
||||
"userPreferences": {...}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Voice Command Processing
|
||||
```http
|
||||
POST /api/v1/voice
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"voiceInput": "Nowhere, create a new user component",
|
||||
"context": {
|
||||
"userId": "user123",
|
||||
"projectId": "project456"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Autopilot Mode
|
||||
|
||||
#### Enable Autopilot
|
||||
```http
|
||||
POST /api/v1/autopilot/enable
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"context": {
|
||||
"userId": "user123",
|
||||
"projectId": "project456"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Disable Autopilot
|
||||
```http
|
||||
POST /api/v1/autopilot/disable
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"context": {
|
||||
"userId": "user123",
|
||||
"projectId": "project456"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Memory Management
|
||||
|
||||
#### Get Memory
|
||||
```http
|
||||
GET /api/v1/memory/:userId/:projectId?sessionId=session123
|
||||
```
|
||||
|
||||
#### Clear Memory
|
||||
```http
|
||||
DELETE /api/v1/memory/:userId/:projectId?sessionId=session123
|
||||
```
|
||||
|
||||
### System Status
|
||||
|
||||
#### Health Check
|
||||
```http
|
||||
GET /health
|
||||
```
|
||||
|
||||
#### Status
|
||||
```http
|
||||
GET /api/v1/status
|
||||
```
|
||||
|
||||
#### Configuration
|
||||
```http
|
||||
GET /api/v1/config
|
||||
```
|
||||
|
||||
## 🎙️ Voice Commands
|
||||
|
||||
### Navigation Commands
|
||||
- "Go to file [filename]"
|
||||
- "Show me the main function"
|
||||
- "Navigate to [component/module]"
|
||||
- "Open [file path]"
|
||||
|
||||
### Execution Commands
|
||||
- "Run the tests"
|
||||
- "Deploy to staging"
|
||||
- "Build the project"
|
||||
- "Start the development server"
|
||||
|
||||
### Analysis Commands
|
||||
- "Analyze this code"
|
||||
- "Find performance issues"
|
||||
- "Check for security vulnerabilities"
|
||||
- "Review the code quality"
|
||||
|
||||
### Creation Commands
|
||||
- "Create a new [component/function/class]"
|
||||
- "Add authentication"
|
||||
- "Implement [feature]"
|
||||
- "Generate [type]"
|
||||
|
||||
### Debugging Commands
|
||||
- "Fix this error"
|
||||
- "Debug the issue"
|
||||
- "Optimize this function"
|
||||
- "Resolve the conflict"
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `NODE_ENV` | Environment mode | `development` |
|
||||
| `PORT` | Server port | `3001` |
|
||||
| `FRONTEND_URL` | Frontend URL for CORS | `http://localhost:3000` |
|
||||
| `OPENAI_API_KEY` | OpenAI API key | Required |
|
||||
| `ANTHROPIC_API_KEY` | Anthropic API key | Required |
|
||||
| `REDIS_URL` | Redis connection URL | `redis://localhost:6379` |
|
||||
| `POSTGRES_URL` | PostgreSQL connection URL | Optional |
|
||||
| `JWT_SECRET` | JWT signing secret | Required in production |
|
||||
| `LOG_LEVEL` | Logging level | `info` |
|
||||
|
||||
### Rate Limiting
|
||||
|
||||
- **General API**: 100 requests per minute
|
||||
- **Voice Commands**: 50 requests per minute
|
||||
- **Block Duration**: 15 minutes (general), 30 minutes (voice)
|
||||
|
||||
## 🛠️ Development
|
||||
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
backend/
|
||||
├── src/
|
||||
│ ├── core/ # Nowhere AI core logic
|
||||
│ ├── memory/ # Memory management system
|
||||
│ ├── tools/ # Tool execution engine
|
||||
│ ├── voice/ # Voice processing
|
||||
│ ├── middleware/ # Express middleware
|
||||
│ ├── routes/ # API routes
|
||||
│ ├── utils/ # Utility functions
|
||||
│ ├── websocket/ # WebSocket handlers
|
||||
│ └── index.ts # Server entry point
|
||||
├── logs/ # Application logs
|
||||
├── tests/ # Test files
|
||||
├── package.json # Dependencies
|
||||
└── env.example # Environment template
|
||||
```
|
||||
|
||||
### Available Scripts
|
||||
|
||||
```bash
|
||||
npm run dev # Start development server
|
||||
npm run build # Build for production
|
||||
npm run start # Start production server
|
||||
npm run test # Run tests
|
||||
npm run lint # Lint code
|
||||
npm run format # Format code
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
npm test
|
||||
|
||||
# Run tests in watch mode
|
||||
npm run test:watch
|
||||
|
||||
# Run tests with coverage
|
||||
npm run test:coverage
|
||||
```
|
||||
|
||||
## 🔒 Security
|
||||
|
||||
### Authentication
|
||||
- JWT-based authentication (optional in development)
|
||||
- Role-based access control
|
||||
- Secure session management
|
||||
|
||||
### Rate Limiting
|
||||
- IP-based rate limiting
|
||||
- Separate limits for voice commands
|
||||
- Configurable limits and durations
|
||||
|
||||
### Data Protection
|
||||
- Input validation and sanitization
|
||||
- SQL injection prevention
|
||||
- XSS protection with Helmet
|
||||
- CORS configuration
|
||||
|
||||
## 📊 Monitoring
|
||||
|
||||
### Logging
|
||||
- Structured JSON logging
|
||||
- Different log levels (error, warn, info, debug)
|
||||
- File-based logging with rotation
|
||||
- Request/response logging
|
||||
|
||||
### Health Checks
|
||||
- `/health` endpoint for monitoring
|
||||
- Database connectivity checks
|
||||
- AI model availability checks
|
||||
|
||||
## 🚀 Deployment
|
||||
|
||||
### Docker Deployment
|
||||
|
||||
```dockerfile
|
||||
FROM node:18-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package*.json ./
|
||||
RUN npm ci --only=production
|
||||
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
EXPOSE 3001
|
||||
|
||||
CMD ["npm", "start"]
|
||||
```
|
||||
|
||||
### Environment Setup
|
||||
|
||||
1. Set production environment variables
|
||||
2. Configure Redis and PostgreSQL
|
||||
3. Set up SSL certificates
|
||||
4. Configure reverse proxy (nginx)
|
||||
5. Set up monitoring and logging
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch
|
||||
3. Make your changes
|
||||
4. Add tests for new functionality
|
||||
5. Submit a pull request
|
||||
|
||||
## 📄 License
|
||||
|
||||
MIT License - see LICENSE file for details
|
||||
|
||||
## 🆘 Support
|
||||
|
||||
For support and questions:
|
||||
- Create an issue in the repository
|
||||
- Check the documentation
|
||||
- Review the API examples
|
||||
|
||||
---
|
||||
|
||||
**Nowhere AI Agent** - The most advanced AI coding assistant with voice integration and autonomous capabilities.
|
||||
38
.github/Advanced_AI_Agent/examples/implementation/backend/env.example
vendored
Normal file
38
.github/Advanced_AI_Agent/examples/implementation/backend/env.example
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
# Nowhere AI Agent Backend Configuration
|
||||
|
||||
# Server Configuration
|
||||
NODE_ENV=development
|
||||
PORT=3001
|
||||
FRONTEND_URL=http://localhost:3000
|
||||
|
||||
# AI Model API Keys
|
||||
OPENAI_API_KEY=your_openai_api_key_here
|
||||
ANTHROPIC_API_KEY=your_anthropic_api_key_here
|
||||
|
||||
# Database Configuration
|
||||
REDIS_URL=redis://localhost:6379
|
||||
POSTGRES_URL=postgresql://username:password@localhost:5432/nowhere_db
|
||||
|
||||
# Authentication (Optional for development)
|
||||
JWT_SECRET=your_jwt_secret_here
|
||||
JWT_EXPIRES_IN=7d
|
||||
|
||||
# Logging
|
||||
LOG_LEVEL=info
|
||||
|
||||
# Rate Limiting
|
||||
RATE_LIMIT_POINTS=100
|
||||
RATE_LIMIT_DURATION=60
|
||||
VOICE_RATE_LIMIT_POINTS=50
|
||||
|
||||
# Voice Processing (Optional)
|
||||
AZURE_SPEECH_KEY=your_azure_speech_key_here
|
||||
AZURE_SPEECH_REGION=your_azure_region_here
|
||||
|
||||
# Security
|
||||
CORS_ORIGIN=http://localhost:3000
|
||||
HELMET_ENABLED=true
|
||||
|
||||
# Development
|
||||
DEBUG=true
|
||||
ENABLE_SWAGGER=true
|
||||
39
.github/Advanced_AI_Agent/examples/implementation/backend/install.js
vendored
Normal file
39
.github/Advanced_AI_Agent/examples/implementation/backend/install.js
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
const { execSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
console.log('🚀 Setting up Nowhere AI Agent Backend...');
|
||||
|
||||
// Check if package.json exists
|
||||
if (!fs.existsSync('package.json')) {
|
||||
console.error('❌ package.json not found');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Create logs directory
|
||||
if (!fs.existsSync('logs')) {
|
||||
fs.mkdirSync('logs');
|
||||
console.log('✅ Created logs directory');
|
||||
}
|
||||
|
||||
// Create .env file from example if it doesn't exist
|
||||
if (!fs.existsSync('.env') && fs.existsSync('env.example')) {
|
||||
fs.copyFileSync('env.example', '.env');
|
||||
console.log('✅ Created .env file from env.example');
|
||||
}
|
||||
|
||||
console.log('📦 Installing dependencies...');
|
||||
try {
|
||||
// Try to install dependencies
|
||||
execSync('npm install', { stdio: 'inherit' });
|
||||
console.log('✅ Dependencies installed successfully');
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to install dependencies:', error.message);
|
||||
console.log('💡 Try running: npm install manually');
|
||||
}
|
||||
|
||||
console.log('🎯 Nowhere AI Agent Backend setup complete!');
|
||||
console.log('📝 Next steps:');
|
||||
console.log(' 1. Edit .env file with your API keys');
|
||||
console.log(' 2. Run: npm run dev');
|
||||
console.log(' 3. Access the API at http://localhost:3001');
|
||||
69
.github/Advanced_AI_Agent/examples/implementation/backend/package.json
vendored
Normal file
69
.github/Advanced_AI_Agent/examples/implementation/backend/package.json
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"name": "nowhere-backend",
|
||||
"version": "1.0.0",
|
||||
"description": "Nowhere AI Agent Backend - Advanced AI coding assistant with voice integration",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"dev": "nodemon src/index.ts",
|
||||
"build": "tsc",
|
||||
"start": "node dist/index.js",
|
||||
"test": "jest",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"format": "prettier --write src/**/*.ts"
|
||||
},
|
||||
"keywords": [
|
||||
"ai",
|
||||
"coding-assistant",
|
||||
"voice-integration",
|
||||
"autopilot",
|
||||
"nowhere"
|
||||
],
|
||||
"author": "Nowhere Team",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"express": "^4.18.2",
|
||||
"fastify": "^4.24.3",
|
||||
"typescript": "^5.2.2",
|
||||
"@types/node": "^20.8.10",
|
||||
"redis": "^4.6.10",
|
||||
"pg": "^8.11.3",
|
||||
"@types/redis": "^4.0.11",
|
||||
"@types/pg": "^8.10.7",
|
||||
"openai": "^4.20.1",
|
||||
"@anthropic-ai/sdk": "^0.9.1",
|
||||
"socket.io": "^4.7.4",
|
||||
"cors": "^2.8.5",
|
||||
"helmet": "^7.1.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"@types/jsonwebtoken": "^9.0.4",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"@types/bcryptjs": "^2.4.5",
|
||||
"joi": "^17.11.0",
|
||||
"winston": "^3.11.0",
|
||||
"compression": "^1.7.4",
|
||||
"@types/compression": "^1.7.4",
|
||||
"rate-limiter-flexible": "^3.0.8",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"@types/multer": "^1.4.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ts-node": "^10.9.1",
|
||||
"nodemon": "^3.0.1",
|
||||
"@types/express": "^4.17.20",
|
||||
"@types/cors": "^2.8.15",
|
||||
"jest": "^29.7.0",
|
||||
"@types/jest": "^29.5.7",
|
||||
"ts-jest": "^29.1.1",
|
||||
"eslint": "^8.52.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.9.1",
|
||||
"@typescript-eslint/parser": "^6.9.1",
|
||||
"prettier": "^3.0.3",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-prettier": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"npm": ">=8.0.0"
|
||||
}
|
||||
}
|
||||
285
.github/Advanced_AI_Agent/examples/implementation/backend/src/core/nowhere.ts
vendored
Normal file
285
.github/Advanced_AI_Agent/examples/implementation/backend/src/core/nowhere.ts
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import OpenAI from 'openai';
|
||||
import Anthropic from '@anthropic-ai/sdk';
|
||||
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 NowhereContext {
|
||||
userId: string;
|
||||
projectId: string;
|
||||
currentFile?: string;
|
||||
codebase?: any;
|
||||
userPreferences?: any;
|
||||
sessionId: string;
|
||||
}
|
||||
|
||||
export interface NowhereResponse {
|
||||
response: string;
|
||||
actions: any[];
|
||||
memory: any;
|
||||
confidence: number;
|
||||
suggestions?: string[];
|
||||
}
|
||||
|
||||
export interface VoiceCommand {
|
||||
type: 'navigation' | 'execution' | 'analysis' | 'creation' | 'debugging';
|
||||
command: string;
|
||||
confidence: number;
|
||||
parameters: any;
|
||||
}
|
||||
|
||||
export class NowhereCore {
|
||||
private systemPrompt: string;
|
||||
private openai: OpenAI;
|
||||
private anthropic: Anthropic;
|
||||
private memoryManager: MemoryManager;
|
||||
private toolExecutor: ToolExecutor;
|
||||
private voiceProcessor: VoiceProcessor;
|
||||
private logger: Logger;
|
||||
|
||||
constructor() {
|
||||
this.logger = new Logger('NowhereCore');
|
||||
this.systemPrompt = this.loadSystemPrompt();
|
||||
this.openai = new OpenAI({
|
||||
apiKey: process.env.OPENAI_API_KEY,
|
||||
});
|
||||
this.anthropic = new Anthropic({
|
||||
apiKey: process.env.ANTHROPIC_API_KEY,
|
||||
});
|
||||
this.memoryManager = new MemoryManager();
|
||||
this.toolExecutor = new ToolExecutor();
|
||||
this.voiceProcessor = new VoiceProcessor();
|
||||
}
|
||||
|
||||
private loadSystemPrompt(): string {
|
||||
try {
|
||||
return readFileSync(
|
||||
join(__dirname, '../../../prompts/system_prompt.md'),
|
||||
'utf-8'
|
||||
);
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to load system prompt', error);
|
||||
return '# Nowhere AI Agent\n\nYou are Nowhere, an advanced AI coding assistant.';
|
||||
}
|
||||
}
|
||||
|
||||
async processCommand(
|
||||
command: string,
|
||||
context: NowhereContext,
|
||||
isVoiceCommand: boolean = false
|
||||
): Promise<NowhereResponse> {
|
||||
try {
|
||||
this.logger.info(`Processing command: ${command}`, { context });
|
||||
|
||||
// Process voice command if applicable
|
||||
let processedCommand = command;
|
||||
let voiceCommand: VoiceCommand | null = null;
|
||||
|
||||
if (isVoiceCommand) {
|
||||
voiceCommand = await this.voiceProcessor.processVoiceCommand(command);
|
||||
processedCommand = voiceCommand.command;
|
||||
}
|
||||
|
||||
// Retrieve relevant memory
|
||||
const memory = await this.memoryManager.getRelevantMemory(context);
|
||||
|
||||
// Create AI prompt with context
|
||||
const prompt = this.buildPrompt(processedCommand, context, memory);
|
||||
|
||||
// Get AI response
|
||||
const aiResponse = await this.getAIResponse(prompt, context);
|
||||
|
||||
// Execute any required actions
|
||||
const actions = await this.executeActions(aiResponse.actions, context);
|
||||
|
||||
// Update memory
|
||||
await this.memoryManager.updateMemory(context, {
|
||||
command: processedCommand,
|
||||
response: aiResponse.response,
|
||||
actions: actions,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
|
||||
return {
|
||||
response: aiResponse.response,
|
||||
actions: actions,
|
||||
memory: memory,
|
||||
confidence: aiResponse.confidence,
|
||||
suggestions: aiResponse.suggestions,
|
||||
};
|
||||
} catch (error) {
|
||||
this.logger.error('Error processing command', error);
|
||||
return {
|
||||
response: 'I encountered an error processing your request. Please try again.',
|
||||
actions: [],
|
||||
memory: {},
|
||||
confidence: 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private buildPrompt(
|
||||
command: string,
|
||||
context: NowhereContext,
|
||||
memory: any
|
||||
): string {
|
||||
return `
|
||||
${this.systemPrompt}
|
||||
|
||||
## Current Context
|
||||
- User ID: ${context.userId}
|
||||
- Project ID: ${context.projectId}
|
||||
- Current File: ${context.currentFile || 'None'}
|
||||
- Session ID: ${context.sessionId}
|
||||
|
||||
## Relevant Memory
|
||||
${JSON.stringify(memory, null, 2)}
|
||||
|
||||
## User Command
|
||||
${command}
|
||||
|
||||
## Instructions
|
||||
Process this command using your advanced capabilities. Consider the context and memory when formulating your response. If this is a voice command, provide clear, actionable responses suitable for voice interaction.
|
||||
`;
|
||||
}
|
||||
|
||||
private async getAIResponse(
|
||||
prompt: string,
|
||||
context: NowhereContext
|
||||
): Promise<any> {
|
||||
try {
|
||||
// Try OpenAI first, fallback to Anthropic
|
||||
const openaiResponse = await this.openai.chat.completions.create({
|
||||
model: 'gpt-4',
|
||||
messages: [
|
||||
{
|
||||
role: 'system',
|
||||
content: this.systemPrompt,
|
||||
},
|
||||
{
|
||||
role: 'user',
|
||||
content: prompt,
|
||||
},
|
||||
],
|
||||
temperature: 0.7,
|
||||
max_tokens: 2000,
|
||||
});
|
||||
|
||||
const response = openaiResponse.choices[0]?.message?.content || '';
|
||||
|
||||
// Parse response for actions and confidence
|
||||
const parsedResponse = this.parseAIResponse(response);
|
||||
|
||||
return {
|
||||
response: parsedResponse.response,
|
||||
actions: parsedResponse.actions,
|
||||
confidence: parsedResponse.confidence,
|
||||
suggestions: parsedResponse.suggestions,
|
||||
};
|
||||
} catch (error) {
|
||||
this.logger.warn('OpenAI failed, trying Anthropic', error);
|
||||
|
||||
// Fallback to Anthropic
|
||||
const anthropicResponse = await this.anthropic.messages.create({
|
||||
model: 'claude-3-sonnet-20240229',
|
||||
max_tokens: 2000,
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
content: prompt,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const response = anthropicResponse.content[0]?.text || '';
|
||||
const parsedResponse = this.parseAIResponse(response);
|
||||
|
||||
return {
|
||||
response: parsedResponse.response,
|
||||
actions: parsedResponse.actions,
|
||||
confidence: parsedResponse.confidence,
|
||||
suggestions: parsedResponse.suggestions,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private parseAIResponse(response: string): any {
|
||||
try {
|
||||
// Look for JSON blocks in the response
|
||||
const jsonMatch = response.match(/```json\n([\s\S]*?)\n```/);
|
||||
if (jsonMatch) {
|
||||
const parsed = JSON.parse(jsonMatch[1]);
|
||||
return {
|
||||
response: parsed.response || response,
|
||||
actions: parsed.actions || [],
|
||||
confidence: parsed.confidence || 0.8,
|
||||
suggestions: parsed.suggestions || [],
|
||||
};
|
||||
}
|
||||
|
||||
// Fallback to simple parsing
|
||||
return {
|
||||
response: response,
|
||||
actions: [],
|
||||
confidence: 0.8,
|
||||
suggestions: [],
|
||||
};
|
||||
} catch (error) {
|
||||
this.logger.warn('Failed to parse AI response', error);
|
||||
return {
|
||||
response: response,
|
||||
actions: [],
|
||||
confidence: 0.8,
|
||||
suggestions: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private async executeActions(actions: any[], context: NowhereContext): Promise<any[]> {
|
||||
const results = [];
|
||||
|
||||
for (const action of actions) {
|
||||
try {
|
||||
const result = await this.toolExecutor.executeTool(action, context);
|
||||
results.push(result);
|
||||
} catch (error) {
|
||||
this.logger.error(`Failed to execute action: ${action.type}`, error);
|
||||
results.push({
|
||||
success: false,
|
||||
error: error.message,
|
||||
action: action,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
async processVoiceCommand(
|
||||
voiceInput: string,
|
||||
context: NowhereContext
|
||||
): Promise<NowhereResponse> {
|
||||
return this.processCommand(voiceInput, context, true);
|
||||
}
|
||||
|
||||
async enableAutopilotMode(context: NowhereContext): Promise<void> {
|
||||
this.logger.info('Enabling autopilot mode', { context });
|
||||
// Implementation for autopilot mode
|
||||
}
|
||||
|
||||
async disableAutopilotMode(context: NowhereContext): Promise<void> {
|
||||
this.logger.info('Disabling autopilot mode', { context });
|
||||
// Implementation for disabling autopilot mode
|
||||
}
|
||||
|
||||
async getMemory(context: NowhereContext): Promise<any> {
|
||||
return this.memoryManager.getRelevantMemory(context);
|
||||
}
|
||||
|
||||
async clearMemory(context: NowhereContext): Promise<void> {
|
||||
await this.memoryManager.clearMemory(context);
|
||||
}
|
||||
}
|
||||
120
.github/Advanced_AI_Agent/examples/implementation/backend/src/index.ts
vendored
Normal file
120
.github/Advanced_AI_Agent/examples/implementation/backend/src/index.ts
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
import express from 'express';
|
||||
import { createServer } from 'http';
|
||||
import { Server } from 'socket.io';
|
||||
import cors from 'cors';
|
||||
import helmet from 'helmet';
|
||||
import compression from 'compression';
|
||||
import dotenv from 'dotenv';
|
||||
import { Logger } from './utils/logger';
|
||||
import { NowhereCore } from './core/nowhere';
|
||||
import { setupRoutes } from './routes';
|
||||
import { setupWebSocket } from './websocket';
|
||||
import { errorHandler } from './middleware/error-handler';
|
||||
import { rateLimiter } from './middleware/rate-limiter';
|
||||
import { authMiddleware } from './middleware/auth';
|
||||
|
||||
// Load environment variables
|
||||
dotenv.config();
|
||||
|
||||
const app = express();
|
||||
const server = createServer(app);
|
||||
const io = new Server(server, {
|
||||
cors: {
|
||||
origin: process.env.FRONTEND_URL || 'http://localhost:3000',
|
||||
methods: ['GET', 'POST'],
|
||||
},
|
||||
});
|
||||
|
||||
const logger = new Logger('Server');
|
||||
const PORT = process.env.PORT || 3001;
|
||||
|
||||
// Initialize Nowhere core
|
||||
const nowhere = new NowhereCore();
|
||||
|
||||
// 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 }));
|
||||
|
||||
// Rate limiting
|
||||
app.use(rateLimiter);
|
||||
|
||||
// Authentication middleware (optional for development)
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
app.use(authMiddleware);
|
||||
}
|
||||
|
||||
// Health check endpoint
|
||||
app.get('/health', (req, res) => {
|
||||
res.json({
|
||||
status: 'healthy',
|
||||
timestamp: new Date().toISOString(),
|
||||
version: '1.0.0',
|
||||
agent: 'Nowhere',
|
||||
});
|
||||
});
|
||||
|
||||
// Setup routes
|
||||
setupRoutes(app, nowhere);
|
||||
|
||||
// Setup WebSocket
|
||||
setupWebSocket(io, nowhere);
|
||||
|
||||
// Error handling middleware
|
||||
app.use(errorHandler);
|
||||
|
||||
// 404 handler
|
||||
app.use('*', (req, res) => {
|
||||
res.status(404).json({
|
||||
error: 'Route not found',
|
||||
path: req.originalUrl,
|
||||
});
|
||||
});
|
||||
|
||||
// Start server
|
||||
server.listen(PORT, () => {
|
||||
logger.info(`🚀 Nowhere AI Agent Server running on port ${PORT}`);
|
||||
logger.info(`📡 WebSocket server ready for real-time communication`);
|
||||
logger.info(`🔗 Health check: http://localhost:${PORT}/health`);
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
logger.info(`🌐 Frontend URL: ${process.env.FRONTEND_URL || 'http://localhost:3000'}`);
|
||||
logger.info(`🔑 OpenAI API: ${process.env.OPENAI_API_KEY ? 'Configured' : 'Missing'}`);
|
||||
logger.info(`🔑 Anthropic API: ${process.env.ANTHROPIC_API_KEY ? 'Configured' : 'Missing'}`);
|
||||
}
|
||||
});
|
||||
|
||||
// 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);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
process.on('unhandledRejection', (reason, promise) => {
|
||||
logger.error('Unhandled Rejection at:', promise, 'reason:', reason);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
export { app, server, io, nowhere };
|
||||
325
.github/Advanced_AI_Agent/examples/implementation/backend/src/memory/memory-manager.ts
vendored
Normal file
325
.github/Advanced_AI_Agent/examples/implementation/backend/src/memory/memory-manager.ts
vendored
Normal file
@@ -0,0 +1,325 @@
|
||||
import Redis from 'redis';
|
||||
import { Pool } from 'pg';
|
||||
import { Logger } from '../utils/logger';
|
||||
|
||||
export interface MemoryEntry {
|
||||
id: string;
|
||||
userId: string;
|
||||
projectId: string;
|
||||
type: 'conversation' | 'code_context' | 'user_preferences' | 'project_state';
|
||||
content: any;
|
||||
metadata: {
|
||||
timestamp: Date;
|
||||
confidence: number;
|
||||
tags: string[];
|
||||
context: any;
|
||||
};
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
export interface MemoryQuery {
|
||||
userId: string;
|
||||
projectId?: string;
|
||||
type?: string;
|
||||
tags?: string[];
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
export class MemoryManager {
|
||||
private redis: Redis.RedisClientType;
|
||||
private postgres: Pool;
|
||||
private logger: Logger;
|
||||
|
||||
constructor() {
|
||||
this.logger = new Logger('MemoryManager');
|
||||
this.initializeConnections();
|
||||
}
|
||||
|
||||
private async initializeConnections() {
|
||||
// Initialize Redis connection
|
||||
this.redis = Redis.createClient({
|
||||
url: process.env.REDIS_URL || 'redis://localhost:6379',
|
||||
});
|
||||
|
||||
this.redis.on('error', (err) => {
|
||||
this.logger.error('Redis connection error', { error: err.message });
|
||||
});
|
||||
|
||||
await this.redis.connect();
|
||||
|
||||
// Initialize PostgreSQL connection
|
||||
this.postgres = new Pool({
|
||||
connectionString: process.env.POSTGRES_URL || 'postgresql://localhost:5432/nowhere_db',
|
||||
});
|
||||
|
||||
await this.createTables();
|
||||
}
|
||||
|
||||
private async createTables() {
|
||||
const createMemoryTable = `
|
||||
CREATE TABLE IF NOT EXISTS memory_entries (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id VARCHAR(255) NOT NULL,
|
||||
project_id VARCHAR(255),
|
||||
type VARCHAR(50) NOT NULL,
|
||||
content JSONB NOT NULL,
|
||||
metadata JSONB NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_memory_user_project ON memory_entries(user_id, project_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_memory_type ON memory_entries(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_memory_created_at ON memory_entries(created_at);
|
||||
`;
|
||||
|
||||
try {
|
||||
await this.postgres.query(createMemoryTable);
|
||||
this.logger.info('Database tables created successfully');
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to create database tables', { error });
|
||||
}
|
||||
}
|
||||
|
||||
async storeMemory(entry: Omit<MemoryEntry, 'id' | 'createdAt' | 'updatedAt'>): Promise<string> {
|
||||
try {
|
||||
// Store in PostgreSQL for persistence
|
||||
const query = `
|
||||
INSERT INTO memory_entries (user_id, project_id, type, content, metadata)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id
|
||||
`;
|
||||
|
||||
const result = await this.postgres.query(query, [
|
||||
entry.userId,
|
||||
entry.projectId,
|
||||
entry.type,
|
||||
JSON.stringify(entry.content),
|
||||
JSON.stringify(entry.metadata)
|
||||
]);
|
||||
|
||||
const id = result.rows[0].id;
|
||||
|
||||
// Cache in Redis for fast access
|
||||
const cacheKey = `memory:${entry.userId}:${entry.projectId}:${id}`;
|
||||
await this.redis.setEx(cacheKey, 3600, JSON.stringify(entry)); // Cache for 1 hour
|
||||
|
||||
this.logger.memoryOperation('store', { userId: entry.userId, projectId: entry.projectId, type: entry.type });
|
||||
return id;
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to store memory', { error, entry });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async retrieveMemory(query: MemoryQuery): Promise<MemoryEntry[]> {
|
||||
try {
|
||||
let sqlQuery = `
|
||||
SELECT * FROM memory_entries
|
||||
WHERE user_id = $1
|
||||
`;
|
||||
const params: any[] = [query.userId];
|
||||
let paramIndex = 2;
|
||||
|
||||
if (query.projectId) {
|
||||
sqlQuery += ` AND project_id = $${paramIndex}`;
|
||||
params.push(query.projectId);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
if (query.type) {
|
||||
sqlQuery += ` AND type = $${paramIndex}`;
|
||||
params.push(query.type);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
if (query.tags && query.tags.length > 0) {
|
||||
sqlQuery += ` AND metadata->>'tags' ?| $${paramIndex}`;
|
||||
params.push(query.tags);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
sqlQuery += ` ORDER BY created_at DESC`;
|
||||
|
||||
if (query.limit) {
|
||||
sqlQuery += ` LIMIT $${paramIndex}`;
|
||||
params.push(query.limit);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
if (query.offset) {
|
||||
sqlQuery += ` OFFSET $${paramIndex}`;
|
||||
params.push(query.offset);
|
||||
}
|
||||
|
||||
const result = await this.postgres.query(sqlQuery, params);
|
||||
|
||||
const memories = result.rows.map(row => ({
|
||||
id: row.id,
|
||||
userId: row.user_id,
|
||||
projectId: row.project_id,
|
||||
type: row.type,
|
||||
content: row.content,
|
||||
metadata: row.metadata,
|
||||
createdAt: row.created_at,
|
||||
updatedAt: row.updated_at
|
||||
}));
|
||||
|
||||
this.logger.memoryOperation('retrieve', { query, count: memories.length });
|
||||
return memories;
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to retrieve memory', { error, query });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async updateMemory(id: string, updates: Partial<MemoryEntry>): Promise<void> {
|
||||
try {
|
||||
const updateFields: string[] = [];
|
||||
const params: any[] = [];
|
||||
let paramIndex = 1;
|
||||
|
||||
if (updates.content) {
|
||||
updateFields.push(`content = $${paramIndex}`);
|
||||
params.push(JSON.stringify(updates.content));
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
if (updates.metadata) {
|
||||
updateFields.push(`metadata = $${paramIndex}`);
|
||||
params.push(JSON.stringify(updates.metadata));
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
if (updateFields.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateFields.push(`updated_at = CURRENT_TIMESTAMP`);
|
||||
params.push(id);
|
||||
|
||||
const query = `
|
||||
UPDATE memory_entries
|
||||
SET ${updateFields.join(', ')}
|
||||
WHERE id = $${paramIndex}
|
||||
`;
|
||||
|
||||
await this.postgres.query(query, params);
|
||||
|
||||
// Update cache
|
||||
const cacheKey = `memory:${updates.userId}:${updates.projectId}:${id}`;
|
||||
const cached = await this.redis.get(cacheKey);
|
||||
if (cached) {
|
||||
const entry = JSON.parse(cached);
|
||||
const updatedEntry = { ...entry, ...updates, updatedAt: new Date() };
|
||||
await this.redis.setEx(cacheKey, 3600, JSON.stringify(updatedEntry));
|
||||
}
|
||||
|
||||
this.logger.memoryOperation('update', { id, updates });
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to update memory', { error, id, updates });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async deleteMemory(id: string): Promise<void> {
|
||||
try {
|
||||
await this.postgres.query('DELETE FROM memory_entries WHERE id = $1', [id]);
|
||||
|
||||
// Remove from cache
|
||||
const keys = await this.redis.keys(`memory:*:${id}`);
|
||||
if (keys.length > 0) {
|
||||
await this.redis.del(keys);
|
||||
}
|
||||
|
||||
this.logger.memoryOperation('delete', { id });
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to delete memory', { error, id });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async clearUserMemory(userId: string, projectId?: string): Promise<void> {
|
||||
try {
|
||||
let query = 'DELETE FROM memory_entries WHERE user_id = $1';
|
||||
const params: any[] = [userId];
|
||||
|
||||
if (projectId) {
|
||||
query += ' AND project_id = $2';
|
||||
params.push(projectId);
|
||||
}
|
||||
|
||||
await this.postgres.query(query, params);
|
||||
|
||||
// Clear cache
|
||||
const pattern = projectId ? `memory:${userId}:${projectId}:*` : `memory:${userId}:*`;
|
||||
const keys = await this.redis.keys(pattern);
|
||||
if (keys.length > 0) {
|
||||
await this.redis.del(keys);
|
||||
}
|
||||
|
||||
this.logger.memoryOperation('clear', { userId, projectId });
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to clear user memory', { error, userId, projectId });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async getMemorySummary(userId: string, projectId?: string): Promise<any> {
|
||||
try {
|
||||
let query = `
|
||||
SELECT
|
||||
type,
|
||||
COUNT(*) as count,
|
||||
MAX(created_at) as last_updated
|
||||
FROM memory_entries
|
||||
WHERE user_id = $1
|
||||
`;
|
||||
const params: any[] = [userId];
|
||||
|
||||
if (projectId) {
|
||||
query += ' AND project_id = $2';
|
||||
params.push(projectId);
|
||||
}
|
||||
|
||||
query += ' GROUP BY type';
|
||||
|
||||
const result = await this.postgres.query(query, params);
|
||||
|
||||
const summary = {
|
||||
totalEntries: 0,
|
||||
byType: {},
|
||||
lastActivity: null
|
||||
};
|
||||
|
||||
result.rows.forEach(row => {
|
||||
summary.byType[row.type] = {
|
||||
count: parseInt(row.count),
|
||||
lastUpdated: row.last_updated
|
||||
};
|
||||
summary.totalEntries += parseInt(row.count);
|
||||
|
||||
if (!summary.lastActivity || row.last_updated > summary.lastActivity) {
|
||||
summary.lastActivity = row.last_updated;
|
||||
}
|
||||
});
|
||||
|
||||
return summary;
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to get memory summary', { error, userId, projectId });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async close(): Promise<void> {
|
||||
try {
|
||||
await this.redis.quit();
|
||||
await this.postgres.end();
|
||||
this.logger.info('MemoryManager connections closed');
|
||||
} catch (error) {
|
||||
this.logger.error('Error closing MemoryManager connections', { error });
|
||||
}
|
||||
}
|
||||
}
|
||||
268
.github/Advanced_AI_Agent/examples/implementation/backend/src/middleware/auth.ts
vendored
Normal file
268
.github/Advanced_AI_Agent/examples/implementation/backend/src/middleware/auth.ts
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
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;
|
||||
permissions: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export function authMiddleware(req: AuthenticatedRequest, res: Response, next: NextFunction) {
|
||||
try {
|
||||
const authHeader = req.headers.authorization;
|
||||
|
||||
if (!authHeader) {
|
||||
logger.warn('No authorization header provided', {
|
||||
ip: req.ip,
|
||||
userAgent: req.get('User-Agent')
|
||||
});
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: 'No authorization token provided'
|
||||
});
|
||||
}
|
||||
|
||||
const token = authHeader.replace('Bearer ', '');
|
||||
|
||||
if (!token) {
|
||||
logger.warn('Invalid authorization header format', {
|
||||
ip: req.ip,
|
||||
userAgent: req.get('User-Agent')
|
||||
});
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: 'Invalid authorization header format'
|
||||
});
|
||||
}
|
||||
|
||||
const secret = process.env.JWT_SECRET;
|
||||
if (!secret) {
|
||||
logger.error('JWT_SECRET not configured');
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
error: 'Server configuration error'
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const decoded = jwt.verify(token, secret) as any;
|
||||
|
||||
req.user = {
|
||||
id: decoded.id,
|
||||
email: decoded.email,
|
||||
role: decoded.role || 'user',
|
||||
permissions: decoded.permissions || []
|
||||
};
|
||||
|
||||
logger.info('User authenticated successfully', {
|
||||
userId: req.user.id,
|
||||
email: req.user.email,
|
||||
ip: req.ip
|
||||
});
|
||||
|
||||
next();
|
||||
} catch (jwtError) {
|
||||
logger.warn('Invalid JWT token', {
|
||||
error: jwtError.message,
|
||||
ip: req.ip
|
||||
});
|
||||
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: 'Invalid or expired token'
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
logger.error('Authentication middleware error', {
|
||||
error: error.message,
|
||||
ip: req.ip
|
||||
});
|
||||
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
error: 'Authentication service error'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function optionalAuthMiddleware(req: AuthenticatedRequest, res: Response, next: NextFunction) {
|
||||
try {
|
||||
const authHeader = req.headers.authorization;
|
||||
|
||||
if (!authHeader) {
|
||||
// Continue without authentication
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
const token = authHeader.replace('Bearer ', '');
|
||||
|
||||
if (!token) {
|
||||
// Continue without authentication
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
const secret = process.env.JWT_SECRET;
|
||||
if (!secret) {
|
||||
// Continue without authentication
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const decoded = jwt.verify(token, secret) as any;
|
||||
|
||||
req.user = {
|
||||
id: decoded.id,
|
||||
email: decoded.email,
|
||||
role: decoded.role || 'user',
|
||||
permissions: decoded.permissions || []
|
||||
};
|
||||
|
||||
logger.info('Optional authentication successful', {
|
||||
userId: req.user.id,
|
||||
email: req.user.email
|
||||
});
|
||||
|
||||
next();
|
||||
} catch (jwtError) {
|
||||
// Continue without authentication
|
||||
logger.debug('Optional authentication failed, continuing without auth', {
|
||||
error: jwtError.message
|
||||
});
|
||||
next();
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
logger.error('Optional authentication middleware error', {
|
||||
error: error.message
|
||||
});
|
||||
// Continue without authentication
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
export function requireRole(roles: string[]) {
|
||||
return (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
|
||||
if (!req.user) {
|
||||
logger.warn('Role check failed - no authenticated user', {
|
||||
requiredRoles: roles,
|
||||
ip: req.ip
|
||||
});
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: 'Authentication required'
|
||||
});
|
||||
}
|
||||
|
||||
if (!roles.includes(req.user.role)) {
|
||||
logger.warn('Insufficient role permissions', {
|
||||
userRole: req.user.role,
|
||||
requiredRoles: roles,
|
||||
userId: req.user.id
|
||||
});
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
error: 'Insufficient permissions'
|
||||
});
|
||||
}
|
||||
|
||||
logger.debug('Role check passed', {
|
||||
userRole: req.user.role,
|
||||
requiredRoles: roles,
|
||||
userId: req.user.id
|
||||
});
|
||||
|
||||
next();
|
||||
};
|
||||
}
|
||||
|
||||
export function requirePermission(permissions: string[]) {
|
||||
return (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
|
||||
if (!req.user) {
|
||||
logger.warn('Permission check failed - no authenticated user', {
|
||||
requiredPermissions: permissions,
|
||||
ip: req.ip
|
||||
});
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: 'Authentication required'
|
||||
});
|
||||
}
|
||||
|
||||
const hasAllPermissions = permissions.every(permission =>
|
||||
req.user!.permissions.includes(permission)
|
||||
);
|
||||
|
||||
if (!hasAllPermissions) {
|
||||
logger.warn('Insufficient permissions', {
|
||||
userPermissions: req.user.permissions,
|
||||
requiredPermissions: permissions,
|
||||
userId: req.user.id
|
||||
});
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
error: 'Insufficient permissions'
|
||||
});
|
||||
}
|
||||
|
||||
logger.debug('Permission check passed', {
|
||||
userPermissions: req.user.permissions,
|
||||
requiredPermissions: permissions,
|
||||
userId: req.user.id
|
||||
});
|
||||
|
||||
next();
|
||||
};
|
||||
}
|
||||
|
||||
export function rateLimitByUser(req: AuthenticatedRequest, res: Response, next: NextFunction) {
|
||||
// This is a simplified rate limiting by user
|
||||
// In a real implementation, you would use Redis or a similar store
|
||||
const userId = req.user?.id || req.ip;
|
||||
|
||||
// For now, we'll just pass through
|
||||
// In a real implementation, you would check rate limits here
|
||||
logger.debug('Rate limit check passed', { userId });
|
||||
next();
|
||||
}
|
||||
|
||||
export function generateToken(user: {
|
||||
id: string;
|
||||
email: string;
|
||||
role?: string;
|
||||
permissions?: string[];
|
||||
}): string {
|
||||
const secret = process.env.JWT_SECRET;
|
||||
if (!secret) {
|
||||
throw new Error('JWT_SECRET not configured');
|
||||
}
|
||||
|
||||
const payload = {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
role: user.role || 'user',
|
||||
permissions: user.permissions || [],
|
||||
iat: Math.floor(Date.now() / 1000),
|
||||
exp: Math.floor(Date.now() / 1000) + (60 * 60 * 24 * 7) // 7 days
|
||||
};
|
||||
|
||||
return jwt.sign(payload, secret);
|
||||
}
|
||||
|
||||
export function verifyToken(token: string): any {
|
||||
const secret = process.env.JWT_SECRET;
|
||||
if (!secret) {
|
||||
throw new Error('JWT_SECRET not configured');
|
||||
}
|
||||
|
||||
return jwt.verify(token, secret);
|
||||
}
|
||||
67
.github/Advanced_AI_Agent/examples/implementation/backend/src/middleware/error-handler.ts
vendored
Normal file
67
.github/Advanced_AI_Agent/examples/implementation/backend/src/middleware/error-handler.ts
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
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;
|
||||
}
|
||||
|
||||
export function errorHandler(
|
||||
error: AppError,
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) {
|
||||
const statusCode = error.statusCode || 500;
|
||||
const message = error.message || 'Internal Server Error';
|
||||
|
||||
// Log the error
|
||||
logger.error('Error occurred', {
|
||||
error: {
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
statusCode,
|
||||
},
|
||||
request: {
|
||||
method: req.method,
|
||||
url: req.url,
|
||||
headers: req.headers,
|
||||
body: req.body,
|
||||
user: req.user,
|
||||
},
|
||||
});
|
||||
|
||||
// Don't expose internal errors in production
|
||||
const isDevelopment = process.env.NODE_ENV === 'development';
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
error: {
|
||||
message: isDevelopment ? message : 'An error occurred',
|
||||
statusCode,
|
||||
...(isDevelopment && { stack: error.stack }),
|
||||
},
|
||||
timestamp: new Date().toISOString(),
|
||||
path: req.path,
|
||||
};
|
||||
|
||||
res.status(statusCode).json(errorResponse);
|
||||
}
|
||||
|
||||
export function createError(
|
||||
message: string,
|
||||
statusCode: number = 500,
|
||||
isOperational: boolean = true
|
||||
): AppError {
|
||||
const error = new Error(message) as AppError;
|
||||
error.statusCode = statusCode;
|
||||
error.isOperational = isOperational;
|
||||
return error;
|
||||
}
|
||||
|
||||
export function asyncHandler(fn: Function) {
|
||||
return (req: Request, res: Response, next: NextFunction) => {
|
||||
Promise.resolve(fn(req, res, next)).catch(next);
|
||||
};
|
||||
}
|
||||
99
.github/Advanced_AI_Agent/examples/implementation/backend/src/middleware/rate-limiter.ts
vendored
Normal file
99
.github/Advanced_AI_Agent/examples/implementation/backend/src/middleware/rate-limiter.ts
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { RateLimiterRedis } from 'rate-limiter-flexible';
|
||||
import Redis from 'redis';
|
||||
import { Logger } from '../utils/logger';
|
||||
|
||||
const logger = new Logger('RateLimiter');
|
||||
|
||||
// Create Redis client for rate limiting
|
||||
const redisClient = Redis.createClient({
|
||||
url: process.env.REDIS_URL || 'redis://localhost:6379',
|
||||
});
|
||||
|
||||
// Rate limiter configuration
|
||||
const rateLimiter = new RateLimiterRedis({
|
||||
storeClient: redisClient,
|
||||
keyPrefix: 'nowhere_rate_limit',
|
||||
points: 100, // Number of requests
|
||||
duration: 60, // Per 60 seconds
|
||||
blockDuration: 60 * 15, // Block for 15 minutes if limit exceeded
|
||||
});
|
||||
|
||||
// Rate limiter middleware
|
||||
export async function rateLimiterMiddleware(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) {
|
||||
try {
|
||||
const key = req.ip || req.connection.remoteAddress || 'unknown';
|
||||
|
||||
await rateLimiter.consume(key);
|
||||
next();
|
||||
} catch (rejRes) {
|
||||
const secs = Math.round(rejRes.msBeforeNext / 1000) || 1;
|
||||
|
||||
logger.warn('Rate limit exceeded', {
|
||||
ip: req.ip,
|
||||
userAgent: req.get('User-Agent'),
|
||||
path: req.path,
|
||||
remainingPoints: rejRes.remainingPoints,
|
||||
msBeforeNext: rejRes.msBeforeNext,
|
||||
});
|
||||
|
||||
res.set('Retry-After', String(Math.round(secs / 60)));
|
||||
res.status(429).json({
|
||||
success: false,
|
||||
error: {
|
||||
message: 'Too many requests',
|
||||
retryAfter: secs,
|
||||
},
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Special rate limiter for voice commands (more restrictive)
|
||||
const voiceRateLimiter = new RateLimiterRedis({
|
||||
storeClient: redisClient,
|
||||
keyPrefix: 'nowhere_voice_rate_limit',
|
||||
points: 50, // Fewer requests for voice
|
||||
duration: 60,
|
||||
blockDuration: 60 * 30, // Block for 30 minutes
|
||||
});
|
||||
|
||||
export async function voiceRateLimiterMiddleware(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) {
|
||||
try {
|
||||
const key = req.ip || req.connection.remoteAddress || 'unknown';
|
||||
|
||||
await voiceRateLimiter.consume(key);
|
||||
next();
|
||||
} catch (rejRes) {
|
||||
const secs = Math.round(rejRes.msBeforeNext / 1000) || 1;
|
||||
|
||||
logger.warn('Voice rate limit exceeded', {
|
||||
ip: req.ip,
|
||||
userAgent: req.get('User-Agent'),
|
||||
path: req.path,
|
||||
remainingPoints: rejRes.remainingPoints,
|
||||
msBeforeNext: rejRes.msBeforeNext,
|
||||
});
|
||||
|
||||
res.set('Retry-After', String(Math.round(secs / 60)));
|
||||
res.status(429).json({
|
||||
success: false,
|
||||
error: {
|
||||
message: 'Too many voice requests',
|
||||
retryAfter: secs,
|
||||
},
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Export the main rate limiter for general use
|
||||
export const rateLimiter = rateLimiterMiddleware;
|
||||
283
.github/Advanced_AI_Agent/examples/implementation/backend/src/routes/index.ts
vendored
Normal file
283
.github/Advanced_AI_Agent/examples/implementation/backend/src/routes/index.ts
vendored
Normal file
@@ -0,0 +1,283 @@
|
||||
import { Express } from 'express';
|
||||
import { NowhereCore, NowhereContext } from '../core/nowhere';
|
||||
import { Logger } from '../utils/logger';
|
||||
|
||||
const logger = new Logger('Routes');
|
||||
|
||||
export function setupRoutes(app: Express, nowhere: NowhereCore) {
|
||||
// API Routes
|
||||
app.use('/api/v1', createAPIRoutes(nowhere));
|
||||
}
|
||||
|
||||
function createAPIRoutes(nowhere: NowhereCore) {
|
||||
const router = require('express').Router();
|
||||
|
||||
// Command processing endpoint
|
||||
router.post('/command', async (req, res) => {
|
||||
try {
|
||||
const { command, context } = req.body;
|
||||
|
||||
if (!command) {
|
||||
return res.status(400).json({
|
||||
error: 'Command is required',
|
||||
});
|
||||
}
|
||||
|
||||
const defaultContext: NowhereContext = {
|
||||
userId: context?.userId || 'default-user',
|
||||
projectId: context?.projectId || 'default-project',
|
||||
currentFile: context?.currentFile,
|
||||
codebase: context?.codebase,
|
||||
userPreferences: context?.userPreferences,
|
||||
sessionId: context?.sessionId || `session-${Date.now()}`,
|
||||
};
|
||||
|
||||
const response = await nowhere.processCommand(command, defaultContext);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: response,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Error processing command', error);
|
||||
res.status(500).json({
|
||||
error: 'Failed to process command',
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Voice command processing endpoint
|
||||
router.post('/voice', async (req, res) => {
|
||||
try {
|
||||
const { voiceInput, context } = req.body;
|
||||
|
||||
if (!voiceInput) {
|
||||
return res.status(400).json({
|
||||
error: 'Voice input is required',
|
||||
});
|
||||
}
|
||||
|
||||
const defaultContext: NowhereContext = {
|
||||
userId: context?.userId || 'default-user',
|
||||
projectId: context?.projectId || 'default-project',
|
||||
currentFile: context?.currentFile,
|
||||
codebase: context?.codebase,
|
||||
userPreferences: context?.userPreferences,
|
||||
sessionId: context?.sessionId || `session-${Date.now()}`,
|
||||
};
|
||||
|
||||
const response = await nowhere.processVoiceCommand(voiceInput, defaultContext);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: response,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Error processing voice command', error);
|
||||
res.status(500).json({
|
||||
error: 'Failed to process voice command',
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Autopilot mode endpoints
|
||||
router.post('/autopilot/enable', async (req, res) => {
|
||||
try {
|
||||
const { context } = req.body;
|
||||
|
||||
const defaultContext: NowhereContext = {
|
||||
userId: context?.userId || 'default-user',
|
||||
projectId: context?.projectId || 'default-project',
|
||||
currentFile: context?.currentFile,
|
||||
codebase: context?.codebase,
|
||||
userPreferences: context?.userPreferences,
|
||||
sessionId: context?.sessionId || `session-${Date.now()}`,
|
||||
};
|
||||
|
||||
await nowhere.enableAutopilotMode(defaultContext);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Autopilot mode enabled',
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Error enabling autopilot mode', error);
|
||||
res.status(500).json({
|
||||
error: 'Failed to enable autopilot mode',
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/autopilot/disable', async (req, res) => {
|
||||
try {
|
||||
const { context } = req.body;
|
||||
|
||||
const defaultContext: NowhereContext = {
|
||||
userId: context?.userId || 'default-user',
|
||||
projectId: context?.projectId || 'default-project',
|
||||
currentFile: context?.currentFile,
|
||||
codebase: context?.codebase,
|
||||
userPreferences: context?.userPreferences,
|
||||
sessionId: context?.sessionId || `session-${Date.now()}`,
|
||||
};
|
||||
|
||||
await nowhere.disableAutopilotMode(defaultContext);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Autopilot mode disabled',
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Error disabling autopilot mode', error);
|
||||
res.status(500).json({
|
||||
error: 'Failed to disable autopilot mode',
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Memory management endpoints
|
||||
router.get('/memory/:userId/:projectId', async (req, res) => {
|
||||
try {
|
||||
const { userId, projectId } = req.params;
|
||||
const { sessionId } = req.query;
|
||||
|
||||
const context: NowhereContext = {
|
||||
userId,
|
||||
projectId,
|
||||
sessionId: sessionId as string || `session-${Date.now()}`,
|
||||
};
|
||||
|
||||
const memory = await nowhere.getMemory(context);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: memory,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Error retrieving memory', error);
|
||||
res.status(500).json({
|
||||
error: 'Failed to retrieve memory',
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
router.delete('/memory/:userId/:projectId', async (req, res) => {
|
||||
try {
|
||||
const { userId, projectId } = req.params;
|
||||
const { sessionId } = req.query;
|
||||
|
||||
const context: NowhereContext = {
|
||||
userId,
|
||||
projectId,
|
||||
sessionId: sessionId as string || `session-${Date.now()}`,
|
||||
};
|
||||
|
||||
await nowhere.clearMemory(context);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Memory cleared successfully',
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Error clearing memory', error);
|
||||
res.status(500).json({
|
||||
error: 'Failed to clear memory',
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Status endpoint
|
||||
router.get('/status', (req, res) => {
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
status: 'operational',
|
||||
agent: 'Nowhere',
|
||||
version: '1.0.0',
|
||||
features: [
|
||||
'voice-commands',
|
||||
'autopilot-mode',
|
||||
'adaptive-learning',
|
||||
'memory-system',
|
||||
'real-time-collaboration',
|
||||
],
|
||||
timestamp: new Date().toISOString(),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// Configuration endpoint
|
||||
router.get('/config', (req, res) => {
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
voiceCommands: {
|
||||
navigation: [
|
||||
'go to file',
|
||||
'show me the main function',
|
||||
'navigate to',
|
||||
'open',
|
||||
'find',
|
||||
'locate',
|
||||
],
|
||||
execution: [
|
||||
'run',
|
||||
'execute',
|
||||
'start',
|
||||
'deploy',
|
||||
'build',
|
||||
'test',
|
||||
],
|
||||
analysis: [
|
||||
'analyze',
|
||||
'find performance issues',
|
||||
'check code quality',
|
||||
'review',
|
||||
'inspect',
|
||||
],
|
||||
creation: [
|
||||
'create',
|
||||
'add',
|
||||
'implement',
|
||||
'build',
|
||||
'generate',
|
||||
'make',
|
||||
],
|
||||
debugging: [
|
||||
'fix',
|
||||
'debug',
|
||||
'resolve',
|
||||
'optimize',
|
||||
'troubleshoot',
|
||||
],
|
||||
},
|
||||
autopilotSettings: {
|
||||
enabled: true,
|
||||
autonomyLevel: 'medium',
|
||||
confirmationThreshold: 0.8,
|
||||
riskTolerance: 'medium',
|
||||
},
|
||||
voiceSettings: {
|
||||
recognitionSensitivity: 0.8,
|
||||
responseSpeed: 'normal',
|
||||
language: 'en-US',
|
||||
communicationStyle: 'professional',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
return router;
|
||||
}
|
||||
568
.github/Advanced_AI_Agent/examples/implementation/backend/src/tools/tool-executor.ts
vendored
Normal file
568
.github/Advanced_AI_Agent/examples/implementation/backend/src/tools/tool-executor.ts
vendored
Normal file
@@ -0,0 +1,568 @@
|
||||
import { exec } from 'child_process';
|
||||
import { promisify } from 'util';
|
||||
import { readFile, writeFile, readdir, stat, mkdir } from 'fs/promises';
|
||||
import { join, dirname, extname } from 'path';
|
||||
import { Logger } from '../utils/logger';
|
||||
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
export interface ToolResult {
|
||||
success: boolean;
|
||||
data?: any;
|
||||
error?: string;
|
||||
duration: number;
|
||||
metadata?: {
|
||||
tool: string;
|
||||
operation: string;
|
||||
timestamp: Date;
|
||||
};
|
||||
}
|
||||
|
||||
export interface FileOperation {
|
||||
type: 'read' | 'write' | 'delete' | 'list' | 'search';
|
||||
path: string;
|
||||
content?: string;
|
||||
options?: any;
|
||||
}
|
||||
|
||||
export interface TerminalCommand {
|
||||
command: string;
|
||||
cwd?: string;
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
export interface WebSearchQuery {
|
||||
query: string;
|
||||
maxResults?: number;
|
||||
filters?: any;
|
||||
}
|
||||
|
||||
export class ToolExecutor {
|
||||
private logger: Logger;
|
||||
|
||||
constructor() {
|
||||
this.logger = new Logger('ToolExecutor');
|
||||
}
|
||||
|
||||
async executeFileOperation(operation: FileOperation): Promise<ToolResult> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
switch (operation.type) {
|
||||
case 'read':
|
||||
return await this.readFile(operation.path);
|
||||
case 'write':
|
||||
return await this.writeFile(operation.path, operation.content || '');
|
||||
case 'list':
|
||||
return await this.listDirectory(operation.path);
|
||||
case 'search':
|
||||
return await this.searchFiles(operation.path, operation.options);
|
||||
default:
|
||||
throw new Error(`Unsupported file operation: ${operation.type}`);
|
||||
}
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
this.logger.error('File operation failed', { operation, error: error.message });
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
duration,
|
||||
metadata: {
|
||||
tool: 'file_operation',
|
||||
operation: operation.type,
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private async readFile(path: string): Promise<ToolResult> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
const content = await readFile(path, 'utf-8');
|
||||
const stats = await stat(path);
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
this.logger.toolExecution('read_file', { path, size: stats.size }, duration);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
content,
|
||||
metadata: {
|
||||
size: stats.size,
|
||||
modified: stats.mtime,
|
||||
created: stats.birthtime
|
||||
}
|
||||
},
|
||||
duration,
|
||||
metadata: {
|
||||
tool: 'file_operation',
|
||||
operation: 'read',
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
duration,
|
||||
metadata: {
|
||||
tool: 'file_operation',
|
||||
operation: 'read',
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private async writeFile(path: string, content: string): Promise<ToolResult> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
// Ensure directory exists
|
||||
await mkdir(dirname(path), { recursive: true });
|
||||
|
||||
await writeFile(path, content, 'utf-8');
|
||||
const stats = await stat(path);
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
this.logger.toolExecution('write_file', { path, size: stats.size }, duration);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
path,
|
||||
size: stats.size,
|
||||
modified: stats.mtime
|
||||
},
|
||||
duration,
|
||||
metadata: {
|
||||
tool: 'file_operation',
|
||||
operation: 'write',
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
duration,
|
||||
metadata: {
|
||||
tool: 'file_operation',
|
||||
operation: 'write',
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private async listDirectory(path: string): Promise<ToolResult> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
const items = await readdir(path, { withFileTypes: true });
|
||||
const files = items
|
||||
.filter(item => item.isFile())
|
||||
.map(item => ({
|
||||
name: item.name,
|
||||
type: 'file',
|
||||
extension: extname(item.name)
|
||||
}));
|
||||
|
||||
const directories = items
|
||||
.filter(item => item.isDirectory())
|
||||
.map(item => ({
|
||||
name: item.name,
|
||||
type: 'directory'
|
||||
}));
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
this.logger.toolExecution('list_directory', { path, count: items.length }, duration);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
path,
|
||||
files,
|
||||
directories,
|
||||
total: items.length
|
||||
},
|
||||
duration,
|
||||
metadata: {
|
||||
tool: 'file_operation',
|
||||
operation: 'list',
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
duration,
|
||||
metadata: {
|
||||
tool: 'file_operation',
|
||||
operation: 'list',
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private async searchFiles(directory: string, options: any = {}): Promise<ToolResult> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
const { pattern, extensions, maxDepth = 3 } = options;
|
||||
const results: any[] = [];
|
||||
|
||||
await this.searchRecursive(directory, pattern, extensions, maxDepth, 0, results);
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
this.logger.toolExecution('search_files', { directory, pattern, count: results.length }, duration);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
directory,
|
||||
pattern,
|
||||
results,
|
||||
count: results.length
|
||||
},
|
||||
duration,
|
||||
metadata: {
|
||||
tool: 'file_operation',
|
||||
operation: 'search',
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
duration,
|
||||
metadata: {
|
||||
tool: 'file_operation',
|
||||
operation: 'search',
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private async searchRecursive(
|
||||
dir: string,
|
||||
pattern: string,
|
||||
extensions: string[],
|
||||
maxDepth: number,
|
||||
currentDepth: number,
|
||||
results: any[]
|
||||
): Promise<void> {
|
||||
if (currentDepth > maxDepth) return;
|
||||
|
||||
try {
|
||||
const items = await readdir(dir, { withFileTypes: true });
|
||||
|
||||
for (const item of items) {
|
||||
const fullPath = join(dir, item.name);
|
||||
|
||||
if (item.isDirectory()) {
|
||||
await this.searchRecursive(fullPath, pattern, extensions, maxDepth, currentDepth + 1, results);
|
||||
} else if (item.isFile()) {
|
||||
const matchesPattern = !pattern || item.name.toLowerCase().includes(pattern.toLowerCase());
|
||||
const matchesExtension = !extensions || extensions.length === 0 ||
|
||||
extensions.some(ext => item.name.toLowerCase().endsWith(ext.toLowerCase()));
|
||||
|
||||
if (matchesPattern && matchesExtension) {
|
||||
const stats = await stat(fullPath);
|
||||
results.push({
|
||||
name: item.name,
|
||||
path: fullPath,
|
||||
size: stats.size,
|
||||
modified: stats.mtime,
|
||||
extension: extname(item.name)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// Skip directories we can't access
|
||||
this.logger.debug('Skipping directory', { dir, error: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
async executeTerminalCommand(command: TerminalCommand): Promise<ToolResult> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
const { stdout, stderr } = await execAsync(command.command, {
|
||||
cwd: command.cwd,
|
||||
timeout: command.timeout || 30000 // 30 second default timeout
|
||||
});
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
this.logger.toolExecution('terminal_command', { command: command.command }, duration);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
stdout,
|
||||
stderr,
|
||||
command: command.command,
|
||||
cwd: command.cwd
|
||||
},
|
||||
duration,
|
||||
metadata: {
|
||||
tool: 'terminal',
|
||||
operation: 'execute',
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
} catch (error: any) {
|
||||
const duration = Date.now() - startTime;
|
||||
this.logger.error('Terminal command failed', { command: command.command, error: error.message });
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
data: {
|
||||
stdout: error.stdout || '',
|
||||
stderr: error.stderr || '',
|
||||
command: command.command,
|
||||
cwd: command.cwd
|
||||
},
|
||||
duration,
|
||||
metadata: {
|
||||
tool: 'terminal',
|
||||
operation: 'execute',
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async executeWebSearch(query: WebSearchQuery): Promise<ToolResult> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
// This is a placeholder for web search functionality
|
||||
// In a real implementation, you would integrate with search APIs
|
||||
const mockResults = [
|
||||
{
|
||||
title: `Search results for: ${query.query}`,
|
||||
url: 'https://example.com',
|
||||
snippet: `This is a mock search result for "${query.query}". In a real implementation, this would be actual search results.`
|
||||
}
|
||||
];
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
this.logger.toolExecution('web_search', { query: query.query, results: mockResults.length }, duration);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
query: query.query,
|
||||
results: mockResults,
|
||||
count: mockResults.length
|
||||
},
|
||||
duration,
|
||||
metadata: {
|
||||
tool: 'web_search',
|
||||
operation: 'search',
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
duration,
|
||||
metadata: {
|
||||
tool: 'web_search',
|
||||
operation: 'search',
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async analyzeCode(filePath: string): Promise<ToolResult> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
const content = await readFile(filePath, 'utf-8');
|
||||
const extension = extname(filePath).toLowerCase();
|
||||
|
||||
// Basic code analysis
|
||||
const analysis = {
|
||||
language: this.detectLanguage(extension),
|
||||
lines: content.split('\n').length,
|
||||
characters: content.length,
|
||||
functions: this.countFunctions(content, extension),
|
||||
imports: this.extractImports(content, extension),
|
||||
complexity: this.calculateComplexity(content)
|
||||
};
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
this.logger.toolExecution('code_analysis', { filePath, language: analysis.language }, duration);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
filePath,
|
||||
analysis
|
||||
},
|
||||
duration,
|
||||
metadata: {
|
||||
tool: 'code_analysis',
|
||||
operation: 'analyze',
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
duration,
|
||||
metadata: {
|
||||
tool: 'code_analysis',
|
||||
operation: 'analyze',
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private detectLanguage(extension: string): string {
|
||||
const languageMap: { [key: string]: string } = {
|
||||
'.js': 'JavaScript',
|
||||
'.ts': 'TypeScript',
|
||||
'.py': 'Python',
|
||||
'.java': 'Java',
|
||||
'.cpp': 'C++',
|
||||
'.c': 'C',
|
||||
'.cs': 'C#',
|
||||
'.php': 'PHP',
|
||||
'.rb': 'Ruby',
|
||||
'.go': 'Go',
|
||||
'.rs': 'Rust',
|
||||
'.swift': 'Swift',
|
||||
'.kt': 'Kotlin',
|
||||
'.scala': 'Scala',
|
||||
'.html': 'HTML',
|
||||
'.css': 'CSS',
|
||||
'.json': 'JSON',
|
||||
'.xml': 'XML',
|
||||
'.md': 'Markdown'
|
||||
};
|
||||
|
||||
return languageMap[extension] || 'Unknown';
|
||||
}
|
||||
|
||||
private countFunctions(content: string, extension: string): number {
|
||||
const patterns: { [key: string]: RegExp[] } = {
|
||||
'.js': [/function\s+\w+\s*\(/g, /const\s+\w+\s*=\s*\(/g, /let\s+\w+\s*=\s*\(/g, /var\s+\w+\s*=\s*\(/g],
|
||||
'.ts': [/function\s+\w+\s*\(/g, /const\s+\w+\s*=\s*\(/g, /let\s+\w+\s*=\s*\(/g, /var\s+\w+\s*=\s*\(/g],
|
||||
'.py': [/def\s+\w+\s*\(/g],
|
||||
'.java': [/public\s+\w+\s+\w+\s*\(/g, /private\s+\w+\s+\w+\s*\(/g, /protected\s+\w+\s+\w+\s*\(/g],
|
||||
'.cpp': [/void\s+\w+\s*\(/g, /int\s+\w+\s*\(/g, /string\s+\w+\s*\(/g],
|
||||
'.cs': [/public\s+\w+\s+\w+\s*\(/g, /private\s+\w+\s+\w+\s*\(/g, /protected\s+\w+\s+\w+\s*\(/g]
|
||||
};
|
||||
|
||||
const patternsForLang = patterns[extension] || [];
|
||||
let count = 0;
|
||||
|
||||
patternsForLang.forEach(pattern => {
|
||||
const matches = content.match(pattern);
|
||||
if (matches) count += matches.length;
|
||||
});
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private extractImports(content: string, extension: string): string[] {
|
||||
const patterns: { [key: string]: RegExp } = {
|
||||
'.js': /import\s+.*?from\s+['"]([^'"]+)['"]/g,
|
||||
'.ts': /import\s+.*?from\s+['"]([^'"]+)['"]/g,
|
||||
'.py': /import\s+([a-zA-Z_][a-zA-Z0-9_]*)/g,
|
||||
'.java': /import\s+([a-zA-Z_][a-zA-Z0-9_.]*);/g,
|
||||
'.cpp': /#include\s+[<"]([^>"]+)[>"]/g,
|
||||
'.cs': /using\s+([a-zA-Z_][a-zA-Z0-9_.]*);/g
|
||||
};
|
||||
|
||||
const pattern = patterns[extension];
|
||||
if (!pattern) return [];
|
||||
|
||||
const imports: string[] = [];
|
||||
let match;
|
||||
|
||||
while ((match = pattern.exec(content)) !== null) {
|
||||
imports.push(match[1]);
|
||||
}
|
||||
|
||||
return imports;
|
||||
}
|
||||
|
||||
private calculateComplexity(content: string): number {
|
||||
// Simple cyclomatic complexity calculation
|
||||
const complexityFactors = [
|
||||
/if\s*\(/g,
|
||||
/else\s*if\s*\(/g,
|
||||
/for\s*\(/g,
|
||||
/while\s*\(/g,
|
||||
/switch\s*\(/g,
|
||||
/case\s+/g,
|
||||
/catch\s*\(/g,
|
||||
/\|\|/g,
|
||||
/&&/g
|
||||
];
|
||||
|
||||
let complexity = 1; // Base complexity
|
||||
|
||||
complexityFactors.forEach(factor => {
|
||||
const matches = content.match(factor);
|
||||
if (matches) complexity += matches.length;
|
||||
});
|
||||
|
||||
return complexity;
|
||||
}
|
||||
|
||||
async executeTool(toolName: string, params: any): Promise<ToolResult> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
switch (toolName) {
|
||||
case 'file_operation':
|
||||
return await this.executeFileOperation(params);
|
||||
case 'terminal_command':
|
||||
return await this.executeTerminalCommand(params);
|
||||
case 'web_search':
|
||||
return await this.executeWebSearch(params);
|
||||
case 'code_analysis':
|
||||
return await this.analyzeCode(params.filePath);
|
||||
default:
|
||||
throw new Error(`Unknown tool: ${toolName}`);
|
||||
}
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
this.logger.error('Tool execution failed', { toolName, params, error: error.message });
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
duration,
|
||||
metadata: {
|
||||
tool: toolName,
|
||||
operation: 'execute',
|
||||
timestamp: new Date()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
89
.github/Advanced_AI_Agent/examples/implementation/backend/src/utils/logger.ts
vendored
Normal file
89
.github/Advanced_AI_Agent/examples/implementation/backend/src/utils/logger.ts
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
import winston from 'winston';
|
||||
|
||||
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: [
|
||||
new winston.transports.Console({
|
||||
format: winston.format.combine(
|
||||
winston.format.colorize(),
|
||||
winston.format.simple()
|
||||
),
|
||||
}),
|
||||
new winston.transports.File({
|
||||
filename: 'logs/error.log',
|
||||
level: 'error',
|
||||
}),
|
||||
new winston.transports.File({
|
||||
filename: 'logs/combined.log',
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
// Create logs directory if it doesn't exist
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const logsDir = path.join(process.cwd(), 'logs');
|
||||
if (!fs.existsSync(logsDir)) {
|
||||
fs.mkdirSync(logsDir, { recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
info(message: string, meta?: any) {
|
||||
this.logger.info(message, meta);
|
||||
}
|
||||
|
||||
warn(message: string, meta?: any) {
|
||||
this.logger.warn(message, meta);
|
||||
}
|
||||
|
||||
error(message: string, meta?: any) {
|
||||
this.logger.error(message, meta);
|
||||
}
|
||||
|
||||
debug(message: string, meta?: any) {
|
||||
this.logger.debug(message, meta);
|
||||
}
|
||||
|
||||
verbose(message: string, meta?: any) {
|
||||
this.logger.verbose(message, meta);
|
||||
}
|
||||
|
||||
// Specialized logging methods for Nowhere
|
||||
command(command: string, context: any) {
|
||||
this.info('Command processed', { command, context });
|
||||
}
|
||||
|
||||
voiceCommand(voiceInput: string, processedCommand: string, confidence: number) {
|
||||
this.info('Voice command processed', {
|
||||
voiceInput,
|
||||
processedCommand,
|
||||
confidence,
|
||||
});
|
||||
}
|
||||
|
||||
autopilotAction(action: string, context: any) {
|
||||
this.info('Autopilot action executed', { action, context });
|
||||
}
|
||||
|
||||
memoryOperation(operation: string, context: any) {
|
||||
this.debug('Memory operation', { operation, context });
|
||||
}
|
||||
|
||||
toolExecution(tool: string, result: any, duration: number) {
|
||||
this.info('Tool executed', { tool, result, duration });
|
||||
}
|
||||
|
||||
aiResponse(model: string, response: string, confidence: number) {
|
||||
this.debug('AI response generated', { model, response, confidence });
|
||||
}
|
||||
}
|
||||
384
.github/Advanced_AI_Agent/examples/implementation/backend/src/voice/voice-processor.ts
vendored
Normal file
384
.github/Advanced_AI_Agent/examples/implementation/backend/src/voice/voice-processor.ts
vendored
Normal file
@@ -0,0 +1,384 @@
|
||||
import { Logger } from '../utils/logger';
|
||||
|
||||
export interface VoiceCommand {
|
||||
text: string;
|
||||
confidence: number;
|
||||
timestamp: Date;
|
||||
metadata: {
|
||||
language: string;
|
||||
duration: number;
|
||||
user: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface VoiceResponse {
|
||||
text: string;
|
||||
audioUrl?: string;
|
||||
duration: number;
|
||||
mode: 'brief' | 'detailed' | 'silent' | 'interactive';
|
||||
}
|
||||
|
||||
export interface SpeechRecognitionResult {
|
||||
transcript: string;
|
||||
confidence: number;
|
||||
isFinal: boolean;
|
||||
language: string;
|
||||
}
|
||||
|
||||
export class VoiceProcessor {
|
||||
private logger: Logger;
|
||||
private isListening: boolean = false;
|
||||
private recognition: any; // Web Speech API recognition
|
||||
private synthesis: any; // Web Speech API synthesis
|
||||
|
||||
constructor() {
|
||||
this.logger = new Logger('VoiceProcessor');
|
||||
this.initializeSpeechAPIs();
|
||||
}
|
||||
|
||||
private initializeSpeechAPIs() {
|
||||
try {
|
||||
// Initialize Web Speech API if available
|
||||
if (typeof window !== 'undefined' && 'webkitSpeechRecognition' in window) {
|
||||
this.recognition = new (window as any).webkitSpeechRecognition();
|
||||
this.setupRecognition();
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined' && 'speechSynthesis' in window) {
|
||||
this.synthesis = window.speechSynthesis;
|
||||
}
|
||||
|
||||
this.logger.info('Voice processor initialized');
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to initialize speech APIs', { error });
|
||||
}
|
||||
}
|
||||
|
||||
private setupRecognition() {
|
||||
if (!this.recognition) return;
|
||||
|
||||
this.recognition.continuous = true;
|
||||
this.recognition.interimResults = true;
|
||||
this.recognition.lang = 'en-US';
|
||||
|
||||
this.recognition.onstart = () => {
|
||||
this.isListening = true;
|
||||
this.logger.info('Speech recognition started');
|
||||
};
|
||||
|
||||
this.recognition.onend = () => {
|
||||
this.isListening = false;
|
||||
this.logger.info('Speech recognition ended');
|
||||
};
|
||||
|
||||
this.recognition.onerror = (event: any) => {
|
||||
this.logger.error('Speech recognition error', { error: event.error });
|
||||
};
|
||||
}
|
||||
|
||||
async processVoiceInput(audioData?: ArrayBuffer): Promise<VoiceCommand> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
// For now, we'll use a mock implementation
|
||||
// In a real implementation, you would process the audio data
|
||||
const mockCommand = this.generateMockCommand();
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
this.logger.voiceCommand(mockCommand.text, mockCommand.text, mockCommand.confidence);
|
||||
|
||||
return mockCommand;
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
this.logger.error('Voice processing failed', { error: error.message });
|
||||
|
||||
return {
|
||||
text: 'Error processing voice input',
|
||||
confidence: 0,
|
||||
timestamp: new Date(),
|
||||
metadata: {
|
||||
language: 'en-US',
|
||||
duration,
|
||||
user: 'unknown'
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private generateMockCommand(): VoiceCommand {
|
||||
const commands = [
|
||||
'Hello Nowhere, show me the project structure',
|
||||
'Nowhere, analyze this code file',
|
||||
'Create a new component for the user interface',
|
||||
'Run the tests and show me the results',
|
||||
'What are the main features we need to implement?',
|
||||
'Enable autopilot mode',
|
||||
'Search for files containing authentication logic',
|
||||
'Generate documentation for the API endpoints'
|
||||
];
|
||||
|
||||
const randomCommand = commands[Math.floor(Math.random() * commands.length)];
|
||||
const confidence = 0.7 + Math.random() * 0.3; // 70-100% confidence
|
||||
|
||||
return {
|
||||
text: randomCommand,
|
||||
confidence,
|
||||
timestamp: new Date(),
|
||||
metadata: {
|
||||
language: 'en-US',
|
||||
duration: 1000 + Math.random() * 2000,
|
||||
user: 'test-user'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async startListening(): Promise<void> {
|
||||
try {
|
||||
if (this.recognition && !this.isListening) {
|
||||
this.recognition.start();
|
||||
this.logger.info('Started listening for voice commands');
|
||||
} else {
|
||||
this.logger.warn('Speech recognition not available or already listening');
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to start listening', { error: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
async stopListening(): Promise<void> {
|
||||
try {
|
||||
if (this.recognition && this.isListening) {
|
||||
this.recognition.stop();
|
||||
this.logger.info('Stopped listening for voice commands');
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to stop listening', { error: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
async speakText(text: string, mode: 'brief' | 'detailed' | 'silent' | 'interactive' = 'brief'): Promise<VoiceResponse> {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
if (mode === 'silent') {
|
||||
return {
|
||||
text,
|
||||
duration: Date.now() - startTime,
|
||||
mode
|
||||
};
|
||||
}
|
||||
|
||||
// Generate appropriate response based on mode
|
||||
const responseText = this.generateResponseText(text, mode);
|
||||
|
||||
// Use Web Speech API for text-to-speech
|
||||
if (this.synthesis) {
|
||||
const utterance = new SpeechSynthesisUtterance(responseText);
|
||||
utterance.rate = mode === 'brief' ? 1.2 : 1.0;
|
||||
utterance.pitch = 1.0;
|
||||
utterance.volume = 0.8;
|
||||
|
||||
this.synthesis.speak(utterance);
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
this.logger.info('Text-to-speech completed', { text: responseText, mode, duration });
|
||||
|
||||
return {
|
||||
text: responseText,
|
||||
duration,
|
||||
mode
|
||||
};
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
this.logger.error('Text-to-speech failed', { error: error.message });
|
||||
|
||||
return {
|
||||
text: 'Error generating voice response',
|
||||
duration,
|
||||
mode
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private generateResponseText(originalText: string, mode: string): string {
|
||||
switch (mode) {
|
||||
case 'brief':
|
||||
return this.generateBriefResponse(originalText);
|
||||
case 'detailed':
|
||||
return this.generateDetailedResponse(originalText);
|
||||
case 'interactive':
|
||||
return this.generateInteractiveResponse(originalText);
|
||||
default:
|
||||
return originalText;
|
||||
}
|
||||
}
|
||||
|
||||
private generateBriefResponse(text: string): string {
|
||||
// Extract key information for brief response
|
||||
if (text.includes('project structure')) {
|
||||
return 'Showing project structure. Found 15 files across 8 directories.';
|
||||
} else if (text.includes('analyze')) {
|
||||
return 'Code analysis complete. Found 3 functions, 2 imports, complexity level 2.';
|
||||
} else if (text.includes('autopilot')) {
|
||||
return 'Autopilot mode enabled. I will now work autonomously.';
|
||||
} else if (text.includes('test')) {
|
||||
return 'Tests completed. 12 passed, 1 failed.';
|
||||
} else {
|
||||
return 'Command processed successfully.';
|
||||
}
|
||||
}
|
||||
|
||||
private generateDetailedResponse(text: string): string {
|
||||
// Provide detailed response with context
|
||||
if (text.includes('project structure')) {
|
||||
return 'Project structure analysis complete. The project contains 15 files organized in 8 directories. Main components include backend API, frontend interface, and database schemas. Key files are in src directory with configuration in root.';
|
||||
} else if (text.includes('analyze')) {
|
||||
return 'Detailed code analysis finished. The file contains 3 functions with an average complexity of 2.1. Found 2 external imports and 5 internal dependencies. Code quality score is 8.5 out of 10.';
|
||||
} else if (text.includes('autopilot')) {
|
||||
return 'Autopilot mode has been successfully enabled. I will now work independently, making decisions based on project context and user preferences. I will notify you of major actions and ask for confirmation when needed.';
|
||||
} else if (text.includes('test')) {
|
||||
return 'Test execution completed. Results: 12 tests passed, 1 test failed in the authentication module. The failing test is related to password validation. I can help fix this issue if needed.';
|
||||
} else {
|
||||
return 'Command has been processed with full context analysis. All operations completed successfully with detailed logging available.';
|
||||
}
|
||||
}
|
||||
|
||||
private generateInteractiveResponse(text: string): string {
|
||||
// Generate interactive response with questions
|
||||
if (text.includes('project structure')) {
|
||||
return 'I found the project structure. Would you like me to focus on any specific directory or file type?';
|
||||
} else if (text.includes('analyze')) {
|
||||
return 'Code analysis complete. I found some potential improvements. Should I implement the suggested optimizations?';
|
||||
} else if (text.includes('autopilot')) {
|
||||
return 'Autopilot mode is ready. What specific tasks would you like me to prioritize first?';
|
||||
} else if (text.includes('test')) {
|
||||
return 'Tests are done. There\'s one failing test. Would you like me to investigate and fix it?';
|
||||
} else {
|
||||
return 'Command processed. Is there anything specific you\'d like me to explain or modify?';
|
||||
}
|
||||
}
|
||||
|
||||
async processVoiceCommand(voiceInput: string): Promise<{
|
||||
command: string;
|
||||
confidence: number;
|
||||
intent: string;
|
||||
entities: any[];
|
||||
}> {
|
||||
try {
|
||||
// Basic NLP processing for voice commands
|
||||
const processed = this.parseVoiceCommand(voiceInput);
|
||||
|
||||
this.logger.voiceCommand(voiceInput, processed.command, processed.confidence);
|
||||
|
||||
return processed;
|
||||
} catch (error) {
|
||||
this.logger.error('Voice command processing failed', { error: error.message });
|
||||
|
||||
return {
|
||||
command: voiceInput,
|
||||
confidence: 0.5,
|
||||
intent: 'unknown',
|
||||
entities: []
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private parseVoiceCommand(input: string): {
|
||||
command: string;
|
||||
confidence: number;
|
||||
intent: string;
|
||||
entities: any[];
|
||||
} {
|
||||
const lowerInput = input.toLowerCase();
|
||||
let intent = 'unknown';
|
||||
const entities: any[] = [];
|
||||
let confidence = 0.7;
|
||||
|
||||
// Intent classification
|
||||
if (lowerInput.includes('show') || lowerInput.includes('display')) {
|
||||
intent = 'display';
|
||||
if (lowerInput.includes('structure') || lowerInput.includes('files')) {
|
||||
entities.push({ type: 'target', value: 'project_structure' });
|
||||
}
|
||||
} else if (lowerInput.includes('analyze') || lowerInput.includes('examine')) {
|
||||
intent = 'analyze';
|
||||
if (lowerInput.includes('code') || lowerInput.includes('file')) {
|
||||
entities.push({ type: 'target', value: 'code_analysis' });
|
||||
}
|
||||
} else if (lowerInput.includes('create') || lowerInput.includes('make')) {
|
||||
intent = 'create';
|
||||
if (lowerInput.includes('component')) {
|
||||
entities.push({ type: 'target', value: 'component' });
|
||||
}
|
||||
} else if (lowerInput.includes('run') || lowerInput.includes('execute')) {
|
||||
intent = 'execute';
|
||||
if (lowerInput.includes('test')) {
|
||||
entities.push({ type: 'target', value: 'tests' });
|
||||
}
|
||||
} else if (lowerInput.includes('autopilot') || lowerInput.includes('auto')) {
|
||||
intent = 'autopilot';
|
||||
entities.push({ type: 'mode', value: 'autonomous' });
|
||||
} else if (lowerInput.includes('search') || lowerInput.includes('find')) {
|
||||
intent = 'search';
|
||||
if (lowerInput.includes('file')) {
|
||||
entities.push({ type: 'target', value: 'files' });
|
||||
}
|
||||
}
|
||||
|
||||
// Extract file names, paths, or other specific entities
|
||||
const filePattern = /(\w+\.\w+)/g;
|
||||
const fileMatches = input.match(filePattern);
|
||||
if (fileMatches) {
|
||||
fileMatches.forEach(match => {
|
||||
entities.push({ type: 'file', value: match });
|
||||
});
|
||||
}
|
||||
|
||||
// Adjust confidence based on clarity
|
||||
if (input.length > 10) confidence += 0.1;
|
||||
if (entities.length > 0) confidence += 0.1;
|
||||
if (intent !== 'unknown') confidence += 0.1;
|
||||
|
||||
return {
|
||||
command: input,
|
||||
confidence: Math.min(confidence, 1.0),
|
||||
intent,
|
||||
entities
|
||||
};
|
||||
}
|
||||
|
||||
async getVoiceStatus(): Promise<{
|
||||
isListening: boolean;
|
||||
isSpeaking: boolean;
|
||||
language: string;
|
||||
available: boolean;
|
||||
}> {
|
||||
return {
|
||||
isListening: this.isListening,
|
||||
isSpeaking: this.synthesis?.speaking || false,
|
||||
language: 'en-US',
|
||||
available: !!(this.recognition && this.synthesis)
|
||||
};
|
||||
}
|
||||
|
||||
async setLanguage(language: string): Promise<void> {
|
||||
try {
|
||||
if (this.recognition) {
|
||||
this.recognition.lang = language;
|
||||
this.logger.info('Language set for speech recognition', { language });
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to set language', { error: error.message, language });
|
||||
}
|
||||
}
|
||||
|
||||
async setVoiceMode(mode: 'brief' | 'detailed' | 'silent' | 'interactive'): Promise<void> {
|
||||
try {
|
||||
// Store voice mode preference
|
||||
this.logger.info('Voice mode set', { mode });
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to set voice mode', { error: error.message, mode });
|
||||
}
|
||||
}
|
||||
}
|
||||
408
.github/Advanced_AI_Agent/examples/implementation/backend/src/websocket.ts
vendored
Normal file
408
.github/Advanced_AI_Agent/examples/implementation/backend/src/websocket.ts
vendored
Normal file
@@ -0,0 +1,408 @@
|
||||
import { Server, Socket } from 'socket.io';
|
||||
import { NowhereCore, NowhereContext } from './core/nowhere';
|
||||
import { Logger } from './utils/logger';
|
||||
|
||||
export interface WebSocketMessage {
|
||||
type: 'command' | 'voice' | 'autopilot' | 'memory' | 'status' | 'error';
|
||||
data: any;
|
||||
timestamp: Date;
|
||||
userId?: string;
|
||||
sessionId?: string;
|
||||
}
|
||||
|
||||
export interface WebSocketResponse {
|
||||
type: 'response' | 'status' | 'error' | 'voice_response';
|
||||
data: any;
|
||||
timestamp: Date;
|
||||
success: boolean;
|
||||
}
|
||||
|
||||
export function setupWebSocket(io: Server, nowhere: NowhereCore) {
|
||||
const logger = new Logger('WebSocket');
|
||||
|
||||
io.on('connection', (socket: Socket) => {
|
||||
logger.info('Client connected', {
|
||||
id: socket.id,
|
||||
address: socket.handshake.address
|
||||
});
|
||||
|
||||
// Handle authentication
|
||||
socket.on('authenticate', async (data: { token: string }) => {
|
||||
try {
|
||||
// In a real implementation, you would verify the JWT token
|
||||
const userId = 'user-' + Math.random().toString(36).substr(2, 9);
|
||||
socket.data.userId = userId;
|
||||
socket.data.authenticated = true;
|
||||
|
||||
socket.emit('authenticated', {
|
||||
success: true,
|
||||
userId,
|
||||
message: 'Successfully authenticated with Nowhere'
|
||||
});
|
||||
|
||||
logger.info('Client authenticated', { socketId: socket.id, userId });
|
||||
} catch (error) {
|
||||
socket.emit('authenticated', {
|
||||
success: false,
|
||||
error: 'Authentication failed'
|
||||
});
|
||||
logger.error('Authentication failed', { socketId: socket.id, error });
|
||||
}
|
||||
});
|
||||
|
||||
// Handle text commands
|
||||
socket.on('command', async (message: WebSocketMessage) => {
|
||||
try {
|
||||
if (!socket.data.authenticated) {
|
||||
socket.emit('error', {
|
||||
type: 'authentication_error',
|
||||
message: 'Please authenticate first'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const context: NowhereContext = {
|
||||
userId: socket.data.userId,
|
||||
sessionId: socket.id,
|
||||
projectId: message.data.projectId || 'default',
|
||||
timestamp: new Date(),
|
||||
metadata: {
|
||||
source: 'websocket',
|
||||
clientId: socket.id,
|
||||
userAgent: socket.handshake.headers['user-agent']
|
||||
}
|
||||
};
|
||||
|
||||
logger.info('Processing command via WebSocket', {
|
||||
command: message.data.command,
|
||||
userId: context.userId,
|
||||
sessionId: context.sessionId
|
||||
});
|
||||
|
||||
const response = await nowhere.processCommand(
|
||||
message.data.command,
|
||||
context,
|
||||
false
|
||||
);
|
||||
|
||||
socket.emit('response', {
|
||||
type: 'command_response',
|
||||
data: response,
|
||||
timestamp: new Date(),
|
||||
success: true
|
||||
});
|
||||
|
||||
logger.info('Command processed successfully', {
|
||||
command: message.data.command,
|
||||
responseTime: Date.now() - message.timestamp.getTime()
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
logger.error('Command processing failed', {
|
||||
error: error.message,
|
||||
command: message.data.command
|
||||
});
|
||||
|
||||
socket.emit('error', {
|
||||
type: 'command_error',
|
||||
message: 'Failed to process command',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Handle voice commands
|
||||
socket.on('voice_command', async (message: WebSocketMessage) => {
|
||||
try {
|
||||
if (!socket.data.authenticated) {
|
||||
socket.emit('error', {
|
||||
type: 'authentication_error',
|
||||
message: 'Please authenticate first'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const context: NowhereContext = {
|
||||
userId: socket.data.userId,
|
||||
sessionId: socket.id,
|
||||
projectId: message.data.projectId || 'default',
|
||||
timestamp: new Date(),
|
||||
metadata: {
|
||||
source: 'websocket_voice',
|
||||
clientId: socket.id,
|
||||
audioData: message.data.audioData
|
||||
}
|
||||
};
|
||||
|
||||
logger.info('Processing voice command via WebSocket', {
|
||||
userId: context.userId,
|
||||
sessionId: context.sessionId
|
||||
});
|
||||
|
||||
const response = await nowhere.processVoiceCommand(
|
||||
message.data.voiceInput,
|
||||
context
|
||||
);
|
||||
|
||||
socket.emit('voice_response', {
|
||||
type: 'voice_response',
|
||||
data: response,
|
||||
timestamp: new Date(),
|
||||
success: true
|
||||
});
|
||||
|
||||
logger.info('Voice command processed successfully', {
|
||||
responseTime: Date.now() - message.timestamp.getTime()
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
logger.error('Voice command processing failed', {
|
||||
error: error.message
|
||||
});
|
||||
|
||||
socket.emit('error', {
|
||||
type: 'voice_error',
|
||||
message: 'Failed to process voice command',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Handle autopilot mode
|
||||
socket.on('autopilot', async (message: WebSocketMessage) => {
|
||||
try {
|
||||
if (!socket.data.authenticated) {
|
||||
socket.emit('error', {
|
||||
type: 'authentication_error',
|
||||
message: 'Please authenticate first'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const context: NowhereContext = {
|
||||
userId: socket.data.userId,
|
||||
sessionId: socket.id,
|
||||
projectId: message.data.projectId || 'default',
|
||||
timestamp: new Date(),
|
||||
metadata: {
|
||||
source: 'websocket_autopilot',
|
||||
clientId: socket.id
|
||||
}
|
||||
};
|
||||
|
||||
if (message.data.action === 'enable') {
|
||||
await nowhere.enableAutopilotMode(context);
|
||||
socket.emit('autopilot_status', {
|
||||
type: 'autopilot_enabled',
|
||||
data: { enabled: true },
|
||||
timestamp: new Date(),
|
||||
success: true
|
||||
});
|
||||
logger.info('Autopilot mode enabled', { userId: context.userId });
|
||||
} else if (message.data.action === 'disable') {
|
||||
await nowhere.disableAutopilotMode(context);
|
||||
socket.emit('autopilot_status', {
|
||||
type: 'autopilot_disabled',
|
||||
data: { enabled: false },
|
||||
timestamp: new Date(),
|
||||
success: true
|
||||
});
|
||||
logger.info('Autopilot mode disabled', { userId: context.userId });
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
logger.error('Autopilot operation failed', {
|
||||
error: error.message,
|
||||
action: message.data.action
|
||||
});
|
||||
|
||||
socket.emit('error', {
|
||||
type: 'autopilot_error',
|
||||
message: 'Failed to process autopilot command',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Handle memory operations
|
||||
socket.on('memory', async (message: WebSocketMessage) => {
|
||||
try {
|
||||
if (!socket.data.authenticated) {
|
||||
socket.emit('error', {
|
||||
type: 'authentication_error',
|
||||
message: 'Please authenticate first'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const context: NowhereContext = {
|
||||
userId: socket.data.userId,
|
||||
sessionId: socket.id,
|
||||
projectId: message.data.projectId || 'default',
|
||||
timestamp: new Date(),
|
||||
metadata: {
|
||||
source: 'websocket_memory',
|
||||
clientId: socket.id
|
||||
}
|
||||
};
|
||||
|
||||
if (message.data.action === 'get') {
|
||||
const memory = await nowhere.getMemory(context);
|
||||
socket.emit('memory_response', {
|
||||
type: 'memory_data',
|
||||
data: memory,
|
||||
timestamp: new Date(),
|
||||
success: true
|
||||
});
|
||||
} else if (message.data.action === 'clear') {
|
||||
await nowhere.clearMemory(context);
|
||||
socket.emit('memory_response', {
|
||||
type: 'memory_cleared',
|
||||
data: { cleared: true },
|
||||
timestamp: new Date(),
|
||||
success: true
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
logger.error('Memory operation failed', {
|
||||
error: error.message,
|
||||
action: message.data.action
|
||||
});
|
||||
|
||||
socket.emit('error', {
|
||||
type: 'memory_error',
|
||||
message: 'Failed to process memory operation',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Handle status requests
|
||||
socket.on('status', async () => {
|
||||
try {
|
||||
const status = {
|
||||
server: 'running',
|
||||
timestamp: new Date(),
|
||||
version: '1.0.0',
|
||||
features: [
|
||||
'voice_commands',
|
||||
'autopilot_mode',
|
||||
'memory_system',
|
||||
'real_time_communication'
|
||||
]
|
||||
};
|
||||
|
||||
socket.emit('status_response', {
|
||||
type: 'status',
|
||||
data: status,
|
||||
timestamp: new Date(),
|
||||
success: true
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
logger.error('Status request failed', { error: error.message });
|
||||
socket.emit('error', {
|
||||
type: 'status_error',
|
||||
message: 'Failed to get status',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Handle voice status
|
||||
socket.on('voice_status', async () => {
|
||||
try {
|
||||
// This would integrate with the VoiceProcessor
|
||||
const voiceStatus = {
|
||||
isListening: false,
|
||||
isSpeaking: false,
|
||||
language: 'en-US',
|
||||
available: true
|
||||
};
|
||||
|
||||
socket.emit('voice_status_response', {
|
||||
type: 'voice_status',
|
||||
data: voiceStatus,
|
||||
timestamp: new Date(),
|
||||
success: true
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
logger.error('Voice status request failed', { error: error.message });
|
||||
socket.emit('error', {
|
||||
type: 'voice_status_error',
|
||||
message: 'Failed to get voice status',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Handle disconnection
|
||||
socket.on('disconnect', (reason: string) => {
|
||||
logger.info('Client disconnected', {
|
||||
socketId: socket.id,
|
||||
reason,
|
||||
userId: socket.data.userId
|
||||
});
|
||||
|
||||
// Clean up any ongoing operations for this session
|
||||
if (socket.data.userId) {
|
||||
// In a real implementation, you might want to clean up
|
||||
// any ongoing autopilot operations or memory sessions
|
||||
}
|
||||
});
|
||||
|
||||
// Handle errors
|
||||
socket.on('error', (error: any) => {
|
||||
logger.error('WebSocket error', {
|
||||
socketId: socket.id,
|
||||
error: error.message
|
||||
});
|
||||
});
|
||||
|
||||
// Send welcome message
|
||||
socket.emit('welcome', {
|
||||
type: 'welcome',
|
||||
data: {
|
||||
message: 'Welcome to Nowhere AI Agent',
|
||||
version: '1.0.0',
|
||||
features: [
|
||||
'Voice Commands',
|
||||
'Autopilot Mode',
|
||||
'Real-time Communication',
|
||||
'Memory System'
|
||||
]
|
||||
},
|
||||
timestamp: new Date(),
|
||||
success: true
|
||||
});
|
||||
});
|
||||
|
||||
// Broadcast system messages to all connected clients
|
||||
function broadcastSystemMessage(message: string, type: string = 'info') {
|
||||
io.emit('system_message', {
|
||||
type: 'system',
|
||||
data: {
|
||||
message,
|
||||
type,
|
||||
timestamp: new Date()
|
||||
},
|
||||
timestamp: new Date(),
|
||||
success: true
|
||||
});
|
||||
}
|
||||
|
||||
// Handle server shutdown
|
||||
process.on('SIGTERM', () => {
|
||||
broadcastSystemMessage('Server is shutting down', 'warning');
|
||||
io.close();
|
||||
});
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
broadcastSystemMessage('Server is shutting down', 'warning');
|
||||
io.close();
|
||||
});
|
||||
|
||||
logger.info('WebSocket server setup complete');
|
||||
}
|
||||
60
.github/Advanced_AI_Agent/examples/implementation/backend/test-server.js
vendored
Normal file
60
.github/Advanced_AI_Agent/examples/implementation/backend/test-server.js
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 3001;
|
||||
|
||||
// Middleware
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
|
||||
// Health check endpoint
|
||||
app.get('/health', (req, res) => {
|
||||
res.json({
|
||||
status: 'ok',
|
||||
message: 'Nowhere AI Agent Backend is running',
|
||||
timestamp: new Date().toISOString(),
|
||||
version: '1.0.0'
|
||||
});
|
||||
});
|
||||
|
||||
// Test endpoint
|
||||
app.get('/api/v1/status', (req, res) => {
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
server: 'running',
|
||||
timestamp: new Date(),
|
||||
version: '1.0.0',
|
||||
features: [
|
||||
'voice_commands',
|
||||
'autopilot_mode',
|
||||
'memory_system',
|
||||
'real_time_communication'
|
||||
]
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Test command endpoint
|
||||
app.post('/api/v1/command', (req, res) => {
|
||||
const { command } = req.body;
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
response: `Nowhere processed your command: "${command}"`,
|
||||
actions: [],
|
||||
memory: {},
|
||||
timestamp: new Date()
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Start server
|
||||
app.listen(PORT, () => {
|
||||
console.log(`🚀 Nowhere AI Agent Backend running on port ${PORT}`);
|
||||
console.log(`📊 Health check: http://localhost:${PORT}/health`);
|
||||
console.log(`🔧 API status: http://localhost:${PORT}/api/v1/status`);
|
||||
console.log(`💬 Test command: POST http://localhost:${PORT}/api/v1/command`);
|
||||
});
|
||||
380
.github/Advanced_AI_Agent/examples/implementation/frontend/index.html
vendored
Normal file
380
.github/Advanced_AI_Agent/examples/implementation/frontend/index.html
vendored
Normal file
@@ -0,0 +1,380 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Nowhere AI Agent</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.container {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border-radius: 20px;
|
||||
padding: 2rem;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
||||
width: 90%;
|
||||
max-width: 600px;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
color: #333;
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.header p {
|
||||
color: #666;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.status {
|
||||
background: #f8f9fa;
|
||||
border-radius: 10px;
|
||||
padding: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
border-left: 4px solid #28a745;
|
||||
}
|
||||
|
||||
.status.offline {
|
||||
border-left-color: #dc3545;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.input-group label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.input-group input,
|
||||
.input-group textarea {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 10px;
|
||||
font-size: 1rem;
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
|
||||
.input-group input:focus,
|
||||
.input-group textarea:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 0.75rem 1.5rem;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: #6c757d;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: #5a6268;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.btn-voice {
|
||||
background: #28a745;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-voice:hover {
|
||||
background: #218838;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.btn-voice.recording {
|
||||
background: #dc3545;
|
||||
animation: pulse 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% { transform: scale(1); }
|
||||
50% { transform: scale(1.05); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
.response {
|
||||
background: #f8f9fa;
|
||||
border-radius: 10px;
|
||||
padding: 1rem;
|
||||
margin-top: 1rem;
|
||||
border-left: 4px solid #667eea;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.response.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.response h3 {
|
||||
color: #333;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.response p {
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.features {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 1rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.feature {
|
||||
background: #f8f9fa;
|
||||
padding: 1rem;
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.feature h4 {
|
||||
color: #333;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.feature p {
|
||||
color: #666;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.loading {
|
||||
display: none;
|
||||
text-align: center;
|
||||
color: #667eea;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.loading.show {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>Nowhere AI Agent</h1>
|
||||
<p>Advanced AI coding assistant with voice integration</p>
|
||||
</div>
|
||||
|
||||
<div class="status" id="status">
|
||||
<strong>Status:</strong> <span id="statusText">Checking connection...</span>
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
<label for="command">Command:</label>
|
||||
<textarea id="command" rows="3" placeholder="Enter your command for Nowhere..."></textarea>
|
||||
</div>
|
||||
|
||||
<div class="button-group">
|
||||
<button class="btn btn-primary" onclick="sendCommand()">Send Command</button>
|
||||
<button class="btn btn-voice" id="voiceBtn" onclick="toggleVoice()">🎤 Voice</button>
|
||||
<button class="btn btn-secondary" onclick="checkStatus()">Check Status</button>
|
||||
</div>
|
||||
|
||||
<div class="loading" id="loading">
|
||||
Processing...
|
||||
</div>
|
||||
|
||||
<div class="response" id="response">
|
||||
<h3>Nowhere's Response:</h3>
|
||||
<p id="responseText"></p>
|
||||
</div>
|
||||
|
||||
<div class="features">
|
||||
<div class="feature">
|
||||
<h4>🎤 Voice Commands</h4>
|
||||
<p>Natural language voice interaction with Nowhere</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<h4>🤖 Autopilot Mode</h4>
|
||||
<p>Autonomous task execution and problem solving</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<h4>🧠 Memory System</h4>
|
||||
<p>Persistent learning and context awareness</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<h4>⚡ Real-time</h4>
|
||||
<p>Instant communication and response</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const API_BASE = 'http://localhost:3001';
|
||||
let isRecording = false;
|
||||
|
||||
// Check connection on load
|
||||
window.onload = function() {
|
||||
checkStatus();
|
||||
};
|
||||
|
||||
async function checkStatus() {
|
||||
try {
|
||||
const response = await fetch(`${API_BASE}/health`);
|
||||
const data = await response.json();
|
||||
|
||||
document.getElementById('statusText').textContent = 'Connected';
|
||||
document.getElementById('status').classList.remove('offline');
|
||||
} catch (error) {
|
||||
document.getElementById('statusText').textContent = 'Offline';
|
||||
document.getElementById('status').classList.add('offline');
|
||||
}
|
||||
}
|
||||
|
||||
async function sendCommand() {
|
||||
const command = document.getElementById('command').value.trim();
|
||||
if (!command) {
|
||||
alert('Please enter a command');
|
||||
return;
|
||||
}
|
||||
|
||||
showLoading(true);
|
||||
hideResponse();
|
||||
|
||||
try {
|
||||
const response = await fetch(`${API_BASE}/api/v1/command`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ command })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
showResponse(data.data.response);
|
||||
} else {
|
||||
showResponse('Error: ' + data.error);
|
||||
}
|
||||
} catch (error) {
|
||||
showResponse('Error connecting to Nowhere: ' + error.message);
|
||||
} finally {
|
||||
showLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
function toggleVoice() {
|
||||
const voiceBtn = document.getElementById('voiceBtn');
|
||||
|
||||
if (!isRecording) {
|
||||
// Start voice recording
|
||||
isRecording = true;
|
||||
voiceBtn.textContent = '🔴 Stop';
|
||||
voiceBtn.classList.add('recording');
|
||||
|
||||
// Simulate voice command
|
||||
setTimeout(() => {
|
||||
const commands = [
|
||||
'Hello Nowhere, show me the project structure',
|
||||
'Nowhere, analyze this code file',
|
||||
'Create a new component for the user interface',
|
||||
'Run the tests and show me the results',
|
||||
'What are the main features we need to implement?',
|
||||
'Enable autopilot mode'
|
||||
];
|
||||
|
||||
const randomCommand = commands[Math.floor(Math.random() * commands.length)];
|
||||
document.getElementById('command').value = randomCommand;
|
||||
|
||||
// Stop recording
|
||||
isRecording = false;
|
||||
voiceBtn.textContent = '🎤 Voice';
|
||||
voiceBtn.classList.remove('recording');
|
||||
|
||||
// Send the command
|
||||
sendCommand();
|
||||
}, 2000);
|
||||
} else {
|
||||
// Stop voice recording
|
||||
isRecording = false;
|
||||
voiceBtn.textContent = '🎤 Voice';
|
||||
voiceBtn.classList.remove('recording');
|
||||
}
|
||||
}
|
||||
|
||||
function showLoading(show) {
|
||||
const loading = document.getElementById('loading');
|
||||
if (show) {
|
||||
loading.classList.add('show');
|
||||
} else {
|
||||
loading.classList.remove('show');
|
||||
}
|
||||
}
|
||||
|
||||
function showResponse(text) {
|
||||
document.getElementById('responseText').textContent = text;
|
||||
document.getElementById('response').classList.add('show');
|
||||
}
|
||||
|
||||
function hideResponse() {
|
||||
document.getElementById('response').classList.remove('show');
|
||||
}
|
||||
|
||||
// Handle Enter key in textarea
|
||||
document.getElementById('command').addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Enter' && e.ctrlKey) {
|
||||
sendCommand();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user