import type { ChatMessage, CompactionInfo, MessageContent } from "../schemas/message"; import type { ContentBlock, PatchEnvelope, TurnProjection } from "../schemas/projection"; import type { ReplaySpeed, ReplayState, SessionStatus } from "../schemas/session"; import { type SessionQueueSnapshot } from "./queue"; /** 一次 AskUserQuestion 的用户作答(选项选择 + 自定义输入 + 可选补充)。 */ export interface AskUserAnswerData { selections: Record; custom: Record; /** 选完选项后的自由补充,空着就是没有。 */ note?: string; } export interface AgentLoopInfo { toolCallId: string; description: string; status: "running" | "done" | "error" | "cancelled" | "awaiting_answer"; } export interface ActiveCompactionState extends CompactionInfo { turn_id: string; status: "streaming" | "completed" | "paused" | "failed" | "interrupted"; } export type ConnectionStatus = "connecting" | "connected" | "reconnecting" | "disconnected"; /** * 一个会话的完整快照。引用不可变:任何变更都会产生新对象, * 满足 React `useSyncExternalStore` / Vue `shallowRef` 的订阅契约。 */ export interface SessionState { sessionId: string; /** 服务端投影的原始 turn 列表(按 sequence 有序)。 */ turns: TurnProjection[]; /** 由 turns 物化出的聊天消息列表,UI 直接渲染。 */ messages: ChatMessage[]; /** 智能体是否正在流式回复。 */ isStreaming: boolean; /** 会话状态(running / completed / failed / waiting_for_input / interrupted …)。 */ status: SessionStatus | null; /** 当前模式(planning / executing),来自 mode_change 事件。 */ mode: "planning" | "executing" | null; /** Socket.IO 连接状态(同一 client 下所有会话共享)。 */ connection: ConnectionStatus; /** 最近一次运行错误消息(system:error 等)。 */ errorMessage: string | null; askAnswers: Record; agentLoops: Record; activeCompaction: ActiveCompactionState | null; /** 回放(演示 / 彩排)状态;不是回放会话时为 null。 */ replay: ReplaySnapshot | null; /** 服务端持久化的等待消息队列快照;只在 revision 更新时替换。 */ queue: SessionQueueSnapshot; /** 当前身份对这个会话的权限;"viewer" 表示只读(分享链接打开的)。 */ viewerRole: "owner" | "viewer" | null; /** Stable anchor for the next older projected page. */ nextBefore: string | null; loadingOlder: boolean; } /** 回放会话的快照视图,由服务端的 replay_state 归一化而来。 */ export interface ReplaySnapshot { /** 仍在按录制内容走;转自主运行后为 false。 */ isReplay: boolean; speed: ReplaySpeed; sourceSessionId: string | null; } /** 把服务端的 replay_state 归一化成快照;不是回放会话时返回 null。 */ export declare function toReplaySnapshot(raw: ReplayState | null | undefined): ReplaySnapshot | null; export declare function createInitialSessionState(sessionId: string): SessionState; export declare function extractModeFromBlocks(blocks: ContentBlock[]): "planning" | "executing" | null; export declare function reconcileOptimisticUserTurns(currentTurns: TurnProjection[], incomingTurns: TurnProjection[]): TurnProjection[]; /** Reconcile a bulk authoritative window only by an echoed request identity. * Positional fallback is reserved for a single live turn from an older server. */ export declare function reconcileHistoricalUserTurns(currentTurns: TurnProjection[], incomingTurns: TurnProjection[]): TurnProjection[]; /** * 用一份新的 turn 列表重建会话状态。 * addErrorMessage 注入的 role==="error" 消息不在 turns 里,默认会被物化过程抹掉; * 这里沿用锚点策略:只保留锚定在"当前最后一个 turn"上的错误气泡, * turn 推进(新消息 / rewind / 重连)时旧错误自动消失。 */ export declare function withTurns(state: SessionState, turns: TurnProjection[]): SessionState; /** * 安装一份服务端权威队列快照。旧 revision、别的会话或结构不合法的快照一律不采纳, * 直接返回原 state——引用不变,订阅者不会收到多余通知。 */ export declare function withQueue(state: SessionState, snapshot: SessionQueueSnapshot): SessionState; export declare function addUserMessage(state: SessionState, content: MessageContent, clientRequestId?: string): SessionState; export declare function upsertTurn(state: SessionState, turn: TurnProjection): SessionState; export declare function applyTurnPatch(state: SessionState, patch: PatchEnvelope): SessionState; export declare function addErrorMessage(state: SessionState, content: string): SessionState; export declare function markInterrupted(state: SessionState): SessionState; export declare function markFailed(state: SessionState): SessionState;