import { ActionType } from "../common/actions.js";
import type { StringOrMarkdown, ErrorInfo, FileEdit, UsageInfo, URI } from "../common/state.js";
import { ToolCallConfirmationReason, ToolCallCancellationReason, PendingMessageKind, type Message, type ResponsePart, type ToolCallResult, type ToolResultContent, type ToolDefinition, type SessionActiveClient, type Customization, type McpServerState, type SessionInputAnswer, type SessionInputRequest, type SessionInputResponseKind, type ConfirmationOption, type AgentSelection, type ToolCallContributor } from "./state.js";
import type { ModelSelection } from "../channels-root/state.js";
import type { ChangesetSummary } from "../channels-changeset/state.js";
/**
 * Base interface for all tool-call-scoped actions, carrying the common turn
 * and tool call identifiers. The owning session URI is identified by the
 * enclosing {@link ActionEnvelope}'s `channel` field.
 *
 * @category Session Actions
 */
interface ToolCallActionBase {
    /** Turn identifier */
    turnId: string;
    /** Tool call identifier */
    toolCallId: string;
    /**
     * Additional provider-specific metadata for this tool call.
     *
     * Clients MAY look for well-known keys here to provide enhanced UI.
     * For example, a `ptyTerminal` key with `{ input: string; output: string }`
     * indicates the tool operated on a terminal (both `input` and `output` may
     * contain escape sequences).
     */
    _meta?: Record<string, unknown>;
}
/**
 * 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 new message has been sent to the agent, and a new turn starts.
 *
 * A client is only allowed to send {@link MessageKind.User} messages.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionTurnStartedAction {
    type: ActionType.SessionTurnStarted;
    /** Turn identifier */
    turnId: string;
    /** The new message */
    message: Message;
    /** If this turn was auto-started from a queued message, the ID of that message */
    queuedMessageId?: string;
}
/**
 * Streaming text chunk from the assistant, appended to a specific response part.
 *
 * The server MUST first emit a `session/responsePart` to create the target
 * part (markdown or reasoning), then use this action to append text to it.
 *
 * @category Session Actions
 * @version 1
 */
export interface SessionDeltaAction {
    type: ActionType.SessionDelta;
    /** Turn identifier */
    turnId: string;
    /** Identifier of the response part to append to */
    partId: string;
    /** Text chunk */
    content: string;
}
/**
 * Structured content appended to the response.
 *
 * @category Session Actions
 * @version 1
 */
export interface SessionResponsePartAction {
    type: ActionType.SessionResponsePart;
    /** Turn identifier */
    turnId: string;
    /** Response part (markdown or content ref) */
    part: ResponsePart;
}
/**
 * A tool call begins — parameters are streaming from the LM.
 *
 * The server sets {@link ToolCallContributor | `contributor`} to identify
 * the origin of the tool. For client-provided tools, the named client is
 * responsible for executing the tool once it reaches the `running` state
 * and dispatching `session/toolCallComplete`. For MCP-served tools, the
 * server executes the call against the named `McpServerCustomization`.
 *
 * @category Session Actions
 * @version 1
 */
export interface SessionToolCallStartAction extends ToolCallActionBase {
    type: ActionType.SessionToolCallStart;
    /** Internal tool name (for debugging/logging) */
    toolName: string;
    /** Human-readable tool name */
    displayName: string;
    /**
     * Reference to the contributor of the tool being called. Absent for
     * server-side tools that are not contributed by a client or MCP server.
     */
    contributor?: ToolCallContributor;
}
/**
 * Streaming partial parameters for a tool call.
 *
 * @category Session Actions
 * @version 1
 */
export interface SessionToolCallDeltaAction extends ToolCallActionBase {
    type: ActionType.SessionToolCallDelta;
    /** Partial parameter content to append */
    content: string;
    /** Updated progress message */
    invocationMessage?: StringOrMarkdown;
}
/**
 * Tool call parameters are complete, or a running tool requires re-confirmation.
 *
 * When dispatched for a `streaming` tool call, transitions to `pending-confirmation`
 * or directly to `running` if `confirmed` is set.
 *
 * When dispatched for a `running` tool call (e.g. mid-execution permission needed),
 * transitions back to `pending-confirmation`. The `invocationMessage` and `_meta`
 * SHOULD be updated to describe the specific confirmation needed. Clients use the
 * standard `session/toolCallConfirmed` flow to approve or deny.
 *
 * For client-provided tools, the server typically sets `confirmed` to
 * `'not-needed'` so the tool transitions directly to `running`, where the
 * owning client can begin execution immediately.
 *
 * @category Session Actions
 * @version 1
 */
export interface SessionToolCallReadyAction extends ToolCallActionBase {
    type: ActionType.SessionToolCallReady;
    /** Message describing what the tool will do or what confirmation is needed */
    invocationMessage: StringOrMarkdown;
    /** Raw tool input */
    toolInput?: string;
    /** Short title for the confirmation prompt (e.g. `"Run in terminal"`, `"Write file"`) */
    confirmationTitle?: StringOrMarkdown;
    /** File edits that this tool call will perform, for preview before confirmation */
    edits?: {
        items: FileEdit[];
    };
    /** Whether the agent host allows the client to edit the tool's input parameters before confirming */
    editable?: boolean;
    /** If set, the tool was auto-confirmed and transitions directly to `running` */
    confirmed?: ToolCallConfirmationReason;
    /**
     * Options the server offers for this confirmation. When present, the client
     * SHOULD render these instead of a plain approve/deny UI. Each option
     * belongs to a {@link ConfirmationOptionGroup} so the client can still
     * categorise the choices.
     */
    options?: ConfirmationOption[];
}
/**
 * Client approves a pending tool call. The tool transitions to `running`.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionToolCallApprovedAction extends ToolCallActionBase {
    type: ActionType.SessionToolCallConfirmed;
    /** The tool call was approved */
    approved: true;
    /** How the tool was confirmed */
    confirmed: ToolCallConfirmationReason;
    /** Edited tool input parameters, if the client modified them before confirming */
    editedToolInput?: string;
    /** ID of the selected confirmation option, if the server provided options */
    selectedOptionId?: string;
}
/**
 * Client denies a pending tool call. The tool transitions to `cancelled`.
 *
 * For client-provided tools, the owning client MUST dispatch this if it does
 * not recognize the tool or cannot execute it.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionToolCallDeniedAction extends ToolCallActionBase {
    type: ActionType.SessionToolCallConfirmed;
    /** The tool call was denied */
    approved: false;
    /** Why the tool was cancelled */
    reason: ToolCallCancellationReason.Denied | ToolCallCancellationReason.Skipped;
    /** What the user suggested doing instead */
    userSuggestion?: Message;
    /** Optional explanation for the denial */
    reasonMessage?: StringOrMarkdown;
    /** ID of the selected confirmation option, if the server provided options */
    selectedOptionId?: string;
}
/**
 * Client confirms or denies a pending tool call.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export type SessionToolCallConfirmedAction = SessionToolCallApprovedAction | SessionToolCallDeniedAction;
/**
 * Tool execution finished. Transitions to `completed` or `pending-result-confirmation`
 * if `requiresResultConfirmation` is `true`.
 *
 * For client-provided tools (where `toolClientId` is set on the tool call state),
 * the owning client dispatches this action with the execution result. The server
 * SHOULD reject this action if the dispatching client does not match `toolClientId`.
 *
 * Servers waiting on a client tool call MAY time out after a reasonable duration
 * if the implementing client disconnects or becomes unresponsive, and dispatch
 * this action with `result.success = false` and an appropriate error.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionToolCallCompleteAction extends ToolCallActionBase {
    type: ActionType.SessionToolCallComplete;
    /** Execution result */
    result: ToolCallResult;
    /** If true, the result requires client approval before finalizing */
    requiresResultConfirmation?: boolean;
}
/**
 * Client approves or denies a tool's result.
 *
 * If `approved` is `false`, the tool transitions to `cancelled` with reason `result-denied`.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionToolCallResultConfirmedAction extends ToolCallActionBase {
    type: ActionType.SessionToolCallResultConfirmed;
    /** Whether the result was approved */
    approved: boolean;
}
/**
 * Partial content produced while a tool is still executing.
 *
 * Replaces the `content` array on the running tool call state. Clients can
 * use this to display live feedback (e.g. a terminal reference) before the
 * tool completes.
 *
 * For client-provided tools (where `toolClientId` is set on the tool call state),
 * the owning client dispatches this action to stream intermediate content while
 * executing. The server SHOULD reject this action if the dispatching client does
 * not match `toolClientId`.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionToolCallContentChangedAction extends ToolCallActionBase {
    type: ActionType.SessionToolCallContentChanged;
    /** The current partial content for the running tool call */
    content: ToolResultContent[];
}
/**
 * Turn finished — the assistant is idle.
 *
 * @category Session Actions
 * @version 1
 */
export interface SessionTurnCompleteAction {
    type: ActionType.SessionTurnComplete;
    /** Turn identifier */
    turnId: string;
}
/**
 * Turn was aborted; server stops processing.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionTurnCancelledAction {
    type: ActionType.SessionTurnCancelled;
    /** Turn identifier */
    turnId: string;
}
/**
 * Error during turn processing.
 *
 * @category Session Actions
 * @version 1
 */
export interface SessionErrorAction {
    type: ActionType.SessionError;
    /** Turn identifier */
    turnId: string;
    /** Error details */
    error: ErrorInfo;
}
/**
 * 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;
}
/**
 * Token usage report for a turn.
 *
 * @category Session Actions
 * @version 1
 */
export interface SessionUsageAction {
    type: ActionType.SessionUsage;
    /** Turn identifier */
    turnId: string;
    /** Token usage data */
    usage: UsageInfo;
}
/**
 * Reasoning/thinking text from the model, appended to a specific reasoning response part.
 *
 * The server MUST first emit a `session/responsePart` to create the target
 * reasoning part, then use this action to append text to it.
 *
 * @category Session Actions
 * @version 1
 */
export interface SessionReasoningAction {
    type: ActionType.SessionReasoning;
    /** Turn identifier */
    turnId: string;
    /** Identifier of the reasoning response part to append to */
    partId: string;
    /** Reasoning text chunk */
    content: string;
}
/**
 * Model changed for this session.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionModelChangedAction {
    type: ActionType.SessionModelChanged;
    /** New model selection */
    model: ModelSelection;
}
/**
 * Custom agent selection changed for this session.
 *
 * Omitting `agent` (or setting it to `undefined`) clears the selection and
 * resets the session to no selected custom agent (provider default behavior).
 *
 * When a turn is currently active, the server MUST defer the change until
 * the active turn completes, then apply it for the next turn (same rule as
 * {@link SessionModelChangedAction | `session/modelChanged`}).
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionAgentChangedAction {
    type: ActionType.SessionAgentChanged;
    /**
     * New agent selection, or `undefined` to clear the selection and reset the
     * session to no selected custom agent.
     */
    agent?: AgentSelection;
}
/**
 * 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 ChangesetSummary | catalogue of changesets} the agent host
 * advertises for this session changed. Replaces
 * `state.summary.changesets` entirely (full-replacement semantics) — set
 * to `undefined` to clear the catalogue.
 *
 * Producers dispatch this whenever entries are added, removed, or have
 * their aggregate counts (`additions` / `deletions` / `files`) refreshed.
 * 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: ChangesetSummary[] | 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[];
}
/**
 * The active client for this session has changed.
 *
 * A client dispatches this action with its own `SessionActiveClient` to claim
 * the active role, or with `null` to release it. The server SHOULD reject if
 * another client is already active. The server SHOULD automatically dispatch
 * this action with `activeClient: null` when the active client disconnects.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionActiveClientChangedAction {
    type: ActionType.SessionActiveClientChanged;
    /** The new active client, or `null` to unset */
    activeClient: SessionActiveClient | null;
}
/**
 * The active client's tool list has changed.
 *
 * Full-replacement semantics: the `tools` array replaces the active client's
 * previous tools entirely. The server SHOULD reject if the dispatching client
 * is not the current active client.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionActiveClientToolsChangedAction {
    type: ActionType.SessionActiveClientToolsChanged;
    /** Updated client tools list (full replacement) */
    tools: ToolDefinition[];
}
/**
 * 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 toggled a container customization on or off.
 *
 * Targets a top-level container (plugin or directory) by `id`. Only
 * containers have an `enabled` flag; children are always active when
 * their container is enabled. Is a no-op when no matching container is
 * found.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionCustomizationToggledAction {
    type: ActionType.SessionCustomizationToggled;
    /** The id of the container to toggle. */
    id: string;
    /** Whether to enable or disable the container. */
    enabled: boolean;
}
/**
 * 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;
}
/**
 * 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<string, unknown>;
    /** 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<string, unknown> | undefined;
}
/**
 * Truncates a session's history. If `turnId` is provided, all turns after that
 * turn are removed and the specified turn is kept. If `turnId` is omitted, all
 * turns are removed.
 *
 * If there is an active turn it is silently dropped and the session status
 * returns to `idle`.
 *
 * Common use-case: truncate old data then dispatch a new
 * `session/turnStarted` with an edited message.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionTruncatedAction {
    type: ActionType.SessionTruncated;
    /** Keep turns up to and including this turn. Omit to clear all turns. */
    turnId?: string;
}
/**
 * A pending message was set (upsert semantics: creates or replaces).
 *
 * For steering messages, this always replaces the single steering message.
 * For queued messages, if a message with the given `id` already exists it is
 * updated in place; otherwise it is appended to the queue. If the session is
 * idle when a queued message is set, the server SHOULD immediately consume it
 * and start a new turn.
 *
 * A client is only allowed to send {@link MessageKind.User} messages.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionPendingMessageSetAction {
    type: ActionType.SessionPendingMessageSet;
    /** Whether this is a steering or queued message */
    kind: PendingMessageKind;
    /** Unique identifier for this pending message */
    id: string;
    /** The message content */
    message: Message;
}
/**
 * A pending message was removed (steering or queued).
 *
 * Dispatched by clients to cancel a pending message, or by the server when
 * it consumes a message (e.g. starting a turn from a queued message or
 * injecting a steering message into the current turn).
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionPendingMessageRemovedAction {
    type: ActionType.SessionPendingMessageRemoved;
    /** Whether this is a steering or queued message */
    kind: PendingMessageKind;
    /** Identifier of the pending message to remove */
    id: string;
}
/**
 * Reorder the queued messages.
 *
 * The `order` array contains the IDs of queued messages in their new
 * desired order. IDs not present in the current queue are ignored.
 * Queued messages whose IDs are absent from `order` are appended at
 * the end in their original relative order (so a client with a stale
 * view of the queue never silently drops messages).
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionQueuedMessagesReorderedAction {
    type: ActionType.SessionQueuedMessagesReordered;
    /** Queued message IDs in the desired order */
    order: string[];
}
/**
 * A session requested input from the user.
 *
 * Full-request upsert semantics: the `request` replaces any existing request
 * with the same `id`, or is appended if it is new. Answer drafts are preserved
 * unless `request.answers` is provided.
 *
 * @category Session Actions
 * @version 1
 */
export interface SessionInputRequestedAction {
    type: ActionType.SessionInputRequested;
    /** Input request to create or replace */
    request: SessionInputRequest;
}
/**
 * A client updated, submitted, skipped, or removed a single in-progress answer.
 *
 * Dispatching with `answer: undefined` removes that question's answer draft.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionInputAnswerChangedAction {
    type: ActionType.SessionInputAnswerChanged;
    /** Input request identifier */
    requestId: string;
    /** Question identifier within the input request */
    questionId: string;
    /** Updated answer, or `undefined` to clear an answer draft */
    answer?: SessionInputAnswer;
}
/**
 * A client accepted, declined, or cancelled a session input request.
 *
 * If accepted, the server uses `answers` (when provided) plus the request's
 * synced answer state to resume the blocked operation.
 *
 * @category Session Actions
 * @version 1
 * @clientDispatchable
 */
export interface SessionInputCompletedAction {
    type: ActionType.SessionInputCompleted;
    /** Input request identifier */
    requestId: string;
    /** Completion outcome */
    response: SessionInputResponseKind;
    /** Optional final answer replacement, keyed by question ID */
    answers?: Record<string, SessionInputAnswer>;
}
export {};
