rdesign/frontend/node_modules/@copilotkitnext/react/dist/hooks/use-interrupt.d.mts

102 lines
4.8 KiB
TypeScript

import { InterruptEvent, InterruptHandlerProps, InterruptRenderProps } from "../types/interrupt.mjs";
import React from "react";
//#region src/hooks/use-interrupt.d.ts
type InterruptHandlerFn<TValue, TResult> = (props: InterruptHandlerProps<TValue>) => TResult | PromiseLike<TResult>;
type InterruptResultFromHandler<THandler> = THandler extends ((...args: never[]) => infer TResult) ? TResult extends PromiseLike<infer TResolved> ? TResolved | null : TResult | null : null;
type InterruptResult<TValue, TResult> = InterruptResultFromHandler<InterruptHandlerFn<TValue, TResult>>;
type InterruptRenderInChat = boolean | undefined;
type UseInterruptReturn<TRenderInChat extends InterruptRenderInChat> = TRenderInChat extends false ? React.ReactElement | null : TRenderInChat extends true | undefined ? void : React.ReactElement | null | void;
/**
* Configuration options for `useInterrupt`.
*/
interface UseInterruptConfigBase<TValue = unknown, TResult = never> {
/**
* Render function for the interrupt UI.
*
* This is called once an interrupt is finalized and accepted by `enabled` (if provided).
* Use `resolve` from render props to resume the agent run with user input.
*/
render: (props: InterruptRenderProps<TValue, InterruptResult<TValue, TResult>>) => React.ReactElement;
/**
* Optional pre-render handler invoked when an interrupt is received.
*
* Return either a sync value or an async value to pass into `render` as `result`.
* Rejecting/throwing falls back to `result = null`.
*/
handler?: InterruptHandlerFn<TValue, TResult>;
/**
* Optional predicate to filter which interrupts should be handled by this hook.
* Return `false` to ignore an interrupt.
*/
enabled?: (event: InterruptEvent<TValue>) => boolean;
/** Optional agent id. Defaults to the current configured chat agent. */
agentId?: string;
}
type UseInterruptConfig<TValue = unknown, TResult = never, TRenderInChat extends InterruptRenderInChat = undefined> = UseInterruptConfigBase<TValue, TResult> & {
/** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */renderInChat?: TRenderInChat;
};
/**
* Handles agent interrupts (`on_interrupt`) with optional filtering, preprocessing, and resume behavior.
*
* The hook listens to custom events on the active agent, stores interrupt payloads per run,
* and surfaces a render callback once the run finalizes. Call `resolve` from your UI to resume
* execution with user-provided data.
*
* - `renderInChat: true` (default): the element is published into `<CopilotChat>` and this hook returns `void`.
* - `renderInChat: false`: the hook returns the interrupt element so you can place it anywhere in your component tree.
*
* `event.value` is typed as `any` since the interrupt payload shape depends on your agent.
* Type-narrow it in your callbacks (e.g. `handler`, `enabled`, `render`) as needed.
*
* @typeParam TResult - Inferred from `handler` return type. Exposed as `result` in `render`.
* @param config - Interrupt configuration (renderer, optional handler/filter, and render mode).
* @returns When `renderInChat` is `false`, returns the interrupt element (or `null` when idle).
* Otherwise returns `void` and publishes the element into chat. In `render`, `result` is always
* either the handler's resolved return value or `null` (including when no handler is provided,
* when filtering skips the interrupt, or when handler execution fails).
*
* @example
* ```tsx
* import { useInterrupt } from "@copilotkitnext/react";
*
* function InterruptUI() {
* useInterrupt({
* render: ({ event, resolve }) => (
* <div>
* <p>{event.value.question}</p>
* <button onClick={() => resolve({ approved: true })}>Approve</button>
* <button onClick={() => resolve({ approved: false })}>Reject</button>
* </div>
* ),
* });
*
* return null;
* }
* ```
*
* @example
* ```tsx
* import { useInterrupt } from "@copilotkitnext/react";
*
* function CustomPanel() {
* const interruptElement = useInterrupt({
* renderInChat: false,
* enabled: (event) => event.value.startsWith("approval:"),
* handler: async ({ event }) => ({ label: event.value.toUpperCase() }),
* render: ({ event, result, resolve }) => (
* <aside>
* <strong>{result?.label ?? ""}</strong>
* <button onClick={() => resolve({ value: event.value })}>Continue</button>
* </aside>
* ),
* });
*
* return <>{interruptElement}</>;
* }
* ```
*/
declare function useInterrupt<TResult = never, TRenderInChat extends InterruptRenderInChat = undefined>(config: UseInterruptConfig<any, TResult, TRenderInChat>): UseInterruptReturn<TRenderInChat>;
//#endregion
export { UseInterruptConfig, useInterrupt };
//# sourceMappingURL=use-interrupt.d.mts.map