/** * Client half of the panel's workflow PICKER: the durable `selectWorkflow` * write and this session's commit state. * * WHY its own module: the panel's READ is the polled store-backed snapshot * (`mstar/panelSnapshot`, `panel-snapshot-client.ts`). What survives the retired * emission read is the picker's WRITE — committing one session's workflow * choice — so it keeps exactly that surface here and nothing else: no cached * payload, no anchor row, no refresh interval. * * NEVER OPTIMISTIC: a pick is `pending` until the host acknowledges, then * `selected` (with the acknowledged id) or `failed` (with the host's reason). * The acknowledged id is a CONTROL state, not a data source: the panel's * rendered selection comes from the next snapshot's `retained.selection`, which * the host rebuilds from the same durable binding this write commits. * * ONE SUBMISSION PER SESSION: a second pick while the first is on the wire would * race two acknowledgements for one binding, so it answers * `unavailable('selection-pending')` instead of stacking. * * NOTHING HERE THROWS: every transport, parse and timeout fault becomes a * reason the panel renders. The store is written only from a response * continuation, never during a render. * * @module @mstar-harness/dsh/client/panel/workflow-picker-client */ import type { ConnectionRpcResult } from '@deepseek-ai/dsh-client-connection/client'; import { type MstarSelectWorkflowFetch } from './guards.ts'; /** Deadline for one `/api/mstar/selectWorkflow` request (a hanging gateway must not pin `pending`). */ export declare const WORKFLOW_PICK_TIMEOUT_MS = 5000; /** * Structural face of the client `connection` service the picker needs — the * generic RPC caller of the shared gateway. Declared structurally (not imported * as a value) so the bundle stays free of a runtime dependency on the transport * package. */ export interface MstarWorkflowPickerConnection { readonly rpc: { call(channel: string, endpoint: string, payload: unknown, signal?: AbortSignal): Promise>; }; } /** Optional timings (test seams; production uses the constant above). */ export interface MstarWorkflowPickerClientOptions { /** Per-request deadline in ms (`0` disables the bound). */ readonly timeoutMs?: number; } /** * This session's commit state — control feedback only, never a selection source. * `idle` is the shared reference a session with no recorded pick reads. */ export type MstarSelectionState = { readonly state: 'idle'; } | { readonly state: 'pending'; } | { readonly state: 'selected'; readonly workflowId: string; } | { readonly state: 'failed'; readonly reason: string; }; /** The observable store value: one commit state per session. */ export interface MstarWorkflowPickerSnapshot { readonly selections: ReadonlyMap; } /** The panel's picker client: one write at a time per session, no cached reads. */ export declare class MstarWorkflowPickerClient { private readonly connection; private snapshot; private readonly listeners; private disposed; private readonly timeoutMs; constructor(connection: MstarWorkflowPickerConnection | undefined, options?: MstarWorkflowPickerClientOptions); readonly getSnapshot: () => MstarWorkflowPickerSnapshot; readonly subscribe: (listener: () => void) => (() => void); /** * Commit this session's workflow pick over the host's shared gateway. * @param sessionId - the session the panel is showing. * @param cwd - the session's workspace directory (the host cross-checks it). * @param workflowId - the chosen ACTIVE workflow id. * @returns the host's acknowledgement, or the explicit unavailable state. */ selectWorkflow(sessionId: string, cwd: string, workflowId: string): Promise; /** Stop accepting writes and end in-flight requests (plugin teardown). */ dispose(): void; /** One `selectWorkflow` round trip (never throws — every fault is a reason). */ private call; /** Publish one session's commit state (store write outside a render). */ private setSelection; }