diff --git a/clients/go/ahptypes/actions.generated.go b/clients/go/ahptypes/actions.generated.go index 946b4574..137503b7 100644 --- a/clients/go/ahptypes/actions.generated.go +++ b/clients/go/ahptypes/actions.generated.go @@ -898,8 +898,8 @@ type SessionWorkingDirectorySetAction struct { // Removes `directory` from the set; a no-op when it is not present. There is no // atomic backend "remove one" primitive — a host reconfigures its agent to the // reduced set — so this action is safe to model as idempotent. A host MAY -// decline to apply the removal (e.g. a directory still designated as some -// chat's {@link ChatState.primaryWorkingDirectory | primary}); it then leaves +// decline to apply the removal (e.g. an immutable primary directory, see +// {@link MultipleWorkingDirectoriesCapability.immutablePrimary}); it then leaves // the set unchanged. type SessionWorkingDirectoryRemovedAction struct { Type ActionType `json:"type"` diff --git a/clients/go/ahptypes/commands.generated.go b/clients/go/ahptypes/commands.generated.go index d00d0674..aa70d3ad 100644 --- a/clients/go/ahptypes/commands.generated.go +++ b/clients/go/ahptypes/commands.generated.go @@ -318,9 +318,8 @@ type CreateSessionParams struct { // The working directories the session's agent is granted tool access to. // A session may span multiple directories; they are equal peers except when // the agent advertises - // {@link MultipleWorkingDirectoriesCapability.requiresPrimary}, in which case - // one of them should be designated the primary via - // {@link primaryWorkingDirectory}. + // {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (in which case + // the first entry is a fixed process root). // // A client MUST NOT supply more than one entry unless the agent advertises // {@link AgentCapabilities.multipleWorkingDirectories}; a server without that @@ -332,24 +331,6 @@ type CreateSessionParams struct { // Ignored for forked sessions — a fork inherits its working directories // from the source session identified by `fork`. WorkingDirectories []URI `json:"workingDirectories,omitempty"` - // The primary working directory for the session's **default chat**. - // - // A session has no primary of its own — primary is a per-chat notion (see - // {@link ChatState.primaryWorkingDirectory}). But `createSession` implicitly - // creates the session's default chat, and there is no separate `createChat` - // call to carry that chat's create-time fields. This field is therefore the - // only place a client can designate the **default chat's** primary at birth; - // it is copied into that chat's read-only `primaryWorkingDirectory`. For any - // non-default chat, pass {@link CreateChatParams.primaryWorkingDirectory} - // instead. - // - // When set, it MUST be one of {@link workingDirectories}. A client SHOULD - // supply this when the agent advertises - // {@link MultipleWorkingDirectoriesCapability.requiresPrimary}; a host MAY - // reject creation that omits it, or fall back to the first entry of - // `workingDirectories`. Ignored for forked sessions (a fork inherits the - // source session's chats and their primaries). - PrimaryWorkingDirectory *URI `json:"primaryWorkingDirectory,omitempty"` // Fork from an existing session. The new session is populated with content // from the source session up to and including the specified turn's response. Fork *SessionForkSource `json:"fork,omitempty"` @@ -452,16 +433,6 @@ type CreateChatParams struct { // A client MUST NOT supply this field unless the agent advertises // {@link AgentCapabilities.multipleWorkingDirectories}. WorkingDirectories []URI `json:"workingDirectories,omitempty"` - // The chat's primary working directory — the distinguished root this chat is - // centered on. When set, it MUST be one of the chat's effective working - // directories ({@link workingDirectories}, or the session's set when that is - // omitted). A client SHOULD supply this when the agent advertises - // {@link MultipleWorkingDirectoriesCapability.requiresPrimary}; a host MAY - // reject creation that omits it, or fall back to the first of the chat's - // directories. Fixed at creation and reported (read-only) on - // {@link ChatState.primaryWorkingDirectory}. Ignored for forks (a chat whose - // `source.kind` is `"fork"` inherits the source chat's primary). - PrimaryWorkingDirectory *URI `json:"primaryWorkingDirectory,omitempty"` } // Disposes a chat and cleans up server-side resources. diff --git a/clients/go/ahptypes/common.go b/clients/go/ahptypes/common.go index 9b4dddc2..988c7200 100644 --- a/clients/go/ahptypes/common.go +++ b/clients/go/ahptypes/common.go @@ -85,8 +85,6 @@ type PartialChatSummary struct { Origin *ChatOrigin `json:"origin,omitempty"` // The subset of the session's working directories this chat uses. WorkingDirectories []URI `json:"workingDirectories,omitempty"` - // The chat's primary working directory. - PrimaryWorkingDirectory *URI `json:"primaryWorkingDirectory,omitempty"` } // ─── StringOrMarkdown ──────────────────────────────────────────────────── diff --git a/clients/go/ahptypes/notifications.generated.go b/clients/go/ahptypes/notifications.generated.go index ed553996..34e0908d 100644 --- a/clients/go/ahptypes/notifications.generated.go +++ b/clients/go/ahptypes/notifications.generated.go @@ -219,12 +219,13 @@ type PartialSessionSummary struct { Project *ProjectInfo `json:"project,omitempty"` // The working directories the session's agent has tool access to, as // maintained by the `session/workingDirectorySet` / - // `session/workingDirectoryRemoved` actions. Directories are **equal peers** — - // the session has no primary. Individual chats MAY restrict to a subset via - // {@link ChatSummary.workingDirectories | their own `workingDirectories`} and - // designate one of their own directories as primary (see - // {@link ChatState.primaryWorkingDirectory}); a chat that sets no subset - // operates against this full set. + // `session/workingDirectoryRemoved` actions. Directories are equal peers + // except when the agent advertises + // {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first + // entry is then a fixed process root). Individual chats MAY restrict to a + // subset via {@link ChatSummary.workingDirectories | their own + // `workingDirectories`}; a chat that sets none operates against this full + // set. WorkingDirectories []URI `json:"workingDirectories,omitempty"` // Lightweight summary of this session's inline annotations channel // (`ahp-session://annotations`). Surfaced so badge UI can render diff --git a/clients/go/ahptypes/state.generated.go b/clients/go/ahptypes/state.generated.go index 94339110..358822de 100644 --- a/clients/go/ahptypes/state.generated.go +++ b/clients/go/ahptypes/state.generated.go @@ -590,8 +590,8 @@ type AgentCapabilities struct { MultipleChats *MultipleChatsCapability `json:"multipleChats,omitempty"` // The session's agent can be granted tool access to more than one working // directory. The directories are treated as equal peers except where the - // agent advertises {@link MultipleWorkingDirectoriesCapability.requiresPrimary} - // (some backends need one directory designated as a primary root). + // agent advertises {@link MultipleWorkingDirectoriesCapability.immutablePrimary} + // (some backends pin their first directory as a fixed process root). // // When absent, clients MUST NOT mutate a session's or chat's working-directory // set and MUST NOT set more than one entry in @@ -621,19 +621,17 @@ type MultipleChatsCapability struct { // Options for the {@link AgentCapabilities.multipleWorkingDirectories} capability. type MultipleWorkingDirectoriesCapability struct { - // The agent requires each chat to designate one of its working directories as - // the **primary** — a distinguished root the chat is centered on (e.g. the - // agent's process root for that chat, the default location for relative - // paths). Primary is a **per-chat** notion, fixed at chat creation. When - // `true`, a client SHOULD supply {@link CreateChatParams.primaryWorkingDirectory} - // (and {@link CreateSessionParams.primaryWorkingDirectory}, which seeds the - // session's default chat); a host MAY reject creation that omits it, or fall - // back to the first entry of the chat's working directories. The chosen - // primary is reported (read-only) on {@link ChatState.primaryWorkingDirectory}. + // The agent's **first** working directory (index `0` of + // {@link CreateSessionParams.workingDirectories}) is an immutable primary: + // it is fixed for the lifetime of the session — clients MUST NOT remove or + // reorder it. Additional directories after it remain equal peers that can be + // added and removed freely. // - // When absent or `false`, the agent has no primary — all directories are - // equal peers and clients need not designate one. - RequiresPrimary *bool `json:"requiresPrimary,omitempty"` + // Advertised by backends whose agent process is rooted at a single directory + // that cannot change once the session has started (e.g. the SDK's primary + // `workingDirectory`). When absent or `false`, all directories are equal + // peers and any of them may be removed. + ImmutablePrimary *bool `json:"immutablePrimary,omitempty"` } type SessionModelInfo struct { @@ -758,12 +756,13 @@ type SessionState struct { Project *ProjectInfo `json:"project,omitempty"` // The working directories the session's agent has tool access to, as // maintained by the `session/workingDirectorySet` / - // `session/workingDirectoryRemoved` actions. Directories are **equal peers** — - // the session has no primary. Individual chats MAY restrict to a subset via - // {@link ChatSummary.workingDirectories | their own `workingDirectories`} and - // designate one of their own directories as primary (see - // {@link ChatState.primaryWorkingDirectory}); a chat that sets no subset - // operates against this full set. + // `session/workingDirectoryRemoved` actions. Directories are equal peers + // except when the agent advertises + // {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first + // entry is then a fixed process root). Individual chats MAY restrict to a + // subset via {@link ChatSummary.workingDirectories | their own + // `workingDirectories`}; a chat that sets none operates against this full + // set. WorkingDirectories []URI `json:"workingDirectories,omitempty"` // Lightweight summary of this session's inline annotations channel // (`ahp-session://annotations`). Surfaced so badge UI can render @@ -1023,12 +1022,13 @@ type SessionSummary struct { Project *ProjectInfo `json:"project,omitempty"` // The working directories the session's agent has tool access to, as // maintained by the `session/workingDirectorySet` / - // `session/workingDirectoryRemoved` actions. Directories are **equal peers** — - // the session has no primary. Individual chats MAY restrict to a subset via - // {@link ChatSummary.workingDirectories | their own `workingDirectories`} and - // designate one of their own directories as primary (see - // {@link ChatState.primaryWorkingDirectory}); a chat that sets no subset - // operates against this full set. + // `session/workingDirectoryRemoved` actions. Directories are equal peers + // except when the agent advertises + // {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first + // entry is then a fixed process root). Individual chats MAY restrict to a + // subset via {@link ChatSummary.workingDirectories | their own + // `workingDirectories`}; a chat that sets none operates against this full + // set. WorkingDirectories []URI `json:"workingDirectories,omitempty"` // Lightweight summary of this session's inline annotations channel // (`ahp-session://annotations`). Surfaced so badge UI can render @@ -1108,19 +1108,6 @@ type ChatState struct { // Dispatch `chat/workingDirectorySet` / `chat/workingDirectoryRemoved` to // update the subset on a running chat. WorkingDirectories []URI `json:"workingDirectories,omitempty"` - // The chat's primary working directory — the distinguished root this chat is - // centered on (e.g. the agent's process root for this chat, the default - // location for relative paths). MUST be one of this chat's effective working - // directories ({@link workingDirectories}, or the session's set when that is - // absent). Present when the agent advertises - // {@link MultipleWorkingDirectoriesCapability.requiresPrimary}. - // - // **Read-only and fixed at creation.** It is set from - // {@link CreateChatParams.primaryWorkingDirectory} (or, for the session's - // default chat, {@link CreateSessionParams.primaryWorkingDirectory}) and does - // not change over the chat's lifetime — there is no action to mutate it, and - // it does not participate in `session/chatUpdated`. - PrimaryWorkingDirectory *URI `json:"primaryWorkingDirectory,omitempty"` // Completed turns Turns []Turn `json:"turns"` // Cursor for loading older completed turns into this chat state. @@ -1177,9 +1164,6 @@ type ChatSummary struct { // The subset of the session's working directories this chat uses. // See {@link ChatState.workingDirectories} for the full semantics. WorkingDirectories []URI `json:"workingDirectories,omitempty"` - // The chat's primary working directory. - // See {@link ChatState.primaryWorkingDirectory} for the full semantics. - PrimaryWorkingDirectory *URI `json:"primaryWorkingDirectory,omitempty"` } // Immutable selected-text snapshot captured when a side chat is created. diff --git a/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Actions.generated.kt b/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Actions.generated.kt index 1dd8e470..13c2ce9d 100644 --- a/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Actions.generated.kt +++ b/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Actions.generated.kt @@ -1510,12 +1510,7 @@ data class PartialChatSummary( * The subset of the session's working directories this chat uses. * See {@link ChatState.workingDirectories} for the full semantics. */ - val workingDirectories: List? = null, - /** - * The chat's primary working directory. - * See {@link ChatState.primaryWorkingDirectory} for the full semantics. - */ - val primaryWorkingDirectory: String? = null + val workingDirectories: List? = null ) // ─── StateAction Union ────────────────────────────────────────────────────── diff --git a/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Commands.generated.kt b/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Commands.generated.kt index 3d63475e..f259cb67 100644 --- a/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Commands.generated.kt +++ b/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Commands.generated.kt @@ -505,9 +505,8 @@ data class CreateSessionParams( * The working directories the session's agent is granted tool access to. * A session may span multiple directories; they are equal peers except when * the agent advertises - * {@link MultipleWorkingDirectoriesCapability.requiresPrimary}, in which case - * one of them should be designated the primary via - * {@link primaryWorkingDirectory}. + * {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (in which case + * the first entry is a fixed process root). * * A client MUST NOT supply more than one entry unless the agent advertises * {@link AgentCapabilities.multipleWorkingDirectories}; a server without that @@ -520,26 +519,6 @@ data class CreateSessionParams( * from the source session identified by `fork`. */ val workingDirectories: List? = null, - /** - * The primary working directory for the session's **default chat**. - * - * A session has no primary of its own — primary is a per-chat notion (see - * {@link ChatState.primaryWorkingDirectory}). But `createSession` implicitly - * creates the session's default chat, and there is no separate `createChat` - * call to carry that chat's create-time fields. This field is therefore the - * only place a client can designate the **default chat's** primary at birth; - * it is copied into that chat's read-only `primaryWorkingDirectory`. For any - * non-default chat, pass {@link CreateChatParams.primaryWorkingDirectory} - * instead. - * - * When set, it MUST be one of {@link workingDirectories}. A client SHOULD - * supply this when the agent advertises - * {@link MultipleWorkingDirectoriesCapability.requiresPrimary}; a host MAY - * reject creation that omits it, or fall back to the first entry of - * `workingDirectories`. Ignored for forked sessions (a fork inherits the - * source session's chats and their primaries). - */ - val primaryWorkingDirectory: String? = null, /** * Fork from an existing session. The new session is populated with content * from the source session up to and including the specified turn's response. @@ -623,19 +602,7 @@ data class CreateChatParams( * A client MUST NOT supply this field unless the agent advertises * {@link AgentCapabilities.multipleWorkingDirectories}. */ - val workingDirectories: List? = null, - /** - * The chat's primary working directory — the distinguished root this chat is - * centered on. When set, it MUST be one of the chat's effective working - * directories ({@link workingDirectories}, or the session's set when that is - * omitted). A client SHOULD supply this when the agent advertises - * {@link MultipleWorkingDirectoriesCapability.requiresPrimary}; a host MAY - * reject creation that omits it, or fall back to the first of the chat's - * directories. Fixed at creation and reported (read-only) on - * {@link ChatState.primaryWorkingDirectory}. Ignored for forks (a chat whose - * `source.kind` is `"fork"` inherits the source chat's primary). - */ - val primaryWorkingDirectory: String? = null + val workingDirectories: List? = null ) @Serializable diff --git a/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Notifications.generated.kt b/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Notifications.generated.kt index 392401e9..64e93a15 100644 --- a/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Notifications.generated.kt +++ b/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Notifications.generated.kt @@ -198,12 +198,13 @@ data class PartialSessionSummary( /** * The working directories the session's agent has tool access to, as * maintained by the `session/workingDirectorySet` / - * `session/workingDirectoryRemoved` actions. Directories are **equal peers** — - * the session has no primary. Individual chats MAY restrict to a subset via - * {@link ChatSummary.workingDirectories | their own `workingDirectories`} and - * designate one of their own directories as primary (see - * {@link ChatState.primaryWorkingDirectory}); a chat that sets no subset - * operates against this full set. + * `session/workingDirectoryRemoved` actions. Directories are equal peers + * except when the agent advertises + * {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first + * entry is then a fixed process root). Individual chats MAY restrict to a + * subset via {@link ChatSummary.workingDirectories | their own + * `workingDirectories`}; a chat that sets none operates against this full + * set. */ val workingDirectories: List? = null, /** diff --git a/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/State.generated.kt b/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/State.generated.kt index 749be0b3..d59c267b 100644 --- a/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/State.generated.kt +++ b/clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/State.generated.kt @@ -965,8 +965,8 @@ data class AgentCapabilities( /** * The session's agent can be granted tool access to more than one working * directory. The directories are treated as equal peers except where the - * agent advertises {@link MultipleWorkingDirectoriesCapability.requiresPrimary} - * (some backends need one directory designated as a primary root). + * agent advertises {@link MultipleWorkingDirectoriesCapability.immutablePrimary} + * (some backends pin their first directory as a fixed process root). * * When absent, clients MUST NOT mutate a session's or chat's working-directory * set and MUST NOT set more than one entry in @@ -1002,20 +1002,18 @@ data class MultipleChatsCapability( @Serializable data class MultipleWorkingDirectoriesCapability( /** - * The agent requires each chat to designate one of its working directories as - * the **primary** — a distinguished root the chat is centered on (e.g. the - * agent's process root for that chat, the default location for relative - * paths). Primary is a **per-chat** notion, fixed at chat creation. When - * `true`, a client SHOULD supply {@link CreateChatParams.primaryWorkingDirectory} - * (and {@link CreateSessionParams.primaryWorkingDirectory}, which seeds the - * session's default chat); a host MAY reject creation that omits it, or fall - * back to the first entry of the chat's working directories. The chosen - * primary is reported (read-only) on {@link ChatState.primaryWorkingDirectory}. + * The agent's **first** working directory (index `0` of + * {@link CreateSessionParams.workingDirectories}) is an immutable primary: + * it is fixed for the lifetime of the session — clients MUST NOT remove or + * reorder it. Additional directories after it remain equal peers that can be + * added and removed freely. * - * When absent or `false`, the agent has no primary — all directories are - * equal peers and clients need not designate one. + * Advertised by backends whose agent process is rooted at a single directory + * that cannot change once the session has started (e.g. the SDK's primary + * `workingDirectory`). When absent or `false`, all directories are equal + * peers and any of them may be removed. */ - val requiresPrimary: Boolean? = null + val immutablePrimary: Boolean? = null ) @Serializable @@ -1218,21 +1216,6 @@ data class ChatState( * update the subset on a running chat. */ val workingDirectories: List? = null, - /** - * The chat's primary working directory — the distinguished root this chat is - * centered on (e.g. the agent's process root for this chat, the default - * location for relative paths). MUST be one of this chat's effective working - * directories ({@link workingDirectories}, or the session's set when that is - * absent). Present when the agent advertises - * {@link MultipleWorkingDirectoriesCapability.requiresPrimary}. - * - * **Read-only and fixed at creation.** It is set from - * {@link CreateChatParams.primaryWorkingDirectory} (or, for the session's - * default chat, {@link CreateSessionParams.primaryWorkingDirectory}) and does - * not change over the chat's lifetime — there is no action to mutate it, and - * it does not participate in `session/chatUpdated`. - */ - val primaryWorkingDirectory: String? = null, /** * Completed turns */ @@ -1317,12 +1300,7 @@ data class ChatSummary( * The subset of the session's working directories this chat uses. * See {@link ChatState.workingDirectories} for the full semantics. */ - val workingDirectories: List? = null, - /** - * The chat's primary working directory. - * See {@link ChatState.primaryWorkingDirectory} for the full semantics. - */ - val primaryWorkingDirectory: String? = null + val workingDirectories: List? = null ) @Serializable @@ -1368,12 +1346,13 @@ data class SessionState( /** * The working directories the session's agent has tool access to, as * maintained by the `session/workingDirectorySet` / - * `session/workingDirectoryRemoved` actions. Directories are **equal peers** — - * the session has no primary. Individual chats MAY restrict to a subset via - * {@link ChatSummary.workingDirectories | their own `workingDirectories`} and - * designate one of their own directories as primary (see - * {@link ChatState.primaryWorkingDirectory}); a chat that sets no subset - * operates against this full set. + * `session/workingDirectoryRemoved` actions. Directories are equal peers + * except when the agent advertises + * {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first + * entry is then a fixed process root). Individual chats MAY restrict to a + * subset via {@link ChatSummary.workingDirectories | their own + * `workingDirectories`}; a chat that sets none operates against this full + * set. */ val workingDirectories: List? = null, /** @@ -1641,12 +1620,13 @@ data class SessionSummary( /** * The working directories the session's agent has tool access to, as * maintained by the `session/workingDirectorySet` / - * `session/workingDirectoryRemoved` actions. Directories are **equal peers** — - * the session has no primary. Individual chats MAY restrict to a subset via - * {@link ChatSummary.workingDirectories | their own `workingDirectories`} and - * designate one of their own directories as primary (see - * {@link ChatState.primaryWorkingDirectory}); a chat that sets no subset - * operates against this full set. + * `session/workingDirectoryRemoved` actions. Directories are equal peers + * except when the agent advertises + * {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first + * entry is then a fixed process root). Individual chats MAY restrict to a + * subset via {@link ChatSummary.workingDirectories | their own + * `workingDirectories`}; a chat that sets none operates against this full + * set. */ val workingDirectories: List? = null, /** diff --git a/clients/rust/crates/ahp-types/src/actions.rs b/clients/rust/crates/ahp-types/src/actions.rs index 1ff1b20f..e021f88d 100644 --- a/clients/rust/crates/ahp-types/src/actions.rs +++ b/clients/rust/crates/ahp-types/src/actions.rs @@ -954,8 +954,8 @@ pub struct SessionWorkingDirectorySetAction { /// Removes `directory` from the set; a no-op when it is not present. There is no /// atomic backend "remove one" primitive — a host reconfigures its agent to the /// reduced set — so this action is safe to model as idempotent. A host MAY -/// decline to apply the removal (e.g. a directory still designated as some -/// chat's {@link ChatState.primaryWorkingDirectory | primary}); it then leaves +/// decline to apply the removal (e.g. an immutable primary directory, see +/// {@link MultipleWorkingDirectoriesCapability.immutablePrimary}); it then leaves /// the set unchanged. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -1762,10 +1762,6 @@ pub struct PartialChatSummary { /// See {@link ChatState.workingDirectories} for the full semantics. #[serde(default, skip_serializing_if = "Option::is_none")] pub working_directories: Option>, - /// The chat's primary working directory. - /// See {@link ChatState.primaryWorkingDirectory} for the full semantics. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub primary_working_directory: Option, } // ─── StateAction Union ─────────────────────────────────────────────── diff --git a/clients/rust/crates/ahp-types/src/commands.rs b/clients/rust/crates/ahp-types/src/commands.rs index 6f33ec46..565ea531 100644 --- a/clients/rust/crates/ahp-types/src/commands.rs +++ b/clients/rust/crates/ahp-types/src/commands.rs @@ -405,9 +405,8 @@ pub struct CreateSessionParams { /// The working directories the session's agent is granted tool access to. /// A session may span multiple directories; they are equal peers except when /// the agent advertises - /// {@link MultipleWorkingDirectoriesCapability.requiresPrimary}, in which case - /// one of them should be designated the primary via - /// {@link primaryWorkingDirectory}. + /// {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (in which case + /// the first entry is a fixed process root). /// /// A client MUST NOT supply more than one entry unless the agent advertises /// {@link AgentCapabilities.multipleWorkingDirectories}; a server without that @@ -420,25 +419,6 @@ pub struct CreateSessionParams { /// from the source session identified by `fork`. #[serde(default, skip_serializing_if = "Option::is_none")] pub working_directories: Option>, - /// The primary working directory for the session's **default chat**. - /// - /// A session has no primary of its own — primary is a per-chat notion (see - /// {@link ChatState.primaryWorkingDirectory}). But `createSession` implicitly - /// creates the session's default chat, and there is no separate `createChat` - /// call to carry that chat's create-time fields. This field is therefore the - /// only place a client can designate the **default chat's** primary at birth; - /// it is copied into that chat's read-only `primaryWorkingDirectory`. For any - /// non-default chat, pass {@link CreateChatParams.primaryWorkingDirectory} - /// instead. - /// - /// When set, it MUST be one of {@link workingDirectories}. A client SHOULD - /// supply this when the agent advertises - /// {@link MultipleWorkingDirectoriesCapability.requiresPrimary}; a host MAY - /// reject creation that omits it, or fall back to the first entry of - /// `workingDirectories`. Ignored for forked sessions (a fork inherits the - /// source session's chats and their primaries). - #[serde(default, skip_serializing_if = "Option::is_none")] - pub primary_working_directory: Option, /// Fork from an existing session. The new session is populated with content /// from the source session up to and including the specified turn's response. #[serde(default, skip_serializing_if = "Option::is_none")] @@ -553,17 +533,6 @@ pub struct CreateChatParams { /// {@link AgentCapabilities.multipleWorkingDirectories}. #[serde(default, skip_serializing_if = "Option::is_none")] pub working_directories: Option>, - /// The chat's primary working directory — the distinguished root this chat is - /// centered on. When set, it MUST be one of the chat's effective working - /// directories ({@link workingDirectories}, or the session's set when that is - /// omitted). A client SHOULD supply this when the agent advertises - /// {@link MultipleWorkingDirectoriesCapability.requiresPrimary}; a host MAY - /// reject creation that omits it, or fall back to the first of the chat's - /// directories. Fixed at creation and reported (read-only) on - /// {@link ChatState.primaryWorkingDirectory}. Ignored for forks (a chat whose - /// `source.kind` is `"fork"` inherits the source chat's primary). - #[serde(default, skip_serializing_if = "Option::is_none")] - pub primary_working_directory: Option, } /// Disposes a chat and cleans up server-side resources. diff --git a/clients/rust/crates/ahp-types/src/notifications.rs b/clients/rust/crates/ahp-types/src/notifications.rs index e56151bf..e54e9376 100644 --- a/clients/rust/crates/ahp-types/src/notifications.rs +++ b/clients/rust/crates/ahp-types/src/notifications.rs @@ -250,12 +250,13 @@ pub struct PartialSessionSummary { pub project: Option, /// The working directories the session's agent has tool access to, as /// maintained by the `session/workingDirectorySet` / - /// `session/workingDirectoryRemoved` actions. Directories are **equal peers** — - /// the session has no primary. Individual chats MAY restrict to a subset via - /// {@link ChatSummary.workingDirectories | their own `workingDirectories`} and - /// designate one of their own directories as primary (see - /// {@link ChatState.primaryWorkingDirectory}); a chat that sets no subset - /// operates against this full set. + /// `session/workingDirectoryRemoved` actions. Directories are equal peers + /// except when the agent advertises + /// {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first + /// entry is then a fixed process root). Individual chats MAY restrict to a + /// subset via {@link ChatSummary.workingDirectories | their own + /// `workingDirectories`}; a chat that sets none operates against this full + /// set. #[serde(default, skip_serializing_if = "Option::is_none")] pub working_directories: Option>, /// Lightweight summary of this session's inline annotations channel diff --git a/clients/rust/crates/ahp-types/src/state.rs b/clients/rust/crates/ahp-types/src/state.rs index 2d95a162..432c8cff 100644 --- a/clients/rust/crates/ahp-types/src/state.rs +++ b/clients/rust/crates/ahp-types/src/state.rs @@ -810,8 +810,8 @@ pub struct AgentCapabilities { pub multiple_chats: Option, /// The session's agent can be granted tool access to more than one working /// directory. The directories are treated as equal peers except where the - /// agent advertises {@link MultipleWorkingDirectoriesCapability.requiresPrimary} - /// (some backends need one directory designated as a primary root). + /// agent advertises {@link MultipleWorkingDirectoriesCapability.immutablePrimary} + /// (some backends pin their first directory as a fixed process root). /// /// When absent, clients MUST NOT mutate a session's or chat's working-directory /// set and MUST NOT set more than one entry in @@ -848,20 +848,18 @@ pub struct MultipleChatsCapability { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] #[serde(rename_all = "camelCase")] pub struct MultipleWorkingDirectoriesCapability { - /// The agent requires each chat to designate one of its working directories as - /// the **primary** — a distinguished root the chat is centered on (e.g. the - /// agent's process root for that chat, the default location for relative - /// paths). Primary is a **per-chat** notion, fixed at chat creation. When - /// `true`, a client SHOULD supply {@link CreateChatParams.primaryWorkingDirectory} - /// (and {@link CreateSessionParams.primaryWorkingDirectory}, which seeds the - /// session's default chat); a host MAY reject creation that omits it, or fall - /// back to the first entry of the chat's working directories. The chosen - /// primary is reported (read-only) on {@link ChatState.primaryWorkingDirectory}. + /// The agent's **first** working directory (index `0` of + /// {@link CreateSessionParams.workingDirectories}) is an immutable primary: + /// it is fixed for the lifetime of the session — clients MUST NOT remove or + /// reorder it. Additional directories after it remain equal peers that can be + /// added and removed freely. /// - /// When absent or `false`, the agent has no primary — all directories are - /// equal peers and clients need not designate one. + /// Advertised by backends whose agent process is rooted at a single directory + /// that cannot change once the session has started (e.g. the SDK's primary + /// `workingDirectory`). When absent or `false`, all directories are equal + /// peers and any of them may be removed. #[serde(default, skip_serializing_if = "Option::is_none")] - pub requires_primary: Option, + pub immutable_primary: Option, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -1057,20 +1055,6 @@ pub struct ChatState { /// update the subset on a running chat. #[serde(default, skip_serializing_if = "Option::is_none")] pub working_directories: Option>, - /// The chat's primary working directory — the distinguished root this chat is - /// centered on (e.g. the agent's process root for this chat, the default - /// location for relative paths). MUST be one of this chat's effective working - /// directories ({@link workingDirectories}, or the session's set when that is - /// absent). Present when the agent advertises - /// {@link MultipleWorkingDirectoriesCapability.requiresPrimary}. - /// - /// **Read-only and fixed at creation.** It is set from - /// {@link CreateChatParams.primaryWorkingDirectory} (or, for the session's - /// default chat, {@link CreateSessionParams.primaryWorkingDirectory}) and does - /// not change over the chat's lifetime — there is no action to mutate it, and - /// it does not participate in `session/chatUpdated`. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub primary_working_directory: Option, /// Completed turns pub turns: Vec, /// Cursor for loading older completed turns into this chat state. @@ -1139,10 +1123,6 @@ pub struct ChatSummary { /// See {@link ChatState.workingDirectories} for the full semantics. #[serde(default, skip_serializing_if = "Option::is_none")] pub working_directories: Option>, - /// The chat's primary working directory. - /// See {@link ChatState.primaryWorkingDirectory} for the full semantics. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub primary_working_directory: Option, } /// Immutable selected-text snapshot captured when a side chat is created. @@ -1189,12 +1169,13 @@ pub struct SessionState { pub project: Option, /// The working directories the session's agent has tool access to, as /// maintained by the `session/workingDirectorySet` / - /// `session/workingDirectoryRemoved` actions. Directories are **equal peers** — - /// the session has no primary. Individual chats MAY restrict to a subset via - /// {@link ChatSummary.workingDirectories | their own `workingDirectories`} and - /// designate one of their own directories as primary (see - /// {@link ChatState.primaryWorkingDirectory}); a chat that sets no subset - /// operates against this full set. + /// `session/workingDirectoryRemoved` actions. Directories are equal peers + /// except when the agent advertises + /// {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first + /// entry is then a fixed process root). Individual chats MAY restrict to a + /// subset via {@link ChatSummary.workingDirectories | their own + /// `workingDirectories`}; a chat that sets none operates against this full + /// set. #[serde(default, skip_serializing_if = "Option::is_none")] pub working_directories: Option>, /// Lightweight summary of this session's inline annotations channel @@ -1476,12 +1457,13 @@ pub struct SessionSummary { pub project: Option, /// The working directories the session's agent has tool access to, as /// maintained by the `session/workingDirectorySet` / - /// `session/workingDirectoryRemoved` actions. Directories are **equal peers** — - /// the session has no primary. Individual chats MAY restrict to a subset via - /// {@link ChatSummary.workingDirectories | their own `workingDirectories`} and - /// designate one of their own directories as primary (see - /// {@link ChatState.primaryWorkingDirectory}); a chat that sets no subset - /// operates against this full set. + /// `session/workingDirectoryRemoved` actions. Directories are equal peers + /// except when the agent advertises + /// {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first + /// entry is then a fixed process root). Individual chats MAY restrict to a + /// subset via {@link ChatSummary.workingDirectories | their own + /// `workingDirectories`}; a chat that sets none operates against this full + /// set. #[serde(default, skip_serializing_if = "Option::is_none")] pub working_directories: Option>, /// Lightweight summary of this session's inline annotations channel diff --git a/clients/rust/crates/ahp/src/reducers.rs b/clients/rust/crates/ahp/src/reducers.rs index 473e632c..e2b22e53 100644 --- a/clients/rust/crates/ahp/src/reducers.rs +++ b/clients/rust/crates/ahp/src/reducers.rs @@ -1974,7 +1974,6 @@ mod tests { origin: None, interactivity: None, working_directories: None, - primary_working_directory: None, turns: Vec::new(), turns_next_cursor: None, active_turn: None, @@ -2071,7 +2070,6 @@ mod tests { origin: None, interactivity: None, working_directories: None, - primary_working_directory: None, }; let added = StateAction::SessionChatAdded(ahp_types::actions::SessionChatAddedAction { summary: chat.clone(), diff --git a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Actions.generated.swift b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Actions.generated.swift index 2e1b3f56..d9ac6ee1 100644 --- a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Actions.generated.swift +++ b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Actions.generated.swift @@ -1979,9 +1979,6 @@ public struct PartialChatSummary: Codable, Sendable { /// The subset of the session's working directories this chat uses. /// See {@link ChatState.workingDirectories} for the full semantics. public var workingDirectories: [String]? - /// The chat's primary working directory. - /// See {@link ChatState.primaryWorkingDirectory} for the full semantics. - public var primaryWorkingDirectory: String? public init( resource: String? = nil, @@ -1991,8 +1988,7 @@ public struct PartialChatSummary: Codable, Sendable { modifiedAt: String? = nil, origin: ChatOrigin? = nil, interactivity: ChatInteractivity? = nil, - workingDirectories: [String]? = nil, - primaryWorkingDirectory: String? = nil + workingDirectories: [String]? = nil ) { self.resource = resource self.title = title @@ -2002,7 +1998,6 @@ public struct PartialChatSummary: Codable, Sendable { self.origin = origin self.interactivity = interactivity self.workingDirectories = workingDirectories - self.primaryWorkingDirectory = primaryWorkingDirectory } } diff --git a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Commands.generated.swift b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Commands.generated.swift index 00f32732..4abe4305 100644 --- a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Commands.generated.swift +++ b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Commands.generated.swift @@ -465,9 +465,8 @@ public struct CreateSessionParams: Codable, Sendable { /// The working directories the session's agent is granted tool access to. /// A session may span multiple directories; they are equal peers except when /// the agent advertises - /// {@link MultipleWorkingDirectoriesCapability.requiresPrimary}, in which case - /// one of them should be designated the primary via - /// {@link primaryWorkingDirectory}. + /// {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (in which case + /// the first entry is a fixed process root). /// /// A client MUST NOT supply more than one entry unless the agent advertises /// {@link AgentCapabilities.multipleWorkingDirectories}; a server without that @@ -479,24 +478,6 @@ public struct CreateSessionParams: Codable, Sendable { /// Ignored for forked sessions — a fork inherits its working directories /// from the source session identified by `fork`. public var workingDirectories: [String]? - /// The primary working directory for the session's **default chat**. - /// - /// A session has no primary of its own — primary is a per-chat notion (see - /// {@link ChatState.primaryWorkingDirectory}). But `createSession` implicitly - /// creates the session's default chat, and there is no separate `createChat` - /// call to carry that chat's create-time fields. This field is therefore the - /// only place a client can designate the **default chat's** primary at birth; - /// it is copied into that chat's read-only `primaryWorkingDirectory`. For any - /// non-default chat, pass {@link CreateChatParams.primaryWorkingDirectory} - /// instead. - /// - /// When set, it MUST be one of {@link workingDirectories}. A client SHOULD - /// supply this when the agent advertises - /// {@link MultipleWorkingDirectoriesCapability.requiresPrimary}; a host MAY - /// reject creation that omits it, or fall back to the first entry of - /// `workingDirectories`. Ignored for forked sessions (a fork inherits the - /// source session's chats and their primaries). - public var primaryWorkingDirectory: String? /// Fork from an existing session. The new session is populated with content /// from the source session up to and including the specified turn's response. public var fork: SessionForkSource? @@ -526,7 +507,6 @@ public struct CreateSessionParams: Codable, Sendable { channel: String, provider: String? = nil, workingDirectories: [String]? = nil, - primaryWorkingDirectory: String? = nil, fork: SessionForkSource? = nil, config: [String: AnyCodable]? = nil, activeClient: SessionActiveClient? = nil, @@ -535,7 +515,6 @@ public struct CreateSessionParams: Codable, Sendable { self.channel = channel self.provider = provider self.workingDirectories = workingDirectories - self.primaryWorkingDirectory = primaryWorkingDirectory self.fork = fork self.config = config self.activeClient = activeClient @@ -585,31 +564,19 @@ public struct CreateChatParams: Codable, Sendable { /// A client MUST NOT supply this field unless the agent advertises /// {@link AgentCapabilities.multipleWorkingDirectories}. public var workingDirectories: [String]? - /// The chat's primary working directory — the distinguished root this chat is - /// centered on. When set, it MUST be one of the chat's effective working - /// directories ({@link workingDirectories}, or the session's set when that is - /// omitted). A client SHOULD supply this when the agent advertises - /// {@link MultipleWorkingDirectoriesCapability.requiresPrimary}; a host MAY - /// reject creation that omits it, or fall back to the first of the chat's - /// directories. Fixed at creation and reported (read-only) on - /// {@link ChatState.primaryWorkingDirectory}. Ignored for forks (a chat whose - /// `source.kind` is `"fork"` inherits the source chat's primary). - public var primaryWorkingDirectory: String? public init( channel: String, chat: String, initialMessage: Message? = nil, source: ChatSource? = nil, - workingDirectories: [String]? = nil, - primaryWorkingDirectory: String? = nil + workingDirectories: [String]? = nil ) { self.channel = channel self.chat = chat self.initialMessage = initialMessage self.source = source self.workingDirectories = workingDirectories - self.primaryWorkingDirectory = primaryWorkingDirectory } } diff --git a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Notifications.generated.swift b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Notifications.generated.swift index 7c24cd6a..4ffbb95c 100644 --- a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Notifications.generated.swift +++ b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Notifications.generated.swift @@ -184,12 +184,13 @@ public struct PartialSessionSummary: Codable, Sendable { public var project: ProjectInfo? /// The working directories the session's agent has tool access to, as /// maintained by the `session/workingDirectorySet` / - /// `session/workingDirectoryRemoved` actions. Directories are **equal peers** — - /// the session has no primary. Individual chats MAY restrict to a subset via - /// {@link ChatSummary.workingDirectories | their own `workingDirectories`} and - /// designate one of their own directories as primary (see - /// {@link ChatState.primaryWorkingDirectory}); a chat that sets no subset - /// operates against this full set. + /// `session/workingDirectoryRemoved` actions. Directories are equal peers + /// except when the agent advertises + /// {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first + /// entry is then a fixed process root). Individual chats MAY restrict to a + /// subset via {@link ChatSummary.workingDirectories | their own + /// `workingDirectories`}; a chat that sets none operates against this full + /// set. public var workingDirectories: [String]? /// Lightweight summary of this session's inline annotations channel /// (`ahp-session://annotations`). Surfaced so badge UI can render diff --git a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/State.generated.swift b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/State.generated.swift index 3dd42a34..58dc1d77 100644 --- a/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/State.generated.swift +++ b/clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/State.generated.swift @@ -638,8 +638,8 @@ public struct AgentCapabilities: Codable, Sendable { public var multipleChats: MultipleChatsCapability? /// The session's agent can be granted tool access to more than one working /// directory. The directories are treated as equal peers except where the - /// agent advertises {@link MultipleWorkingDirectoriesCapability.requiresPrimary} - /// (some backends need one directory designated as a primary root). + /// agent advertises {@link MultipleWorkingDirectoriesCapability.immutablePrimary} + /// (some backends pin their first directory as a fixed process root). /// /// When absent, clients MUST NOT mutate a session's or chat's working-directory /// set and MUST NOT set more than one entry in @@ -683,24 +683,22 @@ public struct MultipleChatsCapability: Codable, Sendable { } public struct MultipleWorkingDirectoriesCapability: Codable, Sendable { - /// The agent requires each chat to designate one of its working directories as - /// the **primary** — a distinguished root the chat is centered on (e.g. the - /// agent's process root for that chat, the default location for relative - /// paths). Primary is a **per-chat** notion, fixed at chat creation. When - /// `true`, a client SHOULD supply {@link CreateChatParams.primaryWorkingDirectory} - /// (and {@link CreateSessionParams.primaryWorkingDirectory}, which seeds the - /// session's default chat); a host MAY reject creation that omits it, or fall - /// back to the first entry of the chat's working directories. The chosen - /// primary is reported (read-only) on {@link ChatState.primaryWorkingDirectory}. + /// The agent's **first** working directory (index `0` of + /// {@link CreateSessionParams.workingDirectories}) is an immutable primary: + /// it is fixed for the lifetime of the session — clients MUST NOT remove or + /// reorder it. Additional directories after it remain equal peers that can be + /// added and removed freely. /// - /// When absent or `false`, the agent has no primary — all directories are - /// equal peers and clients need not designate one. - public var requiresPrimary: Bool? + /// Advertised by backends whose agent process is rooted at a single directory + /// that cannot change once the session has started (e.g. the SDK's primary + /// `workingDirectory`). When absent or `false`, all directories are equal + /// peers and any of them may be removed. + public var immutablePrimary: Bool? public init( - requiresPrimary: Bool? = nil + immutablePrimary: Bool? = nil ) { - self.requiresPrimary = requiresPrimary + self.immutablePrimary = immutablePrimary } } @@ -932,19 +930,6 @@ public struct ChatState: Codable, Sendable { /// Dispatch `chat/workingDirectorySet` / `chat/workingDirectoryRemoved` to /// update the subset on a running chat. public var workingDirectories: [String]? - /// The chat's primary working directory — the distinguished root this chat is - /// centered on (e.g. the agent's process root for this chat, the default - /// location for relative paths). MUST be one of this chat's effective working - /// directories ({@link workingDirectories}, or the session's set when that is - /// absent). Present when the agent advertises - /// {@link MultipleWorkingDirectoriesCapability.requiresPrimary}. - /// - /// **Read-only and fixed at creation.** It is set from - /// {@link CreateChatParams.primaryWorkingDirectory} (or, for the session's - /// default chat, {@link CreateSessionParams.primaryWorkingDirectory}) and does - /// not change over the chat's lifetime — there is no action to mutate it, and - /// it does not participate in `session/chatUpdated`. - public var primaryWorkingDirectory: String? /// Completed turns public var turns: [Turn] /// Cursor for loading older completed turns into this chat state. @@ -984,7 +969,6 @@ public struct ChatState: Codable, Sendable { case origin case interactivity case workingDirectories - case primaryWorkingDirectory case turns case turnsNextCursor case activeTurn @@ -1003,7 +987,6 @@ public struct ChatState: Codable, Sendable { origin: ChatOrigin? = nil, interactivity: ChatInteractivity? = nil, workingDirectories: [String]? = nil, - primaryWorkingDirectory: String? = nil, turns: [Turn], turnsNextCursor: String? = nil, activeTurn: ActiveTurn? = nil, @@ -1020,7 +1003,6 @@ public struct ChatState: Codable, Sendable { self.origin = origin self.interactivity = interactivity self.workingDirectories = workingDirectories - self.primaryWorkingDirectory = primaryWorkingDirectory self.turns = turns self.turnsNextCursor = turnsNextCursor self.activeTurn = activeTurn @@ -1053,9 +1035,6 @@ public struct ChatSummary: Codable, Sendable { /// The subset of the session's working directories this chat uses. /// See {@link ChatState.workingDirectories} for the full semantics. public var workingDirectories: [String]? - /// The chat's primary working directory. - /// See {@link ChatState.primaryWorkingDirectory} for the full semantics. - public var primaryWorkingDirectory: String? public init( resource: String, @@ -1065,8 +1044,7 @@ public struct ChatSummary: Codable, Sendable { modifiedAt: String, origin: ChatOrigin? = nil, interactivity: ChatInteractivity? = nil, - workingDirectories: [String]? = nil, - primaryWorkingDirectory: String? = nil + workingDirectories: [String]? = nil ) { self.resource = resource self.title = title @@ -1076,7 +1054,6 @@ public struct ChatSummary: Codable, Sendable { self.origin = origin self.interactivity = interactivity self.workingDirectories = workingDirectories - self.primaryWorkingDirectory = primaryWorkingDirectory } } @@ -1114,12 +1091,13 @@ public struct SessionState: Codable, Sendable { public var project: ProjectInfo? /// The working directories the session's agent has tool access to, as /// maintained by the `session/workingDirectorySet` / - /// `session/workingDirectoryRemoved` actions. Directories are **equal peers** — - /// the session has no primary. Individual chats MAY restrict to a subset via - /// {@link ChatSummary.workingDirectories | their own `workingDirectories`} and - /// designate one of their own directories as primary (see - /// {@link ChatState.primaryWorkingDirectory}); a chat that sets no subset - /// operates against this full set. + /// `session/workingDirectoryRemoved` actions. Directories are equal peers + /// except when the agent advertises + /// {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first + /// entry is then a fixed process root). Individual chats MAY restrict to a + /// subset via {@link ChatSummary.workingDirectories | their own + /// `workingDirectories`}; a chat that sets none operates against this full + /// set. public var workingDirectories: [String]? /// Lightweight summary of this session's inline annotations channel /// (`ahp-session://annotations`). Surfaced so badge UI can render @@ -1433,12 +1411,13 @@ public struct SessionSummary: Codable, Sendable { public var project: ProjectInfo? /// The working directories the session's agent has tool access to, as /// maintained by the `session/workingDirectorySet` / - /// `session/workingDirectoryRemoved` actions. Directories are **equal peers** — - /// the session has no primary. Individual chats MAY restrict to a subset via - /// {@link ChatSummary.workingDirectories | their own `workingDirectories`} and - /// designate one of their own directories as primary (see - /// {@link ChatState.primaryWorkingDirectory}); a chat that sets no subset - /// operates against this full set. + /// `session/workingDirectoryRemoved` actions. Directories are equal peers + /// except when the agent advertises + /// {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first + /// entry is then a fixed process root). Individual chats MAY restrict to a + /// subset via {@link ChatSummary.workingDirectories | their own + /// `workingDirectories`}; a chat that sets none operates against this full + /// set. public var workingDirectories: [String]? /// Lightweight summary of this session's inline annotations channel /// (`ahp-session://annotations`). Surfaced so badge UI can render diff --git a/docs/.changes/20260716-multiroot-sessions.json b/docs/.changes/20260716-multiroot-sessions.json index b52dbaac..627ede38 100644 --- a/docs/.changes/20260716-multiroot-sessions.json +++ b/docs/.changes/20260716-multiroot-sessions.json @@ -1,5 +1,5 @@ { "type": "added", - "message": "Multiroot session support: `AgentCapabilities.multipleWorkingDirectories` capability (with `requiresPrimary`), `CreateSessionParams.workingDirectories` and `SessionMetadata.workingDirectories` (an equal-peer set, mirrored onto `SessionState`/`SessionSummary`), `CreateChatParams.workingDirectories` and `ChatState`/`ChatSummary.workingDirectories` (a subset of the session's set), a per-chat read-only `ChatState`/`ChatSummary.primaryWorkingDirectory` (fixed at chat creation; set via `CreateChatParams.primaryWorkingDirectory`, or `CreateSessionParams.primaryWorkingDirectory` for the default chat), and the client-dispatchable `session/workingDirectorySet` / `session/workingDirectoryRemoved` and `chat/workingDirectorySet` / `chat/workingDirectoryRemoved` actions for mutating those sets.", + "message": "Multiroot session support: `AgentCapabilities.multipleWorkingDirectories` capability (with `immutablePrimary`, which pins `workingDirectories[0]` as a fixed primary root that clients MUST NOT remove or reorder), `CreateSessionParams.workingDirectories` and `SessionMetadata.workingDirectories` (equal-peer set, mirrored onto `SessionState`/`SessionSummary`), `CreateChatParams.workingDirectories` and `ChatState`/`ChatSummary.workingDirectories` (a subset of the session's set), and the client-dispatchable `session/workingDirectorySet` / `session/workingDirectoryRemoved` and `chat/workingDirectorySet` / `chat/workingDirectoryRemoved` actions for mutating those sets.", "issues": [337] } diff --git a/docs/guide/state-model.md b/docs/guide/state-model.md index b6d466a1..ab9f1458 100644 --- a/docs/guide/state-model.md +++ b/docs/guide/state-model.md @@ -151,7 +151,6 @@ ChatState { modifiedAt: string origin?: ChatOrigin // how the chat came to exist (user / fork / sideChat / tool) workingDirectories?: URI[] // subset of session's workingDirectories - primaryWorkingDirectory?: URI // this chat's primary, read-only (set at creation, when requiresPrimary) turns: Turn[] // completed turns turnsNextCursor?: string // page older turns via fetchTurns @@ -577,16 +576,16 @@ The forked session is an independent copy — subsequent changes to either sessi ## Multiroot Sessions A session can be granted tool access to more than one working directory when the -agent advertises the `multipleWorkingDirectories` capability. At the session -level the directories are always **equal peers** — a session has no primary. A -**primary** is a per-chat notion (see [below](#per-chat-working-directory-subsets)); -the session simply owns the set every chat draws from. +agent advertises the `multipleWorkingDirectories` capability. The directories are +**equal peers** unless the agent advertises +`multipleWorkingDirectories.immutablePrimary`, in which case the first entry +(`workingDirectories[0]`) is a fixed primary root that clients MUST NOT remove or +reorder — the remaining entries stay equal peers that can be added and removed +freely. ### Creating a multiroot session -Pass `workingDirectories` (plural) in `createSession`. When the agent -`requiresPrimary`, also pass `primaryWorkingDirectory` — it seeds the primary of -the session's **default chat** (the session itself stores no primary): +Pass `workingDirectories` (plural) in `createSession`: ```typescript createSession({ @@ -596,7 +595,6 @@ createSession({ 'file:///workspace/frontend', 'file:///workspace/backend', ], - primaryWorkingDirectory: 'file:///workspace/frontend', // seeds default chat, when requiresPrimary }); ``` @@ -604,21 +602,12 @@ A client MUST NOT pass more than one entry unless the agent advertises `multipleWorkingDirectories`. Servers without that capability treat only the first entry as the session's working directory and ignore the rest. -When the agent advertises `multipleWorkingDirectories.requiresPrimary`, a client -SHOULD supply `primaryWorkingDirectory` (which MUST be one of -`workingDirectories`); a host MAY reject a creation that omits it, or fall back -to the first entry. It becomes the default chat's read-only -`ChatState.primaryWorkingDirectory`. +When the agent advertises `multipleWorkingDirectories.immutablePrimary`, the +first entry (`workingDirectories[0]`) is a fixed process root for the lifetime of +the session — clients MUST NOT remove or reorder it. -> **Why is `primaryWorkingDirectory` on `createSession` if the session has no -> primary?** Because `createSession` implicitly creates the session's **default -> chat**, and there is no separate `createChat` call to carry that chat's -> create-time fields. This field is the only place to designate the default -> chat's primary at birth. For any additional chat, pass its primary to -> `createChat` instead. - -Forked sessions ignore `workingDirectories` / `primaryWorkingDirectory` — they -inherit the working directories (and per-chat primaries) of the source session. +Forked sessions ignore `workingDirectories` — they inherit the working +directories of the source session. ### Managing directories after creation @@ -628,12 +617,20 @@ mutate it by **dispatching actions**, not by calling commands: | Action | Effect | | --- | --- | | `session/workingDirectorySet` | Adds `directory` to the set (creating it if absent). A no-op when the directory is already present. | -| `session/workingDirectoryRemoved` | Removes `directory` from the set. A no-op when it is not present. There is no atomic backend "remove one" primitive — the host reconfigures its agent to the reduced set. A host MAY decline to apply the removal (e.g. a directory still designated as some chat's primary), leaving the set unchanged. | +| `session/workingDirectoryRemoved` | Removes `directory` from the set. A no-op when it is not present. There is no atomic backend "remove one" primitive — the host reconfigures its agent to the reduced set. A host MAY decline to apply the removal (e.g. the immutable primary at index 0), leaving the set unchanged. | Both are `@clientDispatchable`. The resulting set is observed on `SessionState.workingDirectories` like any other state — there is no separate result payload. +> **How the immutable primary is enforced.** The pure reducers apply these +> mutations verbatim — `session/workingDirectorySet` appends, and +> `session/workingDirectoryRemoved` removes by value and *will* drop +> `workingDirectories[0]` if handed such an action. The `immutablePrimary` +> guarantee therefore lives at the **dispatch-validation / host-acceptance** +> layer, not in the reducer: a client MUST NOT dispatch a removal (or reorder) of +> the primary, and a host MAY reject or reconcile one that arrives. + Before dispatching either action, a client MUST verify that the agent advertises `multipleWorkingDirectories`. @@ -648,31 +645,22 @@ The effective set for a chat is recorded in `ChatState.workingDirectories` / `ChatSummary.workingDirectories`. When absent the chat inherits the full session set. -A chat also designates its own **primary** working directory — -`ChatState.primaryWorkingDirectory` (mirrored on `ChatSummary`). It is -**read-only and fixed at chat creation**: there is no action to change it, and -it does not participate in `session/chatUpdated`. Present only when the agent -`requiresPrimary`. Each chat can pick a different primary from its own effective -directories. - #### Setting at create time Pass `workingDirectories` to `createChat`. Every entry must already exist in -the session's `workingDirectories`. When the agent `requiresPrimary`, also pass -`primaryWorkingDirectory` (one of the chat's effective directories): +the session's `workingDirectories`: ```typescript createChat({ channel: 'ahp-session:/', chat: 'ahp-chat:/', workingDirectories: ['file:///workspace/frontend'], // subset - primaryWorkingDirectory: 'file:///workspace/frontend', // this chat's primary, when requiresPrimary }); ``` Forked chats (those whose `source.kind` is `"fork"`) inherit the source -chat's `workingDirectories` and primary, so both fields are ignored for forks. -Side chats can still choose their own subset and primary, +chat's `workingDirectories`, so the field is ignored for forks. +Side chats can still choose their own subset, and they still reference their source with a stable `turnId` whether that turn was active or historical when the side chat was created. They MAY also retain a selected-text snapshot in `origin.selection`; that snapshot is fixed when the diff --git a/docs/proposals/multiroot-sessions.md b/docs/proposals/multiroot-sessions.md index 0887b60d..f89f6afd 100644 --- a/docs/proposals/multiroot-sessions.md +++ b/docs/proposals/multiroot-sessions.md @@ -169,13 +169,10 @@ throughout — no juggling three disconnected sessions. - **It is not per-file or per-glob scoping.** The unit is a working directory (a root), not arbitrary path patterns within it. -- **No mandatory primary; when needed, it's per-chat.** All directories are - peers by default and the **session has no primary at all**. A backend that - *needs* one distinguished root advertises `requiresPrimary`; the client then - designates it explicitly per **chat** via `primaryWorkingDirectory` (on - `createChat`, or `createSession` to seed the default chat). It is read-only - and fixed at chat creation — never inferred from array position, never mutated - after birth. +- **No mandatory primary.** All directories are peers by default. A backend that + *must* pin its first directory (a fixed process root) advertises + `immutablePrimary` on the capability; clients then keep index `0` fixed. The + protocol has no other notion of a "main" directory. - **It is not multi-root *chats as sub-sessions*.** A chat narrowing to a subset is still one thread under one session's trust and identity. Independent agents @@ -233,12 +230,12 @@ as today. | Symbol | File | Kind | | --- | --- | --- | | `AgentCapabilities.multipleWorkingDirectories?` | `channels-root/state.ts` | added (capability) | -| `MultipleWorkingDirectoriesCapability` (`requiresPrimary?`) | `channels-root/state.ts` | added (type) | -| `CreateSessionParams.workingDirectories?` / `primaryWorkingDirectory?` | `channels-session/commands.ts` | added | +| `MultipleWorkingDirectoriesCapability` (`immutablePrimary?`) | `channels-root/state.ts` | added (type) | +| `CreateSessionParams.workingDirectories?` | `channels-session/commands.ts` | added | | `SessionMetadata.workingDirectories?` (→ `SessionState`, `SessionSummary`) | `channels-session/state.ts` | added | | `session/workingDirectorySet` / `session/workingDirectoryRemoved` actions | `channels-session/actions.ts` | added (action) | -| `ChatState.workingDirectories?` / `primaryWorkingDirectory?` (& `ChatSummary`) | `channels-chat/state.ts` | added | -| `CreateChatParams.workingDirectories?` / `primaryWorkingDirectory?` | `channels-chat/commands.ts` | added | +| `ChatState.workingDirectories?` / `ChatSummary.workingDirectories?` | `channels-chat/state.ts` | added | +| `CreateChatParams.workingDirectories?` | `channels-chat/commands.ts` | added | | `chat/workingDirectorySet` / `chat/workingDirectoryRemoved` actions | `channels-chat/actions.ts` | added (action) | | 4 `ActionType` entries + `ACTION_INTRODUCED_IN` (`0.7.0`) | `common/actions.ts`, `version/registry.ts` | added | @@ -265,8 +262,8 @@ interface AgentCapabilities { multipleWorkingDirectories?: MultipleWorkingDirectoriesCapability; } interface MultipleWorkingDirectoriesCapability { - /** The agent needs one directory designated as its primary root. */ - requiresPrimary?: boolean; + /** First directory is a fixed process root; clients MUST NOT remove/reorder it. */ + immutablePrimary?: boolean; } // ── Session create — channels-session/commands.ts ──────────────────────── @@ -274,14 +271,12 @@ interface CreateSessionParams extends BaseParams { // …existing… /** The session's equal-peer working directories. */ workingDirectories?: URI[]; - /** Seeds the default chat's primary (⊆ workingDirectories); when requiresPrimary. */ - primaryWorkingDirectory?: URI; } // ── Session state — channels-session/state.ts (→ SessionState/SessionSummary) interface SessionMetadata { // …existing… - workingDirectories?: URI[]; // equal peers; the session has NO primary + workingDirectories?: URI[]; } // ── Session runtime mutation — channels-session/actions.ts ──────────────── @@ -300,13 +295,10 @@ interface ChatState /* and ChatSummary */ { // …existing… /** The chat's subset — every entry MUST be one of the session's dirs. */ workingDirectories?: URI[]; - /** Read-only, fixed at creation; no action, not in chatUpdated. */ - primaryWorkingDirectory?: URI; } interface CreateChatParams extends BaseParams { // …existing… workingDirectories?: URI[]; // subset ⊆ session; absent → whole session set - primaryWorkingDirectory?: URI; // ⊆ chat's dirs; when requiresPrimary } // channel = chat URI. Gated by multipleWorkingDirectories. @clientDispatchable. interface ChatWorkingDirectorySetAction { @@ -338,27 +330,17 @@ interface ChatWorkingDirectoryRemovedAction { handshake. - Removal actions are idempotent and modelled as *reconfigure-to-the-reduced-set*; a host MAY decline to apply a removal (e.g. - a directory still designated as some chat's primary), leaving the set - unchanged. + an `immutablePrimary` directory), leaving the set unchanged. --- ## 9. Design decisions & resolved questions -- **Primary is per-chat, read-only, fixed at creation.** *Resolved:* the set is - equal peers by default and the **session has no primary**. Rejected a +- **No mandatory primary.** *Resolved:* the set is equal peers. Rejected a "primary + additional" split because it re-introduces the confusion the user - called out ("what's the relation between primary and secondary?"). An agent - that needs one distinguished root advertises `requiresPrimary`; the client - designates it **per chat** via `primaryWorkingDirectory` - (`createChat`, or `createSession` to seed the default chat). It is stored - read-only on `ChatState`/`ChatSummary` (user-visible, recoverable by late - subscribers) but has **no mutating action** and is not part of - `session/chatUpdated` — so it's visible yet immutable. "In state" and - "mutable" are orthogonal in AHP: mutability comes from an action existing, not - from where the value lives. Deliberately *not* positional — never inferred - from array index — and a role-on-entry shape was rejected because it would - couple the immutable primary to the mutable set's lifecycle. + called out ("what's the relation between primary and secondary?"). Backends + that genuinely pin a fixed process root opt in via + `MultipleWorkingDirectoriesCapability.immutablePrimary` (index `0` fixed). - **Hard-remove the singular `workingDirectory`.** *Resolved (per review):* removing these fields is a breaking change, so the feature targets a MINOR @@ -393,8 +375,7 @@ interface ChatWorkingDirectoryRemovedAction { - **Removal semantics.** *Resolved:* no single-remove primitive is assumed; the `*/workingDirectoryRemoved` action reduces to the reduced set, so it is - idempotent and safe to retry. A host MAY decline (e.g. a directory still - designated as some chat's primary). + idempotent and safe to retry. A host MAY decline (e.g. an immutable primary). --- diff --git a/schema/actions.schema.json b/schema/actions.schema.json index f53f1363..5e219e03 100644 --- a/schema/actions.schema.json +++ b/schema/actions.schema.json @@ -239,10 +239,6 @@ "$ref": "#/$defs/URI" }, "description": "The subset of the session's working directories this chat uses.\nSee {@link ChatState.workingDirectories} for the full semantics." - }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The chat's primary working directory.\nSee {@link ChatState.primaryWorkingDirectory} for the full semantics." } }, "description": "Mutable summary fields that changed; omitted fields are unchanged.\n\nIdentity fields (`resource`) never change and MUST be omitted by\nsenders; receivers SHOULD ignore them if present." @@ -431,7 +427,7 @@ }, "SessionWorkingDirectoryRemovedAction": { "type": "object", - "description": "A working directory was removed from the session's\n{@link SessionState.workingDirectories} set.\n\nRemoves `directory` from the set; a no-op when it is not present. There is no\natomic backend \"remove one\" primitive — a host reconfigures its agent to the\nreduced set — so this action is safe to model as idempotent. A host MAY\ndecline to apply the removal (e.g. a directory still designated as some\nchat's {@link ChatState.primaryWorkingDirectory | primary}); it then leaves\nthe set unchanged.", + "description": "A working directory was removed from the session's\n{@link SessionState.workingDirectories} set.\n\nRemoves `directory` from the set; a no-op when it is not present. There is no\natomic backend \"remove one\" primitive — a host reconfigures its agent to the\nreduced set — so this action is safe to model as idempotent. A host MAY\ndecline to apply the removal (e.g. an immutable primary directory, see\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary}); it then leaves\nthe set unchanged.", "properties": { "type": { "const": "session/workingDirectoryRemoved" @@ -2727,7 +2723,7 @@ }, "multipleWorkingDirectories": { "$ref": "#/$defs/MultipleWorkingDirectoriesCapability", - "description": "The session's agent can be granted tool access to more than one working\ndirectory. The directories are treated as equal peers except where the\nagent advertises {@link MultipleWorkingDirectoriesCapability.requiresPrimary}\n(some backends need one directory designated as a primary root).\n\nWhen absent, clients MUST NOT mutate a session's or chat's working-directory\nset and MUST NOT set more than one entry in\n{@link CreateSessionParams.workingDirectories}." + "description": "The session's agent can be granted tool access to more than one working\ndirectory. The directories are treated as equal peers except where the\nagent advertises {@link MultipleWorkingDirectoriesCapability.immutablePrimary}\n(some backends pin their first directory as a fixed process root).\n\nWhen absent, clients MUST NOT mutate a session's or chat's working-directory\nset and MUST NOT set more than one entry in\n{@link CreateSessionParams.workingDirectories}." } } }, @@ -2749,9 +2745,9 @@ "type": "object", "description": "Options for the {@link AgentCapabilities.multipleWorkingDirectories} capability.", "properties": { - "requiresPrimary": { + "immutablePrimary": { "type": "boolean", - "description": "The agent requires each chat to designate one of its working directories as\nthe **primary** — a distinguished root the chat is centered on (e.g. the\nagent's process root for that chat, the default location for relative\npaths). Primary is a **per-chat** notion, fixed at chat creation. When\n`true`, a client SHOULD supply {@link CreateChatParams.primaryWorkingDirectory}\n(and {@link CreateSessionParams.primaryWorkingDirectory}, which seeds the\nsession's default chat); a host MAY reject creation that omits it, or fall\nback to the first entry of the chat's working directories. The chosen\nprimary is reported (read-only) on {@link ChatState.primaryWorkingDirectory}.\n\nWhen absent or `false`, the agent has no primary — all directories are\nequal peers and clients need not designate one." + "description": "The agent's **first** working directory (index `0` of\n{@link CreateSessionParams.workingDirectories}) is an immutable primary:\nit is fixed for the lifetime of the session — clients MUST NOT remove or\nreorder it. Additional directories after it remain equal peers that can be\nadded and removed freely.\n\nAdvertised by backends whose agent process is rooted at a single directory\nthat cannot change once the session has started (e.g. the SDK's primary\n`workingDirectory`). When absent or `false`, all directories are equal\npeers and any of them may be removed." } } }, @@ -2874,7 +2870,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -2916,7 +2912,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -3220,7 +3216,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -4526,10 +4522,6 @@ }, "description": "The subset of the session's\n{@link SessionState.workingDirectories | `workingDirectories`} that this\nchat's agent has tool access to. Every entry MUST be present in the owning\nsession's `workingDirectories`; servers MUST reject a\n`chat/workingDirectorySet` action that violates this constraint.\n\nWhen absent, the chat inherits the full session set. When present but empty\n(not recommended), the chat has no working-directory tool access at all.\n\nDispatch `chat/workingDirectorySet` / `chat/workingDirectoryRemoved` to\nupdate the subset on a running chat." }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The chat's primary working directory — the distinguished root this chat is\ncentered on (e.g. the agent's process root for this chat, the default\nlocation for relative paths). MUST be one of this chat's effective working\ndirectories ({@link workingDirectories}, or the session's set when that is\nabsent). Present when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.requiresPrimary}.\n\n**Read-only and fixed at creation.** It is set from\n{@link CreateChatParams.primaryWorkingDirectory} (or, for the session's\ndefault chat, {@link CreateSessionParams.primaryWorkingDirectory}) and does\nnot change over the chat's lifetime — there is no action to mutate it, and\nit does not participate in `session/chatUpdated`." - }, "turns": { "type": "array", "items": { @@ -4612,10 +4604,6 @@ "$ref": "#/$defs/URI" }, "description": "The subset of the session's working directories this chat uses.\nSee {@link ChatState.workingDirectories} for the full semantics." - }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The chat's primary working directory.\nSee {@link ChatState.primaryWorkingDirectory} for the full semantics." } }, "required": [ diff --git a/schema/commands.schema.json b/schema/commands.schema.json index cd7ef613..92f0c515 100644 --- a/schema/commands.schema.json +++ b/schema/commands.schema.json @@ -967,11 +967,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent is granted tool access to.\nA session may span multiple directories; they are equal peers except when\nthe agent advertises\n{@link MultipleWorkingDirectoriesCapability.requiresPrimary}, in which case\none of them should be designated the primary via\n{@link primaryWorkingDirectory}.\n\nA client MUST NOT supply more than one entry unless the agent advertises\n{@link AgentCapabilities.multipleWorkingDirectories}; a server without that\ncapability treats only the first entry as the session's working directory\nand ignores the rest. Dispatch `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` to change the set after the session has\nstarted.\n\nIgnored for forked sessions — a fork inherits its working directories\nfrom the source session identified by `fork`." - }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The primary working directory for the session's **default chat**.\n\nA session has no primary of its own — primary is a per-chat notion (see\n{@link ChatState.primaryWorkingDirectory}). But `createSession` implicitly\ncreates the session's default chat, and there is no separate `createChat`\ncall to carry that chat's create-time fields. This field is therefore the\nonly place a client can designate the **default chat's** primary at birth;\nit is copied into that chat's read-only `primaryWorkingDirectory`. For any\nnon-default chat, pass {@link CreateChatParams.primaryWorkingDirectory}\ninstead.\n\nWhen set, it MUST be one of {@link workingDirectories}. A client SHOULD\nsupply this when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.requiresPrimary}; a host MAY\nreject creation that omits it, or fall back to the first entry of\n`workingDirectories`. Ignored for forked sessions (a fork inherits the\nsource session's chats and their primaries)." + "description": "The working directories the session's agent is granted tool access to.\nA session may span multiple directories; they are equal peers except when\nthe agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (in which case\nthe first entry is a fixed process root).\n\nA client MUST NOT supply more than one entry unless the agent advertises\n{@link AgentCapabilities.multipleWorkingDirectories}; a server without that\ncapability treats only the first entry as the session's working directory\nand ignores the rest. Dispatch `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` to change the set after the session has\nstarted.\n\nIgnored for forked sessions — a fork inherits its working directories\nfrom the source session identified by `fork`." }, "fork": { "$ref": "#/$defs/SessionForkSource", @@ -1176,10 +1172,6 @@ "$ref": "#/$defs/URI" }, "description": "Initial working-directory subset for this chat. Every entry MUST be\npresent in the owning session's `workingDirectories`; the server MUST\nreject any entry that is not. When absent, the chat inherits the full\nsession set. Forked chats (those whose `source.kind` is `\"fork\"`) inherit\nthe source chat's `workingDirectories`; this field is ignored for forks.\n\nA client MUST NOT supply this field unless the agent advertises\n{@link AgentCapabilities.multipleWorkingDirectories}." - }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The chat's primary working directory — the distinguished root this chat is\ncentered on. When set, it MUST be one of the chat's effective working\ndirectories ({@link workingDirectories}, or the session's set when that is\nomitted). A client SHOULD supply this when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.requiresPrimary}; a host MAY\nreject creation that omits it, or fall back to the first of the chat's\ndirectories. Fixed at creation and reported (read-only) on\n{@link ChatState.primaryWorkingDirectory}. Ignored for forks (a chat whose\n`source.kind` is `\"fork\"` inherits the source chat's primary)." } }, "required": [ @@ -1902,7 +1894,7 @@ }, "multipleWorkingDirectories": { "$ref": "#/$defs/MultipleWorkingDirectoriesCapability", - "description": "The session's agent can be granted tool access to more than one working\ndirectory. The directories are treated as equal peers except where the\nagent advertises {@link MultipleWorkingDirectoriesCapability.requiresPrimary}\n(some backends need one directory designated as a primary root).\n\nWhen absent, clients MUST NOT mutate a session's or chat's working-directory\nset and MUST NOT set more than one entry in\n{@link CreateSessionParams.workingDirectories}." + "description": "The session's agent can be granted tool access to more than one working\ndirectory. The directories are treated as equal peers except where the\nagent advertises {@link MultipleWorkingDirectoriesCapability.immutablePrimary}\n(some backends pin their first directory as a fixed process root).\n\nWhen absent, clients MUST NOT mutate a session's or chat's working-directory\nset and MUST NOT set more than one entry in\n{@link CreateSessionParams.workingDirectories}." } } }, @@ -1924,9 +1916,9 @@ "type": "object", "description": "Options for the {@link AgentCapabilities.multipleWorkingDirectories} capability.", "properties": { - "requiresPrimary": { + "immutablePrimary": { "type": "boolean", - "description": "The agent requires each chat to designate one of its working directories as\nthe **primary** — a distinguished root the chat is centered on (e.g. the\nagent's process root for that chat, the default location for relative\npaths). Primary is a **per-chat** notion, fixed at chat creation. When\n`true`, a client SHOULD supply {@link CreateChatParams.primaryWorkingDirectory}\n(and {@link CreateSessionParams.primaryWorkingDirectory}, which seeds the\nsession's default chat); a host MAY reject creation that omits it, or fall\nback to the first entry of the chat's working directories. The chosen\nprimary is reported (read-only) on {@link ChatState.primaryWorkingDirectory}.\n\nWhen absent or `false`, the agent has no primary — all directories are\nequal peers and clients need not designate one." + "description": "The agent's **first** working directory (index `0` of\n{@link CreateSessionParams.workingDirectories}) is an immutable primary:\nit is fixed for the lifetime of the session — clients MUST NOT remove or\nreorder it. Additional directories after it remain equal peers that can be\nadded and removed freely.\n\nAdvertised by backends whose agent process is rooted at a single directory\nthat cannot change once the session has started (e.g. the SDK's primary\n`workingDirectory`). When absent or `false`, all directories are equal\npeers and any of them may be removed." } } }, @@ -2049,7 +2041,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -2091,7 +2083,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -2395,7 +2387,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -3701,10 +3693,6 @@ }, "description": "The subset of the session's\n{@link SessionState.workingDirectories | `workingDirectories`} that this\nchat's agent has tool access to. Every entry MUST be present in the owning\nsession's `workingDirectories`; servers MUST reject a\n`chat/workingDirectorySet` action that violates this constraint.\n\nWhen absent, the chat inherits the full session set. When present but empty\n(not recommended), the chat has no working-directory tool access at all.\n\nDispatch `chat/workingDirectorySet` / `chat/workingDirectoryRemoved` to\nupdate the subset on a running chat." }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The chat's primary working directory — the distinguished root this chat is\ncentered on (e.g. the agent's process root for this chat, the default\nlocation for relative paths). MUST be one of this chat's effective working\ndirectories ({@link workingDirectories}, or the session's set when that is\nabsent). Present when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.requiresPrimary}.\n\n**Read-only and fixed at creation.** It is set from\n{@link CreateChatParams.primaryWorkingDirectory} (or, for the session's\ndefault chat, {@link CreateSessionParams.primaryWorkingDirectory}) and does\nnot change over the chat's lifetime — there is no action to mutate it, and\nit does not participate in `session/chatUpdated`." - }, "turns": { "type": "array", "items": { @@ -3787,10 +3775,6 @@ "$ref": "#/$defs/URI" }, "description": "The subset of the session's working directories this chat uses.\nSee {@link ChatState.workingDirectories} for the full semantics." - }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The chat's primary working directory.\nSee {@link ChatState.primaryWorkingDirectory} for the full semantics." } }, "required": [ @@ -6510,10 +6494,6 @@ "$ref": "#/$defs/URI" }, "description": "The subset of the session's working directories this chat uses.\nSee {@link ChatState.workingDirectories} for the full semantics." - }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The chat's primary working directory.\nSee {@link ChatState.primaryWorkingDirectory} for the full semantics." } }, "description": "Mutable summary fields that changed; omitted fields are unchanged.\n\nIdentity fields (`resource`) never change and MUST be omitted by\nsenders; receivers SHOULD ignore them if present." @@ -6702,7 +6682,7 @@ }, "SessionWorkingDirectoryRemovedAction": { "type": "object", - "description": "A working directory was removed from the session's\n{@link SessionState.workingDirectories} set.\n\nRemoves `directory` from the set; a no-op when it is not present. There is no\natomic backend \"remove one\" primitive — a host reconfigures its agent to the\nreduced set — so this action is safe to model as idempotent. A host MAY\ndecline to apply the removal (e.g. a directory still designated as some\nchat's {@link ChatState.primaryWorkingDirectory | primary}); it then leaves\nthe set unchanged.", + "description": "A working directory was removed from the session's\n{@link SessionState.workingDirectories} set.\n\nRemoves `directory` from the set; a no-op when it is not present. There is no\natomic backend \"remove one\" primitive — a host reconfigures its agent to the\nreduced set — so this action is safe to model as idempotent. A host MAY\ndecline to apply the removal (e.g. an immutable primary directory, see\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary}); it then leaves\nthe set unchanged.", "properties": { "type": { "const": "session/workingDirectoryRemoved" diff --git a/schema/errors.schema.json b/schema/errors.schema.json index 7da74d1f..063eef19 100644 --- a/schema/errors.schema.json +++ b/schema/errors.schema.json @@ -630,7 +630,7 @@ }, "multipleWorkingDirectories": { "$ref": "#/$defs/MultipleWorkingDirectoriesCapability", - "description": "The session's agent can be granted tool access to more than one working\ndirectory. The directories are treated as equal peers except where the\nagent advertises {@link MultipleWorkingDirectoriesCapability.requiresPrimary}\n(some backends need one directory designated as a primary root).\n\nWhen absent, clients MUST NOT mutate a session's or chat's working-directory\nset and MUST NOT set more than one entry in\n{@link CreateSessionParams.workingDirectories}." + "description": "The session's agent can be granted tool access to more than one working\ndirectory. The directories are treated as equal peers except where the\nagent advertises {@link MultipleWorkingDirectoriesCapability.immutablePrimary}\n(some backends pin their first directory as a fixed process root).\n\nWhen absent, clients MUST NOT mutate a session's or chat's working-directory\nset and MUST NOT set more than one entry in\n{@link CreateSessionParams.workingDirectories}." } } }, @@ -652,9 +652,9 @@ "type": "object", "description": "Options for the {@link AgentCapabilities.multipleWorkingDirectories} capability.", "properties": { - "requiresPrimary": { + "immutablePrimary": { "type": "boolean", - "description": "The agent requires each chat to designate one of its working directories as\nthe **primary** — a distinguished root the chat is centered on (e.g. the\nagent's process root for that chat, the default location for relative\npaths). Primary is a **per-chat** notion, fixed at chat creation. When\n`true`, a client SHOULD supply {@link CreateChatParams.primaryWorkingDirectory}\n(and {@link CreateSessionParams.primaryWorkingDirectory}, which seeds the\nsession's default chat); a host MAY reject creation that omits it, or fall\nback to the first entry of the chat's working directories. The chosen\nprimary is reported (read-only) on {@link ChatState.primaryWorkingDirectory}.\n\nWhen absent or `false`, the agent has no primary — all directories are\nequal peers and clients need not designate one." + "description": "The agent's **first** working directory (index `0` of\n{@link CreateSessionParams.workingDirectories}) is an immutable primary:\nit is fixed for the lifetime of the session — clients MUST NOT remove or\nreorder it. Additional directories after it remain equal peers that can be\nadded and removed freely.\n\nAdvertised by backends whose agent process is rooted at a single directory\nthat cannot change once the session has started (e.g. the SDK's primary\n`workingDirectory`). When absent or `false`, all directories are equal\npeers and any of them may be removed." } } }, @@ -777,7 +777,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -819,7 +819,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -1123,7 +1123,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -2429,10 +2429,6 @@ }, "description": "The subset of the session's\n{@link SessionState.workingDirectories | `workingDirectories`} that this\nchat's agent has tool access to. Every entry MUST be present in the owning\nsession's `workingDirectories`; servers MUST reject a\n`chat/workingDirectorySet` action that violates this constraint.\n\nWhen absent, the chat inherits the full session set. When present but empty\n(not recommended), the chat has no working-directory tool access at all.\n\nDispatch `chat/workingDirectorySet` / `chat/workingDirectoryRemoved` to\nupdate the subset on a running chat." }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The chat's primary working directory — the distinguished root this chat is\ncentered on (e.g. the agent's process root for this chat, the default\nlocation for relative paths). MUST be one of this chat's effective working\ndirectories ({@link workingDirectories}, or the session's set when that is\nabsent). Present when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.requiresPrimary}.\n\n**Read-only and fixed at creation.** It is set from\n{@link CreateChatParams.primaryWorkingDirectory} (or, for the session's\ndefault chat, {@link CreateSessionParams.primaryWorkingDirectory}) and does\nnot change over the chat's lifetime — there is no action to mutate it, and\nit does not participate in `session/chatUpdated`." - }, "turns": { "type": "array", "items": { @@ -2515,10 +2511,6 @@ "$ref": "#/$defs/URI" }, "description": "The subset of the session's working directories this chat uses.\nSee {@link ChatState.workingDirectories} for the full semantics." - }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The chat's primary working directory.\nSee {@link ChatState.primaryWorkingDirectory} for the full semantics." } }, "required": [ @@ -5966,11 +5958,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent is granted tool access to.\nA session may span multiple directories; they are equal peers except when\nthe agent advertises\n{@link MultipleWorkingDirectoriesCapability.requiresPrimary}, in which case\none of them should be designated the primary via\n{@link primaryWorkingDirectory}.\n\nA client MUST NOT supply more than one entry unless the agent advertises\n{@link AgentCapabilities.multipleWorkingDirectories}; a server without that\ncapability treats only the first entry as the session's working directory\nand ignores the rest. Dispatch `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` to change the set after the session has\nstarted.\n\nIgnored for forked sessions — a fork inherits its working directories\nfrom the source session identified by `fork`." - }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The primary working directory for the session's **default chat**.\n\nA session has no primary of its own — primary is a per-chat notion (see\n{@link ChatState.primaryWorkingDirectory}). But `createSession` implicitly\ncreates the session's default chat, and there is no separate `createChat`\ncall to carry that chat's create-time fields. This field is therefore the\nonly place a client can designate the **default chat's** primary at birth;\nit is copied into that chat's read-only `primaryWorkingDirectory`. For any\nnon-default chat, pass {@link CreateChatParams.primaryWorkingDirectory}\ninstead.\n\nWhen set, it MUST be one of {@link workingDirectories}. A client SHOULD\nsupply this when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.requiresPrimary}; a host MAY\nreject creation that omits it, or fall back to the first entry of\n`workingDirectories`. Ignored for forked sessions (a fork inherits the\nsource session's chats and their primaries)." + "description": "The working directories the session's agent is granted tool access to.\nA session may span multiple directories; they are equal peers except when\nthe agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (in which case\nthe first entry is a fixed process root).\n\nA client MUST NOT supply more than one entry unless the agent advertises\n{@link AgentCapabilities.multipleWorkingDirectories}; a server without that\ncapability treats only the first entry as the session's working directory\nand ignores the rest. Dispatch `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` to change the set after the session has\nstarted.\n\nIgnored for forked sessions — a fork inherits its working directories\nfrom the source session identified by `fork`." }, "fork": { "$ref": "#/$defs/SessionForkSource", @@ -6175,10 +6163,6 @@ "$ref": "#/$defs/URI" }, "description": "Initial working-directory subset for this chat. Every entry MUST be\npresent in the owning session's `workingDirectories`; the server MUST\nreject any entry that is not. When absent, the chat inherits the full\nsession set. Forked chats (those whose `source.kind` is `\"fork\"`) inherit\nthe source chat's `workingDirectories`; this field is ignored for forks.\n\nA client MUST NOT supply this field unless the agent advertises\n{@link AgentCapabilities.multipleWorkingDirectories}." - }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The chat's primary working directory — the distinguished root this chat is\ncentered on. When set, it MUST be one of the chat's effective working\ndirectories ({@link workingDirectories}, or the session's set when that is\nomitted). A client SHOULD supply this when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.requiresPrimary}; a host MAY\nreject creation that omits it, or fall back to the first of the chat's\ndirectories. Fixed at creation and reported (read-only) on\n{@link ChatState.primaryWorkingDirectory}. Ignored for forks (a chat whose\n`source.kind` is `\"fork\"` inherits the source chat's primary)." } }, "required": [ @@ -7526,10 +7510,6 @@ "$ref": "#/$defs/URI" }, "description": "The subset of the session's working directories this chat uses.\nSee {@link ChatState.workingDirectories} for the full semantics." - }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The chat's primary working directory.\nSee {@link ChatState.primaryWorkingDirectory} for the full semantics." } }, "description": "Mutable summary fields that changed; omitted fields are unchanged.\n\nIdentity fields (`resource`) never change and MUST be omitted by\nsenders; receivers SHOULD ignore them if present." @@ -7647,7 +7627,7 @@ }, "SessionWorkingDirectoryRemovedAction": { "type": "object", - "description": "A working directory was removed from the session's\n{@link SessionState.workingDirectories} set.\n\nRemoves `directory` from the set; a no-op when it is not present. There is no\natomic backend \"remove one\" primitive — a host reconfigures its agent to the\nreduced set — so this action is safe to model as idempotent. A host MAY\ndecline to apply the removal (e.g. a directory still designated as some\nchat's {@link ChatState.primaryWorkingDirectory | primary}); it then leaves\nthe set unchanged.", + "description": "A working directory was removed from the session's\n{@link SessionState.workingDirectories} set.\n\nRemoves `directory` from the set; a no-op when it is not present. There is no\natomic backend \"remove one\" primitive — a host reconfigures its agent to the\nreduced set — so this action is safe to model as idempotent. A host MAY\ndecline to apply the removal (e.g. an immutable primary directory, see\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary}); it then leaves\nthe set unchanged.", "properties": { "type": { "const": "session/workingDirectoryRemoved" diff --git a/schema/notifications.schema.json b/schema/notifications.schema.json index e9ca429d..29d33349 100644 --- a/schema/notifications.schema.json +++ b/schema/notifications.schema.json @@ -103,7 +103,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -793,7 +793,7 @@ }, "multipleWorkingDirectories": { "$ref": "#/$defs/MultipleWorkingDirectoriesCapability", - "description": "The session's agent can be granted tool access to more than one working\ndirectory. The directories are treated as equal peers except where the\nagent advertises {@link MultipleWorkingDirectoriesCapability.requiresPrimary}\n(some backends need one directory designated as a primary root).\n\nWhen absent, clients MUST NOT mutate a session's or chat's working-directory\nset and MUST NOT set more than one entry in\n{@link CreateSessionParams.workingDirectories}." + "description": "The session's agent can be granted tool access to more than one working\ndirectory. The directories are treated as equal peers except where the\nagent advertises {@link MultipleWorkingDirectoriesCapability.immutablePrimary}\n(some backends pin their first directory as a fixed process root).\n\nWhen absent, clients MUST NOT mutate a session's or chat's working-directory\nset and MUST NOT set more than one entry in\n{@link CreateSessionParams.workingDirectories}." } } }, @@ -815,9 +815,9 @@ "type": "object", "description": "Options for the {@link AgentCapabilities.multipleWorkingDirectories} capability.", "properties": { - "requiresPrimary": { + "immutablePrimary": { "type": "boolean", - "description": "The agent requires each chat to designate one of its working directories as\nthe **primary** — a distinguished root the chat is centered on (e.g. the\nagent's process root for that chat, the default location for relative\npaths). Primary is a **per-chat** notion, fixed at chat creation. When\n`true`, a client SHOULD supply {@link CreateChatParams.primaryWorkingDirectory}\n(and {@link CreateSessionParams.primaryWorkingDirectory}, which seeds the\nsession's default chat); a host MAY reject creation that omits it, or fall\nback to the first entry of the chat's working directories. The chosen\nprimary is reported (read-only) on {@link ChatState.primaryWorkingDirectory}.\n\nWhen absent or `false`, the agent has no primary — all directories are\nequal peers and clients need not designate one." + "description": "The agent's **first** working directory (index `0` of\n{@link CreateSessionParams.workingDirectories}) is an immutable primary:\nit is fixed for the lifetime of the session — clients MUST NOT remove or\nreorder it. Additional directories after it remain equal peers that can be\nadded and removed freely.\n\nAdvertised by backends whose agent process is rooted at a single directory\nthat cannot change once the session has started (e.g. the SDK's primary\n`workingDirectory`). When absent or `false`, all directories are equal\npeers and any of them may be removed." } } }, @@ -940,7 +940,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -982,7 +982,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -1286,7 +1286,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -2592,10 +2592,6 @@ }, "description": "The subset of the session's\n{@link SessionState.workingDirectories | `workingDirectories`} that this\nchat's agent has tool access to. Every entry MUST be present in the owning\nsession's `workingDirectories`; servers MUST reject a\n`chat/workingDirectorySet` action that violates this constraint.\n\nWhen absent, the chat inherits the full session set. When present but empty\n(not recommended), the chat has no working-directory tool access at all.\n\nDispatch `chat/workingDirectorySet` / `chat/workingDirectoryRemoved` to\nupdate the subset on a running chat." }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The chat's primary working directory — the distinguished root this chat is\ncentered on (e.g. the agent's process root for this chat, the default\nlocation for relative paths). MUST be one of this chat's effective working\ndirectories ({@link workingDirectories}, or the session's set when that is\nabsent). Present when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.requiresPrimary}.\n\n**Read-only and fixed at creation.** It is set from\n{@link CreateChatParams.primaryWorkingDirectory} (or, for the session's\ndefault chat, {@link CreateSessionParams.primaryWorkingDirectory}) and does\nnot change over the chat's lifetime — there is no action to mutate it, and\nit does not participate in `session/chatUpdated`." - }, "turns": { "type": "array", "items": { @@ -2678,10 +2674,6 @@ "$ref": "#/$defs/URI" }, "description": "The subset of the session's working directories this chat uses.\nSee {@link ChatState.workingDirectories} for the full semantics." - }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The chat's primary working directory.\nSee {@link ChatState.primaryWorkingDirectory} for the full semantics." } }, "required": [ diff --git a/schema/state.schema.json b/schema/state.schema.json index adb9c20e..6353dedf 100644 --- a/schema/state.schema.json +++ b/schema/state.schema.json @@ -541,7 +541,7 @@ }, "multipleWorkingDirectories": { "$ref": "#/$defs/MultipleWorkingDirectoriesCapability", - "description": "The session's agent can be granted tool access to more than one working\ndirectory. The directories are treated as equal peers except where the\nagent advertises {@link MultipleWorkingDirectoriesCapability.requiresPrimary}\n(some backends need one directory designated as a primary root).\n\nWhen absent, clients MUST NOT mutate a session's or chat's working-directory\nset and MUST NOT set more than one entry in\n{@link CreateSessionParams.workingDirectories}." + "description": "The session's agent can be granted tool access to more than one working\ndirectory. The directories are treated as equal peers except where the\nagent advertises {@link MultipleWorkingDirectoriesCapability.immutablePrimary}\n(some backends pin their first directory as a fixed process root).\n\nWhen absent, clients MUST NOT mutate a session's or chat's working-directory\nset and MUST NOT set more than one entry in\n{@link CreateSessionParams.workingDirectories}." } } }, @@ -563,9 +563,9 @@ "type": "object", "description": "Options for the {@link AgentCapabilities.multipleWorkingDirectories} capability.", "properties": { - "requiresPrimary": { + "immutablePrimary": { "type": "boolean", - "description": "The agent requires each chat to designate one of its working directories as\nthe **primary** — a distinguished root the chat is centered on (e.g. the\nagent's process root for that chat, the default location for relative\npaths). Primary is a **per-chat** notion, fixed at chat creation. When\n`true`, a client SHOULD supply {@link CreateChatParams.primaryWorkingDirectory}\n(and {@link CreateSessionParams.primaryWorkingDirectory}, which seeds the\nsession's default chat); a host MAY reject creation that omits it, or fall\nback to the first entry of the chat's working directories. The chosen\nprimary is reported (read-only) on {@link ChatState.primaryWorkingDirectory}.\n\nWhen absent or `false`, the agent has no primary — all directories are\nequal peers and clients need not designate one." + "description": "The agent's **first** working directory (index `0` of\n{@link CreateSessionParams.workingDirectories}) is an immutable primary:\nit is fixed for the lifetime of the session — clients MUST NOT remove or\nreorder it. Additional directories after it remain equal peers that can be\nadded and removed freely.\n\nAdvertised by backends whose agent process is rooted at a single directory\nthat cannot change once the session has started (e.g. the SDK's primary\n`workingDirectory`). When absent or `false`, all directories are equal\npeers and any of them may be removed." } } }, @@ -688,7 +688,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -730,7 +730,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -1034,7 +1034,7 @@ "items": { "$ref": "#/$defs/URI" }, - "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are **equal peers** —\nthe session has no primary. Individual chats MAY restrict to a subset via\n{@link ChatSummary.workingDirectories | their own `workingDirectories`} and\ndesignate one of their own directories as primary (see\n{@link ChatState.primaryWorkingDirectory}); a chat that sets no subset\noperates against this full set." + "description": "The working directories the session's agent has tool access to, as\nmaintained by the `session/workingDirectorySet` /\n`session/workingDirectoryRemoved` actions. Directories are equal peers\nexcept when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first\nentry is then a fixed process root). Individual chats MAY restrict to a\nsubset via {@link ChatSummary.workingDirectories | their own\n`workingDirectories`}; a chat that sets none operates against this full\nset." }, "annotations": { "$ref": "#/$defs/AnnotationsSummary", @@ -2340,10 +2340,6 @@ }, "description": "The subset of the session's\n{@link SessionState.workingDirectories | `workingDirectories`} that this\nchat's agent has tool access to. Every entry MUST be present in the owning\nsession's `workingDirectories`; servers MUST reject a\n`chat/workingDirectorySet` action that violates this constraint.\n\nWhen absent, the chat inherits the full session set. When present but empty\n(not recommended), the chat has no working-directory tool access at all.\n\nDispatch `chat/workingDirectorySet` / `chat/workingDirectoryRemoved` to\nupdate the subset on a running chat." }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The chat's primary working directory — the distinguished root this chat is\ncentered on (e.g. the agent's process root for this chat, the default\nlocation for relative paths). MUST be one of this chat's effective working\ndirectories ({@link workingDirectories}, or the session's set when that is\nabsent). Present when the agent advertises\n{@link MultipleWorkingDirectoriesCapability.requiresPrimary}.\n\n**Read-only and fixed at creation.** It is set from\n{@link CreateChatParams.primaryWorkingDirectory} (or, for the session's\ndefault chat, {@link CreateSessionParams.primaryWorkingDirectory}) and does\nnot change over the chat's lifetime — there is no action to mutate it, and\nit does not participate in `session/chatUpdated`." - }, "turns": { "type": "array", "items": { @@ -2426,10 +2422,6 @@ "$ref": "#/$defs/URI" }, "description": "The subset of the session's working directories this chat uses.\nSee {@link ChatState.workingDirectories} for the full semantics." - }, - "primaryWorkingDirectory": { - "$ref": "#/$defs/URI", - "description": "The chat's primary working directory.\nSee {@link ChatState.primaryWorkingDirectory} for the full semantics." } }, "required": [ diff --git a/types/channels-chat/commands.ts b/types/channels-chat/commands.ts index 42da6f56..419e3c24 100644 --- a/types/channels-chat/commands.ts +++ b/types/channels-chat/commands.ts @@ -117,18 +117,6 @@ export interface CreateChatParams extends BaseParams { * {@link AgentCapabilities.multipleWorkingDirectories}. */ workingDirectories?: URI[]; - /** - * The chat's primary working directory — the distinguished root this chat is - * centered on. When set, it MUST be one of the chat's effective working - * directories ({@link workingDirectories}, or the session's set when that is - * omitted). A client SHOULD supply this when the agent advertises - * {@link MultipleWorkingDirectoriesCapability.requiresPrimary}; a host MAY - * reject creation that omits it, or fall back to the first of the chat's - * directories. Fixed at creation and reported (read-only) on - * {@link ChatState.primaryWorkingDirectory}. Ignored for forks (a chat whose - * `source.kind` is `"fork"` inherits the source chat's primary). - */ - primaryWorkingDirectory?: URI; } // ─── disposeChat ───────────────────────────────────────────────────────────── diff --git a/types/channels-chat/state.ts b/types/channels-chat/state.ts index a7153e52..cde7138b 100644 --- a/types/channels-chat/state.ts +++ b/types/channels-chat/state.ts @@ -71,21 +71,6 @@ export interface ChatState { * update the subset on a running chat. */ workingDirectories?: URI[]; - /** - * The chat's primary working directory — the distinguished root this chat is - * centered on (e.g. the agent's process root for this chat, the default - * location for relative paths). MUST be one of this chat's effective working - * directories ({@link workingDirectories}, or the session's set when that is - * absent). Present when the agent advertises - * {@link MultipleWorkingDirectoriesCapability.requiresPrimary}. - * - * **Read-only and fixed at creation.** It is set from - * {@link CreateChatParams.primaryWorkingDirectory} (or, for the session's - * default chat, {@link CreateSessionParams.primaryWorkingDirectory}) and does - * not change over the chat's lifetime — there is no action to mutate it, and - * it does not participate in `session/chatUpdated`. - */ - primaryWorkingDirectory?: URI; // ── Conversation contents ────────────────────────────────────────── /** Completed turns */ @@ -158,11 +143,6 @@ export interface ChatSummary { * See {@link ChatState.workingDirectories} for the full semantics. */ workingDirectories?: URI[]; - /** - * The chat's primary working directory. - * See {@link ChatState.primaryWorkingDirectory} for the full semantics. - */ - primaryWorkingDirectory?: URI; } /** diff --git a/types/channels-root/state.ts b/types/channels-root/state.ts index 5b05e45c..eaceed68 100644 --- a/types/channels-root/state.ts +++ b/types/channels-root/state.ts @@ -114,8 +114,8 @@ export interface AgentCapabilities { /** * The session's agent can be granted tool access to more than one working * directory. The directories are treated as equal peers except where the - * agent advertises {@link MultipleWorkingDirectoriesCapability.requiresPrimary} - * (some backends need one directory designated as a primary root). + * agent advertises {@link MultipleWorkingDirectoriesCapability.immutablePrimary} + * (some backends pin their first directory as a fixed process root). * * When absent, clients MUST NOT mutate a session's or chat's working-directory * set and MUST NOT set more than one entry in @@ -159,20 +159,18 @@ export interface MultipleChatsCapability { */ export interface MultipleWorkingDirectoriesCapability { /** - * The agent requires each chat to designate one of its working directories as - * the **primary** — a distinguished root the chat is centered on (e.g. the - * agent's process root for that chat, the default location for relative - * paths). Primary is a **per-chat** notion, fixed at chat creation. When - * `true`, a client SHOULD supply {@link CreateChatParams.primaryWorkingDirectory} - * (and {@link CreateSessionParams.primaryWorkingDirectory}, which seeds the - * session's default chat); a host MAY reject creation that omits it, or fall - * back to the first entry of the chat's working directories. The chosen - * primary is reported (read-only) on {@link ChatState.primaryWorkingDirectory}. + * The agent's **first** working directory (index `0` of + * {@link CreateSessionParams.workingDirectories}) is an immutable primary: + * it is fixed for the lifetime of the session — clients MUST NOT remove or + * reorder it. Additional directories after it remain equal peers that can be + * added and removed freely. * - * When absent or `false`, the agent has no primary — all directories are - * equal peers and clients need not designate one. + * Advertised by backends whose agent process is rooted at a single directory + * that cannot change once the session has started (e.g. the SDK's primary + * `workingDirectory`). When absent or `false`, all directories are equal + * peers and any of them may be removed. */ - requiresPrimary?: boolean; + immutablePrimary?: boolean; } /** diff --git a/types/channels-session/actions.ts b/types/channels-session/actions.ts index 14dbf468..5ba4ef05 100644 --- a/types/channels-session/actions.ts +++ b/types/channels-session/actions.ts @@ -283,8 +283,8 @@ export interface SessionWorkingDirectorySetAction { * Removes `directory` from the set; a no-op when it is not present. There is no * atomic backend "remove one" primitive — a host reconfigures its agent to the * reduced set — so this action is safe to model as idempotent. A host MAY - * decline to apply the removal (e.g. a directory still designated as some - * chat's {@link ChatState.primaryWorkingDirectory | primary}); it then leaves + * decline to apply the removal (e.g. an immutable primary directory, see + * {@link MultipleWorkingDirectoriesCapability.immutablePrimary}); it then leaves * the set unchanged. * * @category Session Actions diff --git a/types/channels-session/commands.ts b/types/channels-session/commands.ts index 66bc3b0a..7b07a61a 100644 --- a/types/channels-session/commands.ts +++ b/types/channels-session/commands.ts @@ -70,9 +70,8 @@ export interface CreateSessionParams extends BaseParams { * The working directories the session's agent is granted tool access to. * A session may span multiple directories; they are equal peers except when * the agent advertises - * {@link MultipleWorkingDirectoriesCapability.requiresPrimary}, in which case - * one of them should be designated the primary via - * {@link primaryWorkingDirectory}. + * {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (in which case + * the first entry is a fixed process root). * * A client MUST NOT supply more than one entry unless the agent advertises * {@link AgentCapabilities.multipleWorkingDirectories}; a server without that @@ -85,26 +84,6 @@ export interface CreateSessionParams extends BaseParams { * from the source session identified by `fork`. */ workingDirectories?: URI[]; - /** - * The primary working directory for the session's **default chat**. - * - * A session has no primary of its own — primary is a per-chat notion (see - * {@link ChatState.primaryWorkingDirectory}). But `createSession` implicitly - * creates the session's default chat, and there is no separate `createChat` - * call to carry that chat's create-time fields. This field is therefore the - * only place a client can designate the **default chat's** primary at birth; - * it is copied into that chat's read-only `primaryWorkingDirectory`. For any - * non-default chat, pass {@link CreateChatParams.primaryWorkingDirectory} - * instead. - * - * When set, it MUST be one of {@link workingDirectories}. A client SHOULD - * supply this when the agent advertises - * {@link MultipleWorkingDirectoriesCapability.requiresPrimary}; a host MAY - * reject creation that omits it, or fall back to the first entry of - * `workingDirectories`. Ignored for forked sessions (a fork inherits the - * source session's chats and their primaries). - */ - primaryWorkingDirectory?: URI; /** * Fork from an existing session. The new session is populated with content * from the source session up to and including the specified turn's response. diff --git a/types/channels-session/state.ts b/types/channels-session/state.ts index 3d873929..6a1832a9 100644 --- a/types/channels-session/state.ts +++ b/types/channels-session/state.ts @@ -86,12 +86,13 @@ export interface SessionMetadata { /** * The working directories the session's agent has tool access to, as * maintained by the `session/workingDirectorySet` / - * `session/workingDirectoryRemoved` actions. Directories are **equal peers** — - * the session has no primary. Individual chats MAY restrict to a subset via - * {@link ChatSummary.workingDirectories | their own `workingDirectories`} and - * designate one of their own directories as primary (see - * {@link ChatState.primaryWorkingDirectory}); a chat that sets no subset - * operates against this full set. + * `session/workingDirectoryRemoved` actions. Directories are equal peers + * except when the agent advertises + * {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (the first + * entry is then a fixed process root). Individual chats MAY restrict to a + * subset via {@link ChatSummary.workingDirectories | their own + * `workingDirectories`}; a chat that sets none operates against this full + * set. */ workingDirectories?: URI[]; /**