2026-11-09 09:55:01 +01:00
using AIStudio.Chat ;
using AIStudio.Settings ;
namespace AIStudio.Assistants.BeyondFactsLab ;
/// <summary>
/// Creates the chats of the BeyondFacts Lab and readies them for a request.
/// </summary>
/// <remarks>
/// A chat of the lab has no profile, no chat template, and no data sources: its context is the prompt of the lab,
2026-11-10 18:17:44 +01:00
/// the guide, and the details of the preparation. The lab manages its tools itself: it names them for each request.
2026-11-09 09:55:01 +01:00
/// </remarks>
public static class BflThreadFactory
{
/// <summary>
2026-11-10 18:17:44 +01:00
/// Creates a chat which the person never sees and the lab never stores, e.g., for a research agent.
2026-11-09 09:55:01 +01:00
/// </summary>
2026-11-10 18:17:44 +01:00
/// <param name="name">The name of the chat, for the log.</param>
/// <returns>The chat, with an ID of its own and without any messages.</returns>
public static ChatThread CreateHidden ( string name ) => new ()
2026-11-09 09:55:01 +01:00
{
2026-11-10 18:17:44 +01:00
ChatId = Guid . NewGuid (),
2026-11-09 09:55:01 +01:00
WorkspaceId = Guid . Empty ,
2026-11-10 18:17:44 +01:00
Name = name ,
2026-11-09 09:55:01 +01:00
IncludeDateTime = true ,
SelectedProfile = Profile . NO_PROFILE . Id ,
SelectedChatTemplate = ChatTemplate . NO_CHAT_TEMPLATE . Id ,
SelectedToolIds = [],
Blocks = []
};
2026-11-10 18:17:44 +01:00
/// <summary>
/// Creates a chat of the lab, without any messages, restricted as its place demands, see BflChatTools.
/// </summary>
/// <param name="location">Where the chat belongs, e.g., to a step of a preparation.</param>
/// <returns>The chat.</returns>
public static ChatThread Create ( BflThreadLocation location )
{
var thread = new ChatThread
{
ChatId = location . ChatId ,
WorkspaceId = Guid . Empty ,
Name = location . ChatName ,
IncludeDateTime = true ,
SelectedProfile = Profile . NO_PROFILE . Id ,
SelectedChatTemplate = ChatTemplate . NO_CHAT_TEMPLATE . Id ,
SelectedToolIds = [],
Blocks = []
};
BflChatTools . Restrict ( thread , location );
return thread ;
}
2026-11-09 09:55:01 +01:00
/// <summary>
/// Readies a chat for the next request: its prompt and provider, and what a chat does not store.
/// </summary>
/// <remarks>
/// The system prompt is put together anew for every request, so a changed detail or form of address counts from
/// the next answer on.
/// </remarks>
/// <param name="thread">The chat.</param>
/// <param name="provider">The provider which answers.</param>
2026-11-09 12:42:59 +01:00
/// <param name="systemPrompt">The system prompt of the chat, see BflPromptComposer.</param>
2026-11-10 18:17:44 +01:00
/// <param name="toolIds">The tools the model may use in this request; none when left out. The request still leaves out every tool which may not run, see ToolRegistry.GetRunnableToolsAsync.</param>
public static void PrepareForRequest ( ChatThread thread , AIStudio . Settings . Provider provider , string systemPrompt , IEnumerable < string >? toolIds = null )
2026-11-09 09:55:01 +01:00
{
thread . SystemPrompt = systemPrompt ;
thread . SelectedProvider = provider . Id ;
thread . SelectedProfile = Profile . NO_PROFILE . Id ;
thread . SelectedChatTemplate = ChatTemplate . NO_CHAT_TEMPLATE . Id ;
thread . DataSourceOptions . DisableDataSources = true ;
thread . RuntimeComponent = Tools . Components . BEYOND_FACTS_LAB_ASSISTANT ;
thread . RuntimeAssistantName = string . Empty ;
2026-11-10 18:17:44 +01:00
thread . RuntimeSelectedToolIds = [.. toolIds ?? []];
2026-11-09 09:55:01 +01:00
thread . RuntimeToolsAreAssistantManaged = true ;
}
}