feat: success console app => api => gemini

This commit is contained in:
Stevan Freeborn
2025-03-15 18:44:10 -05:00
parent 414e712f51
commit 45a0ead7d8
9 changed files with 86 additions and 22 deletions
+1 -1
View File
@@ -24,7 +24,7 @@
<PropertyGroup>
<GeneratedCodeDirectory>Generated</GeneratedCodeDirectory>
<GeneratedConstantsFile>$(GeneratedCodeDirectory)\Constants.cs</GeneratedConstantsFile>
<AltGenApiUri>http://localhost:7297</AltGenApiUri>
<AltGenApiUri>https://localhost:7297</AltGenApiUri>
</PropertyGroup>
<Target Name="GenerateBuildConstants" BeforeTargets="BeforeBuild;BeforeRebuild">
@@ -9,6 +9,13 @@ static class HostBuilderExtensions
app.Configure(static c =>
{
c.SetExceptionHandler(static (ex, resolver) =>
{
var console = resolver?.Resolve(typeof(IAnsiConsole)) as IAnsiConsole;
console?.WriteException(ex, ExceptionFormats.ShortenEverything);
return -99;
});
c.AddBranch("config", static c =>
{
c.AddCommand<AddConfigCommand>("add");
+17
View File
@@ -0,0 +1,17 @@
using System.Globalization;
namespace AltGen.Console.Common;
static class Providers
{
const string Gemini = "gemini";
public static bool IsSupported(string provider)
{
return provider.ToLower(CultureInfo.InvariantCulture) switch
{
Gemini => true,
_ => false
};
}
}
@@ -21,6 +21,16 @@ sealed class AddConfigCommand(
[CommandOption("-d|--default")]
[Description("Set the provider as the default.")]
public bool Default { get; init; }
public override ValidationResult Validate()
{
if (Providers.IsSupported(Provider) is false)
{
return ValidationResult.Error($"The provider '{Provider}' is not supported.");
}
return ValidationResult.Success();
}
}
public override async Task<int> ExecuteAsync(CommandContext context, Settings settings)
+15
View File
@@ -44,4 +44,19 @@ record AppSettings
var updatedProviders = Providers.Where(p => p.Provider != settings.Provider);
return this with { Providers = [.. updatedProviders] };
}
public ProviderSettings[] GetProviders()
{
return Providers;
}
public ProviderSettings? GetProvider(string provider)
{
return Providers.FirstOrDefault(p => p.Provider == provider);
}
public ProviderSettings? GetDefaultProvider()
{
return Providers.FirstOrDefault(static p => p.Default);
}
}
@@ -19,7 +19,7 @@ sealed class ListConfigCommand(
var appSettings = await _settingsManager.GetAppSettingsAsync();
foreach (var provider in appSettings.Providers)
foreach (var provider in appSettings.GetProviders())
{
var providerName = provider.Provider;
var providerKey = provider.Key;
+2 -2
View File
@@ -19,7 +19,7 @@ sealed class AltGenService(HttpClient client) : IAltGenService
{
{ new StringContent(req.Provider), "provider" },
{ new StringContent(req.ProviderKey), "providerKey" },
{ new ByteArrayContent(req.Image), "file", req.FileName }
{ byteContent, "file", req.FileName }
}
};
@@ -41,4 +41,4 @@ record AltTextResponse(string AltText);
class AltTextException(string message) : Exception(message)
{
}
}
+32 -17
View File
@@ -3,13 +3,15 @@ namespace AltGen.Console.Generate;
sealed class GenerateCommand(
IAnsiConsole console,
IFileSystem fileSystem,
IAltGenService altGenService
IAltGenService altGenService,
IAppSettingsManager settingsManager
) : AsyncCommand<GenerateCommand.Settings>
{
readonly IAnsiConsole _console = console;
readonly IFileSystem _fileSystem = fileSystem;
readonly IAltGenService _altGenService = altGenService;
readonly IAppSettingsManager _settingsManager = settingsManager;
public class Settings(IFileSystem fileSystem) : CommandSettings
{
@@ -20,21 +22,17 @@ sealed class GenerateCommand(
[".png"] = "image/png"
};
readonly List<string> _providers = [
"gemini",
];
readonly IFileSystem _fileSystem = fileSystem;
[CommandArgument(1, "<provider>")]
[CommandOption("-p|--provider")]
[Description("The provider to use for generating alt text.")]
public string Provider { get; init; } = string.Empty;
[CommandArgument(2, "<key>")]
[CommandOption("-k|--key")]
[Description("The key for the provider.")]
public string Key { get; init; } = string.Empty;
[CommandArgument(3, "<path>")]
[CommandArgument(1, "<path>")]
[Description("The path to the image to generate alt text for.")]
public string Path { get; init; } = string.Empty;
@@ -42,13 +40,6 @@ sealed class GenerateCommand(
public override ValidationResult Validate()
{
// TODO: We should allow provider and key to be optional
// if they are not passed on the command line then
// we should try to resolve them from configuration
if (_providers.Contains(Provider) is false)
{
return ValidationResult.Error($"The provider '{Provider}' is not supported.");
}
var pathExists = _fileSystem.File.Exists(Path);
@@ -70,12 +61,36 @@ sealed class GenerateCommand(
public override async Task<int> ExecuteAsync(CommandContext context, Settings settings)
{
var appSettings = await _settingsManager.GetAppSettingsAsync();
var provider = settings.Provider;
var key = settings.Key;
if (string.IsNullOrWhiteSpace(provider))
{
var defaultProvider = appSettings.GetDefaultProvider()
?? throw new AltTextException("Please specify a provider or set a default provider.");
provider = defaultProvider.Provider;
}
if (Providers.IsSupported(provider) is false)
{
throw new AltTextException($"The provider '{provider}' is not supported.");
}
if (string.IsNullOrWhiteSpace(key))
{
var selectedProvider = appSettings.GetProvider(provider)
?? throw new AltTextException("Please specify a key or set a default provider.");
key = selectedProvider.Key;
}
var fileName = _fileSystem.Path.GetFileName(settings.Path);
var image = await _fileSystem.File.ReadAllBytesAsync(settings.Path);
var altText = await _altGenService.GenerateAltTextAsync(new(
settings.Provider,
settings.Key,
provider,
key,
fileName,
image,
settings.ContentType
+1 -1
View File
@@ -2,5 +2,5 @@ namespace AltGen.Console.Generated;
static class Constants
{
public const string AltGenApiUri = "http://localhost:7297";
public const string AltGenApiUri = "https://localhost:7297";
}