Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ changes accumulate. Track in-flight protocol changes via PRs touching

### Added

- `InitializeResult.featureStability` — an optional map advertising the
wire/schema stability (`FeatureStabilityLevel`: `stable` / `experimental` /
`deprecated`) of selected surfaces a host emits, keyed by surface identifier.
Surfaces absent from the map are `stable`.
- `SessionModelInfo.maxOutputTokens` and `SessionModelInfo.maxPromptTokens`
optional fields for communicating model token limits.
- `SessionSummary._meta` optional provider metadata field for lightweight
session-list presentation hints.
- `JsonPrimitive` type alias (`string | number | boolean | null`) in `types/common/state.ts`.
- `session/activeClientRemoved` action to release a single active client from a
session by `clientId`.

Expand Down
4 changes: 4 additions & 0 deletions clients/go/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ tag whose matching `## [X.Y.Z]` heading is missing from this file.

### Added

- `InitializeResult.FeatureStability` — an optional
`map[string]FeatureStabilityLevel` advertising the wire/schema stability
(`stable` / `experimental` / `deprecated`) of selected surfaces a host emits,
keyed by surface identifier. Surfaces absent from the map are `stable`.
- `SessionModelInfo.MaxOutputTokens` and `SessionModelInfo.MaxPromptTokens`
optional fields for communicating model token limits.
- `SessionSummary.Meta` (wire `_meta`) optional provider metadata field for
Expand Down
46 changes: 46 additions & 0 deletions clients/go/ahptypes/commands.generated.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,30 @@ const (
ReconnectResultTypeSnapshot ReconnectResultType = "snapshot"
)

// Wire/schema stability of a surface advertised in
// {@link InitializeResult.featureStability}.
//
// Stability describes how settled a surface's shape is within a compatible
// SemVer range. It is deliberately **not** a product-gating, entitlement, or
// preview-access signal — a client uses it only to decide how defensively to
// code against the surface.
type FeatureStabilityLevel string

const (
// Normal additive SemVer guarantees apply; clients MAY build on it freely.
// This is the default for any surface absent from
// {@link InitializeResult.featureStability}, so it never needs to be
// advertised explicitly.
FeatureStabilityLevelStable FeatureStabilityLevel = "stable"
// On the wire, but its shape MAY change or be removed within an otherwise
// compatible version range. Clients SHOULD parse it defensively, gate
// adoption behind a flag, tolerate shape changes, and not assume longevity.
FeatureStabilityLevelExperimental FeatureStabilityLevel = "experimental"
// Still emitted, but scheduled for removal in a future version. Clients
// SHOULD migrate off it and SHOULD NOT adopt it anew.
FeatureStabilityLevelDeprecated FeatureStabilityLevel = "deprecated"
)

// Encoding of fetched content data.
type ContentEncoding string

Expand Down Expand Up @@ -137,6 +161,28 @@ type InitializeResult struct {
// defines a template variable, `{level}`, for subscriber-side severity
// filtering). Clients MAY ignore signals they cannot process.
Telemetry *TelemetryCapabilities `json:"telemetry,omitempty"`
// Wire/schema stability of selected surfaces the host emits, keyed by a
// surface identifier — a notification method (e.g. `"session/canvasOpened"`),
// a command method (e.g. `"listSessions"`), a channel URI scheme (e.g.
// `"ahp-otlp:"`), or a named capability.
//
// A surface absent from this map is {@link FeatureStabilityLevel.Stable |
// `stable`} and carries the normal additive SemVer guarantees, so hosts list
// **only** surfaces that are not stable. The signal is strictly about
// wire/schema volatility ("may change or be removed within a compatible
// version range") — **not** product gating, entitlement, or preview access.
// Clients use it only to decide how defensively to code against a surface.
//
// This is connection-level metadata negotiated once at `initialize`. A
// `reconnect` continues the same logical connection, so clients retain the
// map across reconnects rather than re-requesting it, exactly as they retain
// {@link InitializeResult.defaultDirectory | `defaultDirectory`} and
// {@link InitializeResult.telemetry | `telemetry`}.
//
// Older clients that do not understand this field ignore it and treat every
// surface as stable, consistent with the protocol's "ignore what you don't
// understand" rule.
FeatureStability map[string]FeatureStabilityLevel `json:"featureStability,omitempty"`
}

// Optional capabilities a client declares during `initialize`.
Expand Down
4 changes: 4 additions & 0 deletions clients/kotlin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ versions (`*-SNAPSHOT`) are explicitly rejected by the publish pipeline; bump

### Added

- `InitializeResult.featureStability` — an optional
`Map<String, FeatureStabilityLevel>` advertising the wire/schema stability
(`STABLE` / `EXPERIMENTAL` / `DEPRECATED`) of selected surfaces a host emits,
keyed by surface identifier. Surfaces absent from the map are stable.
- `SessionModelInfo.maxOutputTokens` and `SessionModelInfo.maxPromptTokens`
optional fields for communicating model token limits.
- `SessionSummary.meta` (`_meta` on the wire) optional provider metadata field
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,40 @@ enum class ReconnectResultType {
SNAPSHOT
}

/**
* Wire/schema stability of a surface advertised in
* {@link InitializeResult.featureStability}.
*
* Stability describes how settled a surface's shape is within a compatible
* SemVer range. It is deliberately **not** a product-gating, entitlement, or
* preview-access signal — a client uses it only to decide how defensively to
* code against the surface.
*/
@Serializable
enum class FeatureStabilityLevel {
/**
* Normal additive SemVer guarantees apply; clients MAY build on it freely.
* This is the default for any surface absent from
* {@link InitializeResult.featureStability}, so it never needs to be
* advertised explicitly.
*/
@SerialName("stable")
STABLE,
/**
* On the wire, but its shape MAY change or be removed within an otherwise
* compatible version range. Clients SHOULD parse it defensively, gate
* adoption behind a flag, tolerate shape changes, and not assume longevity.
*/
@SerialName("experimental")
EXPERIMENTAL,
/**
* Still emitted, but scheduled for removal in a future version. Clients
* SHOULD migrate off it and SHOULD NOT adopt it anew.
*/
@SerialName("deprecated")
DEPRECATED
}

/**
* Encoding of fetched content data.
*/
Expand Down Expand Up @@ -177,7 +211,31 @@ data class InitializeResult(
* defines a template variable, `{level}`, for subscriber-side severity
* filtering). Clients MAY ignore signals they cannot process.
*/
val telemetry: TelemetryCapabilities? = null
val telemetry: TelemetryCapabilities? = null,
/**
* Wire/schema stability of selected surfaces the host emits, keyed by a
* surface identifier — a notification method (e.g. `"session/canvasOpened"`),
* a command method (e.g. `"listSessions"`), a channel URI scheme (e.g.
* `"ahp-otlp:"`), or a named capability.
*
* A surface absent from this map is {@link FeatureStabilityLevel.Stable |
* `stable`} and carries the normal additive SemVer guarantees, so hosts list
* **only** surfaces that are not stable. The signal is strictly about
* wire/schema volatility ("may change or be removed within a compatible
* version range") — **not** product gating, entitlement, or preview access.
* Clients use it only to decide how defensively to code against a surface.
*
* This is connection-level metadata negotiated once at `initialize`. A
* `reconnect` continues the same logical connection, so clients retain the
* map across reconnects rather than re-requesting it, exactly as they retain
* {@link InitializeResult.defaultDirectory | `defaultDirectory`} and
* {@link InitializeResult.telemetry | `telemetry`}.
*
* Older clients that do not understand this field ignore it and treat every
* surface as stable, consistent with the protocol's "ignore what you don't
* understand" rule.
*/
val featureStability: Map<String, FeatureStabilityLevel>? = null
)

@Serializable
Expand Down
5 changes: 5 additions & 0 deletions clients/rust/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ matching `## [X.Y.Z]` heading is missing from this file.

### Added

- `InitializeResult.feature_stability` — an optional
`HashMap<String, FeatureStabilityLevel>` advertising the wire/schema
stability (`stable` / `experimental` / `deprecated`) of selected surfaces a
host emits, keyed by surface identifier. Surfaces absent from the map are
`stable`.
- `SessionModelInfo.maxOutputTokens` and `SessionModelInfo.maxPromptTokens`
optional fields for communicating model token limits.
- `SessionSummary.meta` (`_meta` on the wire) optional provider metadata field
Expand Down
49 changes: 49 additions & 0 deletions clients/rust/crates/ahp-types/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,32 @@ pub enum ReconnectResultType {
Snapshot,
}

/// Wire/schema stability of a surface advertised in
/// {@link InitializeResult.featureStability}.
///
/// Stability describes how settled a surface's shape is within a compatible
/// SemVer range. It is deliberately **not** a product-gating, entitlement, or
/// preview-access signal — a client uses it only to decide how defensively to
/// code against the surface.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum FeatureStabilityLevel {
/// Normal additive SemVer guarantees apply; clients MAY build on it freely.
/// This is the default for any surface absent from
/// {@link InitializeResult.featureStability}, so it never needs to be
/// advertised explicitly.
#[serde(rename = "stable")]
Stable,
/// On the wire, but its shape MAY change or be removed within an otherwise
/// compatible version range. Clients SHOULD parse it defensively, gate
/// adoption behind a flag, tolerate shape changes, and not assume longevity.
#[serde(rename = "experimental")]
Experimental,
/// Still emitted, but scheduled for removal in a future version. Clients
/// SHOULD migrate off it and SHOULD NOT adopt it anew.
#[serde(rename = "deprecated")]
Deprecated,
}

/// Encoding of fetched content data.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ContentEncoding {
Expand Down Expand Up @@ -160,6 +186,29 @@ pub struct InitializeResult {
/// filtering). Clients MAY ignore signals they cannot process.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub telemetry: Option<TelemetryCapabilities>,
/// Wire/schema stability of selected surfaces the host emits, keyed by a
/// surface identifier — a notification method (e.g. `"session/canvasOpened"`),
/// a command method (e.g. `"listSessions"`), a channel URI scheme (e.g.
/// `"ahp-otlp:"`), or a named capability.
///
/// A surface absent from this map is {@link FeatureStabilityLevel.Stable |
/// `stable`} and carries the normal additive SemVer guarantees, so hosts list
/// **only** surfaces that are not stable. The signal is strictly about
/// wire/schema volatility ("may change or be removed within a compatible
/// version range") — **not** product gating, entitlement, or preview access.
/// Clients use it only to decide how defensively to code against a surface.
///
/// This is connection-level metadata negotiated once at `initialize`. A
/// `reconnect` continues the same logical connection, so clients retain the
/// map across reconnects rather than re-requesting it, exactly as they retain
/// {@link InitializeResult.defaultDirectory | `defaultDirectory`} and
/// {@link InitializeResult.telemetry | `telemetry`}.
///
/// Older clients that do not understand this field ignore it and treat every
/// surface as stable, consistent with the protocol's "ignore what you don't
/// understand" rule.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub feature_stability: Option<std::collections::HashMap<String, FeatureStabilityLevel>>,
}

/// Optional capabilities a client declares during `initialize`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,28 @@ public enum ReconnectResultType: String, Codable, Sendable {
case snapshot = "snapshot"
}

/// Wire/schema stability of a surface advertised in
/// {@link InitializeResult.featureStability}.
///
/// Stability describes how settled a surface's shape is within a compatible
/// SemVer range. It is deliberately **not** a product-gating, entitlement, or
/// preview-access signal — a client uses it only to decide how defensively to
/// code against the surface.
public enum FeatureStabilityLevel: String, Codable, Sendable {
/// Normal additive SemVer guarantees apply; clients MAY build on it freely.
/// This is the default for any surface absent from
/// {@link InitializeResult.featureStability}, so it never needs to be
/// advertised explicitly.
case stable = "stable"
/// On the wire, but its shape MAY change or be removed within an otherwise
/// compatible version range. Clients SHOULD parse it defensively, gate
/// adoption behind a flag, tolerate shape changes, and not assume longevity.
case experimental = "experimental"
/// Still emitted, but scheduled for removal in a future version. Clients
/// SHOULD migrate off it and SHOULD NOT adopt it anew.
case deprecated = "deprecated"
}

/// Encoding of fetched content data.
public enum ContentEncoding: String, Codable, Sendable {
case base64 = "base64"
Expand Down Expand Up @@ -123,21 +145,45 @@ public struct InitializeResult: Codable, Sendable {
/// defines a template variable, `{level}`, for subscriber-side severity
/// filtering). Clients MAY ignore signals they cannot process.
public var telemetry: TelemetryCapabilities?
/// Wire/schema stability of selected surfaces the host emits, keyed by a
/// surface identifier — a notification method (e.g. `"session/canvasOpened"`),
/// a command method (e.g. `"listSessions"`), a channel URI scheme (e.g.
/// `"ahp-otlp:"`), or a named capability.
///
/// A surface absent from this map is {@link FeatureStabilityLevel.Stable |
/// `stable`} and carries the normal additive SemVer guarantees, so hosts list
/// **only** surfaces that are not stable. The signal is strictly about
/// wire/schema volatility ("may change or be removed within a compatible
/// version range") — **not** product gating, entitlement, or preview access.
/// Clients use it only to decide how defensively to code against a surface.
///
/// This is connection-level metadata negotiated once at `initialize`. A
/// `reconnect` continues the same logical connection, so clients retain the
/// map across reconnects rather than re-requesting it, exactly as they retain
/// {@link InitializeResult.defaultDirectory | `defaultDirectory`} and
/// {@link InitializeResult.telemetry | `telemetry`}.
///
/// Older clients that do not understand this field ignore it and treat every
/// surface as stable, consistent with the protocol's "ignore what you don't
/// understand" rule.
public var featureStability: [String: FeatureStabilityLevel]?

public init(
protocolVersion: String,
serverSeq: Int,
snapshots: [Snapshot],
defaultDirectory: String? = nil,
completionTriggerCharacters: [String]? = nil,
telemetry: TelemetryCapabilities? = nil
telemetry: TelemetryCapabilities? = nil,
featureStability: [String: FeatureStabilityLevel]? = nil
) {
self.protocolVersion = protocolVersion
self.serverSeq = serverSeq
self.snapshots = snapshots
self.defaultDirectory = defaultDirectory
self.completionTriggerCharacters = completionTriggerCharacters
self.telemetry = telemetry
self.featureStability = featureStability
}
}

Expand Down
4 changes: 4 additions & 0 deletions clients/swift/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ the tag matches the version pinned in [`VERSION`](VERSION).

### Added

- `InitializeResult.featureStability` — an optional
`[String: FeatureStabilityLevel]` advertising the wire/schema stability
(`.stable` / `.experimental` / `.deprecated`) of selected surfaces a host
emits, keyed by surface identifier. Surfaces absent from the map are stable.
- `SessionModelInfo.maxOutputTokens` and `SessionModelInfo.maxPromptTokens`
optional fields for communicating model token limits.
- `SessionSummary.meta` (`_meta` on the wire) optional provider metadata field
Expand Down
4 changes: 4 additions & 0 deletions clients/typescript/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ hotfix escape hatch.

### Added

- `InitializeResult.featureStability` — an optional
`Record<string, FeatureStabilityLevel>` advertising the wire/schema stability
(`stable` / `experimental` / `deprecated`) of selected surfaces a host emits,
keyed by surface identifier. Surfaces absent from the map are `stable`.
- `SessionModelInfo.maxOutputTokens` and `SessionModelInfo.maxPromptTokens`
optional fields for communicating model token limits.
- `SessionSummary._meta` optional provider metadata field for lightweight
Expand Down
2 changes: 2 additions & 0 deletions docs/specification/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ The client initiates the connection with an `initialize` **request**. The client

If present, `defaultDirectory` provides a server-local starting location for remote filesystem browsing.

The server MAY also include `featureStability` — a map advertising which emitted surfaces are `experimental` or `deprecated` rather than `stable`. This is connection-level metadata: it is negotiated once here and retained by the client across [reconnects](#reconnection). See [Stability Levels](/specification/versioning#stability-levels) for the semantics.

If the server cannot accept the connection for any other reason, it MUST return a JSON-RPC error. See [Error Codes](/reference/error-codes) for defined codes.

## Authentication
Expand Down
Loading
Loading