import type { AgentCommand, AgentPhase, Message } from "@skaile/workspaces/types"; import type { AgentClientLike, AgentStoreOptions, AgentStoreSnapshot, ConnectionStatus, SubscribableStore } from "./types.js"; /** * Headless reactive store for agent conversation state. * * Framework-agnostic — works with React (`useSyncExternalStore`), * Vue (`shallowRef` + `subscribe`), or any other UI framework. * * Accepts a minimal transport interface (`send` + `onEvent`) so it works * with WebSocket, tRPC, SSE, or any other delivery mechanism. * @docLink packages/store/concepts#agent-store */ export declare class AgentStore implements SubscribableStore { private readonly _options; private _messages; private _streamingText; private _cancelledText; private _status; private _phase; private _pendingQuestion; private _error; private _isAllLoaded; private _seq; private _streamingFlushed; /** Shared state per store namespace — new Map instance on every mutation. */ private _sharedState; /** Protocol v2 capability registry — new Map instance on every mutation. */ private _capabilities; /** Protocol v2 active render invocations — new Map instance on every mutation. */ private _activeRenderInvocations; /** Protocol v2 — most recent `protocol_info` event from the runner. */ private _protocolInfo; /** Protocol v2 — latest incompatible-protocol notice. */ private _incompatibleProtocol; private _snapshot; private readonly _listeners; private readonly _unsubEvent; private readonly _unsubStatus; /** * @param options - Store configuration including transport and optional pagination support. */ constructor(options: AgentStoreOptions); /** Accumulated conversation messages, oldest first. */ get messages(): readonly Message[]; /** Text currently streaming from the agent. Empty when not streaming. */ get streamingText(): string; /** Current connection lifecycle state. */ get status(): ConnectionStatus; /** Current agent execution phase (e.g. `"idle"`, `"thinking"`, `"executing"`). */ get phase(): AgentPhase; /** The pending question the agent is waiting for the user to answer, or null. */ get pendingQuestion(): AgentStoreSnapshot["pendingQuestion"]; /** Most recent error, or null when no error is active. */ get error(): AgentStoreSnapshot["error"]; /** Partial text that was visible when the user cancelled. Empty when not cancelled. */ get cancelledText(): string; /** True when there are no more older messages to load via pagination. */ get isAllLoaded(): boolean; /** * Send a user prompt to the agent and optimistically update local state. * * Clears any previous error and cancelled text, sets phase to `"thinking"`, * and appends the prompt as a local message before forwarding to the agent. * * @param text - The user's prompt text. */ prompt(text: string): void; /** * Send a reply to the agent's pending question. * * Clears the pending question locally before forwarding the reply command. * * @param answer - The user's answer text. * @param question - The sub-question being answered, verbatim from its * `question` event. Required for correctness in hosts that surface several * queued questions at once ({@link pendingQuestion} tracks only the latest, * so those hosts drive this from their own message history): without it the * agent files the answer under its next unanswered sub-question, which * mismatches any non-sequential reply. * @param requestId - Exact identity from the rendered question; never inferred from pending state. */ reply(answer: string, question?: string, requestId?: string): void; /** * Cancel the current agent turn. * * Preserves partial streaming text in {@link cancelledText} so the UI can * display it. Clears streaming state, sets phase to `"cancelling"` (not * yet confirmed idle — see {@link AgentPhase}), and sends a `cancel` * command to the agent. */ cancel(): void; /** * Update shared state for a store namespace. * * Sends a `state_update` command to the agent and optimistically * updates local state so the change is reflected immediately. * * @param store - Store namespace (e.g. "app", "component:render-123"). * @param state - Full state snapshot (replaces previous). */ updateState(store: string, state: Record): void; /** * Send an arbitrary command to the agent. * * Use this for commands that don't have a dedicated convenience method * (e.g. `ui_interaction`). No local state changes — the command is * forwarded as-is to the transport. * * @param cmd - The command to send. */ send(cmd: AgentCommand): void; /** * Load the previous page of messages and prepend them to the current list. * * No-op when `loadMessages` was not provided at construction time or when * all history has already been loaded ({@link isAllLoaded} is true). * Sets {@link isAllLoaded} to true once the server returns fewer messages * than the configured page size. */ loadPreviousMessages(): Promise; /** * Programmatically update the connection status. * * Called by transport wrappers that cannot use the `onStatusChange` * callback (e.g. tRPC subscriptions that track status externally). * * Writing the status the store already holds is a no-op: it neither rotates * the snapshot nor notifies listeners. * * @param status - The new connection status. */ setStatus(status: ConnectionStatus): void; /** * Register a change listener. Called synchronously after every state change. * * Conforms to the `subscribe` parameter of React's `useSyncExternalStore`. * * @param listener - Callback invoked whenever state changes. * @returns Unsubscribe function — call to stop receiving notifications. */ subscribe: (listener: () => void) => (() => void); /** * Return the current immutable state snapshot. * * A new object is produced lazily on the first call after each state change. * Subsequent calls return the same cached object until the next change. * Conforms to the `getSnapshot` parameter of React's `useSyncExternalStore`. */ getSnapshot: () => AgentStoreSnapshot; /** * Unsubscribe from transport events and clear all change listeners. * * Call this when the component or service that owns the store unmounts or * shuts down to prevent memory leaks. */ dispose(): void; /** * Create an {@link AgentStore} connected to a duck-typed agent client. * * Adapts the client's `send`/`onEvent`/`offEvent` API to the * {@link StoreTransport} interface expected by the constructor, without * creating a hard runtime dependency on `@skaile/workspaces/client`. * * @param client - Any object implementing {@link AgentClientLike}. * @param opts - Optional store configuration. * @param opts.sessionId - Session ID for message envelopes (defaults to a new UUID). * @param opts.initialMessages - Messages to pre-populate the store with. * * @example * ```ts * const store = AgentStore.fromClient(agentClient, { sessionId: 'sess-123' }) * ``` */ static fromClient(client: AgentClientLike, opts?: { sessionId?: string; initialMessages?: Message[]; }): AgentStore; private _handleEvent; /** * Finalize buffered streaming text as a `text` Message. * * @returns true when text was flushed; false when there was nothing to flush, * so callers can skip a notify that would change nothing. */ private _flushStreaming; private _appendMessage; private _notify; } //# sourceMappingURL=store.d.ts.map