MindPeeker Logo
Developers

Developer Tools

Essential tools and utilities for MindPeeker platform development

Overview

MindPeeker provides a comprehensive suite of developer tools to streamline integration, testing, and deployment. These tools help you build, test, and maintain your psychic intelligence applications efficiently.

Command Line Interface (CLI)

Installation

npm install -g @mindpeeker/cli

yarn global add @mindpeeker/cli

pip install mindpeeker-cli

brew install mindpeeker/tap/mindpeeker-cli

Authentication

mindpeeker auth login

mindpeeker auth set --key your_api_key_here

mindpeeker auth status

mindpeeker auth logout

Session Management

mindpeeker sessions create \
  --type remote_viewing \
  --target "Missing person investigation" \
  --modality visual \
  --duration 30

mindpeeker sessions list --limit 10 --status completed

mindpeeker sessions get sess_123456789

mindpeeker sessions results sess_123456789

mindpeeker sessions watch sess_123456789

Analysis Operations

mindpeeker analysis submit \
  --target-type location \
  --reference photos.jpg,coordinates.json \
  --analysis-type comprehensive

mindpeeker analysis list --status completed

mindpeeker analysis results anal_123456789

mindpeeker analysis export anal_123456789 --format json --output results.json

Dowsing Queries

mindpeeker dowsing query \
  --type location \
  --question "Find water source" \
  --location "40.7128,-74.0060" \
  --radius 1000

mindpeeker dowsing batch --file queries.json

mindpeeker dowsing interactive

Webhook Management

mindpeeker webhooks create \
  --url https://your-app.com/webhook \
  --events session.completed,analysis.completed \
  --secret your_webhook_secret

mindpeeker webhooks list

mindpeeker webhooks test webhook_123

mindpeeker webhooks delete webhook_123

Configuration Management

mindpeeker config set api_url https://api.mindpeeker.com/v1
mindpeeker config set timeout 30000
mindpeeker config set retry_attempts 3

mindpeeker config get api_url

mindpeeker config list

mindpeeker config reset

Development Environment

Docker Development Container

FROM node:18-alpine

RUN npm install -g @mindpeeker/cli

RUN npm install -g nodemon typescript ts-node

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "run", "dev"]

Docker Compose Setup

version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
      - MINDPEEKER_API_KEY=${MINDPEEKER_API_KEY}
      - MINDPEEKER_WEBHOOK_SECRET=${MINDPEEKER_WEBHOOK_SECRET}
    volumes:
      - .:/app
      - /app/node_modules
    depends_on:
      - redis
      - postgres

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data

  postgres:
    image: postgres:15-alpine
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_DB=mindpeeker_dev
      - POSTGRES_USER=dev
      - POSTGRES_PASSWORD=dev123
    volumes:
      - postgres_data:/var/lib/postgresql/data

  webhook-proxy:
    image: ngrok/ngrok:latest
    command: http 3000
    ports:
      - "4040:4040"
    environment:
      - NGROK_AUTHTOKEN=${NGROK_AUTHTOKEN}

volumes:
  redis_data:
  postgres_data:

Local Development Scripts

#!/bin/bash

echo "Setting up MindPeeker development environment..."

command -v node >/dev/null 2>&1 || { echo "Node.js is required"; exit 1; }
command -v docker >/dev/null 2>&1 || { echo "Docker is required"; exit 1; }

echo "Installing dependencies..."
npm install

echo "Installing MindPeeker CLI..."
npm install -g @mindpeeker/cli

if [ ! -f .env ]; then
    echo "Creating .env file..."
    cp .env.example .env
    echo "Please edit .env with your API keys"
fi

echo "Starting development services..."
docker-compose -f docker-compose.dev.yml up -d

echo "Waiting for services to start..."
sleep 10

echo "Running database migrations..."
npm run migrate

echo "Seeding test data..."
npm run seed

echo "Development environment ready!"
echo "Webhook tunnel URL: $(curl -s http://localhost:4040/api/tunnels | jq -r '.tunnels[0].public_url')"

Testing Tools

Unit Testing Framework

// tests/utils/mindpeeker-mock.js
const { MindPeekerClient } = require('@mindpeeker/javascript');

class MockMindPeekerClient {
  constructor(options = {}) {
    this.apiKey = options.apiKey || 'test_key';
    this.responses = new Map();
    this.requests = [];
  }
  
  // Mock response setup
  setMockResponse(method, response) {
    this.responses.set(method, response);
  }
  
  // Session methods
  async sessions() {
    return {
      create: async (params) => {
        this.requests.push({ method: 'sessions.create', params });
        return this.responses.get('sessions.create') || {
          sessionId: 'test_session_123',
          status: 'initiated',
          createdAt: new Date().toISOString()
        };
      },
      
      getResults: async (sessionId) => {
        this.requests.push({ method: 'sessions.getResults', params: { sessionId } });
        return this.responses.get('sessions.getResults') || {
          sessionId,
          status: 'completed',
          confidenceScore: 0.85,
          results: {
            coordinates: { latitude: 40.7128, longitude: -74.0060 },
            descriptors: ['test descriptor']
          }
        };
      }
    };
  }
  
  // Analysis methods
  async analysis() {
    return {
      submitTarget: async (params) => {
        this.requests.push({ method: 'analysis.submitTarget', params });
        return this.responses.get('analysis.submitTarget') || {
          analysisId: 'test_analysis_123',
          status: 'queued'
        };
      }
    };
  }
  
  // Dowsing methods
  async dowsing() {
    return {
      query: async (params) => {
        this.requests.push({ method: 'dowsing.query', params });
        return this.responses.get('dowsing.query') || {
          queryId: 'test_query_123',
          answer: 'positive',
          confidence: 0.9
        };
      }
    };
  }
  
  // Get request history for testing
  getRequests() {
    return this.requests;
  }
  
  // Clear request history
  clearRequests() {
    this.requests = [];
  }
}

module.exports = { MockMindPeekerClient };

Integration Testing Suite

// tests/integration/psychic-integration.test.js
const request = require('supertest');
const app = require('../../app');
const { MockMindPeekerClient } = require('../utils/mindpeeker-mock');

describe('Psychic Integration API', () => {
  let mockClient;
  
  beforeEach(() => {
    mockClient = new MockMindPeekerClient();
    app.setMindPeekerClient(mockClient);
  });
  
  afterEach(() => {
    mockClient.clearRequests();
  });
  
  describe('POST /api/investigation', () => {
    it('should create a new psychic investigation', async () => {
      // Setup mock response
      mockClient.setMockResponse('sessions.create', {
        sessionId: 'investigation_123',
        status: 'initiated',
        createdAt: '2025-01-15T10:30:00Z'
      });
      
      const response = await request(app)
        .post('/api/investigation')
        .send({
          type: 'remote_viewing',
          target: 'Test investigation',
          modality: 'visual'
        })
        .expect(200);
      
      expect(response.body.sessionId).toBe('investigation_123');
      expect(response.body.status).toBe('initiated');
      
      // Verify API was called correctly
      const requests = mockClient.getRequests();
      expect(requests).toHaveLength(1);
      expect(requests[0].method).toBe('sessions.create');
      expect(requests[0].params.type).toBe('remote_viewing');
    });
  });
  
  describe('GET /api/investigation/:sessionId/results', () => {
    it('should return investigation results', async () => {
      // Setup mock response
      mockClient.setMockResponse('sessions.getResults', {
        sessionId: 'investigation_123',
        status: 'completed',
        confidenceScore: 0.92,
        results: {
          coordinates: { latitude: 40.7128, longitude: -74.0060 },
          descriptors: ['urban environment', 'water nearby']
        }
      });
      
      const response = await request(app)
        .get('/api/investigation/investigation_123/results')
        .expect(200);
      
      expect(response.body.status).toBe('completed');
      expect(response.body.confidenceScore).toBe(0.92);
      expect(response.body.results.descriptors).toContain('urban environment');
    });
  });
});

Load Testing Tool

// tools/load-test.js
import { MindPeekerClient } from '@mindpeeker/javascript';
import { performance } from 'perf_hooks';

class LoadTester {
  constructor(apiKey, concurrency = 10) {
    this.client = new MindPeekerClient({ apiKey });
    this.concurrency = concurrency;
    this.results = [];
  }
  
  async runLoadTest(testType, iterations = 100) {
    console.log(`Starting load test: ${testType} (${iterations} iterations)`);
    
    const startTime = performance.now();
    const promises = [];
    
    for (let i = 0; i < iterations; i++) {
      if (promises.length >= this.concurrency) {
        await Promise.race(promises);
        promises.splice(promises.findIndex(p => p.settled), 1);
      }
      
      const promise = this.runSingleTest(testType, i);
      promises.push(promise);
    }
    
    await Promise.all(promises);
    const endTime = performance.now();
    
    this.analyzeResults(endTime - startTime);
  }
  
  async runSingleTest(testType, iteration) {
    const startTime = performance.now();
    
    try {
      let result;
      
      switch (testType) {
        case 'session_create':
          result = await this.client.sessions.create({
            type: 'remote_viewing',
            target: `Load test ${iteration}`,
            modality: 'visual'
          });
          break;
          
        case 'dowsing_query':
          result = await this.client.dowsing.query({
            query_type: 'yes_no',
            question: `Load test question ${iteration}?`
          });
          break;
          
        case 'analysis_submit':
          result = await this.client.analysis.submitTarget({
            target_type: 'location',
            reference_material: { test: true },
            analysis_type: 'quick_scan'
          });
          break;
      }
      
      const endTime = performance.now();
      const duration = endTime - startTime;
      
      this.results.push({
        iteration,
        success: true,
        duration,
        result: result.sessionId || result.queryId || result.analysisId
      });
      
    } catch (error) {
      const endTime = performance.now();
      const duration = endTime - startTime;
      
      this.results.push({
        iteration,
        success: false,
        duration,
        error: error.message
      });
    }
  }
  
  analyzeResults(totalTime) {
    const successful = this.results.filter(r => r.success);
    const failed = this.results.filter(r => !r.success);
    
    const durations = successful.map(r => r.duration);
    const avgDuration = durations.reduce((a, b) => a + b, 0) / durations.length;
    const minDuration = Math.min(...durations);
    const maxDuration = Math.max(...durations);
    
    console.log('\n=== Load Test Results ===');
    console.log(`Total iterations: ${this.results.length}`);
    console.log(`Successful: ${successful.length}`);
    console.log(`Failed: ${failed.length}`);
    console.log(`Success rate: ${((successful.length / this.results.length) * 100).toFixed(2)}%`);
    console.log(`Total time: ${totalTime.toFixed(2)}ms`);
    console.log(`Average response time: ${avgDuration.toFixed(2)}ms`);
    console.log(`Min response time: ${minDuration.toFixed(2)}ms`);
    console.log(`Max response time: ${maxDuration.toFixed(2)}ms`);
    console.log(`Requests per second: ${(this.results.length / (totalTime / 1000)).toFixed(2)}`);
    
    if (failed.length > 0) {
      console.log('\n=== Failed Requests ===');
      failed.forEach(f => {
        console.log(`Iteration ${f.iteration}: ${f.error}`);
      });
    }
  }
}

// Usage
const tester = new LoadTester(process.env.MINDPEEKER_API_KEY, 5);

await tester.runLoadTest('session_create', 50);
await tester.runLoadTest('dowsing_query', 50);
await tester.runLoadTest('analysis_submit', 50);

Monitoring and Debugging

API Request Logger

// utils/api-logger.js
class APILogger {
  constructor(logLevel = 'info') {
    this.logLevel = logLevel;
    this.requests = [];
    this.maxLogSize = 1000;
  }
  
  logRequest(method, url, headers, body, response, duration) {
    const logEntry = {
      timestamp: new Date().toISOString(),
      method,
      url,
      headers: this.sanitizeHeaders(headers),
      body: this.sanitizeBody(body),
      response: {
        status: response.status,
        headers: response.headers
      },
      duration,
      success: response.status >= 200 && response.status < 300
    };
    
    this.requests.push(logEntry);
    
    // Keep log size manageable
    if (this.requests.length > this.maxLogSize) {
      this.requests.shift();
    }
    
    this.outputLog(logEntry);
  }
  
  sanitizeHeaders(headers) {
    const sanitized = { ...headers };
    const sensitiveHeaders = ['authorization', 'x-api-key', 'cookie'];
    
    sensitiveHeaders.forEach(header => {
      if (sanitized[header]) {
        sanitized[header] = '[REDACTED]';
      }
    });
    
    return sanitized;
  }
  
  sanitizeBody(body) {
    if (!body) return null;
    
    const sensitiveFields = ['api_key', 'password', 'token', 'secret'];
    const sanitized = { ...body };
    
    sensitiveFields.forEach(field => {
      if (sanitized[field]) {
        sanitized[field] = '[REDACTED]';
      }
    });
    
    return sanitized;
  }
  
  outputLog(entry) {
    const logLevel = entry.success ? 'info' : 'error';
    
    if (this.shouldLog(logLevel)) {
      console.log(`[${entry.timestamp}] ${entry.method} ${entry.url} - ${entry.response.status} (${entry.duration}ms)`);
      
      if (!entry.success) {
        console.error(`Request failed: ${JSON.stringify(entry.body)}`);
      }
    }
  }
  
  shouldLog(level) {
    const levels = ['error', 'warn', 'info', 'debug'];
    const currentLevelIndex = levels.indexOf(this.logLevel);
    const messageLevelIndex = levels.indexOf(level);
    
    return messageLevelIndex <= currentLevelIndex;
  }
  
  getRequests(filter = {}) {
    let filtered = this.requests;
    
    if (filter.method) {
      filtered = filtered.filter(r => r.method === filter.method);
    }
    
    if (filter.success !== undefined) {
      filtered = filtered.filter(r => r.success === filter.success);
    }
    
    if (filter.since) {
      const since = new Date(filter.since);
      filtered = filtered.filter(r => new Date(r.timestamp) >= since);
    }
    
    return filtered;
  }
  
  exportLogs(format = 'json') {
    switch (format) {
      case 'json':
        return JSON.stringify(this.requests, null, 2);
        
      case 'csv':
        const headers = ['timestamp', 'method', 'url', 'status', 'duration', 'success'];
        const csvData = this.requests.map(r => [
          r.timestamp,
          r.method,
          r.url,
          r.response.status,
          r.duration,
          r.success
        ]);
        
        return [headers, ...csvData].map(row => row.join(',')).join('\n');
        
      default:
        return this.requests;
    }
  }
}

module.exports = APILogger;

Performance Monitor

// utils/performance-monitor.js
class PerformanceMonitor {
  constructor() {
    this.metrics = {
      requests: {
        total: 0,
        successful: 0,
        failed: 0,
        averageResponseTime: 0
      },
      sessions: {
        created: 0,
        completed: 0,
        failed: 0,
        averageCompletionTime: 0
      },
      errors: {
        rateLimitErrors: 0,
        authenticationErrors: 0,
        validationErrors: 0,
        serverErrors: 0
      }
    };
    
    this.responseTimes = [];
    this.completionTimes = [];
  }
  
  recordRequest(duration, success, statusCode) {
    this.metrics.requests.total++;
    
    if (success) {
      this.metrics.requests.successful++;
    } else {
      this.metrics.requests.failed++;
      
      // Categorize errors
      if (statusCode === 429) {
        this.metrics.errors.rateLimitErrors++;
      } else if (statusCode === 401 || statusCode === 403) {
        this.metrics.errors.authenticationErrors++;
      } else if (statusCode >= 400 && statusCode < 500) {
        this.metrics.errors.validationErrors++;
      } else if (statusCode >= 500) {
        this.metrics.errors.serverErrors++;
      }
    }
    
    this.responseTimes.push(duration);
    this.updateAverageResponseTime();
  }
  
  recordSession(action, duration = null) {
    switch (action) {
      case 'created':
        this.metrics.sessions.created++;
        break;
      case 'completed':
        this.metrics.sessions.completed++;
        if (duration) {
          this.completionTimes.push(duration);
          this.updateAverageCompletionTime();
        }
        break;
      case 'failed':
        this.metrics.sessions.failed++;
        break;
    }
  }
  
  updateAverageResponseTime() {
    if (this.responseTimes.length === 0) return;
    
    const sum = this.responseTimes.reduce((a, b) => a + b, 0);
    this.metrics.requests.averageResponseTime = sum / this.responseTimes.length;
  }
  
  updateAverageCompletionTime() {
    if (this.completionTimes.length === 0) return;
    
    const sum = this.completionTimes.reduce((a, b) => a + b, 0);
    this.metrics.sessions.averageCompletionTime = sum / this.completionTimes.length;
  }
  
  getMetrics() {
    return {
      ...this.metrics,
      successRate: this.metrics.requests.total > 0 
        ? (this.metrics.requests.successful / this.metrics.requests.total) * 100 
        : 0,
      sessionSuccessRate: this.metrics.sessions.created > 0
        ? (this.metrics.sessions.completed / this.metrics.sessions.created) * 100
        : 0
    };
  }
  
  reset() {
    this.metrics = {
      requests: { total: 0, successful: 0, failed: 0, averageResponseTime: 0 },
      sessions: { created: 0, completed: 0, failed: 0, averageCompletionTime: 0 },
      errors: { rateLimitErrors: 0, authenticationErrors: 0, validationErrors: 0, serverErrors: 0 }
    };
    this.responseTimes = [];
    this.completionTimes = [];
  }
  
  exportMetrics() {
    return {
      timestamp: new Date().toISOString(),
      metrics: this.getMetrics(),
      responseTimeDistribution: this.getResponseTimeDistribution(),
      completionTimeDistribution: this.getCompletionTimeDistribution()
    };
  }
  
  getResponseTimeDistribution() {
    if (this.responseTimes.length === 0) return {};
    
    const sorted = [...this.responseTimes].sort((a, b) => a - b);
    
    return {
      min: sorted[0],
      max: sorted[sorted.length - 1],
      p50: sorted[Math.floor(sorted.length * 0.5)],
      p90: sorted[Math.floor(sorted.length * 0.9)],
      p95: sorted[Math.floor(sorted.length * 0.95)],
      p99: sorted[Math.floor(sorted.length * 0.99)]
    };
  }
  
  getCompletionTimeDistribution() {
    if (this.completionTimes.length === 0) return {};
    
    const sorted = [...this.completionTimes].sort((a, b) => a - b);
    
    return {
      min: sorted[0],
      max: sorted[sorted.length - 1],
      p50: sorted[Math.floor(sorted.length * 0.5)],
      p90: sorted[Math.floor(sorted.length * 0.9)],
      p95: sorted[Math.floor(sorted.length * 0.95)],
      p99: sorted[Math.floor(sorted.length * 0.99)]
    };
  }
}

module.exports = PerformanceMonitor;

IDE Extensions

VS Code Extension

// .vscode/extensions.json
{
  "recommendations": [
    "mindpeeker.mindpeeker-vscode",
    "ms-vscode.vscode-typescript-next",
    "esbenp.prettier-vscode",
    "ms-vscode.vscode-eslint",
    "bradlc.vscode-tailwindcss"
  ]
}

VS Code Settings

// .vscode/settings.json
{
  "mindpeeker.apiKey": "${env:MINDPEEKER_API_KEY}",
  "mindpeeker.defaultEnvironment": "sandbox",
  "mindpeeker.autoComplete": true,
  "mindpeeker.syntaxHighlighting": true,
  "mindpeeker.debugMode": false,
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  }
}

Deployment Tools

CI/CD Pipeline

name: MindPeeker CI/CD

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    services:
      redis:
        image: redis:7
        ports:
          - 6379:6379
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Install MindPeeker CLI
      run: npm install -g @mindpeeker/cli
    
    - name: Run linting
      run: npm run lint
    
    - name: Run type checking
      run: npm run typecheck
    
    - name: Run unit tests
      run: npm run test:unit
    
    - name: Run integration tests
      env:
        MINDPEEKER_API_KEY: ${{ secrets.MINDPEEKER_TEST_API_KEY }}
      run: npm run test:integration
    
    - name: Test CLI functionality
      env:
        MINDPEEKER_API_KEY: ${{ secrets.MINDPEEKER_TEST_API_KEY }}
      run: |
        mindpeeker auth login --key $MINDPEEKER_API_KEY
        mindpeeker sessions create --type dowsing --question "CI test"
  
  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Deploy to production
      env:
        MINDPEEKER_API_KEY: ${{ secrets.MINDPEEKER_PROD_API_KEY }}
      run: |
        npm run build
        npm run deploy

Support and Resources