journal/Journal.AI/ServiceCollectionExtensions.cs
Jacob Schmidt 0d77300c22 feat: Project Journal backend monorepo
Monorepo with centralized build props, npm workspaces, LlamaSharp AI,
SQLite/SQLCipher storage, Svelte frontend, and unified smoke tests.

Co-Authored-By: Oz <oz-agent@warp.dev>
2026-03-02 20:56:26 -06:00

58 lines
2.1 KiB
C#

using Journal.Core.Services.Ai;
using Journal.Core.Services.Config;
using Microsoft.Extensions.DependencyInjection;
namespace Journal.AI;
public static class ServiceCollectionExtensions
{
/// <summary>
/// Registers LLamaSharp-based AI and Coach services.
/// Call this AFTER <c>AddFragmentServices()</c> so that <c>IJournalConfigService</c> is available.
/// When the provider is "llamasharp", this replaces the default <c>IAiService</c> registration.
/// </summary>
public static IServiceCollection AddLlamaSharpServices(this IServiceCollection services)
{
// Override IAiService — last registration wins in MS DI
services.AddSingleton<IAiService>(provider =>
{
var config = provider.GetRequiredService<IJournalConfigService>().Current;
if (string.Equals(config.AiProvider, "llamasharp", StringComparison.OrdinalIgnoreCase))
{
try
{
return new LlamaSharpAiService(config);
}
catch (Exception ex)
{
return new DisabledAiService(
provider: "llamasharp",
message: $"LLamaSharp unavailable: {ex.Message}",
healthy: false);
}
}
return new DisabledAiService(config.AiProvider);
});
// Register coach service
services.AddSingleton<ICoachService>(provider =>
{
var config = provider.GetRequiredService<IJournalConfigService>().Current;
var ai = provider.GetRequiredService<IAiService>();
if (ai is LlamaSharpAiService llamaAi)
return new LlamaSharpCoachService(llamaAi);
if (string.Equals(config.AiProvider, "none", StringComparison.OrdinalIgnoreCase))
return new DisabledCoachService();
return new DisabledCoachService(
$"Coach requires llamasharp provider (current: {config.AiProvider}).");
});
return services;
}
}