using AIStudio.Chat; namespace AIStudio.Tools.ChatArchive; /// /// Visits every file path stored inside a chat thread. Export and import use this to /// translate between absolute paths on this machine and archive-relative paths. /// public static class ChatArchiveAttachmentPaths { /// /// Replaces every file path of the given chat thread by the result of the rewrite function. /// Paths which the rewrite function returns unchanged stay untouched. /// /// The chat thread to process. It is modified in place. /// Maps an existing path to its replacement. public static void Rewrite(ChatThread chat, Func rewrite) { foreach (var block in chat.Blocks) { if (block.Content is not { } content) continue; RewriteAttachments(content.FileAttachments, rewrite); // Images might reference a file on this machine as well: if (content is ContentImage { SourceType: ContentImageSource.LOCAL_PATH } image && !string.IsNullOrWhiteSpace(image.Source)) image.Source = rewrite(image.Source); } // Transcripts which were prepared for the composer but not sent yet: for (var index = 0; index < chat.PendingMediaTranscripts.Count; index++) { var transcript = chat.PendingMediaTranscripts[index]; if (string.IsNullOrWhiteSpace(transcript.FilePath)) continue; chat.PendingMediaTranscripts[index] = transcript with { FilePath = rewrite(transcript.FilePath) }; } } private static void RewriteAttachments(List attachments, Func rewrite) { for (var index = 0; index < attachments.Count; index++) { var attachment = attachments[index]; if (string.IsNullOrWhiteSpace(attachment.FilePath)) continue; var rewrittenPath = rewrite(attachment.FilePath); if (rewrittenPath == attachment.FilePath) continue; attachments[index] = attachment switch { ManagedTranscriptAttachment managed => managed with { FilePath = rewrittenPath }, FileAttachmentImage image => image with { FilePath = rewrittenPath }, _ => attachment with { FilePath = rewrittenPath }, }; } } }