Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -784,19 +784,20 @@ public sealed record SessionActiveClientRemovedAction
public required string ClientId { get; init; }
}

/// <summary>A working directory was added to the session's
/// <summary>A working directory was added or updated in the session's
/// {@link SessionState.workingDirectories} set.
///
/// Membership semantics keyed by the directory URI: the reducer appends
/// `directory` when the set does not already contain it (creating the set if
/// absent) and is a no-op when it is already present. Only valid when the agent
/// advertises {@link AgentCapabilities.multipleWorkingDirectories}.</summary>
/// Upsert keyed by URI. A rich record replaces the existing entry in place;
/// a URI-only duplicate preserves known metadata. Only valid when the agent
/// advertises {@link AgentCapabilities.multipleWorkingDirectories}. Clients
/// MUST omit `repo` and use only local or absent `origin`; the host validates
/// and enriches the entry before accepting it.</summary>
public sealed record SessionWorkingDirectorySetAction
{
public ActionType Type { get; init; } = ActionType.SessionWorkingDirectorySet;

/// <summary>The working directory to grant the session's agent tool access to.</summary>
public required string Directory { get; init; }
public required WorkingDirectoryEntry Directory { get; init; }
}

/// <summary>A working directory was removed from the session's
Expand Down Expand Up @@ -829,22 +830,25 @@ public sealed record SessionWorkingDirectoryRemovedAction
/// for example, `[A, B, C]` with `B → C` becomes `[A, C]`. When it occurs
/// before the target, it retains its earlier position and the target is removed;
/// `[A, B, C]` with `C → A` becomes `[A, B]`.
/// A rich replacement supplies the complete entry; a URI-only replacement
/// preserves metadata already known for that URI.
///
/// Only valid when the agent advertises
/// {@link AgentCapabilities.multipleWorkingDirectories}. Replacing index `0`
/// additionally requires
/// {@link MultipleWorkingDirectoriesCapability.primaryReplacement}; clients
/// MUST NOT target an immutable primary. The host MUST validate and apply its
/// backend side effect before broadcasting an accepted action, or reject it.</summary>
/// backend side effect before broadcasting an accepted action, or reject it.
/// Clients MUST omit `repo` and use only local or absent `origin`.</summary>
public sealed record SessionWorkingDirectoryReplacedAction
{
public ActionType Type { get; init; } = ActionType.SessionWorkingDirectoryReplaced;

/// <summary>URI of the existing entry to replace.</summary>
public required string Directory { get; init; }

/// <summary>URI to place in the replaced entry's position.</summary>
public required string Replacement { get; init; }
/// <summary>Complete entry to place in the replaced entry's position.</summary>
public required WorkingDirectoryEntry Replacement { get; init; }
}

/// <summary>A session-level input request was added or updated.
Expand Down Expand Up @@ -1869,8 +1873,9 @@ public sealed record CanvasStateChangedAction
/// Membership semantics keyed by the directory URI: the reducer appends
/// `directory` when the chat's subset does not already contain it (creating the
/// subset if absent) and is a no-op when it is already present. `directory` MUST
/// be one of the owning session's {@link SessionState.workingDirectories}; a host
/// MUST reject a directory that is not. Only valid when the agent advertises
/// match a URI string or record's `uri` in the owning session's
/// {@link SessionState.workingDirectories}; a host MUST reject a directory that
/// does not. Only valid when the agent advertises
/// {@link AgentCapabilities.multipleWorkingDirectories}.</summary>
public sealed record ChatWorkingDirectorySetAction
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,21 @@ public override void Write(Utf8JsonWriter writer, AuthenticateTargetKind value,

// ─── Command Payloads ─────────────────────────────────────────────────

/// <summary>Requested repository source, not a resolved working directory.</summary>
public sealed record RepositorySource
{
/// <summary>Credential-free repository source URI.</summary>
public required string Source { get; init; }

/// <summary>Requested branch, tag, or commit. Omit to use the host's default revision.</summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Revision { get; init; }

/// <summary>Repository-relative selected folder; omit for the root. Hosts reject empty, absolute, or escaping paths.</summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Subdirectory { get; init; }
}

/// <summary>Opens a TCP connection from the host to a destination on the host's network.
///
/// The client chooses the channel URI. This command does not subscribe: after it
Expand Down Expand Up @@ -495,6 +510,10 @@ public sealed record InitializeResult
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? DefaultDirectory { get; init; }

/// <summary>Host repository preparation support; absent when unsupported.</summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public RepositoryPreparationCapability? RepositoryPreparation { get; init; }

/// <summary>Characters that, when typed in a {@link Message} input, SHOULD cause
/// the client to issue a `completions` request with
/// {@link CompletionItemKind.UserMessage}. Typically includes characters like
Expand Down Expand Up @@ -576,6 +595,11 @@ public sealed record Implementation
/// are reserved for future per-capability options.</summary>
public sealed record ClientCapabilities
{
/// <summary>Client accepts rich {@link WorkingDirectory} records as well as URI strings.
/// Hosts project records to URIs when absent and retain this choice on reconnect.</summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public WorkingDirectoryInfoCapability? WorkingDirectoryInfo { get; init; }

/// <summary>Client can render
/// [MCP Apps](https://github.com/modelcontextprotocol/ext-apps) — i.e.
/// it can host the View sandbox, run the `ui/*` protocol against it,
Expand All @@ -591,6 +615,24 @@ public sealed record ClientCapabilities
public Dictionary<string, JsonElement>? McpApps { get; init; }
}

/// <summary>Host support for repository preparation at session creation. Presence
/// alone supports one repository at its default revision.</summary>
public sealed record RepositoryPreparationCapability
{
/// <summary>When true, clients may supply {@link RepositorySource.revision}.</summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? Revision { get; init; }

/// <summary>When true, clients may supply more than one repository.</summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? MultipleRepositories { get; init; }
}

/// <summary>Presence capability for {@link ClientCapabilities.workingDirectoryInfo}.</summary>
public sealed record WorkingDirectoryInfoCapability
{
}

/// <summary>Automation features supported by this host authority.
///
/// The presence of this object advertises the baseline `ahp-automations://`
Expand Down Expand Up @@ -947,6 +989,11 @@ public sealed record CreateSessionParams
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public List<string>? WorkingDirectories { get; init; }

/// <summary>Repositories to prepare instead of an explicit `workingDirectories` list.
/// An empty list is equivalent to omission.</summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public List<RepositorySource>? Repositories { get; init; }

/// <summary>Agent-specific configuration values collected via `resolveSessionConfig`.
/// Keys and values correspond to the schema returned by the server.</summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
Expand Down Expand Up @@ -1070,9 +1117,9 @@ public sealed record CreateChatParams
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ChatSource? Source { get; init; }

/// <summary>Initial working-directory subset for this chat. Every entry MUST be
/// present in the owning session's `workingDirectories`; the server MUST
/// reject any entry that is not. When absent, the chat inherits the full
/// <summary>Initial working-directory URI subset for this chat. Every URI MUST match
/// a URI string or record's `uri` in the owning session's `workingDirectories`;
/// the server MUST reject any entry that does not. When absent, the chat inherits the full
/// session set. Forked chats (those whose `source.kind` is `"fork"`) inherit
/// the source chat's `workingDirectories`; this field is ignored for forks.
///
Expand Down Expand Up @@ -2002,6 +2049,10 @@ public sealed record ResolveSessionConfigParams
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? WorkingDirectory { get; init; }

/// <summary>Repositories used as configuration context; an empty list is equivalent to omission.</summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public List<RepositorySource>? Repositories { get; init; }

/// <summary>Current user-filled configuration values</summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Dictionary<string, JsonElement>? Config { get; init; }
Expand Down Expand Up @@ -2040,6 +2091,10 @@ public sealed record SessionConfigCompletionsParams
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? WorkingDirectory { get; init; }

/// <summary>Repositories used as configuration context; an empty list is equivalent to omission.</summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public List<RepositorySource>? Repositories { get; init; }

/// <summary>Current user-filled configuration values (provides context for the query)</summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Dictionary<string, JsonElement>? Config { get; init; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ namespace Microsoft.AgentHostProtocol;
[JsonSerializable(typeof(ListAutomationTriggerDefinitionsResult))]
[JsonSerializable(typeof(ListSessionsParams))]
[JsonSerializable(typeof(ListSessionsResult))]
[JsonSerializable(typeof(LocalWorkingDirectoryOrigin))]
[JsonSerializable(typeof(MarkdownResponsePart))]
[JsonSerializable(typeof(McpAuthRequiredReason))]
[JsonSerializable(typeof(McpAuthRequirement))]
Expand Down Expand Up @@ -316,6 +317,9 @@ namespace Microsoft.AgentHostProtocol;
[JsonSerializable(typeof(ReconnectResult))]
[JsonSerializable(typeof(ReconnectResultType))]
[JsonSerializable(typeof(ReconnectSnapshotResult))]
[JsonSerializable(typeof(RepositoryPreparationCapability))]
[JsonSerializable(typeof(RepositorySource))]
[JsonSerializable(typeof(RepoWorkingDirectoryOrigin))]
[JsonSerializable(typeof(ResolveSessionConfigParams))]
[JsonSerializable(typeof(ResolveSessionConfigResult))]
[JsonSerializable(typeof(ResourceChange))]
Expand Down Expand Up @@ -514,6 +518,12 @@ namespace Microsoft.AgentHostProtocol;
[JsonSerializable(typeof(UnsubscribeParams))]
[JsonSerializable(typeof(UnsupportedProtocolVersionErrorData))]
[JsonSerializable(typeof(UsageInfo))]
[JsonSerializable(typeof(WorkingDirectory))]
[JsonSerializable(typeof(WorkingDirectoryEntry))]
[JsonSerializable(typeof(WorkingDirectoryInfoCapability))]
[JsonSerializable(typeof(WorkingDirectoryOrigin))]
[JsonSerializable(typeof(WorkingDirectoryOriginKind))]
[JsonSerializable(typeof(WorktreeWorkingDirectoryOrigin))]
[JsonSourceGenerationOptions(
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.Never,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,9 +443,11 @@ public sealed record PartialSessionSummary
/// (the first entry is a protected, replaceable primary slot). Individual chats
/// MAY restrict to a subset via
/// {@link ChatSummary.workingDirectories | their own `workingDirectories`}; a
/// chat that sets none operates against this full set.</summary>
/// chat that sets none operates against this full set.
/// Entries are uniquely keyed by URI. Rich records require
/// {@link ClientCapabilities.workingDirectoryInfo}; other clients receive URIs.</summary>
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public List<string>? WorkingDirectories { get; init; }
public List<WorkingDirectoryEntry>? WorkingDirectories { get; init; }

/// <summary>Lightweight summary of this session's inline annotations channel
/// (`ahp-annotations:/&lt;uuid&gt;`). Surfaced so badge UI can render
Expand Down
Loading
Loading