namespace AIStudio.Tools.ChatArchive;
///
/// Finds the files AI Studio keeps inside a chat directory itself, such as transcripts.
///
///
/// Documents the user attaches are never copied into a chat directory: they stay where the
/// user put them and the chat only stores their path. Everything below a chat directory was
/// therefore written by AI Studio, which makes the directory contents a reliable definition
/// of "the app's own files" — minus the two files the chat storage owns itself.
///
public static class ChatArchiveChatFiles
{
///
/// Collects the app-owned files of one chat.
///
/// The directory of the chat.
/// The absolute paths of the files, keyed by their chat-relative path.
public static Dictionary Collect(string chatDirectory)
{
var files = new Dictionary(PathTools.COMPARER);
if (!Directory.Exists(chatDirectory))
return files;
foreach (var filePath in Directory.EnumerateFiles(chatDirectory, "*", SearchOption.AllDirectories))
{
// Skip the temporary files the chat storage writes while saving a chat:
var fileName = Path.GetFileName(filePath);
if (fileName.StartsWith('.') && fileName.EndsWith(".tmp", StringComparison.OrdinalIgnoreCase))
continue;
var chatRelativePath = Path.GetRelativePath(chatDirectory, filePath).Replace(Path.DirectorySeparatorChar, ChatArchiveFormat.ENTRY_SEPARATOR);
// The chat itself is always exported and is not one of its own attachments:
if (chatRelativePath.Equals(ChatArchiveFormat.THREAD_FILE_NAME, StringComparison.OrdinalIgnoreCase) ||
chatRelativePath.Equals(ChatArchiveFormat.NAME_FILE_NAME, StringComparison.OrdinalIgnoreCase))
continue;
files[chatRelativePath] = filePath;
}
return files;
}
///
/// Determines whether at least one of the given chats owns a file.
///
///
/// This stops at the first file found, so that asking the question stays cheap even for
/// a large chat storage.
///
/// The directories of the chats to check.
/// Cancels the search.
/// Whether any app-owned file exists.
public static bool HasAny(IEnumerable chatDirectories, CancellationToken token)
{
foreach (var chatDirectory in chatDirectories)
{
token.ThrowIfCancellationRequested();
if (Collect(chatDirectory).Count > 0)
return true;
}
return false;
}
}