diff --git a/CHANGELOG.md b/CHANGELOG.md index 72580408..7bade68a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,14 @@ Nightly builds of `master` are on [GitHub Packages](README.md#nightly-builds-github-packages) as `0.9.0-nightly.{yyyyMMdd}.g{shortSha}`. +### 🐛 Fixes + +- **IntelliSense reaches implementing members and restores declared halves.** Properties that + implement a documented interface member (durable envelopes' `Seq` and `Version`, the MCP + timeouts and `Codemode`, inbox and compaction `Created` times) show that member's documentation, + and 26 summaries that preview.12 dropped as partly implementation-only return with the part + upstream declares. SDK types and runtime behavior are unchanged. + ## [0.9.0-preview.12] - 2026-10-17 **Streams and automatic traversals take per-call options, and the public surface sheds its last diff --git a/docs/architecture/protocol-and-generation.md b/docs/architecture/protocol-and-generation.md index ee13c4a5..98801000 100644 --- a/docs/architecture/protocol-and-generation.md +++ b/docs/architecture/protocol-and-generation.md @@ -162,7 +162,9 @@ Curation may: `sources` list (each a `packages/path:line` location and a verbatim excerpt) that the curation validator requires and a Tools test proves against the pinned upstream tree, and facts inferred only from implementation are reported upstream instead and never change protocol semantics - (ADR-0013); + (ADR-0013). A curated interface member's documentation reaches each implementing public property + without its own row through ``; different curated documentation from two owners + for such a property refuses generation; - place a model in a slice where its name carries no family prefix, through a reason-bearing `modelOwners` row; a family's prefixes are its name, its singular, its group key and the group's `prefixAliases`, and a model with no prefix and no row fails generation. A diff --git a/src/OpenCode.Sdk/Experimental/ExperimentalSessionStatsRequest.cs b/src/OpenCode.Sdk/Experimental/ExperimentalSessionStatsRequest.cs index bdbaff79..3c5290dd 100644 --- a/src/OpenCode.Sdk/Experimental/ExperimentalSessionStatsRequest.cs +++ b/src/OpenCode.Sdk/Experimental/ExperimentalSessionStatsRequest.cs @@ -10,11 +10,11 @@ namespace OpenCode.Sdk; public sealed record ExperimentalSessionStatsRequest { /// - /// Gets the 'from' query value; the server default applies when unset. + /// The start of the aggregated time range. /// public long? From { get; init; } /// - /// Gets the 'to' query value; the server default applies when unset. + /// The end of the aggregated time range. /// public long? To { get; init; } /// diff --git a/src/OpenCode.Sdk/McpServers/Models/IMcp.cs b/src/OpenCode.Sdk/McpServers/Models/IMcp.cs index 08a7a2e6..655092ea 100644 --- a/src/OpenCode.Sdk/McpServers/Models/IMcp.cs +++ b/src/OpenCode.Sdk/McpServers/Models/IMcp.cs @@ -26,8 +26,11 @@ public interface IMcp public bool? Disabled { get; } /// - /// Gets the codemode value. Every declared variant carries it; the value is null when the payload is an unrecognized variant preserved as UnknownMcp. + /// Expose this server's tools through Code Mode. Defaults to true. /// + /// + /// Every declared variant carries it; an unrecognized variant preserved as UnknownMcp returns null through this interface. An ordinary optional property may also be absent. + /// [JsonPropertyName("codemode")] public bool? Codemode { get; } diff --git a/src/OpenCode.Sdk/McpServers/Models/IMcpTimeout.cs b/src/OpenCode.Sdk/McpServers/Models/IMcpTimeout.cs index 27c64e2f..45a86c13 100644 --- a/src/OpenCode.Sdk/McpServers/Models/IMcpTimeout.cs +++ b/src/OpenCode.Sdk/McpServers/Models/IMcpTimeout.cs @@ -12,19 +12,19 @@ namespace OpenCode.Sdk.Models; public interface IMcpTimeout { /// - /// Gets the startup value. + /// Maximum time in milliseconds to establish and initialize the MCP server. /// [JsonPropertyName("startup")] public long? Startup { get; } /// - /// Gets the catalog value. + /// Maximum time in milliseconds to wait for MCP discovery requests such as tools/list and prompts/list. /// [JsonPropertyName("catalog")] public long? Catalog { get; } /// - /// Gets the execution value. + /// Maximum time in milliseconds to wait for MCP tool and prompt execution. /// [JsonPropertyName("execution")] public long? Execution { get; } diff --git a/src/OpenCode.Sdk/McpServers/Models/McpLocalConfig.cs b/src/OpenCode.Sdk/McpServers/Models/McpLocalConfig.cs index f4f5ec73..5e346d16 100644 --- a/src/OpenCode.Sdk/McpServers/Models/McpLocalConfig.cs +++ b/src/OpenCode.Sdk/McpServers/Models/McpLocalConfig.cs @@ -42,9 +42,7 @@ public sealed record McpLocalConfig : IMcp [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public bool? Disabled { get; init; } - /// - /// Gets the codemode value. - /// + /// [JsonPropertyName("codemode")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public bool? Codemode { get; init; } diff --git a/src/OpenCode.Sdk/McpServers/Models/McpLocalConfigTimeout.cs b/src/OpenCode.Sdk/McpServers/Models/McpLocalConfigTimeout.cs index d00c29fc..9830dfe1 100644 --- a/src/OpenCode.Sdk/McpServers/Models/McpLocalConfigTimeout.cs +++ b/src/OpenCode.Sdk/McpServers/Models/McpLocalConfigTimeout.cs @@ -8,23 +8,17 @@ namespace OpenCode.Sdk.Models; /// public sealed record McpLocalConfigTimeout : IMcpTimeout { - /// - /// Gets the startup value. - /// + /// [JsonPropertyName("startup")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public long? Startup { get; init; } - /// - /// Gets the catalog value. - /// + /// [JsonPropertyName("catalog")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public long? Catalog { get; init; } - /// - /// Gets the execution value. - /// + /// [JsonPropertyName("execution")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public long? Execution { get; init; } diff --git a/src/OpenCode.Sdk/McpServers/Models/McpRemoteConfig.cs b/src/OpenCode.Sdk/McpServers/Models/McpRemoteConfig.cs index 5511d2cd..a9b977ca 100644 --- a/src/OpenCode.Sdk/McpServers/Models/McpRemoteConfig.cs +++ b/src/OpenCode.Sdk/McpServers/Models/McpRemoteConfig.cs @@ -42,9 +42,7 @@ public sealed record McpRemoteConfig : IMcp [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public bool? Disabled { get; init; } - /// - /// Gets the codemode value. - /// + /// [JsonPropertyName("codemode")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public bool? Codemode { get; init; } diff --git a/src/OpenCode.Sdk/McpServers/Models/McpRemoteConfigTimeout.cs b/src/OpenCode.Sdk/McpServers/Models/McpRemoteConfigTimeout.cs index d16ebfe7..a9600629 100644 --- a/src/OpenCode.Sdk/McpServers/Models/McpRemoteConfigTimeout.cs +++ b/src/OpenCode.Sdk/McpServers/Models/McpRemoteConfigTimeout.cs @@ -8,23 +8,17 @@ namespace OpenCode.Sdk.Models; /// public sealed record McpRemoteConfigTimeout : IMcpTimeout { - /// - /// Gets the startup value. - /// + /// [JsonPropertyName("startup")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public long? Startup { get; init; } - /// - /// Gets the catalog value. - /// + /// [JsonPropertyName("catalog")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public long? Catalog { get; init; } - /// - /// Gets the execution value. - /// + /// [JsonPropertyName("execution")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public long? Execution { get; init; } diff --git a/src/OpenCode.Sdk/Sessions/Models/Compaction/SessionCompactionEndedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Compaction/SessionCompactionEndedDurable.cs index 68af1a03..b7fef42f 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Compaction/SessionCompactionEndedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Compaction/SessionCompactionEndedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionCompactionEndedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Compaction/SessionCompactionFailedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Compaction/SessionCompactionFailedDurable.cs index 4d5112a4..309bf9b3 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Compaction/SessionCompactionFailedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Compaction/SessionCompactionFailedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionCompactionFailedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Compaction/SessionCompactionStartedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Compaction/SessionCompactionStartedDurable.cs index 875c4370..5b7aff65 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Compaction/SessionCompactionStartedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Compaction/SessionCompactionStartedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionCompactionStartedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionFailed.cs b/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionFailed.cs index de67dd2b..916b9a3f 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionFailed.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionFailed.cs @@ -5,7 +5,7 @@ namespace OpenCode.Sdk.Models; /// -/// The 'session.execution.failed' event. +/// Reports an execution failure with its error in Data.Error. /// public sealed record SessionExecutionFailed : ISessionEventDurable, IEvent, ISessionScopedEvent { diff --git a/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionFailedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionFailedDurable.cs index c3c9f7f9..a772aed6 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionFailedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionFailedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionExecutionFailedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionInterrupted.cs b/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionInterrupted.cs index 0eb7d4e7..9d215424 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionInterrupted.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionInterrupted.cs @@ -5,7 +5,7 @@ namespace OpenCode.Sdk.Models; /// -/// The 'session.execution.interrupted' event. +/// Reports interrupted execution; the pinned Data.Reason values are user, shutdown, superseded and inactivity. /// public sealed record SessionExecutionInterrupted : ISessionEventDurable, IEvent, ISessionScopedEvent { diff --git a/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionInterruptedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionInterruptedDurable.cs index 75442f75..f51ff176 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionInterruptedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionInterruptedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionExecutionInterruptedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionStartedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionStartedDurable.cs index d2636bbe..6139e92f 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionStartedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionStartedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionExecutionStartedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionSucceededDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionSucceededDurable.cs index 39410a69..9cdd3f9b 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionSucceededDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Execution/SessionExecutionSucceededDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionExecutionSucceededDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/IDurableEnvelope.cs b/src/OpenCode.Sdk/Sessions/Models/IDurableEnvelope.cs index 30ef3a3f..b6360682 100644 --- a/src/OpenCode.Sdk/Sessions/Models/IDurableEnvelope.cs +++ b/src/OpenCode.Sdk/Sessions/Models/IDurableEnvelope.cs @@ -18,13 +18,13 @@ public interface IDurableEnvelope public string AggregateId { get; } /// - /// Gets the seq value. + /// Position in one aggregate's durable log. Use only values from durable envelopes or synced markers as after cursors. /// [JsonPropertyName("seq")] public long Seq { get; } /// - /// Gets the version value. + /// Durable schema version of this event type, from the event definition that committed it. /// [JsonPropertyName("version")] public double Version { get; } diff --git a/src/OpenCode.Sdk/Sessions/Models/Inbox/ISessionInboxInfoTime.cs b/src/OpenCode.Sdk/Sessions/Models/Inbox/ISessionInboxInfoTime.cs index 0c9a955c..55977c17 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Inbox/ISessionInboxInfoTime.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Inbox/ISessionInboxInfoTime.cs @@ -12,7 +12,7 @@ namespace OpenCode.Sdk.Models; public interface ISessionInboxInfoTime { /// - /// Gets the created value. + /// Enqueue time in milliseconds since the Unix epoch. /// [JsonPropertyName("created")] public double Created { get; } diff --git a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxCancelledDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxCancelledDurable.cs index 3a7ee25d..95f8b3f2 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxCancelledDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxCancelledDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionInboxCancelledDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxCompactionTime.cs b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxCompactionTime.cs index 85f09381..94cff6e4 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxCompactionTime.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxCompactionTime.cs @@ -8,9 +8,7 @@ namespace OpenCode.Sdk.Models; /// public sealed record SessionInboxCompactionTime : ISessionInboxInfoTime { - /// - /// Gets the created value. - /// + /// [JsonPropertyName("created")] public required double Created { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxDeliveredDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxDeliveredDurable.cs index 5286f8e1..ae0bea80 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxDeliveredDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxDeliveredDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionInboxDeliveredDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxDeliveryChangedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxDeliveryChangedDurable.cs index 82620763..3681e9c8 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxDeliveryChangedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxDeliveryChangedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionInboxDeliveryChangedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxEnqueuedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxEnqueuedDurable.cs index 5e900e51..f4f36c07 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxEnqueuedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxEnqueuedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionInboxEnqueuedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxMoveTime.cs b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxMoveTime.cs index d9aac4e6..0bd18615 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxMoveTime.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxMoveTime.cs @@ -8,9 +8,7 @@ namespace OpenCode.Sdk.Models; /// public sealed record SessionInboxMoveTime : ISessionInboxInfoTime { - /// - /// Gets the created value. - /// + /// [JsonPropertyName("created")] public required double Created { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxSyntheticTime.cs b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxSyntheticTime.cs index 218bce7b..ae7115fb 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxSyntheticTime.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxSyntheticTime.cs @@ -8,9 +8,7 @@ namespace OpenCode.Sdk.Models; /// public sealed record SessionInboxSyntheticTime : ISessionInboxInfoTime { - /// - /// Gets the created value. - /// + /// [JsonPropertyName("created")] public required double Created { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxUserTime.cs b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxUserTime.cs index 4af7dd49..4a2ca797 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxUserTime.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Inbox/SessionInboxUserTime.cs @@ -8,9 +8,7 @@ namespace OpenCode.Sdk.Models; /// public sealed record SessionInboxUserTime : ISessionInboxInfoTime { - /// - /// Gets the created value. - /// + /// [JsonPropertyName("created")] public required double Created { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionAgentSelectedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionAgentSelectedDurable.cs index 610c4982..d32ff7ac 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionAgentSelectedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionAgentSelectedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionAgentSelectedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionCreatedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionCreatedDurable.cs index 9ab268f1..d739185f 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionCreatedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionCreatedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionCreatedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionDeletedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionDeletedDurable.cs index 6d084ee3..b4c3d4c3 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionDeletedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionDeletedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionDeletedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionForkedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionForkedDurable.cs index 4d956307..d5d5566f 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionForkedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionForkedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionForkedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionInstructionsUpdatedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionInstructionsUpdatedDurable.cs index c9205a69..3a32775d 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionInstructionsUpdatedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionInstructionsUpdatedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionInstructionsUpdatedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionMetadataUpdatedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionMetadataUpdatedDurable.cs index 611a4adc..09f71a2e 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionMetadataUpdatedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionMetadataUpdatedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionMetadataUpdatedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionModelSelectedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionModelSelectedDurable.cs index 214c4b4b..f7f96ce9 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionModelSelectedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionModelSelectedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionModelSelectedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionMovedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionMovedDurable.cs index a892114d..9ab2702b 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionMovedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionMovedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionMovedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionPermissionsDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionPermissionsDurable.cs index 23b49c35..fffe8717 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionPermissionsDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionPermissionsDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionPermissionsDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionRenamedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionRenamedDurable.cs index 614bc8b0..7566a63d 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionRenamedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionRenamedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionRenamedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionSkillActivatedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionSkillActivatedDurable.cs index d53c2320..e7cb5af7 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionSkillActivatedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionSkillActivatedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionSkillActivatedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionSyntheticDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionSyntheticDurable.cs index e04ae91c..970ac4b1 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionSyntheticDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionSyntheticDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionSyntheticDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionViewedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionViewedDurable.cs index 0a25963a..15ba4bcb 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionViewedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Lifecycle/SessionViewedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionViewedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Messages/ISessionMessageCompactionTime.cs b/src/OpenCode.Sdk/Sessions/Models/Messages/ISessionMessageCompactionTime.cs index caa1f5bc..548c6381 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Messages/ISessionMessageCompactionTime.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Messages/ISessionMessageCompactionTime.cs @@ -12,7 +12,7 @@ namespace OpenCode.Sdk.Models; public interface ISessionMessageCompactionTime { /// - /// Gets the created value. + /// Creation time in milliseconds since the Unix epoch. /// [JsonPropertyName("created")] public double Created { get; } diff --git a/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageAssistant.cs b/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageAssistant.cs index 056c3e89..40b88b6c 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageAssistant.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageAssistant.cs @@ -5,7 +5,7 @@ namespace OpenCode.Sdk.Models; /// -/// Represents a session message assistant value. +/// An assistant message with text, reasoning or tool-call output parts. /// public sealed record SessionMessageAssistant : ISessionMessageInfo { @@ -47,7 +47,7 @@ public sealed record SessionMessageAssistant : ISessionMessageInfo public required ModelRef Model { get; init; } /// - /// Gets the content value. + /// Assistant output parts: text, reasoning and tool calls. /// [JsonPropertyName("content")] public required IReadOnlyList Content { get; init; } @@ -60,7 +60,7 @@ public sealed record SessionMessageAssistant : ISessionMessageInfo public SessionMessageAssistantSnapshot? Snapshot { get; init; } /// - /// Gets the finish value. + /// The finish reason; the pinned values are stop, length, tool-calls, content-filter, error and unknown. /// [JsonPropertyName("finish")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -81,14 +81,14 @@ public sealed record SessionMessageAssistant : ISessionMessageInfo public IReadOnlyDictionary? ProviderState { get; init; } /// - /// Gets the cost value. + /// Cost in US dollars recorded on the assistant message. /// [JsonPropertyName("cost")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public double? Cost { get; init; } /// - /// Gets the tokens value. + /// Token usage with input, output, reasoning and cache read/write parts. /// [JsonPropertyName("tokens")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -102,7 +102,7 @@ public sealed record SessionMessageAssistant : ISessionMessageInfo public SessionStructuredError? Error { get; init; } /// - /// Gets the retry value. + /// Retry information containing an attempt number, time and error. /// [JsonPropertyName("retry")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] diff --git a/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageCompactionCompletedTime.cs b/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageCompactionCompletedTime.cs index 0ed9c9ea..e981212d 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageCompactionCompletedTime.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageCompactionCompletedTime.cs @@ -8,9 +8,7 @@ namespace OpenCode.Sdk.Models; /// public sealed record SessionMessageCompactionCompletedTime : ISessionMessageCompactionTime { - /// - /// Gets the created value. - /// + /// [JsonPropertyName("created")] public required double Created { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageCompactionFailedTime.cs b/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageCompactionFailedTime.cs index 0de086d1..94dd8fc0 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageCompactionFailedTime.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageCompactionFailedTime.cs @@ -8,9 +8,7 @@ namespace OpenCode.Sdk.Models; /// public sealed record SessionMessageCompactionFailedTime : ISessionMessageCompactionTime { - /// - /// Gets the created value. - /// + /// [JsonPropertyName("created")] public required double Created { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageCompactionRunningTime.cs b/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageCompactionRunningTime.cs index b8dd6704..45ca8c09 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageCompactionRunningTime.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageCompactionRunningTime.cs @@ -8,9 +8,7 @@ namespace OpenCode.Sdk.Models; /// public sealed record SessionMessageCompactionRunningTime : ISessionMessageCompactionTime { - /// - /// Gets the created value. - /// + /// [JsonPropertyName("created")] public required double Created { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageContentUpdatedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageContentUpdatedDurable.cs index 5d877c91..85f8b9da 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageContentUpdatedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Messages/SessionMessageContentUpdatedDurable.cs @@ -15,15 +15,11 @@ public sealed record SessionMessageContentUpdatedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Revert/SessionRevertClearedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Revert/SessionRevertClearedDurable.cs index e9530f70..4fdfc000 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Revert/SessionRevertClearedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Revert/SessionRevertClearedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionRevertClearedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Revert/SessionRevertCommittedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Revert/SessionRevertCommittedDurable.cs index b3bb89e7..b2440a8d 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Revert/SessionRevertCommittedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Revert/SessionRevertCommittedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionRevertCommittedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Revert/SessionRevertStagedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Revert/SessionRevertStagedDurable.cs index a0834dcb..b23548f3 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Revert/SessionRevertStagedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Revert/SessionRevertStagedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionRevertStagedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Shell/SessionShellEndedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Shell/SessionShellEndedDurable.cs index 68932582..0d2dde3f 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Shell/SessionShellEndedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Shell/SessionShellEndedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionShellEndedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Shell/SessionShellStartedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Shell/SessionShellStartedDurable.cs index 0c1a1882..7d631b35 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Shell/SessionShellStartedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Shell/SessionShellStartedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionShellStartedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Status/SessionRetryScheduledDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Status/SessionRetryScheduledDurable.cs index 04993e76..3e393876 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Status/SessionRetryScheduledDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Status/SessionRetryScheduledDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionRetryScheduledDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionReasoningEndedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionReasoningEndedDurable.cs index 959c0ae4..4ec38f2a 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionReasoningEndedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionReasoningEndedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionReasoningEndedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionReasoningStartedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionReasoningStartedDurable.cs index bc194fac..c53da836 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionReasoningStartedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionReasoningStartedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionReasoningStartedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepEndedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepEndedDurable.cs index ca1fe2dc..3899155d 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepEndedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepEndedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionStepEndedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepFailedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepFailedDurable.cs index 29dfe934..9c5befd2 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepFailedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepFailedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionStepFailedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepStartedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepStartedDurable.cs index c111acd0..02048bf3 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepStartedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepStartedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionStepStartedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepStreamedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepStreamedDurable.cs index f9a419d5..5a613900 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepStreamedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionStepStreamedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionStepStreamedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextDeltaData.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextDeltaData.cs index 8ff585aa..c2215c18 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextDeltaData.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextDeltaData.cs @@ -21,13 +21,13 @@ public sealed record SessionTextDeltaData public required string AssistantMessageId { get; init; } /// - /// Gets the ordinal value. + /// A non-negative ordinal for this text part. /// [JsonPropertyName("ordinal")] public required long Ordinal { get; init; } /// - /// Gets the delta value. + /// A live-only text fragment. /// [JsonPropertyName("delta")] public required string Delta { get; init; } diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextEndedData.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextEndedData.cs index 9c99d31f..e3e202c8 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextEndedData.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextEndedData.cs @@ -28,13 +28,13 @@ public sealed record SessionTextEndedData public required long Ordinal { get; init; } /// - /// Gets the text value. + /// The complete text of the part at the replayable full-value boundary. /// [JsonPropertyName("text")] public required string Text { get; init; } /// - /// Gets the state value. + /// Opaque provider state for the text part. /// [JsonPropertyName("state")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextEndedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextEndedDurable.cs index cf578aa1..51095eab 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextEndedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextEndedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionTextEndedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextStartedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextStartedDurable.cs index 2f7f6ad4..87b06bf0 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextStartedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionTextStartedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionTextStartedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolCalledDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolCalledDurable.cs index 594378e2..e09ae4a3 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolCalledDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolCalledDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionToolCalledDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolFailedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolFailedDurable.cs index 972296a8..5509dce8 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolFailedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolFailedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionToolFailedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolInputEndedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolInputEndedDurable.cs index 4cc83a29..c1733944 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolInputEndedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolInputEndedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionToolInputEndedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolInputStartedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolInputStartedDurable.cs index d0941847..171b5e86 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolInputStartedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolInputStartedDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionToolInputStartedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolSuccessDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolSuccessDurable.cs index dec3c6cf..98c549af 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolSuccessDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionToolSuccessDurable.cs @@ -14,15 +14,11 @@ public sealed record SessionToolSuccessDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionUsageRecordedDurable.cs b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionUsageRecordedDurable.cs index e350418b..6e5a1182 100644 --- a/src/OpenCode.Sdk/Sessions/Models/Turn/SessionUsageRecordedDurable.cs +++ b/src/OpenCode.Sdk/Sessions/Models/Turn/SessionUsageRecordedDurable.cs @@ -15,15 +15,11 @@ public sealed record SessionUsageRecordedDurable : IDurableEnvelope [JsonPropertyName("aggregateID")] public required string AggregateId { get; init; } - /// - /// Gets the seq value. - /// + /// [JsonPropertyName("seq")] public required long Seq { get; init; } - /// - /// Gets the version value. - /// + /// [JsonPropertyName("version")] public required double Version { get; init; } } diff --git a/src/OpenCode.Sdk/Sessions/SessionCreateRequest.cs b/src/OpenCode.Sdk/Sessions/SessionCreateRequest.cs index b9499c82..3b979635 100644 --- a/src/OpenCode.Sdk/Sessions/SessionCreateRequest.cs +++ b/src/OpenCode.Sdk/Sessions/SessionCreateRequest.cs @@ -6,12 +6,12 @@ namespace OpenCode.Sdk.Models; /// -/// The body of 'session.create' (POST /api/session). +/// A request to create a session at the requested location; ParentId links a child at its parent's location. /// public sealed record SessionCreateRequest { /// - /// Gets the id value. + /// An optional session identifier starting with ses. /// [JsonPropertyName("id")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] @@ -19,7 +19,7 @@ public sealed record SessionCreateRequest public Optional Id { get; init; } /// - /// Gets the parent id value. + /// Links a child session to its parent at the parent's location. /// [JsonPropertyName("parentID")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] @@ -43,7 +43,7 @@ public sealed record SessionCreateRequest public Optional Agent { get; init; } /// - /// Gets the model value. + /// A model reference identifying the provider, model and optional variant. /// [JsonPropertyName("model")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] @@ -51,7 +51,7 @@ public sealed record SessionCreateRequest public Optional Model { get; init; } /// - /// Gets the location value. + /// The requested location for a session; ParentId places a child at its parent's location. /// [JsonPropertyName("location")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] @@ -67,7 +67,7 @@ public sealed record SessionCreateRequest public Optional?> Metadata { get; init; } /// - /// Gets the permissions value. + /// When at least one rule matches, the last matching rule wins; session rules are evaluated after the agent's rules. /// [JsonPropertyName("permissions")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] diff --git a/src/OpenCode.Sdk/Sessions/SessionPromptRequest.cs b/src/OpenCode.Sdk/Sessions/SessionPromptRequest.cs index c28cda14..e96a19b0 100644 --- a/src/OpenCode.Sdk/Sessions/SessionPromptRequest.cs +++ b/src/OpenCode.Sdk/Sessions/SessionPromptRequest.cs @@ -6,12 +6,12 @@ namespace OpenCode.Sdk.Models; /// -/// The body of 'session.prompt' (POST /api/session/{sessionID}/prompt). +/// A session input durably admitted to the inbox, scheduling agent-loop execution unless Resume is false. /// public sealed record SessionPromptRequest { /// - /// Gets the id value. + /// An optional message identifier starting with msg_. /// [JsonPropertyName("id")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] @@ -25,7 +25,7 @@ public sealed record SessionPromptRequest public required string Text { get; init; } /// - /// Gets the files value. + /// File attachments, each referencing a file by its Uri member. /// [JsonPropertyName("files")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -39,7 +39,7 @@ public sealed record SessionPromptRequest public IReadOnlyList? Agents { get; init; } /// - /// Gets the skills value. + /// Skills to attach by identifier. /// [JsonPropertyName("skills")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -53,7 +53,7 @@ public sealed record SessionPromptRequest public IReadOnlyDictionary? Metadata { get; init; } /// - /// Gets the delivery value. + /// The input delivery mode; the pinned values are steer and queue. /// [JsonPropertyName("delivery")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] @@ -61,7 +61,7 @@ public sealed record SessionPromptRequest public Optional Delivery { get; init; } /// - /// Gets the resume value. + /// Controls scheduling of agent-loop execution after durable admission: false omits that scheduling. /// [JsonPropertyName("resume")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] diff --git a/tests/OpenCode.Sdk.Tools.Tests/Generator/Binding/DescriptionCurationBinderTests.cs b/tests/OpenCode.Sdk.Tools.Tests/Generator/Binding/DescriptionCurationBinderTests.cs index 769212d3..7fcb3153 100644 --- a/tests/OpenCode.Sdk.Tools.Tests/Generator/Binding/DescriptionCurationBinderTests.cs +++ b/tests/OpenCode.Sdk.Tools.Tests/Generator/Binding/DescriptionCurationBinderTests.cs @@ -6,6 +6,7 @@ using OpenCode.Sdk.Tools.Generator.Emission; using OpenCode.Sdk.Tools.Serialization; using OpenCode.Sdk.Tools.Tests.Generator.Binding.Support; +using OpenCode.Sdk.Tools.Tests.Generator.Emission.Support; using OpenCode.Sdk.Tools.Tests.Support; using Testably.Abstractions.Testing; using TUnit.Assertions.Enums; @@ -16,6 +17,69 @@ namespace OpenCode.Sdk.Tools.Tests.Generator.Binding; [ClassDataSource(Shared = SharedType.PerTestSession)] public sealed class DescriptionCurationBinderTests(PinnedBinding pinned) { + [Test] + public async Task Apply_Should_Emit_A_Direct_Row_Without_Resolving_Conflicting_Owners() + { + var plan = EmitterPlanFixture.CreateHoistPlan(); + var carrier = plan.HoistedInterfaces.Single(); + var model = plan.Models.OfType().Single(static model => model.Name == "CreatedEventDurable"); + plan = plan with + { + HoistedInterfaces = [carrier, carrier with { Name = "IAOwner" }], + Models = [model with { ImplementedHoistedInterfaceNames = [carrier.Name, "IAOwner"] }], + }; + var errors = new BindingErrorCollector(); + + var bound = DescriptionCurationBinder.Apply(plan, + [ + Description("IDurableEnvelope", "Seq", "The first owner summary."), + Description("IAOwner", "Seq", "The other owner summary."), + Description("CreatedEventDurable", "Seq", "The direct summary.", "The direct remarks."), + ], errors); + + await Assert.That(errors.Snapshot()).IsEquivalentTo(Array.Empty(), CollectionOrdering.Matching); + var source = Unindented(Source(bound, "CreatedEventDurable")); + await Assert.That(source).Contains("/// \n/// The direct summary.\n/// \n/// \n/// The direct remarks.\n/// "); + await Assert.That(source).DoesNotContain(" model is ObjectModelPlan concrete && concrete.ImplementedHoistedInterfaceNames.Count > 0 + ? concrete with { ImplementedHoistedInterfaceNames = [carrier.Name, "IAOwner"] } : model)], + }; + var errors = new BindingErrorCollector(); + var rows = new[] + { + Description("IDurableEnvelope", "Seq", "The owner summary.", "The owner remarks."), + Description("IAOwner", "Seq", difference == "summary" ? "Another summary." : "The owner summary.", + difference == "remarks" ? "Other remarks." : "The owner remarks."), + }; + + var bound = DescriptionCurationBinder.Apply(plan, rows, errors); + + string[] subjects = + [ + "CreatedEventDurable.Seq", "DeletedEventDurable.Seq", "PhaseEndedEventDurable.Seq", "PhaseStartedEventDurable.Seq", + ]; + BindingError[] expected = difference == "identical" ? [] : [.. subjects.Select(static subject => new BindingError(BindingErrorCategory.Curation, subject, + "description has conflicting curated owners: IAOwner.Seq, IDurableEnvelope.Seq"))]; + await Assert.That(errors.Snapshot()).IsEquivalentTo(expected, CollectionOrdering.Matching); + if (difference == "identical") + { + await Assert.That(Source(bound, "CreatedEventDurable")).Contains("/// "); + } + } + [Test] [Arguments("location", false, "location must be a packages/-relative path with a positive line")] [Arguments("excerpt", false, "excerpt must be non-empty")] @@ -267,4 +331,42 @@ public async Task Emit_Should_Keep_The_Consume_Only_Remark_On_A_Curated_Hoisted_ private static string Source(EmitPlan plan, string type) => Encoding.UTF8.GetString(ModelEmitter.Emit(plan) .Single(source => source.RelativePath.EndsWith("/" + type + ".cs", StringComparison.Ordinal)).Utf8Source.Span); + /// + /// The union emitter adds "an ordinary optional property may also be absent" to every curated + /// hoisted member, because HoistedMemberPlan carries no requiredness (#453). Until it does, no such + /// member may be required in any variant at the pin. + /// + [Test] + public async Task Pinned_Plan_Should_Keep_Every_Remarked_Hoisted_Member_Optional_In_Every_Variant() + { + await Assert.That(RequiredRemarkedHoistedMembers(pinned.Plan)).IsEmpty(); + } + + /// The guard above fails when a remarked member's source becomes required in one variant. + [Test] + public async Task RequiredRemarkedHoistedMembers_Should_Name_A_Member_Required_In_One_Variant() + { + var plan = pinned.Plan; + var union = plan.Unions.Single(static union => union.Name == "IMcp"); + var variant = plan.Models.OfType().Single(model => model.Name == union.Variants[0].TypeName); + var required = variant with + { + Properties = [.. variant.Properties.Select(static property => property.WireName == "codemode" ? property with { IsRequired = true } : property)], + }; + plan = plan with { Models = [.. plan.Models.Select(model => ReferenceEquals(model, variant) ? required : model)] }; + + await Assert.That(RequiredRemarkedHoistedMembers(plan)).IsEquivalentTo(["IMcp.Codemode"], CollectionOrdering.Matching); + } + + private static List RequiredRemarkedHoistedMembers(EmitPlan plan) + { + var models = plan.Models.OfType().ToDictionary(static model => model.Name, StringComparer.Ordinal); + return [.. plan.Unions + .SelectMany(static union => union.HoistedMembers + .Where(member => union.Documentation.Members.ContainsKey(member.Name)) + .Select(member => (union, member))) + .Where(pair => pair.union.Variants.Any(variant => models.TryGetValue(variant.TypeName, out var model) + && model.Properties.Any(property => property.WireName == pair.member.WireName && property.IsRequired))) + .Select(static pair => pair.union.Name + "." + pair.member.Name)]; + } } diff --git a/tests/OpenCode.Sdk.Tools.Tests/Generator/Emission/GeneratedDocumentationTests.cs b/tests/OpenCode.Sdk.Tools.Tests/Generator/Emission/GeneratedDocumentationTests.cs index 507bbb7d..c41c4b01 100644 --- a/tests/OpenCode.Sdk.Tools.Tests/Generator/Emission/GeneratedDocumentationTests.cs +++ b/tests/OpenCode.Sdk.Tools.Tests/Generator/Emission/GeneratedDocumentationTests.cs @@ -12,6 +12,50 @@ namespace OpenCode.Sdk.Tools.Tests.Generator.Emission; public sealed class GeneratedDocumentationTests { + [Test] + [Arguments("P:Owner.Member", false)] + [Arguments("P:Missing.Member", true)] + [Arguments("P:Implementer.Member", true)] + public async Task EffectiveSummary_Should_Resolve_Inheritance_Or_Refuse_Unresolved_And_Cyclic_Targets(string target, bool refuses) + { + var docs = new Dictionary(StringComparer.Ordinal) + { + ["P:Implementer.Member"] = new("member", new XElement("inheritdoc", new XAttribute("cref", target))), + ["P:Owner.Member"] = new("member", new XElement("inheritdoc", new XAttribute("cref", "P:Root.Member"))), + ["P:Root.Member"] = new("member", new XElement("summary", "The effective owner summary.")), + }; + if (refuses) + { + var exception = await Assert.That(() => EffectiveSummary("P:Implementer.Member", docs)).Throws(); + await Assert.That(exception!.Message).IsEqualTo("Unresolved or cyclic documentation target: " + target); + } + else + { + await Assert.That(EffectiveSummary("P:Implementer.Member", docs)?.Value).IsEqualTo("The effective owner summary."); + } + } + + private static XElement? EffectiveSummary(string id, Dictionary docs) + { + var visited = new HashSet(StringComparer.Ordinal); + while (visited.Add(id) && docs.TryGetValue(id, out var doc)) + { + if (doc.Element("summary") is { } summary) + { + return summary; + } + + if ((string?)doc.Element("inheritdoc")?.Attribute("cref") is not { } target) + { + return null; + } + + id = target; + } + + throw new InvalidOperationException("Unresolved or cyclic documentation target: " + id); + } + [Test] [ParallelLimiter] public async Task Summaries_Should_Keep_Shrink_Only_Placeholder_Ceilings_And_Reject_Grammar_Defects() @@ -54,8 +98,8 @@ public async Task Summaries_Should_Keep_Shrink_Only_Placeholder_Ceilings_And_Rej var helperFed = summaries.Where(pair => placeholders.Any(pattern => Matches(pair.Value, pattern)) || Matches(pair.Value, @"^(?:Preserves an unknown [a-z0-9 ]+ payload\.$|The [a-z0-9 ]+\. The pinned server's values are the static properties;)")).ToArray(); using var assertions = Assert.Multiple(); - await Assert.That(100m * historical / summaries.Count).IsLessThanOrEqualTo(44.702440m); - await Assert.That(100m * broad / summaries.Count).IsLessThanOrEqualTo(61.073171m); + await Assert.That(100m * historical / summaries.Count).IsLessThanOrEqualTo(42.243903m); + await Assert.That(100m * broad / summaries.Count).IsLessThanOrEqualTo(58.575610m); foreach (var defect in defects) { var offenders = helperFed.Where(pair => Matches(pair.Value, defect)).ToArray(); @@ -78,6 +122,15 @@ private static async Task> LoadSummariesAsyn await fileSystem.File.ReadAllTextAsync(fileSystem.Path.Combine(root, path), CancellationToken.None), path: path))); var compilation = CSharpCompilation.Create("GeneratedDocumentation", trees); + var roots = await Task.WhenAll(trees.Select(static tree => tree.GetRootAsync())); + var docs = roots.SelectMany(static root => root.DescendantNodes().Where(static node => node is MemberDeclarationSyntax or VariableDeclaratorSyntax)) + .Select(node => compilation.GetSemanticModel(node.SyntaxTree).GetDeclaredSymbol(node)) + .OfType().Where(static symbol => symbol is not INamespaceSymbol && IsPublic(symbol)) + .ToDictionary(static symbol => symbol.GetDocumentationCommentId() ?? throw new InvalidOperationException("Missing documentation ID: " + symbol), static symbol => + { + var xml = symbol.GetDocumentationCommentXml(); + return string.IsNullOrWhiteSpace(xml) ? new XElement("member") : XElement.Parse(xml); + }, StringComparer.Ordinal); var summaries = new Dictionary(StringComparer.Ordinal); var missing = new List(); foreach (var tree in trees) @@ -93,8 +146,7 @@ private static async Task> LoadSummariesAsyn } var key = string.Create(CultureInfo.InvariantCulture, $"{tree.FilePath}:{declaration.GetLocation().GetLineSpan().StartLinePosition.Line + 1}: {symbol}"); - var xml = symbol.GetDocumentationCommentXml(); - var summary = string.IsNullOrWhiteSpace(xml) ? null : XElement.Parse(xml).Element("summary"); + var summary = EffectiveSummary(symbol.GetDocumentationCommentId() ?? throw new InvalidOperationException("Missing documentation ID: " + symbol), docs); foreach (var see in summary?.Descendants("see").ToArray() ?? []) { var cref = (string?)see.Attribute("cref"); diff --git a/tests/OpenCode.Sdk.Tools.Tests/Generator/Emission/HoistedMemberEmissionTests.cs b/tests/OpenCode.Sdk.Tools.Tests/Generator/Emission/HoistedMemberEmissionTests.cs index 023fa731..21e92421 100644 --- a/tests/OpenCode.Sdk.Tools.Tests/Generator/Emission/HoistedMemberEmissionTests.cs +++ b/tests/OpenCode.Sdk.Tools.Tests/Generator/Emission/HoistedMemberEmissionTests.cs @@ -1,6 +1,9 @@ +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; using OpenCode.Sdk.Tools.Generator.Binding.Models; using OpenCode.Sdk.Tools.Generator.Emission; using OpenCode.Sdk.Tools.Tests.Generator.Emission.Support; +using TUnit.Assertions.Enums; using static OpenCode.Sdk.Tools.Tests.Support.BindingScenarioData; using static OpenCode.Sdk.Tools.Tests.Support.UnionHoistPlanData; @@ -8,6 +11,68 @@ namespace OpenCode.Sdk.Tools.Tests.Generator.Emission; public sealed class HoistedMemberEmissionTests { + [Test] + [Arguments(false)] + [Arguments(true)] + public async Task Emit_Should_Inherit_Only_Curated_Public_Members_Unless_Directly_Documented(bool direct) + { + var plan = EmitterPlanFixture.CreateHoistPlan(); + var text = new DocumentationPlan("A & value.", "Owner remarks."); + plan = plan with + { + HoistedInterfaces = [.. plan.HoistedInterfaces.Select(carrier => carrier with + { + Documentation = new() { Members = new Dictionary(StringComparer.Ordinal) { ["Seq"] = text } }, + })], + Unions = [.. plan.Unions.Select(union => union with + { + Documentation = new() { Members = new Dictionary(StringComparer.Ordinal) + { + [union.Name == "IExampleEvent" ? "Created" : "Phase"] = text, + } }, + })], + Models = [.. plan.Models.Select(model => model is ObjectModelPlan { Name: "CreatedEvent" } concrete ? concrete with + { + Properties = [.. concrete.Properties.Select(property => property.Name == "Created" ? property with { Name = "Born" } : property)], + ExplicitHoistedImplementations = [.. concrete.ExplicitHoistedImplementations.Select(bridge => + bridge.MemberName == "Created" ? bridge with { PropertyName = "Born" } : bridge)], + } : model).Select(model => model.Name == "CreatedEventDurable" && direct ? model with + { + Documentation = new() { Members = new Dictionary(StringComparer.Ordinal) { ["Seq"] = new("Direct summary.", null) } }, + } : model)], + }; + var sources = SourceEmitter.Emit(plan); + var roots = await Task.WhenAll(sources.Select(source => CSharpSyntaxTree.ParseText(System.Text.Encoding.UTF8.GetString(source.Utf8Source.Span)).GetRootAsync())); + var inherited = roots.SelectMany(root => root.DescendantNodes().OfType() + .Where(static property => property.GetLeadingTrivia().ToFullString().Contains(" ((TypeDeclarationSyntax)property.Parent!).Identifier.ValueText + "." + property.Identifier.ValueText + + ": " + property.GetLeadingTrivia().ToFullString().Trim())) + .Order(StringComparer.Ordinal).ToArray(); + string[] expected = + [ + "CreatedEvent.Born: /// ", + "DeletedEvent.Created: /// ", + "DeletedEventDurable.Seq: /// ", + "PhaseEndedEvent.Created: /// ", + "PhaseEndedEvent.Phase: /// ", + "PhaseEndedEventDurable.Seq: /// ", + "PhaseStartedEvent.Created: /// ", + "PhaseStartedEvent.Phase: /// ", + "PhaseStartedEventDurable.Seq: /// ", + ]; + if (!direct) + { + expected = [expected[0], "CreatedEventDurable.Seq: /// ", .. expected[1..]]; + } + + await Assert.That(inherited).IsEquivalentTo(expected, CollectionOrdering.Matching); + await Assert.That(EmitterSnapshot.Content(sources, "Example/Models/IExampleEvent.cs")).Contains("A <curated> & value."); + await Assert.That(EmitterSnapshot.Content(sources, "Example/Models/IExampleEvent.cs")) + .Contains("Owner remarks. Every declared variant carries it; an unrecognized variant preserved as UnknownExampleEvent returns null through this interface. An ordinary optional property may also be absent."); + await Assert.That(EmitterSnapshot.Content(sources, "Example/Models/CreatedEventDurable.cs")) + .Contains(direct ? "/// Direct summary." : "/// "); + } + [Test] public async Task Emit_Should_Render_The_Carrier_Fallback_And_Value_Grammatically() { diff --git a/tools/OpenCode.Sdk.Tools/Generator/Binding/DescriptionCurationBinder.cs b/tools/OpenCode.Sdk.Tools/Generator/Binding/DescriptionCurationBinder.cs index 48969e40..77d125af 100644 --- a/tools/OpenCode.Sdk.Tools/Generator/Binding/DescriptionCurationBinder.cs +++ b/tools/OpenCode.Sdk.Tools/Generator/Binding/DescriptionCurationBinder.cs @@ -31,7 +31,7 @@ public static EmitPlan Apply(EmitPlan plan, IReadOnlyList r var byType = rows.GroupBy(static row => row.Type, StringComparer.Ordinal) .ToDictionary(static group => group.Key, static group => group.ToArray(), StringComparer.Ordinal); - return plan with + var bound = plan with { Models = [.. plan.Models.Select(model => BindModel(model, byType))], Unions = [.. plan.Unions.Select(union => union with @@ -59,6 +59,61 @@ public static EmitPlan Apply(EmitPlan plan, IReadOnlyList r })], })], }; + _ = InheritedMemberOwners(bound, bound.Unions.ToDictionary(static union => union.Name, StringComparer.Ordinal), errors); + + return bound; + } + + public static IReadOnlyDictionary> InheritedMemberOwners(EmitPlan plan, + IReadOnlyDictionary unions, + BindingErrorCollector? errors = null) + { + ArgumentNullException.ThrowIfNull(plan); + ArgumentNullException.ThrowIfNull(unions); + var result = new Dictionary>(StringComparer.Ordinal); + foreach (var model in plan.Models.OfType().OrderBy(static model => model.Name, StringComparer.Ordinal)) + { + var owners = plan.HoistedInterfaces.Where(carrier => carrier.ImplementedBy.Contains(model.Name, StringComparer.Ordinal) + || model.ImplementedHoistedInterfaceNames.Contains(carrier.Name, StringComparer.Ordinal)) + .ToDictionary(static carrier => carrier.Name, static carrier => carrier.Documentation, StringComparer.Ordinal); + var pending = new Queue(model.ImplementedUnionNames.Concat(plan.Unions + .Where(union => union.Variants.Any(variant => string.Equals(variant.TypeName, model.Name, StringComparison.Ordinal)) + || string.Equals(union.PrefixVariant?.TypeName, model.Name, StringComparison.Ordinal)) + .Select(static union => union.Name))); + while (pending.TryDequeue(out var name)) + { + if (unions.TryGetValue(name, out var union) && owners.TryAdd(name, union.Documentation) + && union.BaseTypeName is { } parent) + { + pending.Enqueue(parent); + } + } + + var candidates = owners.SelectMany(owner => owner.Value.Members.Select(member => + { + var property = model.ExplicitHoistedImplementations.FirstOrDefault(bridge => + string.Equals(bridge.InterfaceName, owner.Key, StringComparison.Ordinal) + && string.Equals(bridge.MemberName, member.Key, StringComparison.Ordinal))?.PropertyName ?? member.Key; + return (Property: property, Reference: owner.Key + "." + member.Key, Documentation: member.Value); + })).Where(candidate => !model.Documentation.Members.ContainsKey(candidate.Property) + && model.Properties.Any(property => string.Equals(property.Name, candidate.Property, StringComparison.Ordinal))); + var members = new Dictionary(StringComparer.Ordinal); + foreach (var group in candidates.GroupBy(static candidate => candidate.Property, StringComparer.Ordinal)) + { + var ordered = group.OrderBy(static candidate => candidate.Reference, StringComparer.Ordinal).ToArray(); + if (ordered.Select(static candidate => candidate.Documentation).Distinct().Count() > 1) + { + errors?.Add(BindingErrorCategory.Curation, model.Name + "." + group.Key, + "description has conflicting curated owners: " + string.Join(", ", ordered.Select(static candidate => candidate.Reference))); + } + + members.Add(group.Key, ordered[0].Reference); + } + + result.Add(model.Name, members); + } + + return result; } private static void Validate(IReadOnlyDictionary> targets, diff --git a/tools/OpenCode.Sdk.Tools/Generator/Emission/EmissionSyntax.cs b/tools/OpenCode.Sdk.Tools/Generator/Emission/EmissionSyntax.cs index 853ff00c..c4e0448e 100644 --- a/tools/OpenCode.Sdk.Tools/Generator/Emission/EmissionSyntax.cs +++ b/tools/OpenCode.Sdk.Tools/Generator/Emission/EmissionSyntax.cs @@ -89,15 +89,28 @@ public static SyntaxTriviaList Documentation(string summary, string? remarks) => /// Applies bound text to a type and its directly declared properties, without interpreting wire roles. public static T DocumentedType(T declaration, TypeDocumentationPlan documentation, - IReadOnlyList? existingRemarks = null) where T : TypeDeclarationSyntax + IReadOnlyList? existingRemarks = null, + IReadOnlyDictionary? inheritedMembers = null) where T : TypeDeclarationSyntax { ArgumentNullException.ThrowIfNull(declaration); ArgumentNullException.ThrowIfNull(documentation); - var members = declaration.Members.Select(member => member is PropertyDeclarationSyntax { ExplicitInterfaceSpecifier: null } property - && documentation.Members.TryGetValue(property.Identifier.ValueText, out var text) - ? property.WithLeadingTrivia(MemberDocumentation(text.Summary, [], remarks: ProseRemarks(text.Remarks))) - : member); + var members = declaration.Members.Select(member => + { + if (member is not PropertyDeclarationSyntax { ExplicitInterfaceSpecifier: null } property) + { + return member; + } + + if (documentation.Members.TryGetValue(property.Identifier.ValueText, out var text)) + { + return property.WithLeadingTrivia(MemberDocumentation(text.Summary, [], remarks: ProseRemarks(text.Remarks))); + } + + return inheritedMembers?.TryGetValue(property.Identifier.ValueText, out var owner) is true + ? property.WithLeadingTrivia(SyntaxFactory.Comment($"/// "), LineFeed) + : member; + }); var result = (T)declaration.WithMembers(SyntaxFactory.List(members)); if (documentation.Summary is { } summary) { diff --git a/tools/OpenCode.Sdk.Tools/Generator/Emission/ModelEmitter.cs b/tools/OpenCode.Sdk.Tools/Generator/Emission/ModelEmitter.cs index 4ed6e28f..7c0dc96d 100644 --- a/tools/OpenCode.Sdk.Tools/Generator/Emission/ModelEmitter.cs +++ b/tools/OpenCode.Sdk.Tools/Generator/Emission/ModelEmitter.cs @@ -12,9 +12,10 @@ internal static class ModelEmitter public static IReadOnlyList Emit(EmitPlan plan) { ArgumentNullException.ThrowIfNull(plan); - var unions = plan.Unions.ToDictionary(static union => union.Name, StringComparer.Ordinal); var result = new List(plan.Models.Count); + var unions = plan.Unions.ToDictionary(static union => union.Name, StringComparer.Ordinal); + var owners = DescriptionCurationBinder.InheritedMemberOwners(plan, unions); foreach (var model in plan.Models.OrderBy(static model => model.Name, StringComparer.Ordinal)) { if (model is StructuralUnionModelPlan) @@ -24,8 +25,7 @@ public static IReadOnlyList Emit(EmitPlan plan) result.AddRange(model switch { - ObjectModelPlan objectModel => [EmitObject(objectModel, ResolveImplementedUnions(objectModel, unions), unions, - GeneratedPlacement.ModelPathOf(plan.Placement, model.Name))], + ObjectModelPlan objectModel => [EmitObject(objectModel, unions, owners[model.Name], GeneratedPlacement.ModelPathOf(plan.Placement, model.Name))], EnumModelPlan enumModel => ExtensibleEnumEmitter.Emit(enumModel, plan.Placement), _ => throw new InvalidOperationException($"Unknown model plan '{model.GetType().Name}'."), }); @@ -34,9 +34,10 @@ public static IReadOnlyList Emit(EmitPlan plan) return Array.AsReadOnly([.. result]); } - private static GeneratedSource EmitObject(ObjectModelPlan model, IReadOnlyList implemented, - IReadOnlyDictionary unions, string relativePath) + private static GeneratedSource EmitObject(ObjectModelPlan model, Dictionary unions, + IReadOnlyDictionary owners, string relativePath) { + var implemented = ResolveImplementedUnions(model, unions); // A variant overrides one abstract marker per level of its union chain: a nested // union's variant carries both its own tag and the fixed outer tag. A union's one // prefix-tagged arm carries that union's marker as a guarded string in place of a tag. @@ -79,7 +80,8 @@ .. baseTypes.Select(static name => SyntaxFactory.SimpleBaseType(TypeSyntaxEmitte } var guardsPrefix = chainMarkers.Any(static marker => marker.Prefix is not null); - declaration = EmissionSyntax.DocumentedType(declaration, model.Documentation); + declaration = EmissionSyntax.DocumentedType(declaration, model.Documentation, + inheritedMembers: owners); var unit = EmissionSyntax.CompilationUnit(model.Namespace, CollectUsings(model, guardsPrefix), [declaration]); return EmissionSyntax.CreateSource(relativePath, unit); } @@ -501,7 +503,7 @@ private static bool IsDiscriminator(ModelPropertyPlan property, ChainMarker mark /// serving both contracts. /// private static List GetChainMarkers(string modelName, - IReadOnlyList implemented, IReadOnlyDictionary unions) + IReadOnlyList implemented, Dictionary unions) { var result = new List(); foreach (var union in implemented) diff --git a/tools/OpenCode.Sdk.Tools/Generator/Emission/UnionEmitter.cs b/tools/OpenCode.Sdk.Tools/Generator/Emission/UnionEmitter.cs index b794877a..302c17ee 100644 --- a/tools/OpenCode.Sdk.Tools/Generator/Emission/UnionEmitter.cs +++ b/tools/OpenCode.Sdk.Tools/Generator/Emission/UnionEmitter.cs @@ -71,7 +71,18 @@ private static GeneratedSource EmitBase(UnionPlan union, IReadOnlyDictionary pair.Key, pair => + union.HoistedMembers.Any(member => string.Equals(member.Name, pair.Key, StringComparison.Ordinal)) + ? pair.Value with + { + Remarks = pair.Value.Remarks + " Every declared variant carries it; an unrecognized variant preserved as " + + union.UnknownTypeName + " returns null through this interface. An ordinary optional property may also be absent." + } + : pair.Value, StringComparer.Ordinal), + }; + declaration = EmissionSyntax.DocumentedType(declaration, documentation, PinBoundInterfaceRemarks.Runs); var unit = EmissionSyntax.CompilationUnit( union.Namespace, HoistedUsings(union.HoistedMembers, [GeneratedNamespace.Internal, "System.Text.Json.Serialization"]), diff --git a/tools/curation.json b/tools/curation.json index 6eef9fdd..175cf315 100644 --- a/tools/curation.json +++ b/tools/curation.json @@ -1,5 +1,339 @@ { "descriptions": [ + { + "type": "IMcpTimeout", + "member": "Startup", + "summary": "Maximum time in milliseconds to establish and initialize the MCP server.", + "reason": "The optional annotation is absent from OpenAPI; document the shared timeout owner.", + "sources": [ + { "location": "packages/schema/src/mcp.ts:9", "excerpt": " description: \"Maximum time in milliseconds to establish and initialize the MCP server.\"," } + ] + }, + { + "type": "IMcpTimeout", + "member": "Catalog", + "summary": "Maximum time in milliseconds to wait for MCP discovery requests such as tools/list and prompts/list.", + "reason": "The optional annotation is absent from OpenAPI; document the shared timeout owner.", + "sources": [ + { "location": "packages/schema/src/mcp.ts:12", "excerpt": " description: \"Maximum time in milliseconds to wait for MCP discovery requests such as tools/list and prompts/list.\"," } + ] + }, + { + "type": "IMcpTimeout", + "member": "Execution", + "summary": "Maximum time in milliseconds to wait for MCP tool and prompt execution.", + "reason": "The optional annotation is absent from OpenAPI; document the shared timeout owner.", + "sources": [ + { "location": "packages/schema/src/mcp.ts:15", "excerpt": " description: \"Maximum time in milliseconds to wait for MCP tool and prompt execution.\"," } + ] + }, + { + "type": "IMcp", + "member": "Codemode", + "summary": "Expose this server's tools through Code Mode. Defaults to true.", + "reason": "The optional annotation is absent from OpenAPI; the union owner supplies the known configurations' documentation.", + "sources": [ + { "location": "packages/schema/src/mcp.ts:35", "excerpt": " description: \"Expose this server's tools through Code Mode. Defaults to true.\"," }, + { "location": "packages/schema/src/mcp.ts:60", "excerpt": " description: \"Expose this server's tools through Code Mode. Defaults to true.\"," } + ] + }, + { + "type": "ISessionMessageCompactionTime", + "member": "Created", + "summary": "Creation time in milliseconds since the Unix epoch.", + "reason": "The shared Base declares the epoch-millisecond codec, but OpenAPI retains only its numeric representation.", + "sources": [ + { "location": "packages/schema/src/session-message.ts:36", "excerpt": " time: Schema.Struct({ created: DateTimeUtcFromMillis })," } + ] + }, + { + "type": "ISessionInboxInfoTime", + "member": "Created", + "summary": "Enqueue time in milliseconds since the Unix epoch.", + "reason": "The shared enqueued shape declares the epoch-millisecond codec, but OpenAPI retains only its numeric representation.", + "sources": [ + { "location": "packages/schema/src/session-inbox.ts:52", "excerpt": "const Enqueued = {" }, + { "location": "packages/schema/src/session-inbox.ts:55", "excerpt": " time: Schema.Struct({ created: DateTimeUtcFromMillis })," } + ] + }, + { + "type": "IDurableEnvelope", + "member": "Seq", + "summary": "Position in one aggregate's durable log. Use only values from durable envelopes or synced markers as after cursors.", + "reason": "The shared durable owner documents cursor provenance once for its implementing records.", + "sources": [ + { "location": "packages/schema/src/event.ts:17", "excerpt": " * Position in one aggregate's durable log. Values originate from the durable" }, + { "location": "packages/schema/src/event.ts:18", "excerpt": " * event envelope and synced markers;" }, + { "location": "packages/schema/src/event.ts:19", "excerpt": " * `after` cursors accept only values that came from those sources." } + ] + }, + { + "type": "IDurableEnvelope", + "member": "Version", + "summary": "Durable schema version of this event type, from the event definition that committed it.", + "reason": "The shared durable owner documents the version's declared role once for its implementing records.", + "sources": [ + { "location": "packages/schema/src/event.ts:27", "excerpt": "/** Durable schema version of one event type, from the event definition that committed it. */" } + ] + }, + { + "type": "SessionMessageAssistant", + "summary": "An assistant message with text, reasoning or tool-call output parts.", + "reason": "Retain the declared output alternatives without the implementation-only per-step and failure lifecycle.", + "sources": [ + { "location": "packages/schema/src/session-message.ts:215", "excerpt": " type: Schema.tag(\"assistant\")," }, + { "location": "packages/schema/src/session-message.ts:218", "excerpt": " content: AssistantContent.pipe(Schema.Array)," }, + { "location": "packages/schema/src/session-message.ts:195", "excerpt": "export const AssistantContent = Schema.Union([AssistantText, AssistantReasoning, AssistantTool]).pipe(" } + ] + }, + { + "type": "SessionMessageAssistant", + "member": "Finish", + "summary": "The finish reason; the pinned values are stop, length, tool-calls, content-filter, error and unknown.", + "reason": "Retain the declared reason set without running-null or failure-normalization claims.", + "sources": [ + { "location": "packages/schema/src/session-message.ts:224", "excerpt": " finish: FinishReason.pipe(optional)," }, + { "location": "packages/schema/src/llm.ts:5", "excerpt": "export const FinishReason = Schema.Literals([\"stop\", \"length\", \"tool-calls\", \"content-filter\", \"error\", \"unknown\"])" } + ] + }, + { + "type": "SessionMessageAssistant", + "member": "Content", + "summary": "Assistant output parts: text, reasoning and tool calls.", + "reason": "Retain the declared output alternatives without inferring streaming order.", + "sources": [ + { "location": "packages/schema/src/session-message.ts:218", "excerpt": " content: AssistantContent.pipe(Schema.Array)," }, + { "location": "packages/schema/src/session-message.ts:195", "excerpt": "export const AssistantContent = Schema.Union([AssistantText, AssistantReasoning, AssistantTool]).pipe(" } + ] + }, + { + "type": "SessionMessageAssistant", + "member": "Cost", + "summary": "Cost in US dollars recorded on the assistant message.", + "reason": "Retain the declared currency without inferring computation, per-step scope or absence lifecycle.", + "sources": [ + { "location": "packages/schema/src/session-message.ts:227", "excerpt": " cost: Money.USD.pipe(optional)," }, + { "location": "packages/schema/src/money.ts:7", "excerpt": " Schema.brand(\"Money.USD\")," } + ] + }, + { + "type": "SessionTextDeltaData", + "member": "Delta", + "summary": "A live-only text fragment.", + "reason": "Retain the declared fragment role without the implementation-only batching policy.", + "sources": [ + { "location": "packages/schema/src/session-event.ts:403", "excerpt": " // Stream fragments are live-only; Text.Ended is the replayable full-value boundary." }, + { "location": "packages/schema/src/session-event.ts:410", "excerpt": " delta: Schema.String," } + ] + }, + { + "type": "SessionTextEndedData", + "member": "Text", + "summary": "The complete text of the part at the replayable full-value boundary.", + "reason": "Retain the declared full-value boundary without prescribing replacement of accumulated deltas.", + "sources": [ + { "location": "packages/schema/src/session-event.ts:403", "excerpt": " // Stream fragments are live-only; Text.Ended is the replayable full-value boundary." }, + { "location": "packages/schema/src/session-event.ts:422", "excerpt": " text: Schema.String," } + ] + }, + { + "type": "SessionTextEndedData", + "member": "State", + "summary": "Opaque provider state for the text part.", + "reason": "Retain the declared opaque state without promising future-request reuse.", + "sources": [ + { "location": "packages/schema/src/session-event.ts:423", "excerpt": " state: SessionMessage.ProviderState.pipe(optional)," }, + { "location": "packages/schema/src/session-message.ts:39", "excerpt": "export const ProviderState = Schema.Record(Schema.String, Schema.Unknown).annotate({" } + ] + }, + { + "type": "SessionPromptRequest", + "summary": "A session input durably admitted to the inbox, scheduling agent-loop execution unless Resume is false.", + "reason": "Retain the route's admission and scheduling contract without inferring response-before-model timing.", + "sources": [ + { "location": "packages/protocol/src/groups/session.ts:405", "excerpt": " success: Schema.Struct({ data: SessionInbox.User })," }, + { "location": "packages/protocol/src/groups/session.ts:413", "excerpt": " description: \"Durably admit one session input and schedule agent-loop execution unless resume is false.\"," } + ] + }, + { + "type": "SessionPromptRequest", + "member": "Id", + "summary": "An optional message identifier starting with msg_.", + "reason": "Retain the declared identifier prefix without inferring idempotence or conflict behavior.", + "sources": [ + { "location": "packages/protocol/src/groups/session.ts:399", "excerpt": " id: SessionMessage.ID.pipe(Schema.optional)," }, + { "location": "packages/schema/src/session-message.ts:23", "excerpt": "export const ID = Schema.String.check(Schema.isStartingWith(\"msg_\")).pipe(" } + ] + }, + { + "type": "SessionPromptRequest", + "member": "Files", + "summary": "File attachments, each referencing a file by its Uri member.", + "reason": "Retain the declared attachment reference without inventing URI schemes, size limits or file-reading policy.", + "sources": [ + { "location": "packages/schema/src/prompt-input.ts:31", "excerpt": " files: Schema.Array(FileAttachment).pipe(optional)," }, + { "location": "packages/schema/src/prompt-input.ts:10", "excerpt": " uri: Schema.String," } + ] + }, + { + "type": "SessionPromptRequest", + "member": "Skills", + "summary": "Skills to attach by identifier.", + "reason": "Retain the declared attachment role without inferring text placement or unknown-identifier errors.", + "sources": [ + { "location": "packages/schema/src/prompt-input.ts:33", "excerpt": " skills: Schema.Array(SkillAttachment).pipe(optional)," }, + { "location": "packages/schema/src/prompt-input.ts:25", "excerpt": " id: Skill.ID," } + ] + }, + { + "type": "SessionPromptRequest", + "member": "Delivery", + "summary": "The input delivery mode; the pinned values are steer and queue.", + "reason": "Retain the declared modes without inferring a default or boundary-ordering policy.", + "sources": [ + { "location": "packages/protocol/src/groups/session.ts:402", "excerpt": " delivery: SessionInbox.Delivery.pipe(Schema.optional)," }, + { "location": "packages/schema/src/session-inbox.ts:11", "excerpt": "export const Delivery = Schema.Literals([\"steer\", \"queue\"]).annotate({ identifier: \"Session.Inbox.Delivery\" })" } + ] + }, + { + "type": "SessionPromptRequest", + "member": "Resume", + "summary": "Controls scheduling of agent-loop execution after durable admission: false omits that scheduling.", + "reason": "Retain the route's scheduling qualification without inferring a true default or pending-input lifecycle.", + "sources": [ + { "location": "packages/protocol/src/groups/session.ts:413", "excerpt": " description: \"Durably admit one session input and schedule agent-loop execution unless resume is false.\"," } + ] + }, + { + "type": "SessionCreateRequest", + "summary": "A request to create a session at the requested location; ParentId links a child at its parent's location.", + "reason": "Retain the route's create and parent-location roles without inferring existing-identifier adoption.", + "sources": [ + { "location": "packages/protocol/src/groups/session.ts:239", "excerpt": " \"Create a session at the requested location. A parentID creates a linked child session at its parent's location.\"," } + ] + }, + { + "type": "SessionCreateRequest", + "member": "ParentId", + "summary": "Links a child session to its parent at the parent's location.", + "reason": "Retain the declared parent-location relationship without inferring metadata, permission, agent or model inheritance.", + "sources": [ + { "location": "packages/protocol/src/groups/session.ts:239", "excerpt": " \"Create a session at the requested location. A parentID creates a linked child session at its parent's location.\"," } + ] + }, + { + "type": "SessionCreateRequest", + "member": "Location", + "summary": "The requested location for a session; ParentId places a child at its parent's location.", + "reason": "Retain the declared parent-location qualification without inferring a process-working-directory default.", + "sources": [ + { "location": "packages/protocol/src/groups/session.ts:239", "excerpt": " \"Create a session at the requested location. A parentID creates a linked child session at its parent's location.\"," } + ] + }, + { + "type": "SessionCreateRequest", + "member": "Permissions", + "summary": "When at least one rule matches, the last matching rule wins; session rules are evaluated after the agent's rules.", + "reason": "Retain the declared ordering and precedence without implying what happens when no rule matches.", + "sources": [ + { "location": "packages/schema/src/session.ts:56", "excerpt": " /** Evaluated after the agent's rules; the last matching rule wins. */" }, + { "location": "packages/protocol/src/groups/session.ts:230", "excerpt": " permissions: Permission.Ruleset.pipe(Schema.optional)," } + ] + }, + { + "type": "SessionExecutionFailed", + "summary": "Reports an execution failure with its error in Data.Error.", + "reason": "Retain the declared failure payload without inferring idle transitions or exhausted-restart publication.", + "sources": [ + { "location": "packages/schema/src/session-event.ts:247", "excerpt": " type: \"session.execution.failed\"," }, + { "location": "packages/schema/src/session-event.ts:249", "excerpt": " schema: { ...Base, error: SessionError.Error }," } + ] + }, + { + "type": "SessionExecutionInterrupted", + "summary": "Reports interrupted execution; the pinned Data.Reason values are user, shutdown, superseded and inactivity.", + "reason": "Retain the declared interruption reasons without inferring preservation, resumption or restart-exhaustion behavior.", + "sources": [ + { "location": "packages/schema/src/session-event.ts:254", "excerpt": " type: \"session.execution.interrupted\"," }, + { "location": "packages/schema/src/session-event.ts:256", "excerpt": " schema: { ...Base, reason: Schema.Literals([\"user\", \"shutdown\", \"superseded\", \"inactivity\"]) }," } + ] + }, + { + "type": "SessionCreateRequest", + "member": "Id", + "summary": "An optional session identifier starting with ses.", + "reason": "Retain the declared identifier prefix without inferring existing-session adoption.", + "sources": [ + { "location": "packages/schema/src/session-id.ts:5", "excerpt": "export const SessionID = Schema.String.check(Schema.isStartingWith(\"ses\")).pipe(" }, + { "location": "packages/protocol/src/groups/session.ts:223", "excerpt": " id: Session.ID.pipe(Schema.optional)," } + ] + }, + { + "type": "SessionMessageAssistant", + "member": "Tokens", + "summary": "Token usage with input, output, reasoning and cache read/write parts.", + "reason": "Retain the declared usage structure without inferring per-step scope or absence lifecycle.", + "sources": [ + { "location": "packages/schema/src/session-message.ts:228", "excerpt": " tokens: TokenUsage.Info.pipe(optional)," }, + { "location": "packages/schema/src/token-usage.ts:6", "excerpt": "export const Info = Schema.Struct({" }, + { "location": "packages/schema/src/token-usage.ts:10", "excerpt": " cache: Schema.Struct({" } + ] + }, + { + "type": "SessionMessageAssistant", + "member": "Retry", + "summary": "Retry information containing an attempt number, time and error.", + "reason": "Retain the declared retry structure without inferring attempt numbering or clearing lifecycle.", + "sources": [ + { "location": "packages/schema/src/session-message.ts:230", "excerpt": " retry: AssistantRetry.pipe(optional)," }, + { "location": "packages/schema/src/session-message.ts:207", "excerpt": " attempt: PositiveInt," }, + { "location": "packages/schema/src/session-message.ts:208", "excerpt": " at: DateTimeUtcFromMillis," }, + { "location": "packages/schema/src/session-message.ts:209", "excerpt": " error: SessionError.Error," } + ] + }, + { + "type": "SessionTextDeltaData", + "member": "Ordinal", + "summary": "A non-negative ordinal for this text part.", + "reason": "Retain the declared non-negative ordinal without inferring zero-based indexing or separate reasoning numbering.", + "sources": [ + { "location": "packages/schema/src/session-event.ts:405", "excerpt": " type: \"session.text.delta\"," }, + { "location": "packages/schema/src/session-event.ts:409", "excerpt": " ordinal: NonNegativeInt," }, + { "location": "packages/schema/src/schema.ts:4", "excerpt": "export const NonNegativeInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))" } + ] + }, + { + "type": "SessionCreateRequest", + "member": "Model", + "summary": "A model reference identifying the provider, model and optional variant.", + "reason": "Retain the declared model-reference structure without inferring defaults or validation timing.", + "sources": [ + { "location": "packages/protocol/src/groups/session.ts:227", "excerpt": " model: Model.Ref.pipe(Schema.optional)," }, + { "location": "packages/schema/src/model.ts:19", "excerpt": "export const Ref = Schema.Struct({" }, + { "location": "packages/schema/src/model.ts:21", "excerpt": " providerID: Provider.ID," }, + { "location": "packages/schema/src/model.ts:22", "excerpt": " variant: VariantID.pipe(optional)," } + ] + }, + { + "type": "ExperimentalSessionStatsRequest", + "member": "From", + "summary": "The start of the aggregated time range.", + "reason": "Retain the declared time-range role without inferring a unit or bound inclusion.", + "sources": [ + { "location": "packages/protocol/src/groups/session.ts:204", "excerpt": " from: Schema.NumberFromString.pipe(Schema.optional)," }, + { "location": "packages/protocol/src/groups/session.ts:216", "excerpt": " description: \"Aggregate local session activity, usage, and tool reliability for a time range.\"," } + ] + }, + { + "type": "ExperimentalSessionStatsRequest", + "member": "To", + "summary": "The end of the aggregated time range.", + "reason": "Retain the declared time-range role without inferring a unit or bound inclusion.", + "sources": [ + { "location": "packages/protocol/src/groups/session.ts:205", "excerpt": " to: Schema.NumberFromString.pipe(Schema.optional)," }, + { "location": "packages/protocol/src/groups/session.ts:216", "excerpt": " description: \"Aggregate local session activity, usage, and tool reliability for a time range.\"," } + ] + }, { "type": "SessionTextDelta", "member": null,