OverviewFilesCommitsIssuesDocsReleasesPeers

ollama_semantic_function_calling / ollamatools-new / tests / keet_cli.js

325 lines · javascript ref:
#!/usr/bin/env node
/**
 * Command-line interface for Keet messaging.
 * This script provides a command-line interface for interacting with the Keet messaging platform.
 */

import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { parseArgs } from 'node:util';

// Get the directory name of the current module
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Configure logging
const logLevels = {
  INFO: 'INFO',
  ERROR: 'ERROR',
  WARNING: 'WARNING'
};

function log(level, message) {
  const timestamp = new Date().toISOString();
  console.log(`[${timestamp}] [${level}] ${message}`);
}

// Import Keet dependencies or mock implementations
let KeetBackend, KeetCoreApi;
let KEET_AVAILABLE = false;
let useMock = false;

async function importDependencies() {
  try {
    // Try to import the real Keet dependencies
    const backendModule = await import('@holepunchto/keet-backend');
    const coreApiModule = await import('@holepunchto/keet-core-api');
    
    // Try to get the exports
    KeetBackend = backendModule.default || backendModule;
    KeetCoreApi = coreApiModule.default || coreApiModule;
    
    KEET_AVAILABLE = true;
    
    log(logLevels.INFO, 'Successfully imported Keet dependencies');
  } catch (error) {
    log(logLevels.WARNING, `Failed to import Keet dependencies: ${error.message}`);
    log(logLevels.WARNING, 'Using mock implementation');
    
    // Import the mock implementation
    const { KeetBackend: MockKeetBackend, KeetCoreApi: MockKeetCoreApi } = await import('./keet_messaging_mock_test.js');
    
    KeetBackend = MockKeetBackend;
    KeetCoreApi = MockKeetCoreApi;
    KEET_AVAILABLE = true;
    useMock = true;
  }
}

/**
 * Parse command-line arguments.
 */
function parseArguments() {
  const options = {
    command: { type: 'string' },
    storage: { type: 'string' },
    output: { type: 'string' },
    'room-key': { type: 'string' },
    message: { type: 'string' },
    name: { type: 'string' },
    mock: { type: 'boolean', default: false }
  };
  
  const { values } = parseArgs({ options });
  
  // Force mock mode if specified
  if (values.mock) {
    useMock = true;
  }
  
  return values;
}

/**
 * Get the current identity.
 */
async function getIdentity(backend, outputPath) {
  try {
    const identity = await backend.api.core.getIdentity();
    
    if (outputPath) {
      fs.writeFileSync(outputPath, JSON.stringify(identity || {}));
    } else {
      console.log(JSON.stringify(identity || {}));
    }
    
    return true;
  } catch (error) {
    log(logLevels.ERROR, `Failed to get identity: ${error.message}`);
    return false;
  }
}

/**
 * Create a new identity.
 */
async function createIdentity(backend, name, outputPath) {
  try {
    // Generate a new identity
    await backend.api.core.generateIdentity();
    
    // Get the new identity
    const identity = await backend.api.core.getIdentity();
    
    // Set the display name if provided
    if (name && identity) {
      // TODO: Set the display name if the API supports it
    }
    
    if (outputPath) {
      fs.writeFileSync(outputPath, JSON.stringify(identity || {}));
    } else {
      console.log(JSON.stringify(identity || {}));
    }
    
    return true;
  } catch (error) {
    log(logLevels.ERROR, `Failed to create identity: ${error.message}`);
    return false;
  }
}

/**
 * Get recent rooms.
 */
async function getRecentRooms(backend, outputPath) {
  try {
    const rooms = await backend.api.core.getRecentRooms();
    
    if (outputPath) {
      fs.writeFileSync(outputPath, JSON.stringify(rooms || []));
    } else {
      console.log(JSON.stringify(rooms || []));
    }
    
    return true;
  } catch (error) {
    log(logLevels.ERROR, `Failed to get recent rooms: ${error.message}`);
    return false;
  }
}

/**
 * Join a room.
 */
async function joinRoom(backend, roomKey) {
  try {
    // Extract the room key from the invite link if needed
    if (roomKey.startsWith('pear://keet/')) {
      roomKey = roomKey.replace('pear://keet/', '');
    }
    
    // Check if there's a pairRoom method available
    if (backend.api.core.pairRoom) {
      log(logLevels.INFO, 'Using pairRoom method to join the room...');
      await backend.api.core.pairRoom(roomKey);
      log(logLevels.INFO, 'Successfully paired with the room');
    } else {
      log(logLevels.WARNING, 'pairRoom method not available');
      return false;
    }
    
    return true;
  } catch (error) {
    log(logLevels.ERROR, `Failed to join room: ${error.message}`);
    return false;
  }
}

/**
 * Get messages from a room.
 */
async function getMessages(backend, roomKey, outputPath) {
  try {
    // Extract the room key from the invite link if needed
    if (roomKey.startsWith('pear://keet/')) {
      roomKey = roomKey.replace('pear://keet/', '');
    }
    
    const messages = await backend.api.core.getChatMessages(roomKey);
    
    if (outputPath) {
      fs.writeFileSync(outputPath, JSON.stringify(messages || []));
    } else {
      console.log(JSON.stringify(messages || []));
    }
    
    return true;
  } catch (error) {
    log(logLevels.ERROR, `Failed to get messages: ${error.message}`);
    return false;
  }
}

/**
 * Send a message to a room.
 */
async function sendMessage(backend, roomKey, message) {
  try {
    // Extract the room key from the invite link if needed
    if (roomKey.startsWith('pear://keet/')) {
      roomKey = roomKey.replace('pear://keet/', '');
    }
    
    await backend.api.core.addChatMessage(roomKey, message);
    log(logLevels.INFO, 'Message sent successfully');
    
    return true;
  } catch (error) {
    log(logLevels.ERROR, `Failed to send message: ${error.message}`);
    return false;
  }
}

/**
 * Main function.
 */
async function main() {
  // Parse command-line arguments
  const args = parseArguments();
  
  // Import dependencies
  await importDependencies();
  
  if (!KEET_AVAILABLE) {
    log(logLevels.ERROR, 'Keet dependencies not available');
    return 1;
  }
  
  // Create a storage directory if it doesn't exist
  const storagePath = args.storage || path.join(__dirname, '..', 'test-keet-storage');
  if (!fs.existsSync(storagePath)) {
    fs.mkdirSync(storagePath, { recursive: true });
  }
  
  // Initialize Keet backend
  log(logLevels.INFO, 'Initializing Keet backend...');
  const backend = new KeetBackend(storagePath, {
    experimental: false,
    devMirrors: false
  });
  
  // Wait for backend to be ready
  await backend.ready();
  
  let success = false;
  
  // Execute the command
  switch (args.command) {
    case 'get-identity':
      success = await getIdentity(backend, args.output);
      break;
    
    case 'create-identity':
      success = await createIdentity(backend, args.name, args.output);
      break;
    
    case 'get-recent-rooms':
      success = await getRecentRooms(backend, args.output);
      break;
    
    case 'join-room':
      if (!args['room-key']) {
        log(logLevels.ERROR, 'Room key is required');
        success = false;
      } else {
        success = await joinRoom(backend, args['room-key']);
      }
      break;
    
    case 'get-messages':
      if (!args['room-key']) {
        log(logLevels.ERROR, 'Room key is required');
        success = false;
      } else {
        success = await getMessages(backend, args['room-key'], args.output);
      }
      break;
    
    case 'send-message':
      if (!args['room-key']) {
        log(logLevels.ERROR, 'Room key is required');
        success = false;
      } else if (!args.message) {
        log(logLevels.ERROR, 'Message is required');
        success = false;
      } else {
        success = await sendMessage(backend, args['room-key'], args.message);
      }
      break;
    
    default:
      log(logLevels.ERROR, `Unknown command: ${args.command}`);
      success = false;
  }
  
  // Close the backend
  log(logLevels.INFO, 'Closing backend...');
  await backend.close();
  
  return success ? 0 : 1;
}

// Run the main function if this file is executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
  try {
    const exitCode = await main();
    process.exit(exitCode);
  } catch (error) {
    log(logLevels.ERROR, `Unhandled error: ${error.message}`);
    log(logLevels.ERROR, error.stack);
    process.exit(1);
  }
}