From ca1f7876f48e922d868c34b54371245b0b616cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deniz=20=C4=B0rgin?= Date: Sat, 17 Oct 2026 18:49:49 +0300 Subject: [PATCH] docs(generator): curated interface documentation reaches its implementing members, and partly declared rows return narrowed A public implementing property with a curated interface owner and no row of its own now emits ``, resolved through the bound relationships (carrier and union membership, base chains, explicit bridges), never names. A direct row wins over an inherited owner, and two different curated owners for one property refuse generation by name. This reaches 105 public members: the durable envelopes' Seq and Version, the MCP timeouts and Codemode, and the inbox and compaction Created times. Earlier rows whose qualification was only partly declared return narrowed to their declared half, each with its own sources, worded so the sentence is true on its own and implies nothing about the dropped half. A guard keeps every curated hoisted member that carries the "ordinary optional property" remark optional in every variant, until the plan carries requiredness (#453). --- CHANGELOG.md | 8 + docs/architecture/protocol-and-generation.md | 4 +- .../ExperimentalSessionStatsRequest.cs | 4 +- src/OpenCode.Sdk/McpServers/Models/IMcp.cs | 5 +- .../McpServers/Models/IMcpTimeout.cs | 6 +- .../McpServers/Models/McpLocalConfig.cs | 4 +- .../Models/McpLocalConfigTimeout.cs | 12 +- .../McpServers/Models/McpRemoteConfig.cs | 4 +- .../Models/McpRemoteConfigTimeout.cs | 12 +- .../SessionCompactionEndedDurable.cs | 8 +- .../SessionCompactionFailedDurable.cs | 8 +- .../SessionCompactionStartedDurable.cs | 8 +- .../Execution/SessionExecutionFailed.cs | 2 +- .../SessionExecutionFailedDurable.cs | 8 +- .../Execution/SessionExecutionInterrupted.cs | 2 +- .../SessionExecutionInterruptedDurable.cs | 8 +- .../SessionExecutionStartedDurable.cs | 8 +- .../SessionExecutionSucceededDurable.cs | 8 +- .../Sessions/Models/IDurableEnvelope.cs | 4 +- .../Models/Inbox/ISessionInboxInfoTime.cs | 2 +- .../Inbox/SessionInboxCancelledDurable.cs | 8 +- .../Inbox/SessionInboxCompactionTime.cs | 4 +- .../Inbox/SessionInboxDeliveredDurable.cs | 8 +- .../SessionInboxDeliveryChangedDurable.cs | 8 +- .../Inbox/SessionInboxEnqueuedDurable.cs | 8 +- .../Models/Inbox/SessionInboxMoveTime.cs | 4 +- .../Models/Inbox/SessionInboxSyntheticTime.cs | 4 +- .../Models/Inbox/SessionInboxUserTime.cs | 4 +- .../Lifecycle/SessionAgentSelectedDurable.cs | 8 +- .../Models/Lifecycle/SessionCreatedDurable.cs | 8 +- .../Models/Lifecycle/SessionDeletedDurable.cs | 8 +- .../Models/Lifecycle/SessionForkedDurable.cs | 8 +- .../SessionInstructionsUpdatedDurable.cs | 8 +- .../SessionMetadataUpdatedDurable.cs | 8 +- .../Lifecycle/SessionModelSelectedDurable.cs | 8 +- .../Models/Lifecycle/SessionMovedDurable.cs | 8 +- .../Lifecycle/SessionPermissionsDurable.cs | 8 +- .../Models/Lifecycle/SessionRenamedDurable.cs | 8 +- .../Lifecycle/SessionSkillActivatedDurable.cs | 8 +- .../Lifecycle/SessionSyntheticDurable.cs | 8 +- .../Models/Lifecycle/SessionViewedDurable.cs | 8 +- .../Messages/ISessionMessageCompactionTime.cs | 2 +- .../Messages/SessionMessageAssistant.cs | 12 +- .../SessionMessageCompactionCompletedTime.cs | 4 +- .../SessionMessageCompactionFailedTime.cs | 4 +- .../SessionMessageCompactionRunningTime.cs | 4 +- .../SessionMessageContentUpdatedDurable.cs | 8 +- .../Revert/SessionRevertClearedDurable.cs | 8 +- .../Revert/SessionRevertCommittedDurable.cs | 8 +- .../Revert/SessionRevertStagedDurable.cs | 8 +- .../Models/Shell/SessionShellEndedDurable.cs | 8 +- .../Shell/SessionShellStartedDurable.cs | 8 +- .../Status/SessionRetryScheduledDurable.cs | 8 +- .../Turn/SessionReasoningEndedDurable.cs | 8 +- .../Turn/SessionReasoningStartedDurable.cs | 8 +- .../Models/Turn/SessionStepEndedDurable.cs | 8 +- .../Models/Turn/SessionStepFailedDurable.cs | 8 +- .../Models/Turn/SessionStepStartedDurable.cs | 8 +- .../Models/Turn/SessionStepStreamedDurable.cs | 8 +- .../Models/Turn/SessionTextDeltaData.cs | 4 +- .../Models/Turn/SessionTextEndedData.cs | 4 +- .../Models/Turn/SessionTextEndedDurable.cs | 8 +- .../Models/Turn/SessionTextStartedDurable.cs | 8 +- .../Models/Turn/SessionToolCalledDurable.cs | 8 +- .../Models/Turn/SessionToolFailedDurable.cs | 8 +- .../Turn/SessionToolInputEndedDurable.cs | 8 +- .../Turn/SessionToolInputStartedDurable.cs | 8 +- .../Models/Turn/SessionToolSuccessDurable.cs | 8 +- .../Turn/SessionUsageRecordedDurable.cs | 8 +- .../Sessions/SessionCreateRequest.cs | 12 +- .../Sessions/SessionPromptRequest.cs | 12 +- .../Binding/DescriptionCurationBinderTests.cs | 102 ++++++ .../Emission/GeneratedDocumentationTests.cs | 60 +++- .../Emission/HoistedMemberEmissionTests.cs | 65 ++++ .../Binding/DescriptionCurationBinder.cs | 57 ++- .../Generator/Emission/EmissionSyntax.cs | 23 +- .../Generator/Emission/ModelEmitter.cs | 16 +- .../Generator/Emission/UnionEmitter.cs | 13 +- tools/curation.json | 334 ++++++++++++++++++ 79 files changed, 805 insertions(+), 368 deletions(-) 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,