diff --git a/Directory.Build.props b/Directory.Build.props
index 4fa69d1..6843c07 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -2,6 +2,8 @@
LICENSE
+
+ true
diff --git a/src/Coven.Agents.OpenAI/OpenAIChunkBatchTransmuter.cs b/src/Coven.Agents.OpenAI/OpenAIChunkBatchTransmuter.cs
deleted file mode 100644
index 144f1d0..0000000
--- a/src/Coven.Agents.OpenAI/OpenAIChunkBatchTransmuter.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-// SPDX-License-Identifier: BUSL-1.1
-using System.Text;
-using Coven.Transmutation;
-
-namespace Coven.Agents.OpenAI;
-
-public sealed class OpenAIChunkBatchTransmuter : IBatchTransmuter
-{
- public Task> Transmute(IEnumerable Input, CancellationToken cancellationToken = default)
- {
- ArgumentNullException.ThrowIfNull(Input);
-
- string sender = string.Empty;
- string responseId = string.Empty;
- string model = string.Empty;
- DateTimeOffset timestamp = DateTimeOffset.MinValue;
- StringBuilder sb = new();
-
- foreach (OpenAIAfferentChunk chunk in Input)
- {
- cancellationToken.ThrowIfCancellationRequested();
- if (!string.IsNullOrEmpty(chunk.Sender))
- {
- sender = chunk.Sender;
- }
- if (!string.IsNullOrEmpty(chunk.ResponseId))
- {
- responseId = chunk.ResponseId;
- }
- if (!string.IsNullOrEmpty(chunk.Model))
- {
- model = chunk.Model;
- }
- if (chunk.Timestamp != default)
- {
- timestamp = chunk.Timestamp;
- }
- if (!string.IsNullOrEmpty(chunk.Text))
- {
- sb.Append(chunk.Text);
- }
- }
-
- OpenAIThought output = new(sender, sb.ToString(), responseId, timestamp, model);
- return Task.FromResult(new BatchTransmuteResult(output, false, null));
- }
-}
diff --git a/src/Coven.Agents.OpenAI/OpenAIClientConfig.cs b/src/Coven.Agents.OpenAI/OpenAIClientConfig.cs
index 5099dfe..81bfd6e 100644
--- a/src/Coven.Agents.OpenAI/OpenAIClientConfig.cs
+++ b/src/Coven.Agents.OpenAI/OpenAIClientConfig.cs
@@ -7,18 +7,48 @@ namespace Coven.Agents.OpenAI;
///
public sealed record OpenAIClientConfig
{
+ ///
+ /// API key used to authenticate with the OpenAI Responses API.
+ ///
public required string ApiKey { get; init; }
+
+ ///
+ /// The model identifier to use for responses (e.g., gpt-5-2025-08-07).
+ ///
public required string Model { get; init; }
+ ///
+ /// Optional organization id for the client.
+ ///
public string? Organization { get; init; }
+
+ ///
+ /// Optional project id for the client.
+ ///
public string? Project { get; init; }
+ ///
+ /// Temperature sampling setting (model-dependent).
+ ///
public float? Temperature { get; init; }
+
+ ///
+ /// Top-p nucleus sampling (model-dependent).
+ ///
public float? TopP { get; init; }
+
+ ///
+ /// Maximum number of output tokens to generate.
+ ///
public int? MaxOutputTokens { get; init; }
- // Max number of transcript items to include; default is unlimited
+
+ ///
+ /// Max number of transcript items to include; defaults to unlimited.
+ ///
public int HistoryClip { get; init; } = int.MaxValue;
- // Configures reasoning options for models that support it.
+ ///
+ /// Configures reasoning options for models that support it.
+ ///
public ReasoningConfig Reasoning { get; init; } = new ReasoningConfig();
}
diff --git a/src/Coven.Agents.OpenAI/OpenAIEntry.cs b/src/Coven.Agents.OpenAI/OpenAIEntry.cs
index 2ee2b10..0c2aa2b 100644
--- a/src/Coven.Agents.OpenAI/OpenAIEntry.cs
+++ b/src/Coven.Agents.OpenAI/OpenAIEntry.cs
@@ -2,15 +2,20 @@
namespace Coven.Agents.OpenAI;
+///
+/// Base entry type for OpenAI agent journals (requests, responses, thoughts, chunks, acknowledgements).
+///
public abstract record OpenAIEntry(
string Sender
);
+/// Outgoing request payload destined for OpenAI.
public sealed record OpenAIEfferent(
string Sender,
string Text
) : OpenAIEntry(Sender);
+/// Incoming response from OpenAI after completion.
public sealed record OpenAIAfferent(
string Sender,
string Text,
@@ -19,6 +24,7 @@ public sealed record OpenAIAfferent(
string Model
) : OpenAIEntry(Sender);
+/// Incoming response chunk (streaming) from OpenAI.
public sealed record OpenAIAfferentChunk(
string Sender,
string Text,
@@ -28,6 +34,7 @@ string Model
) : OpenAIEntry(Sender);
// Streaming thought chunks (afferent): model streams thoughts back
+/// Incoming thought chunk from OpenAI.
public sealed record OpenAIAfferentThoughtChunk(
string Sender,
string Text,
@@ -36,6 +43,7 @@ public sealed record OpenAIAfferentThoughtChunk(
string Model
) : OpenAIEntry(Sender);
+/// Full thought message from OpenAI (non-chunked).
public sealed record OpenAIThought(
string Sender,
string Text,
@@ -44,17 +52,20 @@ public sealed record OpenAIThought(
string Model
) : OpenAIEntry(Sender);
+/// OpenAI acknowledgement used for synchronization.
public sealed record OpenAIAck(
string Sender,
string Text
) : OpenAIEntry(Sender);
// Streaming thought chunks (efferent): agent streams thoughts out
+/// Outgoing thought chunk destined for OpenAI (not forwarded by gateway today).
public sealed record OpenAIEfferentThoughtChunk(
string Sender,
string Text
) : OpenAIEntry(Sender);
+/// Marks completion of a streaming response from OpenAI.
public sealed record OpenAIStreamCompleted(
string Sender,
string ResponseId,
diff --git a/src/Coven.Agents.OpenAI/OpenAIEntryToResponseItemTransmuter.cs b/src/Coven.Agents.OpenAI/OpenAIEntryToResponseItemTransmuter.cs
index 1b5262f..2913be3 100644
--- a/src/Coven.Agents.OpenAI/OpenAIEntryToResponseItemTransmuter.cs
+++ b/src/Coven.Agents.OpenAI/OpenAIEntryToResponseItemTransmuter.cs
@@ -9,7 +9,7 @@ namespace Coven.Agents.OpenAI;
/// Maps OpenAI journal entries to OpenAI SDK inputs.
/// Only user/assistant textual entries are emitted; others return null.
///
-public sealed class OpenAIEntryToResponseItemTransmuter : ITransmuter
+internal sealed class OpenAIEntryToResponseItemTransmuter : ITransmuter
{
public Task Transmute(OpenAIEntry Input, CancellationToken cancellationToken = default)
{
diff --git a/src/Coven.Agents.OpenAI/OpenAIMaxLengthWindowPolicy.cs b/src/Coven.Agents.OpenAI/OpenAIMaxLengthWindowPolicy.cs
index da05ea6..1c0f346 100644
--- a/src/Coven.Agents.OpenAI/OpenAIMaxLengthWindowPolicy.cs
+++ b/src/Coven.Agents.OpenAI/OpenAIMaxLengthWindowPolicy.cs
@@ -7,7 +7,7 @@ namespace Coven.Agents.OpenAI;
/// Emits when the recent OpenAI chunk(s) length reaches a max.
/// Minimal lookback of 1; intended as a safety cap in combination with semantic policies.
///
-public sealed class OpenAIMaxLengthWindowPolicy : IWindowPolicy
+internal sealed class OpenAIMaxLengthWindowPolicy : IWindowPolicy
{
private readonly int _max;
diff --git a/src/Coven.Agents.OpenAI/OpenAIParagraphShatterPolicy.cs b/src/Coven.Agents.OpenAI/OpenAIParagraphShatterPolicy.cs
index 6c254f7..acef0de 100644
--- a/src/Coven.Agents.OpenAI/OpenAIParagraphShatterPolicy.cs
+++ b/src/Coven.Agents.OpenAI/OpenAIParagraphShatterPolicy.cs
@@ -11,7 +11,7 @@ namespace Coven.Agents.OpenAI;
/// - Second: remainder of the original text
/// If no boundary exists, produces no outputs (forward unchanged).
///
-public sealed class OpenAIThoughtParagraphShatterPolicy : IShatterPolicy
+internal sealed class OpenAIThoughtParagraphShatterPolicy : IShatterPolicy
{
public IEnumerable Shatter(OpenAIEntry entry)
{
diff --git a/src/Coven.Agents.OpenAI/OpenAIParagraphWindowPolicy.cs b/src/Coven.Agents.OpenAI/OpenAIParagraphWindowPolicy.cs
index b9ad0cf..49fe273 100644
--- a/src/Coven.Agents.OpenAI/OpenAIParagraphWindowPolicy.cs
+++ b/src/Coven.Agents.OpenAI/OpenAIParagraphWindowPolicy.cs
@@ -9,7 +9,7 @@ namespace Coven.Agents.OpenAI;
/// A paragraph boundary is a double newline sequence ("\r\n\r\n" or "\n\n").
/// Uses a minimal lookback of 2 to account for boundaries that straddle chunk edges.
///
-public sealed class OpenAIParagraphWindowPolicy : IWindowPolicy
+internal sealed class OpenAIParagraphWindowPolicy : IWindowPolicy
{
public int MinChunkLookback => 2;
diff --git a/src/Coven.Agents.OpenAI/OpenAIRegistration.cs b/src/Coven.Agents.OpenAI/OpenAIRegistration.cs
index 0805639..7d5dcee 100644
--- a/src/Coven.Agents.OpenAI/OpenAIRegistration.cs
+++ b/src/Coven.Agents.OpenAI/OpenAIRegistration.cs
@@ -1,12 +1,18 @@
// SPDX-License-Identifier: BUSL-1.1
-using Coven.Agents;
namespace Coven.Agents.OpenAI;
+///
+/// Registration customization for the OpenAI integration.
+///
public sealed class OpenAIRegistration
{
internal bool StreamingEnabled { get; private set; }
+ ///
+ /// Enables streaming mode (streaming gateway + windowing daemons).
+ ///
+ /// The same registration for fluent chaining.
public OpenAIRegistration EnableStreaming()
{
StreamingEnabled = true;
diff --git a/src/Coven.Agents.OpenAI/OpenAITransmuter.cs b/src/Coven.Agents.OpenAI/OpenAITransmuter.cs
index eddb714..32ea26d 100644
--- a/src/Coven.Agents.OpenAI/OpenAITransmuter.cs
+++ b/src/Coven.Agents.OpenAI/OpenAITransmuter.cs
@@ -4,7 +4,7 @@
namespace Coven.Agents.OpenAI;
-public sealed class OpenAITransmuter : IBiDirectionalTransmuter
+internal sealed class OpenAITransmuter : IBiDirectionalTransmuter
{
public Task TransmuteAfferent(OpenAIEntry Input, CancellationToken cancellationToken)
{
diff --git a/src/Coven.Agents.OpenAI/ReasoningConfig.cs b/src/Coven.Agents.OpenAI/ReasoningConfig.cs
index 0d3d196..190a4a9 100644
--- a/src/Coven.Agents.OpenAI/ReasoningConfig.cs
+++ b/src/Coven.Agents.OpenAI/ReasoningConfig.cs
@@ -2,9 +2,18 @@
namespace Coven.Agents.OpenAI;
+///
+/// Reasoning configuration for models that support structured reasoning controls.
+///
public sealed class ReasoningConfig
{
- // When reasoning is provided, assume enabled and default required settings.
+ ///
+ /// Reasoning effort setting; defaults to .
+ ///
public ReasoningEffort Effort { get; init; } = ReasoningEffort.Medium;
+
+ ///
+ /// Controls verbosity of returned reasoning summaries.
+ ///
public ReasoningSummaryVerbosity SummaryVerbosity { get; init; } = ReasoningSummaryVerbosity.Auto;
}
diff --git a/src/Coven.Agents.OpenAI/ReasoningSummaryVerbosity.cs b/src/Coven.Agents.OpenAI/ReasoningSummaryVerbosity.cs
index 23631e8..ef780c2 100644
--- a/src/Coven.Agents.OpenAI/ReasoningSummaryVerbosity.cs
+++ b/src/Coven.Agents.OpenAI/ReasoningSummaryVerbosity.cs
@@ -2,10 +2,15 @@
namespace Coven.Agents.OpenAI;
+///
+/// Controls verbosity of model-provided reasoning summaries when available.
+///
public enum ReasoningSummaryVerbosity
{
+ /// Let the model decide verbosity.
Auto,
+ /// Prefer brief summaries.
Concise,
+ /// Prefer detailed summaries.
Detailed
}
-
diff --git a/src/Coven.Agents.OpenAI/ServiceCollectionExtensions.cs b/src/Coven.Agents.OpenAI/ServiceCollectionExtensions.cs
index c57c2c2..96f706c 100644
--- a/src/Coven.Agents.OpenAI/ServiceCollectionExtensions.cs
+++ b/src/Coven.Agents.OpenAI/ServiceCollectionExtensions.cs
@@ -12,11 +12,28 @@
namespace Coven.Agents.OpenAI;
+///
+/// Dependency Injection helpers for wiring the OpenAI agent integration.
+/// Registers journals, gateway connection, transmuters, windowing daemons, and the official OpenAI client.
+///
public static class ServiceCollectionExtensions
{
+ ///
+ /// Registers OpenAI agents with required defaults.
+ ///
+ /// The service collection.
+ /// OpenAI client configuration (API key and model are required).
+ /// The same service collection to enable fluent chaining.
public static IServiceCollection AddOpenAIAgents(this IServiceCollection services, OpenAIClientConfig config)
=> AddOpenAIAgents(services, config, null);
+ ///
+ /// Registers OpenAI agents with optional configuration of streaming/windowing behavior.
+ ///
+ /// The service collection.
+ /// OpenAI client configuration (API key and model are required).
+ /// Optional registration customization (e.g., enable streaming).
+ /// The same service collection to enable fluent chaining.
public static IServiceCollection AddOpenAIAgents(this IServiceCollection services, OpenAIClientConfig config, Action? configure)
{
ArgumentNullException.ThrowIfNull(services);
diff --git a/src/Coven.Agents/AgentAfferentBatchTransmuter.cs b/src/Coven.Agents/AgentAfferentBatchTransmuter.cs
index 7cb0c05..53f9b9d 100644
--- a/src/Coven.Agents/AgentAfferentBatchTransmuter.cs
+++ b/src/Coven.Agents/AgentAfferentBatchTransmuter.cs
@@ -4,8 +4,12 @@
namespace Coven.Agents;
+///
+/// Batches afferent agent chunks into a single .
+///
public sealed class AgentAfferentBatchTransmuter : IBatchTransmuter
{
+ ///
public Task> Transmute(IEnumerable Input, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(Input);
diff --git a/src/Coven.Agents/AgentAfferentThoughtBatchTransmuter.cs b/src/Coven.Agents/AgentAfferentThoughtBatchTransmuter.cs
index 5373314..95ae540 100644
--- a/src/Coven.Agents/AgentAfferentThoughtBatchTransmuter.cs
+++ b/src/Coven.Agents/AgentAfferentThoughtBatchTransmuter.cs
@@ -4,8 +4,12 @@
namespace Coven.Agents;
+///
+/// Batches afferent agent thought chunks into a single .
+///
public sealed class AgentAfferentThoughtBatchTransmuter : IBatchTransmuter
{
+ ///
public Task> Transmute(IEnumerable Input, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(Input);
diff --git a/src/Coven.Agents/AgentEfferentBatchTransmuter.cs b/src/Coven.Agents/AgentEfferentBatchTransmuter.cs
index 00cf9a0..0bcd21d 100644
--- a/src/Coven.Agents/AgentEfferentBatchTransmuter.cs
+++ b/src/Coven.Agents/AgentEfferentBatchTransmuter.cs
@@ -4,8 +4,12 @@
namespace Coven.Agents;
+///
+/// Batches efferent agent chunks into a single .
+///
public sealed class AgentEfferentBatchTransmuter : IBatchTransmuter
{
+ ///
public Task> Transmute(IEnumerable Input, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(Input);
diff --git a/src/Coven.Agents/AgentEntry.cs b/src/Coven.Agents/AgentEntry.cs
index 1a9d984..3cef59f 100644
--- a/src/Coven.Agents/AgentEntry.cs
+++ b/src/Coven.Agents/AgentEntry.cs
@@ -2,26 +2,39 @@
namespace Coven.Agents;
-// Minimal agent entry union used with IScrivener
+///
+/// Base entry type for agent journals (prompts, responses, thoughts, acks, and streaming chunks).
+///
public abstract record AgentEntry(string Sender);
-// Unfixed/draft entries that should never be forwarded by adapters directly
+///
+/// Marker base for draft entries that should not be forwarded out of the agent journal directly.
+///
public abstract record AgentEntryDraft(string Sender) : AgentEntry(Sender);
+/// Represents a user or upstream prompt destined for an agent.
public sealed record AgentPrompt(string Sender, string Text) : AgentEntry(Sender);
+/// Represents an agent's finalized response.
public sealed record AgentResponse(string Sender, string Text) : AgentEntry(Sender);
+/// Represents an agent's introspective thought (not typically user-visible).
public sealed record AgentThought(string Sender, string Text) : AgentEntry(Sender);
+/// Represents an acknowledgement for internal synchronization.
public sealed record AgentAck(string Sender) : AgentEntry(Sender);
// Streaming additions
+/// Outgoing (efferent) response chunk prior to finalization.
public sealed record AgentEfferentChunk(string Sender, string Text) : AgentEntryDraft(Sender);
+/// Incoming (afferent) response chunk prior to finalization.
public sealed record AgentAfferentChunk(string Sender, string Text) : AgentEntryDraft(Sender);
+/// Outgoing (efferent) thought chunk prior to finalization.
public sealed record AgentEfferentThoughtChunk(string Sender, string Text) : AgentEntryDraft(Sender);
+/// Incoming (afferent) thought chunk prior to finalization.
public sealed record AgentAfferentThoughtChunk(string Sender, string Text) : AgentEntryDraft(Sender);
+/// Marks completion of a streaming sequence.
public sealed record AgentStreamCompleted(string Sender) : AgentEntryDraft(Sender);
diff --git a/src/Coven.Chat.Console/ConsoleEntry.cs b/src/Coven.Chat.Console/ConsoleEntry.cs
index 7f8a9de..9df7f67 100644
--- a/src/Coven.Chat.Console/ConsoleEntry.cs
+++ b/src/Coven.Chat.Console/ConsoleEntry.cs
@@ -2,24 +2,28 @@
namespace Coven.Chat.Console;
-// Base entry for Console journal.
+///
+/// Base entry type for the Console chat journal.
+///
public abstract record ConsoleEntry(
string Sender,
string Text
);
+/// Acknowledgement entry for internal synchronization.
public sealed record ConsoleAck(
string Sender,
string Text
) : ConsoleEntry(Sender, Text);
+/// Incoming line read from stdin.
public sealed record ConsoleAfferent(
string Sender,
string Text
) : ConsoleEntry(Sender, Text);
+/// Outgoing line written to stdout.
public sealed record ConsoleEfferent(
string Sender,
string Text
) : ConsoleEntry(Sender, Text);
-
diff --git a/src/Coven.Chat.Console/ConsoleTransmuter.cs b/src/Coven.Chat.Console/ConsoleTransmuter.cs
index 2ad25b7..67b923f 100644
--- a/src/Coven.Chat.Console/ConsoleTransmuter.cs
+++ b/src/Coven.Chat.Console/ConsoleTransmuter.cs
@@ -2,7 +2,7 @@
namespace Coven.Chat.Console;
-public sealed class ConsoleTransmuter(ConsoleClientConfig config) : IBiDirectionalTransmuter
+internal sealed class ConsoleTransmuter(ConsoleClientConfig config) : IBiDirectionalTransmuter
{
private readonly ConsoleClientConfig _config = config ?? throw new ArgumentNullException(nameof(config));
diff --git a/src/Coven.Chat.Console/ServiceCollectionExtensions.cs b/src/Coven.Chat.Console/ServiceCollectionExtensions.cs
index e2e9525..02f2766 100644
--- a/src/Coven.Chat.Console/ServiceCollectionExtensions.cs
+++ b/src/Coven.Chat.Console/ServiceCollectionExtensions.cs
@@ -6,8 +6,18 @@
namespace Coven.Chat.Console;
+///
+/// Dependency Injection helpers for wiring the Console chat adapter.
+/// Registers gateway/session components, journals, the Console↔Chat transmuter, and the console daemon.
+///
public static class ServiceCollectionExtensions
{
+ ///
+ /// Adds Console chat integration using the provided client configuration.
+ ///
+ /// The service collection.
+ /// Console client configuration (input/output sender labels).
+ /// The same service collection to enable fluent chaining.
public static IServiceCollection AddConsoleChat(this IServiceCollection services, ConsoleClientConfig config)
{
ArgumentNullException.ThrowIfNull(services);
diff --git a/src/Coven.Chat.Discord/DiscordEntry.cs b/src/Coven.Chat.Discord/DiscordEntry.cs
index 8751115..d275e67 100644
--- a/src/Coven.Chat.Discord/DiscordEntry.cs
+++ b/src/Coven.Chat.Discord/DiscordEntry.cs
@@ -1,22 +1,27 @@
namespace Coven.Chat.Discord;
-// Base entry for Discord journal.
+///
+/// Base entry type for the Discord chat journal.
+///
public abstract record DiscordEntry(
string Sender,
string Text
);
+/// Acknowledgement entry for internal synchronization.
public sealed record DiscordAck(
string Sender,
string Text
) : DiscordEntry(Sender, Text);
+/// Incoming Discord message received from a channel or DM.
public sealed record DiscordAfferent(
string Sender,
string Text,
string MessageId,
DateTimeOffset Timestamp) : DiscordEntry(Sender, Text);
+/// Outgoing Discord message to be sent.
public sealed record DiscordEfferent(
string Sender,
string Text) : DiscordEntry(Sender, Text);
diff --git a/src/Coven.Chat.Discord/DiscordTransmuter.cs b/src/Coven.Chat.Discord/DiscordTransmuter.cs
index 61b7001..d8e509e 100644
--- a/src/Coven.Chat.Discord/DiscordTransmuter.cs
+++ b/src/Coven.Chat.Discord/DiscordTransmuter.cs
@@ -2,6 +2,10 @@
namespace Coven.Chat.Discord;
+///
+/// Maps between Discord-specific entries and generic Chat entries.
+/// Afferent: Discord → Chat; Efferent: Chat → Discord.
+///
public class DiscordTransmuter : IBiDirectionalTransmuter
{
public Task TransmuteAfferent(DiscordEntry Input, CancellationToken cancellationToken)
diff --git a/src/Coven.Chat.Discord/ServiceCollectionExtensions.cs b/src/Coven.Chat.Discord/ServiceCollectionExtensions.cs
index 99f9b5a..2bba83a 100644
--- a/src/Coven.Chat.Discord/ServiceCollectionExtensions.cs
+++ b/src/Coven.Chat.Discord/ServiceCollectionExtensions.cs
@@ -11,8 +11,18 @@
namespace Coven.Chat.Discord;
+///
+/// Dependency Injection helpers for wiring the Discord chat adapter.
+/// Registers the Discord client, session factory, journals, transmuter, daemon, and default windowing policies.
+///
public static class ServiceCollectionExtensions
{
+ ///
+ /// Adds Discord chat integration using the provided client configuration.
+ ///
+ /// The service collection.
+ /// Configuration including bot token and channel id.
+ /// The same service collection to enable fluent chaining.
public static IServiceCollection AddDiscordChat(this IServiceCollection services, DiscordClientConfig discordClientConfig)
{
ArgumentNullException.ThrowIfNull(services);
diff --git a/src/Coven.Chat/ChatChunkBatchTransmuter.cs b/src/Coven.Chat/ChatChunkBatchTransmuter.cs
index 6457ba0..8d58611 100644
--- a/src/Coven.Chat/ChatChunkBatchTransmuter.cs
+++ b/src/Coven.Chat/ChatChunkBatchTransmuter.cs
@@ -4,8 +4,12 @@
namespace Coven.Chat;
+///
+/// Batches chat chunks into a single message.
+///
public sealed class ChatChunkBatchTransmuter : IBatchTransmuter
{
+ ///
public Task> Transmute(IEnumerable Input, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(Input);
diff --git a/src/Coven.Chat/ChatEntry.cs b/src/Coven.Chat/ChatEntry.cs
index e5dc5e2..fb26494 100644
--- a/src/Coven.Chat/ChatEntry.cs
+++ b/src/Coven.Chat/ChatEntry.cs
@@ -2,23 +2,34 @@
namespace Coven.Chat;
-// Minimal chat entry union used with IScrivener
+///
+/// Base entry type for chat journals (incoming/outgoing messages, acks, and streaming drafts/chunks).
+///
public abstract record ChatEntry(string Sender);
-// Unfixed/draft entries that should never be forwarded by adapters directly
+///
+/// Marker base for draft entries that should not be forwarded by adapters directly.
+///
public abstract record ChatEntryDraft(string Sender) : ChatEntry(Sender);
+/// Outgoing chat message intended for users.
public sealed record ChatEfferent(string Sender, string Text) : ChatEntry(Sender);
+/// Incoming chat message from users or external sources.
public sealed record ChatAfferent(string Sender, string Text) : ChatEntry(Sender);
+/// Local acknowledgement to avoid feedback loops between journals.
public sealed record ChatAck(string Sender, string Text) : ChatEntry(Sender);
// Streaming additions
+/// Outgoing draft message prior to finalization.
public sealed record ChatEfferentDraft(string Sender, string Text) : ChatEntryDraft(Sender);
+/// Incoming draft message prior to finalization.
public sealed record ChatAfferentDraft(string Sender, string Text) : ChatEntryDraft(Sender);
+/// Chunk of chat text for windowing and batching.
public sealed record ChatChunk(string Sender, string Text) : ChatEntryDraft(Sender);
+/// Marks completion of a streaming sequence.
public sealed record ChatStreamCompleted(string Sender) : ChatEntryDraft(Sender);
diff --git a/src/Coven.Chat/ServiceCollectionExtensions.cs b/src/Coven.Chat/ServiceCollectionExtensions.cs
index 1e6ab0e..0db1070 100644
--- a/src/Coven.Chat/ServiceCollectionExtensions.cs
+++ b/src/Coven.Chat/ServiceCollectionExtensions.cs
@@ -7,8 +7,18 @@
namespace Coven.Chat;
+///
+/// Adds generic chat windowing infrastructure (journal, daemon) with a DI-provided window policy.
+/// Useful for chunking and emitting grouped as entries.
+///
public static class ServiceCollectionExtensions
{
+ ///
+ /// Registers chat windowing components and a windowing daemon for .
+ /// A custom can be supplied via DI; otherwise a final-only policy is used.
+ ///
+ /// The service collection.
+ /// The same service collection to enable fluent chaining.
public static IServiceCollection AddChatWindowing(this IServiceCollection services)
{
ArgumentNullException.ThrowIfNull(services);
diff --git a/src/Coven.Core.Streaming/IWindowPolicy.cs b/src/Coven.Core.Streaming/IWindowPolicy.cs
index a7fc5af..f71d72c 100644
--- a/src/Coven.Core.Streaming/IWindowPolicy.cs
+++ b/src/Coven.Core.Streaming/IWindowPolicy.cs
@@ -1,10 +1,21 @@
// SPDX-License-Identifier: BUSL-1.1
namespace Coven.Core.Streaming;
+///
+/// Determines when a buffered stream window should emit one or more outputs.
+///
+/// The chunk type being windowed.
public interface IWindowPolicy
{
+ ///
+ /// The minimum number of recent chunks required to evaluate .
+ ///
int MinChunkLookback { get; }
+ ///
+ /// Returns true when the current window should emit.
+ ///
+ /// The current stream window context.
+ /// true to emit; otherwise false.
bool ShouldEmit(StreamWindow window);
}
-
diff --git a/src/Coven.Core.Streaming/LambdaWindowPolicy.cs b/src/Coven.Core.Streaming/LambdaWindowPolicy.cs
index 31e8f48..584e9fd 100644
--- a/src/Coven.Core.Streaming/LambdaWindowPolicy.cs
+++ b/src/Coven.Core.Streaming/LambdaWindowPolicy.cs
@@ -1,11 +1,20 @@
// SPDX-License-Identifier: BUSL-1.1
namespace Coven.Core.Streaming;
+///
+/// Simple window policy backed by a delegate and a fixed minimum lookback.
+///
public sealed class LambdaWindowPolicy : IWindowPolicy
{
private readonly Func, bool> _shouldEmit;
+ ///
public int MinChunkLookback { get; }
+ ///
+ /// Creates a new policy.
+ ///
+ /// Minimum number of recent chunks to consider (at least 1).
+ /// Delegate that determines whether to emit for a given window.
public LambdaWindowPolicy(int minLookback, Func, bool> shouldEmit)
{
ArgumentOutOfRangeException.ThrowIfLessThan(minLookback, 1);
@@ -13,6 +22,6 @@ public LambdaWindowPolicy(int minLookback, Func, bool> shou
MinChunkLookback = minLookback;
}
+ ///
public bool ShouldEmit(StreamWindow window) => _shouldEmit(window);
}
-
diff --git a/src/Coven.Core.Streaming/StreamWindow.cs b/src/Coven.Core.Streaming/StreamWindow.cs
index faf19e0..0eb4892 100644
--- a/src/Coven.Core.Streaming/StreamWindow.cs
+++ b/src/Coven.Core.Streaming/StreamWindow.cs
@@ -1,10 +1,17 @@
// SPDX-License-Identifier: BUSL-1.1
namespace Coven.Core.Streaming;
+///
+/// Snapshot of the current streaming window passed to window policies.
+///
+/// Chunk type under consideration.
public readonly record struct StreamWindow(
- IEnumerable PendingChunks,
- int ChunkCount,
- DateTimeOffset StartedAt,
- DateTimeOffset LastEmitAt
+/// Recent chunks in the window (respecting MinChunkLookback semantics).
+IEnumerable PendingChunks,
+/// Total number of chunks observed in the current buffer.
+int ChunkCount,
+/// Timestamp when windowing started.
+DateTimeOffset StartedAt,
+/// Timestamp of the last emit.
+DateTimeOffset LastEmitAt
);
-
diff --git a/src/Coven.Core.Streaming/StreamWindowingDaemon.cs b/src/Coven.Core.Streaming/StreamWindowingDaemon.cs
index 69fa9cf..b243446 100644
--- a/src/Coven.Core.Streaming/StreamWindowingDaemon.cs
+++ b/src/Coven.Core.Streaming/StreamWindowingDaemon.cs
@@ -4,6 +4,13 @@
namespace Coven.Core.Streaming;
+///
+/// Generic daemon that windows a stream of journal entries, emitting outputs based on a policy.
+///
+/// Journal entry base type.
+/// Chunk entry type to window.
+/// Output entry type written when a window emits.
+/// Completion marker entry type that flushes buffers.
public sealed class StreamWindowingDaemon(
IScrivener daemonEvents,
IScrivener journal,
@@ -23,6 +30,9 @@ public sealed class StreamWindowingDaemon(
private CancellationTokenSource? _linkedCancellationSource;
private Task? _pumpTask;
+ ///
+ /// Starts the daemon and begins tailing the journal.
+ ///
public override async Task Start(CancellationToken cancellationToken)
{
_linkedCancellationSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
@@ -39,6 +49,9 @@ public override async Task Start(CancellationToken cancellationToken)
await Transition(Status.Running, cancellationToken).ConfigureAwait(false);
}
+ ///
+ /// Initiates cooperative shutdown and awaits the pump loop completion.
+ ///
public override async Task Shutdown(CancellationToken cancellationToken)
{
_linkedCancellationSource?.Cancel();
@@ -167,6 +180,9 @@ private async Task EmitBufferAsync(List buffer, CancellationToken cancel
}
}
+ ///
+ /// Ensures the daemon is shut down and disposes resources.
+ ///
public async ValueTask DisposeAsync()
{
try
diff --git a/src/Coven.Core/Board.cs b/src/Coven.Core/Board.cs
index 57a4376..e31cb23 100644
--- a/src/Coven.Core/Board.cs
+++ b/src/Coven.Core/Board.cs
@@ -11,6 +11,9 @@
namespace Coven.Core;
+///
+/// Orchestration board responsible for selecting and executing MagikBlocks.
+///
public class Board : IBoard
{
internal enum BoardMode
@@ -181,6 +184,7 @@ private static List BuildRegisteredBlocks(IReadOnlyList
public bool WorkSupported(List tags)
{
// Until pull mode and richer admission logic are implemented, assume supported.
@@ -188,6 +192,7 @@ public bool WorkSupported(List tags)
return true;
}
+ ///
public Task GetWork(GetWorkRequest request, IOrchestratorSink sink, CancellationToken cancellationToken = default)
{
if (_currentMode != BoardMode.Pull)
@@ -209,6 +214,7 @@ private async Task ExecutePullStepAsync(GetWorkRequest request, IOrche
await GetWorkPullAsync(request.Input!, branchId, request.Tags, sink, cancellationToken).ConfigureAwait(false);
}
+ ///
public async Task PostWork(T input, List? tags = null, CancellationToken cancellationToken = default)
{
Type startType = typeof(T);
diff --git a/src/Coven.Core/Builder/ServiceCollectionExtensions.cs b/src/Coven.Core/Builder/ServiceCollectionExtensions.cs
index c96ba0c..4cb4dd7 100644
--- a/src/Coven.Core/Builder/ServiceCollectionExtensions.cs
+++ b/src/Coven.Core/Builder/ServiceCollectionExtensions.cs
@@ -8,8 +8,17 @@
namespace Coven.Core.Builder;
+///
+/// DI entry points for composing and finalizing a Coven runtime.
+///
public static class ServiceCollectionExtensions
{
+ ///
+ /// Composes a Coven using the provided builder action and ensures finalization.
+ ///
+ /// The service collection.
+ /// Callback to register MagikBlocks and options.
+ /// The same service collection to enable fluent chaining.
public static IServiceCollection BuildCoven(this IServiceCollection services, Action build)
{
ArgumentNullException.ThrowIfNull(services);
@@ -36,6 +45,9 @@ public static IServiceCollection AddInMemoryScrivener(this IServiceColle
}
}
+///
+/// Fluent builder used to register MagikBlocks and finalize the Coven runtime.
+///
public sealed class CovenServiceBuilder
{
private readonly IServiceCollection _services;
@@ -47,6 +59,15 @@ internal CovenServiceBuilder(IServiceCollection services)
_services = services;
}
+ ///
+ /// Registers a MagikBlock type for the specified input/output pair.
+ ///
+ /// Input type.
+ /// Output type.
+ /// Concrete block implementing .
+ /// DI lifetime for the block type; transient by default.
+ /// Optional capability tags that influence selection.
+ /// The same builder for chaining.
public CovenServiceBuilder MagikBlock(ServiceLifetime lifetime = ServiceLifetime.Transient, IEnumerable? capabilities = null)
where TBlock : class, IMagikBlock
{
@@ -80,12 +101,25 @@ public CovenServiceBuilder MagikBlock(ServiceLifetime lifetim
return this;
}
+ ///
+ /// Overrides the default selection strategy used to choose blocks at runtime.
+ ///
+ /// The selection strategy.
+ /// The same builder for chaining.
public CovenServiceBuilder UseSelectionStrategy(ISelectionStrategy strategy)
{
_registry.SetSelectionStrategy(strategy);
return this;
}
+ ///
+ /// Registers an inline lambda-based MagikBlock for the specified input/output pair.
+ ///
+ /// Input type.
+ /// Output type.
+ /// Async function invoked to perform the work.
+ /// Optional capability tags that influence selection.
+ /// The same builder for chaining.
public CovenServiceBuilder LambdaBlock(Func> func, IEnumerable? capabilities = null)
{
ArgumentNullException.ThrowIfNull(func);
@@ -95,6 +129,12 @@ public CovenServiceBuilder LambdaBlock(Func
+ /// Finalizes the builder and registers the runtime services.
+ ///
+ /// When true, creates a pull-oriented board.
+ /// Optional configuration for pull mode.
+ /// The service collection used by the builder.
public IServiceCollection Done(bool pull = false, PullOptions? pullOptions = null)
{
if (finalized)
diff --git a/src/Coven.Core/Empty.cs b/src/Coven.Core/Empty.cs
index 381da90..5b9e86e 100644
--- a/src/Coven.Core/Empty.cs
+++ b/src/Coven.Core/Empty.cs
@@ -2,7 +2,9 @@
namespace Coven.Core;
-// Marker type representing absence of input for rituals
+///
+/// Marker type representing absence of input for rituals.
+///
public readonly struct Empty
{
}
diff --git a/src/Coven.Core/IBoard.cs b/src/Coven.Core/IBoard.cs
index 98a108e..0d1cd67 100644
--- a/src/Coven.Core/IBoard.cs
+++ b/src/Coven.Core/IBoard.cs
@@ -2,10 +2,36 @@
namespace Coven.Core;
+///
+/// Internal orchestration board that schedules and executes work across MagikBlocks.
+///
public interface IBoard
{
+ ///
+ /// Posts work to the board and awaits the resulting output.
+ ///
+ /// Input type.
+ /// Output type.
+ /// Input value.
+ /// Optional tags that influence selection.
+ /// A cancellation token.
+ /// The computed output.
Task PostWork(T input, List? tags = null, CancellationToken cancellationToken = default);
+ ///
+ /// Retrieves a unit of work for a worker and delivers results via the provided sink.
+ ///
+ /// Input type for the requested work.
+ /// Work request options.
+ /// Orchestrator callbacks for result delivery.
+ /// A cancellation token.
Task GetWork(GetWorkRequest request, IOrchestratorSink sink, CancellationToken cancellationToken = default);
+
+ ///
+ /// Returns true when a block exists that can handle the given input type and tags.
+ ///
+ /// Input type.
+ /// Candidate tag set.
+ /// true if work is supported; otherwise false.
bool WorkSupported(List tags);
}
diff --git a/src/Coven.Core/ICoven.cs b/src/Coven.Core/ICoven.cs
index fca55be..b005c4b 100644
--- a/src/Coven.Core/ICoven.cs
+++ b/src/Coven.Core/ICoven.cs
@@ -2,13 +2,37 @@
namespace Coven.Core;
+///
+/// Entry point for running rituals: orchestrated pipelines composed of MagikBlocks.
+///
public interface ICoven
{
- // Runs a ritual from T to TOutput with no initial tags
+ ///
+ /// Runs a ritual from to with no initial tags.
+ ///
+ /// Input value.
+ /// A cancellation token.
+ /// Input type.
+ /// Output type.
+ /// The ritual output.
Task Ritual(T input, CancellationToken cancellationToken = default);
- // Runs a ritual from T to TOutput seeding initial tags that influence routing
+ ///
+ /// Runs a ritual from to , seeding initial tags that influence routing.
+ ///
+ /// Input value.
+ /// Optional tag seed to steer selection.
+ /// A cancellation token.
+ /// Input type.
+ /// Output type.
+ /// The ritual output.
Task Ritual(T input, List? tags, CancellationToken cancellationToken = default);
+ ///
+ /// Runs a ritual from to .
+ ///
+ /// A cancellation token.
+ /// Output type.
+ /// The ritual output.
Task Ritual(CancellationToken cancellationToken = default);
}
diff --git a/src/Coven.Core/IMagikBlock.cs b/src/Coven.Core/IMagikBlock.cs
index 70747ff..af5ceb0 100644
--- a/src/Coven.Core/IMagikBlock.cs
+++ b/src/Coven.Core/IMagikBlock.cs
@@ -2,7 +2,17 @@
namespace Coven.Core;
+///
+/// Processing unit that transforms into .
+/// Implementations should be stateless or treat state as ephemeral per invocation.
+///
public interface IMagikBlock
{
+ ///
+ /// Performs the work of the block.
+ ///
+ /// Input value.
+ /// A cancellation token.
+ /// The output value.
Task DoMagik(T input, CancellationToken cancellationToken = default);
}
diff --git a/src/Coven.Core/IOrchestratorSink.cs b/src/Coven.Core/IOrchestratorSink.cs
index 4406c29..5184b9c 100644
--- a/src/Coven.Core/IOrchestratorSink.cs
+++ b/src/Coven.Core/IOrchestratorSink.cs
@@ -2,12 +2,18 @@
namespace Coven.Core;
-// Orchestrator-facing completion callbacks for Pull mode.
+///
+/// Orchestrator-facing completion callbacks for Pull mode.
+///
public interface IOrchestratorSink
{
- // Called when a single step completes; output type is preserved generically.
+ ///
+ /// Called when a single step completes; output type is preserved generically.
+ ///
void Complete(TOut output, string? branchId = null);
- // Called when the Board reaches the final output type for the current Ritual.
+ ///
+ /// Called when the Board reaches the final output type for the current ritual.
+ ///
void CompletedFinal(TFinal result);
}
diff --git a/src/Coven.Core/MagikBlock.cs b/src/Coven.Core/MagikBlock.cs
index aed88f5..cd1a1c8 100644
--- a/src/Coven.Core/MagikBlock.cs
+++ b/src/Coven.Core/MagikBlock.cs
@@ -2,9 +2,13 @@
namespace Coven.Core;
+///
+/// Adapter that turns a lambda into an .
+///
public class MagikBlock(Func> func) : IMagikBlock
{
+ ///
public async Task DoMagik(T input, CancellationToken cancellationToken = default)
{
return await func(input, cancellationToken);
diff --git a/src/Coven.Core/PullOptions.cs b/src/Coven.Core/PullOptions.cs
index 9681285..2cf5a96 100644
--- a/src/Coven.Core/PullOptions.cs
+++ b/src/Coven.Core/PullOptions.cs
@@ -2,16 +2,20 @@
namespace Coven.Core;
-// Options to tune Pull mode behavior.
+///
+/// Options to tune Pull-mode ritual completion behavior.
+///
public sealed class PullOptions
{
- // If provided, this delegate decides whether the ritual should complete
- // when a value (initial or step output) is assignable to the requested final type.
- // Returning true completes the ritual with that value; returning false continues stepping.
- // When null, default behavior is to complete immediately when assignable.
+ ///
+ /// Optional predicate deciding whether the ritual should complete when an assignable value is observed.
+ /// Returning true completes with that value; returning false continues stepping.
+ /// When null, completion occurs immediately upon first assignable value.
+ ///
public Func