import type { ClientModel, EffectiveSessionControl } from "@opengeni/sdk"; import { type ButtonHTMLAttributes, type ChangeEvent, type ClipboardEvent, type ComponentPropsWithoutRef, type DragEvent, type KeyboardEvent, type ReactNode, type RefObject } from "react"; import type { Notice, SlashCommand } from "../commands/types.js"; import type { ComposerState } from "../hooks/use-composer.js"; import type { UseFileAttachmentsResult } from "../hooks/use-file-attachments.js"; import { type ConfirmState, type SlashCommandContext } from "../hooks/use-slash-commands.js"; import { type ResponsiveBasis } from "../lib/composer-responsive-context.js"; import { type ChatComposerMessages } from "../composer-messages.js"; import type { PickerModelRow } from "../model-policy.js"; import { OPEN_WORKSTREAM_CONTROL_EVENT } from "../workstream-control-event.js"; export { OPEN_WORKSTREAM_CONTROL_EVENT }; export type { ResponsiveBasis } from "../lib/composer-responsive-context.js"; export type ComposerDelivery = Pick; export type ComposerDraftState = Pick; export type ComposerControlState = Pick; export type ComposerControlLinks = { workspaceHref?: string | undefined; sessionHref?: ((sessionId: string) => string) | undefined; }; export { defaultChatComposerMessages } from "../composer-messages.js"; export type { ChatComposerMessages } from "../composer-messages.js"; export type ComposerSubmitMode = "queue" | "steer"; export type ComposerSubmitBlocker = "disabled" | "attachment" | "sending" | "command" | "annotations" | "empty" | null; /** * How the composer offers run control. * - `pause`: the workstream Pause control and paused-state strip (default; the * Opengeni console). * - `stop`: a Stop control only while a response runs. Stopping pauses this * conversation; the next message continues it, so people never see a paused * state they have to resume. Pauses applied elsewhere still show. * - `none`: no run control. */ export type ComposerRunControl = "pause" | "stop" | "none"; export type UseChatComposerControllerOptions = { delivery: ComposerDelivery; draft?: ComposerDraftState | undefined; control?: ComposerControlState | undefined; effectiveControl?: EffectiveSessionControl | null | undefined; queuedAheadCount?: number | undefined; canControlWorkspace?: boolean | undefined; controlLinks?: ComposerControlLinks | undefined; disabled?: boolean | undefined; attachments?: UseFileAttachmentsResult | undefined; commands?: readonly SlashCommand[] | undefined; commandContext?: SlashCommandContext | undefined; onClearView?: (() => void) | undefined; onPaste?: ((event: ClipboardEvent) => void) | undefined; messages?: Partial | undefined; /** Run control presentation. Defaults to `pause`. */ runControl?: ComposerRunControl | undefined; /** A response is in progress; shows the Stop control under `runControl="stop"`. */ running?: boolean | undefined; }; /** * Autosize a composer textarea up to `maxPx`. Never writes intermediate * `height: auto` / `0` on the live element — only the final pixel height. * * `measure` is injectable for unit tests; production always uses the off-DOM * mirror so shrink/steady never collapses the laid-out box. */ export declare function applyComposerTextareaHeight(textarea: HTMLTextAreaElement, maxPx?: number, measure?: (el: HTMLTextAreaElement) => number): void; /** * Headless interaction layer for a chat composer. It is the single owner of * delivery guards, keyboard routing, command interception, drag/drop, focus, * confirmation, and feedback state used by both the preset and primitives. */ export declare function useChatComposerController({ delivery, draft, control, effectiveControl, queuedAheadCount, canControlWorkspace, controlLinks, disabled, attachments, commands: commandsProp, commandContext, onClearView, onPaste, messages: messageOverrides, runControl, running, }: UseChatComposerControllerOptions): { id: string; rootRef: RefObject; textareaRef: RefObject; pauseButtonRef: RefObject; fileInputRef: RefObject; listboxId: string; effectiveControl: EffectiveSessionControl | null | undefined; queuedAheadCount: number; canControlWorkspace: boolean; controlLinks: ComposerControlLinks | undefined; disabled: boolean; attachments: UseFileAttachmentsResult | undefined; messages: { messagePlaceholder: string; pausedPlaceholder: string; inputLabel: string; keyboardHint: string; slashCommandBlocked: string; controlChangedError: string; sendFailedError: string; dropFiles: string; attachFiles: string; pauseAriaLabel: string; pauseTitle: string; stopAriaLabel?: string | undefined; stopTitle?: string | undefined; sendMessageAriaLabel: string; sendAndResumeAriaLabel: string; sendTitle: string; steerSendTitle?: string | undefined; steerLabel?: string | undefined; steerTitle?: string | undefined; queueLabel?: string | undefined; queueTitle?: string | undefined; sendAndResumeTitle: string; annotationNotesRequired: string; workspacePaused: string; pausedHere: string; parentBlocker: string; narrowerPause: string; pausedBy: (displayName: string) => string; queuedAhead: (count: number) => string; resumingAndSending: string; nextMessageResumes: string; resumeThisWorkstream: string; resumeShort: string; hidePauseDetails: string; showPauseDetails: string; pauseReasonsLabel: string; pausedByLabel: string; alsoPausedByLabel: string; resumeWorkspace: string; resumeFromSession: string; sessionCanRun: string; stillPausedBy: (displayName: string) => string; restoredResourcesLabel: string; restoredFile: (fileId: string) => string; removeRestoredResource: (index: number) => string; uploading: string; uploadFailed: string; previewAttachment: (name: string) => string; previewUnavailable?: string | undefined; attachmentPreviewLabel: string; downloadAttachment: (name: string) => string; closeAttachmentPreview: string; retryAttachment: (name: string) => string; retryUpload: string; removeAttachment: (name: string) => string; confirmCommand: (name: string) => string; confirmDescription: (command: SlashCommand) => string; cancel: string; runCommand: (name: string) => string; commands: string; slashCommandsLabel: string; modelLabel: string; close: string; danger: string; draftConflict: string; useOtherDraft: string; keepMine: string; savingDraft: string; formatBytes: (bytes: number) => string; formatRelativeTime: (changedAt: string) => string; }; sending: boolean; error: Error | null; clearError: () => void; hasDraftState: boolean; draftConflict: Error | null; draftSaving: boolean; restoredResources: import("@opengeni/sdk").ResourceRef[]; removeRestoredResource: ((index: number) => void) | undefined; resolveDraftConflict: ((choice: "keep_mine" | "use_remote") => Promise) | undefined; hasControl: boolean; runControl: ComposerRunControl; running: boolean; pausing: boolean; resuming: boolean; pause: (reason?: string) => Promise; stop: () => Promise; resume: (reason?: string) => Promise; resumeScope: (option: EffectiveSessionControl["resumeOptions"][number]) => Promise; paused: boolean; controlDetailsOpen: boolean; setControlDetailsOpen: import("react").Dispatch>; paletteMounted: boolean; setPaletteMounted: import("react").Dispatch>; dragging: boolean; handleDragOver: (event: DragEvent) => void; handleDragLeave: (event: DragEvent) => void; handleDrop: (event: DragEvent) => void; palette: import("../index.js").UseSlashCommandsResult; paletteEnabled: boolean; commandDraftBlocked: boolean; confirmState: ConfirmState; settleConfirmation: (confirmed: boolean) => void; helpOpen: boolean; setHelpOpen: import("react").Dispatch>; helpCommands: SlashCommand[]; activeNotice: Notice | null; canSubmit: boolean; submitBlocker: ComposerSubmitBlocker; submit: (mode: ComposerSubmitMode) => Promise; busySend: import("../index.js").ComposerBusySend; singleSend: boolean; alternateSend: import("../index.js").ComposerBusySend | null; submittingMode: ComposerSubmitMode | null; handleKeyDown: (event: KeyboardEvent) => void; handlePaste: (event: ClipboardEvent) => void; handleFileChange: (event: ChangeEvent) => void; focusInput: () => void | undefined; setValue: (next: string) => void; value: string; }; export type ChatComposerController = ReturnType; export type ChatComposerContextValue = Pick; /** Read the nearest compound composer's safe accessory-facing state and actions. */ export declare function useChatComposer(): ChatComposerContextValue; export type ComposerRootProps = Omit, "children"> & { controller: ChatComposerController; children: ReactNode; /** * Measurement surface for responsive composer chrome. `viewport` preserves * the existing breakpoint behavior; `container` responds to this root's * inline size and also bounds composer-owned portalled menus to it. */ responsiveBasis?: ResponsiveBasis | undefined; }; export declare const Root: import("react").ForwardRefExoticComponent, HTMLDivElement>, "ref">, "children"> & { controller: ChatComposerController; children: ReactNode; /** * Measurement surface for responsive composer chrome. `viewport` preserves * the existing breakpoint behavior; `container` responds to this root's * inline size and also bounds composer-owned portalled menus to it. */ responsiveBasis?: ResponsiveBasis | undefined; } & import("react").RefAttributes>; export type ComposerFrameProps = ComponentPropsWithoutRef<"div">; export declare const Frame: import("react").ForwardRefExoticComponent, HTMLDivElement>, "ref"> & import("react").RefAttributes>; export type ComposerCommandPaletteProps = { className?: string | undefined; }; export declare function CommandPalette({ className }: ComposerCommandPaletteProps): import("react").JSX.Element | null; type OwnedSurfaceProps = "onDragOver" | "onDragLeave" | "onDrop"; export type ComposerSurfaceProps = Omit, OwnedSurfaceProps>; export declare const Surface: import("react").ForwardRefExoticComponent>; export declare function PausedState(): import("react").JSX.Element | null; export declare function RestoredResources(): import("react").JSX.Element | null; export declare function Attachments(): import("react").JSX.Element | null; type OwnedInputProps = "value" | "defaultValue" | "onChange" | "onKeyDown" | "onPaste" | "disabled" | "aria-autocomplete" | "aria-controls" | "aria-activedescendant" | "aria-keyshortcuts"; export type ComposerInputProps = Omit, OwnedInputProps>; export declare const Input: import("react").ForwardRefExoticComponent>; export declare function Confirmation(): import("react").JSX.Element | null; export type ComposerFooterProps = ComponentPropsWithoutRef<"div">; export declare const Footer: import("react").ForwardRefExoticComponent, HTMLDivElement>, "ref"> & import("react").RefAttributes>; export type ComposerControlsProps = ComponentPropsWithoutRef<"span">; export declare const Controls: import("react").ForwardRefExoticComponent, HTMLSpanElement>, "ref"> & import("react").RefAttributes>; export type ComposerHintProps = ComponentPropsWithoutRef<"span">; export declare const Hint: import("react").ForwardRefExoticComponent, HTMLSpanElement>, "ref"> & import("react").RefAttributes>; export type ComposerActionsProps = ComponentPropsWithoutRef<"span">; export declare const Actions: import("react").ForwardRefExoticComponent, HTMLSpanElement>, "ref"> & import("react").RefAttributes>; type OwnedButtonProps = "type" | "onClick" | "disabled"; export type ComposerAttachButtonProps = Omit, OwnedButtonProps> & { accept?: string | undefined; multiple?: boolean | undefined; }; export declare const AttachButton: import("react").ForwardRefExoticComponent, OwnedButtonProps> & { accept?: string | undefined; multiple?: boolean | undefined; } & import("react").RefAttributes>; export type ComposerModelPickerProps = { models?: ClientModel[] | undefined; /** Catalog-backed rows preferred over legacy provider-grouped models. */ rows?: PickerModelRow[] | undefined; value?: string | undefined; onChange?: ((modelId: string) => void) | undefined; label?: string | undefined; className?: string | undefined; /** Filter to Codex models for remote_v2-locked sessions. */ codexOnly?: boolean | undefined; }; export declare function ModelPicker({ models, rows, value, onChange, label, className, codexOnly, }: ComposerModelPickerProps): import("react").JSX.Element; export type ComposerPauseButtonProps = Omit, OwnedButtonProps>; export declare const PauseButton: import("react").ForwardRefExoticComponent>; export type ComposerStopButtonProps = Omit, OwnedButtonProps>; /** * Stop the running response. Rendered only under `runControl="stop"` while a * response runs; stopping pauses this conversation and the next message * continues it. */ export declare const StopButton: import("react").ForwardRefExoticComponent>; export type ComposerSendButtonProps = Omit, OwnedButtonProps>; export type ComposerAlternateSendButtonProps = ComposerSendButtonProps; /** * The other way to send while the agent works, beside Send: Steer when Send * queues, Queue when Send steers. It appears once there is something to send, * so touch users (who have no Cmd/Ctrl+Enter) always have both choices. * It is shown exactly when Send takes its busy path (`alternateSend`), and * keeps its word on every width; on narrow composers Pause steps aside while * there is a draft to make room, as on phones. */ export declare const AlternateSendButton: import("react").ForwardRefExoticComponent>; export declare const SendButton: import("react").ForwardRefExoticComponent>; export declare function Help(): import("react").JSX.Element; export declare function Status(): import("react").JSX.Element;