import { CLI, ROVODEV_MODELS, ERROR_MESSAGES, STATUS_MESSAGES } from "../constants.js";
import { executeCommand } from "./commandExecutor.js";
import { logger } from "./logger.js";
/**
* Execute Rovodev CLI with the given options
*/
export async function executeRovodevCLI(options) {
const { prompt, model, sandbox = false, approvalMode, yolo = false, allFiles = false, debug = false, codeMode = false, reviewMode = false, optimize = false, explain = false, onProgress } = options;
if (!prompt || !prompt.trim()) {
throw new Error(ERROR_MESSAGES.NO_PROMPT_PROVIDED);
}
// Build command arguments
const args = [];
// Add subcommand
args.push(CLI.COMMANDS.SUBCOMMAND);
// Add model flag if specified
if (model) {
args.push(CLI.FLAGS.MODEL, model);
}
// Add sandbox flag if enabled
if (sandbox) {
args.push(CLI.FLAGS.SANDBOX);
}
// Add approval mode if specified
if (approvalMode) {
args.push(CLI.FLAGS.APPROVAL_MODE, approvalMode);
}
// Add yolo flag if enabled
if (yolo) {
args.push(CLI.FLAGS.YOLO);
}
// Add all-files flag if enabled
if (allFiles) {
args.push(CLI.FLAGS.ALL_FILES);
}
// Add debug flag if enabled
if (debug) {
args.push(CLI.FLAGS.DEBUG);
}
// Add rovodev-specific flags if enabled
if (codeMode) {
args.push(CLI.FLAGS.CODE_MODE);
}
if (reviewMode) {
args.push(CLI.FLAGS.REVIEW_MODE);
}
if (optimize) {
args.push(CLI.FLAGS.OPTIMIZE);
}
if (explain) {
args.push(CLI.FLAGS.EXPLAIN);
}
// Add prompt flag with the prompt
// Wrap in quotes if it contains @ symbols for file references
const shouldQuote = prompt.includes("@");
args.push(CLI.FLAGS.PROMPT);
args.push(shouldQuote ? `"${prompt}"` : prompt);
logger.info(`Executing Rovodev CLI with model: ${model || "default"}`);
if (onProgress) {
onProgress(STATUS_MESSAGES.STARTING_ANALYSIS);
}
try {
const result = await executeCommand(CLI.COMMANDS.ROVODEV, args, {
onProgress,
timeout: 600000 // 10 minutes
});
if (onProgress) {
onProgress(STATUS_MESSAGES.COMPLETED);
}
return result;
}
catch (error) {
// Check if this is a quota/rate limit error and we used the primary model
const errorMsg = error instanceof Error ? error.message : String(error);
const isQuotaError = errorMsg.toLowerCase().includes("quota") ||
errorMsg.toLowerCase().includes("rate limit");
// If quota error with primary model, try fallback
if (isQuotaError && model === ROVODEV_MODELS.PRIMARY) {
logger.warn(STATUS_MESSAGES.SWITCHING_MODEL);
if (onProgress) {
onProgress(STATUS_MESSAGES.SWITCHING_MODEL);
}
// Retry with fallback model
const fallbackArgs = [...args];
// Remove the primary model and add fallback model
const modelIndex = fallbackArgs.indexOf(CLI.FLAGS.MODEL);
if (modelIndex !== -1 && modelIndex + 1 < fallbackArgs.length) {
fallbackArgs[modelIndex + 1] = ROVODEV_MODELS.FALLBACK;
}
else {
// Model wasn't specified, add it after the subcommand
fallbackArgs.splice(1, 0, CLI.FLAGS.MODEL, ROVODEV_MODELS.FALLBACK);
}
try {
const fallbackResult = await executeCommand(CLI.COMMANDS.ROVODEV, fallbackArgs, {
onProgress,
timeout: 600000
});
if (onProgress) {
onProgress(STATUS_MESSAGES.COMPLETED);
}
return fallbackResult;
}
catch (fallbackError) {
const fallbackErrorMsg = fallbackError instanceof Error ?
fallbackError.message : String(fallbackError);
throw new Error(`Both primary and fallback models failed:\n` +
`Primary: ${errorMsg}\n` +
`Fallback: ${fallbackErrorMsg}`);
}
}
// Not a quota error or already tried fallback
if (onProgress) {
onProgress(STATUS_MESSAGES.FAILED);
}
throw error;
}
}
/**
* Execute a simple command (like echo or help)
*/
export async function executeSimpleCommand(command, args = []) {
logger.debug(`Executing simple command: ${command} ${args.join(" ")}`);
return executeCommand(command, args);
}
//# sourceMappingURL=rovodevExecutor.js.map