Skip to content

WIP: Small refactoring #2188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 180 additions & 0 deletions engine/cli/internal/application/application_impl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// commands/internal/application/application_impl.cc
#include "public/application.h"
#include "application_impl.h"
#include "public/command_registry.h"
#include "internal/chat/chat_completion_cmd.h"

#include <iostream>
#include "services/database_service.h"
#include "services/download_service.h"
#include "utils/system_info_utils.h"

namespace cortex {

Application::Application() : impl_(std::make_unique<Impl>()) {
// Application constructor initializes the implementation
}

Application::~Application() = default;

int Application::Run(int argc, char* argv[]) {
// Check system compatibility
if (!impl_->IsSystemSupported()) {
std::cerr << "Unsupported system" << std::endl;
return 1;
}

// Initialize system
if (!impl_->InitializeSystem()) {
std::cerr << "Failed to initialize system" << std::endl;
return 1;
}

// Initialize services
if (!impl_->InitializeServices()) {
std::cerr << "Failed to initialize services" << std::endl;
return 1;
}

// Register commands
impl_->RegisterCommands();

// Parse command line arguments
std::string command_name;
std::vector<std::string> args;
std::unordered_map<std::string, std::string> options;
impl_->ParseArgs(argc, argv, command_name, args, options);

// Handle help command or no command
if (command_name.empty() || command_name == "help") {
if (args.empty()) {
impl_->command_registry_->PrintHelp();
} else {
impl_->command_registry_->PrintCommandHelp(args[0]);
}
return 0;
}

// Execute the command
auto status = impl_->command_registry_->ExecuteCommand(command_name, args, options);

// Cleanup
impl_->CleanupSystem();

return status == commands::CommandStatus::Success ? 0 : 1;
}

int Application::RunCommand(const std::string& command, const std::vector<std::string>& args) {
// Execute a specific command programmatically
if (!impl_->command_registry_) {
if (!impl_->InitializeServices()) {
return 1;
}
impl_->RegisterCommands();
}

auto status = impl_->command_registry_->ExecuteCommand(command, args, {});
return status == commands::CommandStatus::Success ? 0 : 1;
}

// Implementation class methods

Application::Impl::Impl() = default;

Application::Impl::~Impl() = default;

bool Application::Impl::InitializeServices() {
try {
// Initialize services
db_service_ = std::make_shared<DatabaseService>();
download_service_ = std::make_shared<DownloadService>();

// Create command registry
command_registry_ = commands::CommandRegistry::Create();

return true;
} catch (const std::exception& e) {
std::cerr << "Error initializing services: " << e.what() << std::endl;
return false;
}
}

void Application::Impl::RegisterCommands() {
// Register chat command
command_registry_->RegisterCommand(
std::make_shared<commands::ChatCompletionCommand>(db_service_));

// Register other commands
// command_registry_->RegisterCommand(
// std::make_shared<commands::RunCommand>(db_service_));
// ...
}

void Application::Impl::ParseArgs(int argc, char* argv[],
std::string& command_name,
std::vector<std::string>& args,
std::unordered_map<std::string, std::string>& options) {
// Extract command name (first argument)
if (argc > 1) {
command_name = argv[1];
}

// Process remaining arguments
for (int i = 2; i < argc; ++i) {
std::string arg = argv[i];

// Handle options (--option=value or --flag)
if (arg.size() > 2 && arg.substr(0, 2) == "--") {
size_t pos = arg.find('=');
if (pos != std::string::npos) {
// --option=value format
std::string option_name = arg.substr(2, pos - 2);
std::string option_value = arg.substr(pos + 1);
options[option_name] = option_value;
} else {
// --flag format
options[arg.substr(2)] = "true";
}
} else if (arg.size() > 1 && arg[0] == '-') {
// Handle short options (-f)
std::string option_name = arg.substr(1);

// If next argument isn't an option, treat it as this option's value
if (i + 1 < argc && argv[i + 1][0] != '-') {
options[option_name] = argv[i + 1];
++i; // Skip the value in the next iteration
} else {
// Flag option
options[option_name] = "true";
}
} else {
// Regular argument
args.push_back(arg);
}
}
}

bool Application::Impl::IsSystemSupported() const {
// Check system compatibility
auto system_info = system_info_utils::GetSystemInfo();
return !(system_info->arch == system_info_utils::kUnsupported ||
system_info->os == system_info_utils::kUnsupported);
}

bool Application::Impl::InitializeSystem() {
try {
// Initialize libraries and resources
// This would include things like SSL_library_init() and curl_global_init()
return true;
} catch (const std::exception& e) {
std::cerr << "Error initializing system: " << e.what() << std::endl;
return false;
}
}

void Application::Impl::CleanupSystem() {
// Clean up global resources
// This would include things like curl_global_cleanup()
}

} // namespace cortex
79 changes: 79 additions & 0 deletions engine/cli/internal/application/application_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#pragma once

#include <memory>
#include <string>
#include <vector>
#include <unordered_map>

// Forward declarations to avoid including unnecessary headers
namespace cortex {
namespace commands {
class CommandRegistry;
}
}

class DatabaseService;
class DownloadService;

namespace cortex {

// Implementation class for Application (Pimpl pattern)
class Application::Impl {
public:
Impl();
~Impl();

// Services
std::shared_ptr<DatabaseService> db_service_;
std::shared_ptr<DownloadService> download_service_;

// Command registry
std::shared_ptr<commands::CommandRegistry> command_registry_;

/**
* @brief Initialize services
*
* @return bool True if initialization was successful
*/
bool InitializeServices();

/**
* @brief Register commands with the registry
*/
void RegisterCommands();

/**
* @brief Parse command line arguments
*
* @param argc Argument count
* @param argv Argument values
* @param command_name Output parameter for command name
* @param args Output parameter for command arguments
* @param options Output parameter for command options
*/
void ParseArgs(int argc, char* argv[],
std::string& command_name,
std::vector<std::string>& args,
std::unordered_map<std::string, std::string>& options);

/**
* @brief Check if system is supported
*
* @return bool True if system is supported
*/
bool IsSystemSupported() const;

/**
* @brief Initialize system components
*
* @return bool True if initialization was successful
*/
bool InitializeSystem();

/**
* @brief Cleanup system resources
*/
void CleanupSystem();
};

} // namespace cortex
110 changes: 110 additions & 0 deletions engine/cli/internal/base/command_registry_impl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#include "command_registry_impl.h"
#include <algorithm>
#include <iostream>

namespace cortex {
namespace commands {

bool CommandRegistryImpl::RegisterCommand(std::shared_ptr<Command> command) {
if (!command) {
return false;
}

const auto& name = command->GetName();
if (name.empty() || commands_.find(name) != commands_.end()) {
return false;
}

commands_[name] = std::move(command);
return true;
}

std::shared_ptr<Command> CommandRegistryImpl::FindCommand(const std::string& name) const {
auto it = commands_.find(name);
if (it != commands_.end()) {
return it->second;
}
return nullptr;
}

std::vector<std::shared_ptr<Command>> CommandRegistryImpl::GetAllCommands() const {
std::vector<std::shared_ptr<Command>> result;
result.reserve(commands_.size());

for (const auto& [_, command] : commands_) {
result.push_back(command);
}

// Sort commands by name for consistent output
std::sort(result.begin(), result.end(),
[](const std::shared_ptr<Command>& a, const std::shared_ptr<Command>& b) {
return a->GetName() < b->GetName();
});

return result;
}

CommandStatus CommandRegistryImpl::ExecuteCommand(
const std::string& command_name,
const std::vector<std::string>& args,
const std::unordered_map<std::string, std::string>& options) {

auto command = FindCommand(command_name);
if (!command) {
std::cerr << "Unknown command: " << command_name << std::endl;
PrintHelp();
return CommandStatus::NotFound;
}

return command->Execute(args, options);
}

void CommandRegistryImpl::PrintHelp() const {
std::cout << "Cortex Command Line Interface" << std::endl;
std::cout << "Usage: cortex [command] [options]" << std::endl;
std::cout << std::endl;

std::cout << "Available commands:" << std::endl;

auto all_commands = GetAllCommands();
size_t max_name_length = 0;

// Find the longest command name for alignment
for (const auto& command : all_commands) {
max_name_length = std::max(max_name_length, command->GetName().length());
}

// Print all commands
for (const auto& command : all_commands) {
std::cout << " " << command->GetName();

// Add padding for alignment
for (size_t i = command->GetName().length(); i < max_name_length + 2; ++i) {
std::cout << " ";
}

std::cout << command->GetDescription() << std::endl;
}

std::cout << std::endl;
std::cout << "For more information about a specific command, type 'cortex help [command]'" << std::endl;
}

bool CommandRegistryImpl::PrintCommandHelp(const std::string& command_name) const {
auto command = FindCommand(command_name);
if (!command) {
std::cout << "Unknown command: " << command_name << std::endl;
return false;
}

std::cout << command->GetHelp() << std::endl;
return true;
}

// Static factory method implementation
std::shared_ptr<CommandRegistry> CommandRegistry::Create() {
return std::make_shared<CommandRegistryImpl>();
}

} // namespace commands
} // namespace cortex
Loading
Loading