- Add Journal.AI project with LLamaSharp-based AI service (Phi-3 model) - Implement coach sessions (daily check-in, evening review, weekly review) - Add conversation CRUD with SQLCipher persistence - AI chat with full conversation history for context-aware replies - Frontend: CoachPanel, AI stores, conversation stores, side panel UI - Conversation list with create, rename, and delete support - Fix Phi-3 output quality (system prompt leaking, token cleanup, JSON filtering) - Fix CREATEDRAFT kind override in coach sessions Co-Authored-By: Oz <oz-agent@warp.dev>
69 lines
2.2 KiB
C#
69 lines
2.2 KiB
C#
using System.ComponentModel.DataAnnotations;
|
|
using Journal.Core.Dtos;
|
|
using Journal.Core.Models;
|
|
using Journal.Core.Repositories;
|
|
|
|
namespace Journal.Core.Services.Conversations;
|
|
|
|
public class ConversationService(IConversationRepository repo) : IConversationService
|
|
{
|
|
private readonly IConversationRepository _repo = repo ?? throw new ArgumentNullException(nameof(repo));
|
|
|
|
private static ConversationDto MapSummary(Conversation c) => new(c.Id, c.Title, c.CreatedAt, c.UpdatedAt);
|
|
|
|
private static ConversationMessageDto MapMessage(ConversationMessage m) => new(m.Id, m.Role, m.Text, m.CreatedAt);
|
|
|
|
public List<ConversationDto> GetAll()
|
|
{
|
|
var items = _repo.GetAll();
|
|
return [.. items.Select(MapSummary)];
|
|
}
|
|
|
|
public ConversationDetailDto? GetById(Guid id)
|
|
{
|
|
var c = _repo.GetById(id);
|
|
if (c is null) return null;
|
|
|
|
var messages = _repo.GetMessages(id);
|
|
return new ConversationDetailDto(
|
|
c.Id, c.Title,
|
|
[.. messages.Select(MapMessage)],
|
|
c.CreatedAt, c.UpdatedAt);
|
|
}
|
|
|
|
public ConversationDto Create(CreateConversationDto dto)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(dto);
|
|
var ctx = new ValidationContext(dto);
|
|
Validator.ValidateObject(dto, ctx, validateAllProperties: true);
|
|
|
|
var conversation = new Conversation(dto.Title);
|
|
_repo.Add(conversation);
|
|
return MapSummary(conversation);
|
|
}
|
|
|
|
public bool Update(Guid id, UpdateConversationDto dto)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(dto);
|
|
if (dto.Title is not null && string.IsNullOrWhiteSpace(dto.Title))
|
|
throw new ValidationException("Title cannot be empty");
|
|
|
|
return _repo.Update(id, dto.Title?.Trim());
|
|
}
|
|
|
|
public bool Remove(Guid id) => _repo.Remove(id);
|
|
|
|
public ConversationMessageDto AddMessage(Guid conversationId, string role, string text)
|
|
{
|
|
var message = new ConversationMessage(conversationId, role, text);
|
|
_repo.AddMessage(message);
|
|
return MapMessage(message);
|
|
}
|
|
|
|
public List<ConversationMessageDto> GetMessages(Guid conversationId)
|
|
{
|
|
var messages = _repo.GetMessages(conversationId);
|
|
return [.. messages.Select(MapMessage)];
|
|
}
|
|
}
|