// Generated from types/*.ts — do not edit. // Regenerate with: npm run generate:typescript /** * Session Channel Actions — Mutations of an `ahp-session:` channel's state. * * @module channels-session/actions */ import { ActionType } from '../common/actions.js'; import type { ErrorInfo } from '../common/state.js'; import type { ToolDefinition, SessionActiveClient, SessionInputRequest, Customization, CustomizationEnablement, McpServerState, } from './state.js'; import type { URI } from '../common/state.js'; import type { Changeset } from '../channels-changeset/state.js'; import type { ChatSummary } from '../channels-chat/state.js'; // ─── Session Actions ───────────────────────────────────────────────────────── /** * Session backend initialized successfully. * * @category Session Actions * @version 1 */ export interface SessionReadyAction { type: ActionType.SessionReady; } /** * Session backend failed to initialize. * * @category Session Actions * @version 1 */ export interface SessionCreationFailedAction { type: ActionType.SessionCreationFailed; /** Error details */ error: ErrorInfo; } /** * A chat was added to this session's catalog. Upsert semantics: if a chat * with the same `summary.resource` already exists, the existing entry is * replaced. * * Mirrors the root-channel `root/sessionAdded` notification. * * @category Session Actions * @version 1 */ export interface SessionChatAddedAction { type: ActionType.SessionChatAdded; /** The full summary of the newly added (or upserted) chat. */ summary: ChatSummary; } /** * A chat was removed from this session's catalog. No-op when no entry matches. * * Mirrors the root-channel `root/sessionRemoved` notification. * * @category Session Actions * @version 1 */ export interface SessionChatRemovedAction { type: ActionType.SessionChatRemoved; /** The URI of the chat to remove. */ chat: URI; } /** * One existing chat's summary fields changed. * * Partial-update semantics: only fields present in `changes` are written; * omitted fields are preserved. Identity fields (`resource`) MUST NOT be * carried in `changes`. No-op when no entry with `chat` exists — clients * SHOULD then wait for a {@link SessionChatAddedAction | `session/chatAdded`}. * * Mirrors the root-channel `root/sessionSummaryChanged` notification. * * @category Session Actions * @version 1 */ export interface SessionChatUpdatedAction { type: ActionType.SessionChatUpdated; /** The URI of the chat whose summary changed. */ chat: URI; /** * Mutable summary fields that changed; omitted fields are unchanged. * * Identity fields (`resource`) never change and MUST be omitted by * senders; receivers SHOULD ignore them if present. */ changes: Partial; } /** * The default chat input-routing hint for this session changed. * * @category Session Actions * @version 1 */ export interface SessionDefaultChatChangedAction { type: ActionType.SessionDefaultChatChanged; /** New default chat URI, or `undefined` to clear the hint. */ defaultChat?: URI; } /** * Session title updated. Fired by the server when the title is auto-generated * from conversation, or dispatched by a client to rename a session. * * @category Session Actions * @clientDispatchable * @version 1 */ export interface SessionTitleChangedAction { type: ActionType.SessionTitleChanged; /** New title */ title: string; } /** * The read state of the session changed. * * Dispatched by a client to mark a session as read (e.g. after viewing it) * or unread (e.g. after new activity since the client last looked at it). * * @category Session Actions * @version 1 * @clientDispatchable */ export interface SessionIsReadChangedAction { type: ActionType.SessionIsReadChanged; /** Whether the session has been read */ isRead: boolean; } /** * The archived state of the session changed. * * Dispatched by a client to archive a session (e.g. the task is * complete) or to unarchive it. * * @category Session Actions * @version 1 * @clientDispatchable */ export interface SessionIsArchivedChangedAction { type: ActionType.SessionIsArchivedChanged; /** Whether the session is archived */ isArchived: boolean; } /** * The activity description of the session changed. * * Dispatched by the server to indicate what the session is currently doing * (e.g. running a tool, thinking). Clear activity by setting it to `undefined`. * * @category Session Actions * @version 1 */ export interface SessionActivityChangedAction { type: ActionType.SessionActivityChanged; /** Human-readable description of current activity, or `undefined` to clear */ activity: string | undefined; } /** * The {@link Changeset | catalogue of changesets} the agent host * advertises for this session changed. Replaces * {@link SessionState.changesets | `state.changesets`} entirely * (full-replacement semantics) — set to `undefined` to clear the * catalogue. * * Producers dispatch this whenever entries are added or removed. The * fan-out happens through this action so observers see catalogue * mutations in the same {@link ChangesetAction | per-changeset} action * stream they already follow for file-level updates. * * @category Session Actions * @version 1 */ export interface SessionChangesetsChangedAction { type: ActionType.SessionChangesetsChanged; /** New catalogue, or `undefined` to clear it */ changesets: Changeset[] | undefined; } /** * Server tools for this session have changed. * * Full-replacement semantics: the `tools` array replaces the previous `serverTools` entirely. * * @category Session Actions * @version 1 */ export interface SessionServerToolsChangedAction { type: ActionType.SessionServerToolsChanged; /** Updated server tools list (full replacement) */ tools: ToolDefinition[]; } /** * An active client for this session was added or updated. * * Upsert semantics keyed by {@link SessionActiveClient.clientId | `clientId`}: * a client dispatches this action with its own `SessionActiveClient` to join * the session's active clients or refresh its entry, replacing any existing * entry that has the same `clientId`. Multiple clients may be active at once. * This is also how a client updates its published tools or customizations — * re-dispatch with the full, updated entry. Use * {@link SessionActiveClientRemovedAction | `session/activeClientRemoved`} to * leave. The server SHOULD automatically dispatch that removal when an active * client disconnects. * * @category Session Actions * @version 1 * @clientDispatchable */ export interface SessionActiveClientSetAction { type: ActionType.SessionActiveClientSet; /** The active client to add or update, matched by `clientId`. */ activeClient: SessionActiveClient; } /** * An active client was removed from this session. * * Removes the entry for the client identified by `clientId` from * {@link SessionState.activeClients}; a no-op when no entry matches. * * The host SHOULD dispatch this automatically when a client stops participating * in the session — for example when it unsubscribes from the session channel, * when it disconnects and does not reconnect within a host-defined grace * period, or when a `reconnect` command's `subscriptions` omit a session the * client was still active in. When removing a client, the host SHOULD also * cancel that client's in-flight tool calls — those whose tool call state * carries a client `ToolCallContributor` with the matching `clientId` — by * dispatching `chat/toolCallComplete` with `result.success = false`. (There is * no per-tool-call server cancel; a failed completion is the cancellation * mechanism, and the call ends in `completed` status with a failed result.) * * @category Session Actions * @version 1 * @clientDispatchable */ export interface SessionActiveClientRemovedAction { type: ActionType.SessionActiveClientRemoved; /** The `clientId` of the active client to remove. */ clientId: string; } // ─── Working Directory Actions ─────────────────────────────────────────────── /** * A working directory was added to the session's * {@link SessionState.workingDirectories} set. * * Membership semantics keyed by the directory URI: the reducer appends * `directory` when the set does not already contain it (creating the set if * absent) and is a no-op when it is already present. Only valid when the agent * advertises {@link AgentCapabilities.multipleWorkingDirectories}. * * @category Session Actions * @version 1 * @clientDispatchable */ export interface SessionWorkingDirectorySetAction { type: ActionType.SessionWorkingDirectorySet; /** The working directory to grant the session's agent tool access to. */ directory: URI; } /** * A working directory was removed from the session's * {@link SessionState.workingDirectories} set. * * 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. an immutable primary directory, see * {@link MultipleWorkingDirectoriesCapability.immutablePrimary}); it then leaves * the set unchanged. When the agent advertises * {@link MultipleWorkingDirectoriesCapability.primaryReplacement}, clients MUST * NOT use this generic membership action to remove index `0`; the host MUST * reject such a removal, leaving the protected slot intact. * * @category Session Actions * @version 1 * @clientDispatchable */ export interface SessionWorkingDirectoryRemovedAction { type: ActionType.SessionWorkingDirectoryRemoved; /** The working directory to revoke the session's agent tool access to. */ directory: URI; } /** * Atomically replaces one of the session's working directories. * * This is a targeted compare-and-swap: the reducer is a no-op when * {@link SessionState.workingDirectories} does not contain `directory`. * Otherwise it replaces that entry with `replacement` and deduplicates the * result, preserving every other directory's relative order. When * `replacement` occurs after the target, it moves to the target's position; * for example, `[A, B, C]` with `B → C` becomes `[A, C]`. When it occurs * before the target, it retains its earlier position and the target is removed; * `[A, B, C]` with `C → A` becomes `[A, B]`. * * Only valid when the agent advertises * {@link AgentCapabilities.multipleWorkingDirectories}. Replacing index `0` * additionally requires * {@link MultipleWorkingDirectoriesCapability.primaryReplacement}; clients * MUST NOT target an immutable primary. The host MUST validate and apply its * backend side effect before broadcasting an accepted action, or reject it. * * @category Session Actions * @version 1 * @clientDispatchable */ export interface SessionWorkingDirectoryReplacedAction { type: ActionType.SessionWorkingDirectoryReplaced; /** URI of the existing entry to replace. */ directory: URI; /** URI to place in the replaced entry's position. */ replacement: URI; } // ─── Input Needed Actions ──────────────────────────────────────────────────── /** * A session-level input request was added or updated. * * Upsert semantics keyed by {@link SessionInputRequest.id | `request.id`}: the * host dispatches this with the full {@link SessionInputRequest} to append a new * entry to {@link SessionState.inputNeeded} or replace the existing entry with * the same `id`. * * Server-originated: the host mirrors chat-level requests (elicitations, tool * confirmations, client-tool executions) into the session aggregate so clients * subscribed only to the session channel can discover them. Clients respond by * dispatching the ordinary `chat/*` action to the entry's `chat` channel — see * {@link SessionInputRequest}. * * @category Session Actions * @version 1 */ export interface SessionInputNeededSetAction { type: ActionType.SessionInputNeededSet; /** The input request to add or update, matched by `id`. */ request: SessionInputRequest; } /** * A session-level input request was removed. * * Removes the entry identified by `id` from * {@link SessionState.inputNeeded}; a no-op when no entry matches. * * Server-originated: the host dispatches this once the underlying request * resolves (the user answers, the tool call is confirmed, or the client * reports its result). * * @category Session Actions * @version 1 */ export interface SessionInputNeededRemovedAction { type: ActionType.SessionInputNeededRemoved; /** The `id` of the input request to remove. */ id: string; } // ─── Customization Actions ─────────────────────────────────────────────────── /** * The session's customizations have changed. * * Full-replacement semantics: the `customizations` array replaces the * previous `customizations` entirely. * * @category Session Actions * @version 1 */ export interface SessionCustomizationsChangedAction { type: ActionType.SessionCustomizationsChanged; /** Updated customization list (full replacement). */ customizations: Customization[]; } /** * A client updated a customization's enablement decisions. * * Matches `id` against every top-level customization first — a plugin or * directory container, or a bare top-level MCP server — then against the * children inside each container (a skill, agent, or other entry). Plugins * and MCP servers retain the matched entry's explicit decisions; other * entries update their `enabled` flag. Disabling a plugin still disables all * of its children — the effective state of a plugin child is the plugin's * derived enabled value and `(child.enabled ?? true)` — so toggling a child * only matters while its plugin is enabled. Is a no-op when no * customization has the given `id`. * * The `enablement` array completely replaces all explicit decisions. A caller * changing one scope must include every decision it intends to preserve. * * @category Session Actions * @version 1 * @clientDispatchable */ export interface SessionCustomizationToggledAction { type: ActionType.SessionCustomizationToggled; /** The id of the container or child to update. */ id: string; /** Explicit enablement decisions, replacing the previous list entirely. */ enablement: CustomizationEnablement[]; } /** * Upserts a top-level customization (plugin or directory). * * The reducer locates the existing entry by `customization.id`: * * - If found, the entry is replaced entirely with `customization`, * including its `children` array. To preserve existing children, the * host must include them on the payload. * - If not found, the entry is appended. * * @category Session Actions * @version 1 */ export interface SessionCustomizationUpdatedAction { type: ActionType.SessionCustomizationUpdated; /** The customization to upsert (matched by `customization.id`). */ customization: Customization; } /** * Removes a customization by id. * * Searches every container and its children for the entry. If the entry * is a container, its children are removed with it. Is a no-op when no * matching id is found. * * @category Session Actions * @version 1 */ export interface SessionCustomizationRemovedAction { type: ActionType.SessionCustomizationRemoved; /** The id of the customization to remove. */ id: string; } /** * Updates the runtime fields of an existing * {@link McpServerCustomization} — narrow alternative to * {@link SessionCustomizationUpdatedAction} for the high-frequency * `starting` ↔ `ready` ↔ `authRequired` transitions. * * Locates the target entry by `id`, searching both the top-level * customization list and the `children` array of every container. * Replaces the entry's {@link McpServerCustomization.state | `state`} * and {@link McpServerCustomization.channel | `channel`} * (full-replacement semantics: omit `channel` to clear an existing * channel URI). Other fields of the customization are preserved. * * Is a no-op when no matching `McpServerCustomization` is found. To * update any other field (name, icons, `mcpApp` capabilities, etc.) use * {@link SessionCustomizationUpdatedAction} instead. * * When the transition is to {@link McpServerStatus.AuthRequired} * because of a request issued mid-turn, the host SHOULD also raise * {@link SessionStatus.InputNeeded} on the session — see * {@link McpServerAuthRequiredState} for the rationale. * * @category Session Actions * @version 1 */ export interface SessionMcpServerStateChangedAction { type: ActionType.SessionMcpServerStateChanged; /** The id of the {@link McpServerCustomization} to update. */ id: string; /** The new lifecycle state. */ state: McpServerState; /** * Updated `mcp://` side-channel URI. Full-replacement: omit to clear * an existing channel (typical when leaving * {@link McpServerStatus.Ready | `Ready`}). */ channel?: URI; } /** * Requests that the host start or restart an existing * {@link McpServerCustomization}. * * Locates the target entry by `id`, searching both the top-level * customization list and the `children` array of every container. The * reducer optimistically moves the server to * {@link McpServerStatus.Starting | `starting`} and clears any previous * {@link McpServerCustomization.channel | `channel`}; the host remains * authoritative and SHOULD follow with * {@link SessionMcpServerStateChangedAction | `session/mcpServerStateChanged`} * once the server becomes ready, needs authentication, fails, or is * rejected. Is a no-op when no matching `McpServerCustomization` is found. * * @category Session Actions * @version 1 * @clientDispatchable */ export interface SessionMcpServerStartRequestedAction { type: ActionType.SessionMcpServerStartRequested; /** The id of the {@link McpServerCustomization} to start. */ id: string; } /** * Requests that the host stop an existing {@link McpServerCustomization}. * * Locates the target entry by `id`, searching both the top-level * customization list and the `children` array of every container. The * reducer optimistically moves the server to * {@link McpServerStatus.Stopped | `stopped`} and clears any previous * {@link McpServerCustomization.channel | `channel`}. Replacing an * {@link McpServerStatus.AuthRequired | `authRequired`} lifecycle state with * `stopped` unblocks the server from waiting on authentication. If the host * also raised session-level input-needed state solely for that MCP server, it * SHOULD remove that input-needed entry when accepting the stop. * * The host remains authoritative and MAY reject the action or follow with * {@link SessionMcpServerStateChangedAction | `session/mcpServerStateChanged`} * if the final lifecycle state differs. Is a no-op when no matching * `McpServerCustomization` is found. * * @category Session Actions * @version 1 * @clientDispatchable */ export interface SessionMcpServerStopRequestedAction { type: ActionType.SessionMcpServerStopRequested; /** The id of the {@link McpServerCustomization} to stop. */ id: string; } // ─── Config Actions ────────────────────────────────────────────────────────── /** * Client changed a mutable config value mid-session. * * Only properties with `sessionMutable: true` in the config schema may be * changed. The server validates and broadcasts the action; the reducer merges * the new values into `state.config.values`. * * @category Session Actions * @version 1 * @clientDispatchable */ export interface SessionConfigChangedAction { type: ActionType.SessionConfigChanged; /** Updated config values */ config: Record; /** When `true`, replaces all config values instead of merging */ replace?: boolean; } /** * The session's `_meta` side-channel changed. Replaces `state._meta` * entirely (full-replacement semantics). Producers SHOULD merge any * keys they wish to preserve into the new value before dispatching. * * @category Session Actions * @version 1 */ export interface SessionMetaChangedAction { type: ActionType.SessionMetaChanged; /** New `_meta` payload, or `undefined` to clear it */ _meta: Record | undefined; }