feat: parallel async processing and compact output mode

Major performance improvements:
- Parallel search execution across all queries
- Parallel article fetching with 10 concurrent limit
- Parallel embeddings with rate limiting (4 concurrent)
- Polly integration for retry resilience

New features:
- Add -v/--verbose flag for detailed output
- Compact single-line status mode with braille spinner
- StatusReporter service for unified output handling
- Query generation and errors hidden in compact mode
- ANSI escape codes for clean line updates

New files:
- Services/RateLimiter.cs - Semaphore-based concurrency control
- Services/StatusReporter.cs - Verbose/compact output handler
- Models/ParallelOptions.cs - Parallel processing configuration

All changes maintain Native AOT compatibility.
This commit is contained in:
2026-03-18 22:16:28 +01:00
parent 9d4bec7a17
commit b28d8998f7
9 changed files with 579 additions and 109 deletions

View File

@@ -34,6 +34,11 @@ var longOption = new Option<bool>(
description: "Give a long elaborate detailed answer"
);
var verboseOption = new Option<bool>(
aliases: ["-v", "--verbose"],
description: "Show detailed progress information"
);
var questionArgument = new Argument<string[]>(
name: "question",
description: "The question to ask"
@@ -127,11 +132,12 @@ var rootCommand = new RootCommand("OpenQuery - AI powered search and answer")
queriesOption,
shortOption,
longOption,
verboseOption,
questionArgument,
configureCommand
};
rootCommand.SetHandler(async (chunks, results, queries, isShort, isLong, questionArgs) =>
rootCommand.SetHandler(async (chunks, results, queries, isShort, isLong, verbose, questionArgs) =>
{
var question = string.Join(" ", questionArgs);
if (string.IsNullOrWhiteSpace(question))
@@ -140,7 +146,7 @@ rootCommand.SetHandler(async (chunks, results, queries, isShort, isLong, questio
return;
}
var options = new OpenQueryOptions(chunks, results, queries, isShort, isLong, question);
var options = new OpenQueryOptions(chunks, results, queries, isShort, isLong, verbose, question);
var apiKey = Environment.GetEnvironmentVariable("OPENROUTER_API_KEY");
@@ -183,6 +189,6 @@ rootCommand.SetHandler(async (chunks, results, queries, isShort, isLong, questio
Console.Error.WriteLine($"\n[Error] An unexpected error occurred: {ex.Message}");
Environment.Exit(1);
}
}, chunksOption, resultsOption, queriesOption, shortOption, longOption, questionArgument);
}, chunksOption, resultsOption, queriesOption, shortOption, longOption, verboseOption, questionArgument);
return await rootCommand.InvokeAsync(args);