import { type CommandParser } from '../../client/parser';
import type { RedisArgument } from '../../RESP/types';
import type { RequestRouter, RoutedCommand } from './dispatch';
type ClusterSlots = Parameters<RequestRouter>[0];
/** RediSearch index names are case-sensitive raw wire strings; mirror them. */
export declare function argToString(arg: RedisArgument): string;
/**
 * Uppercased wire command name for command-name gates — `commandIdentifier`
 * preserves the caller's casing, so normalize before matching.
 */
export declare function upperCommand(parser: CommandParser): string;
/**
 * Pull the continuation cursor out of an FT.AGGREGATE …WITHCURSOR /
 * FT.CURSOR READ reply, across every reply path:
 *   - transformed command path → `{ total, results, cursor }` (RESP2 + RESP3),
 *   - raw RESP2 `sendCommand` → `[result, cursor]` (cursor at index 1),
 *   - raw RESP3 `sendCommand` → a map with a `cursor` key (Map or object).
 * The value is returned as decoded (number, or string under a NUMBER type
 * mapping) so a reply rewrite can preserve its wire type. Returns `undefined`
 * when no cursor field is present (e.g. FT.CURSOR DEL).
 */
export declare function extractCursorValue(reply: unknown): number | string | undefined;
/**
 * Sticky router for FT.CURSOR READ/DEL (HLD `request_policy: special`).
 *
 * The cursor argument the caller holds is a client-minted virtual token, not
 * the server's cursor id: server ids are minted per node and two shards can
 * mint the same id for one index, so the raw id cannot identify its node. The
 * token resolves through the binding map to (node address, real cursor id) —
 * pin that node and rewrite the cursor argument to the real id on the wire.
 *
 * A MISS (token never minted here, chain already exhausted, or expired) is
 * unusable by this client, so throw before any network call rather than fan
 * out or guess.
 */
export declare const routeFtCursor: RequestRouter;
/**
 * Command-name-gated post-reply hook for FT.AGGREGATE / FT.CURSOR (invoked
 * from `_executeWithPolicies` after the reducer, like `finalizeScanCursor`).
 * Mints/rebinds/evicts the sticky binding and swaps the server cursor id in
 * the reply for the client token, so the caller only ever loops on tokens.
 * No-op for any other command, and for multi-target plans (cursor commands
 * are single-node). Returns the (possibly rewritten) reply.
 */
export declare function finalizeFtCursor(slots: ClusterSlots, parser: CommandParser, plan: ReadonlyArray<RoutedCommand>, reply: unknown): unknown;
export {};
//# sourceMappingURL=ft-cursor.d.ts.map