/**
 * Generic `--device` passthrough — the single choke point that runs an allowlisted
 * `agents <command>` on a remote host instead of locally. Called once from
 * `index.ts` before commander parses; returns `true` when it handled the
 * invocation (the local command must then NOT run).
 *
 * Transport is SSH (via `ssh-exec.ts`), never a daemon: SSH is the one hardened
 * choke point already used everywhere, and it gives auth + encryption + host-key
 * trust for free. Read-only commands stream synchronously (`sshStream`); the one
 * long-running case — `teams start --watch` — dispatches detached so the remote
 * supervisor outlives a dropped connection.
 *
 * Commands with their own richer `--device` handling (`run`/`sessions`/`feed`/
 * `computer`/`browser`/`secrets`/`logs`/…) are listed in {@link OWN_HOST_COMMANDS} and
 * fall through to their local actions. Everything else either routes via this
 * table or, when `--device` is present, exits with a clear
 * "not supported" message — never commander's raw `unknown option`.
 */
import { type Host } from './types.js';
import { type DeviceRegistry } from '../devices/registry.js';
import { runLocalCommand, runOnDevice } from '../devices/fleet.js';
/** Re-export for callers that historically imported flagValue from this module. */
export { flagValue, hasHostRoutingFlag } from './routing-flag.js';
/** Per-command remote behaviour. Absence from this map = not host-routable here. */
interface RemoteSpec {
    /** Flags appended when running non-interactively (no local TTY / `--no-tty`). */
    nonInteractive?: string[];
    /**
     * Pure read-only RENDER command: draws a screen and exits, never reads stdin.
     * Forwarded over a PLAIN PIPE rather than `ssh -tt` (a forced PTY), because the
     * PTY teardown + local-terminal restore on a CLEAN exit wipes the just-drawn
     * output — so the render "flashes and vanishes" the moment it finishes
     * (PHNX-3583). Over a pipe the output persists exactly as the working non-TTY
     * path already proves; color and terminal geometry are forced into the remote
     * env so it still comes back colored and correctly wrapped
     * ({@link renderForwardDecision}).
     */
    render?: boolean;
    /**
     * For a {@link render} command with a NARROW interactive sub-path, return `true`
     * when THIS argv hits it — the PTY is kept for that one invocation. Absent means
     * the command never prompts, so it is always safe to forward over a pipe.
     */
    interactiveWhen?: (forwarded: string[]) => boolean;
}
/**
 * First-class groups that run transparently on a remote via SSH when
 * `--device` is present. Keep both canonical names and aliases
 * (`repo`/`repos`, `exec`/`run`) so either argv form routes the same way.
 *
 * Prefer adding here over per-command SSH code — this is the single choke point.
 *
 * Every key MUST be a real top-level command (a `KNOWN_TOP_LEVEL_COMMANDS`
 * member) — `passthrough.test.ts` asserts it. A key that is not one is dead:
 * the gate in {@link maybeRunOnHost} rejects the name as unknown before this
 * table is consulted, and before that gate existed it SSH'd a command the peer
 * would also reject. `cli`/`packages`/`versions`/`daemon` were exactly that
 * (the commands are `clis`, `registry`/`search`/`install`/`publish`,
 * `add`/`use`/`list`, and none) and were removed.
 */
export declare const REMOTE_PASSTHROUGH: Record<string, RemoteSpec>;
/**
 * Commands that register and interpret `--device` themselves — must
 * fall through to local commander even when the flag is present. Do not add
 * these to {@link REMOTE_PASSTHROUGH}.
 */
export declare const OWN_HOST_COMMANDS: Set<string>;
/**
 * Argv forwarded over SSH for a `--device` passthrough.
 *
 * `sync`'s umbrella spec appends `--yes` when there is no TTY so a remote
 * reconcile does not hang on a picker. `sync status` is inspect-only unless the
 * caller typed `--yes` themselves: `--yes` on that command is reconcile, not
 * "don't prompt". Nesting it under `sync` must not inherit the umbrella flag
 * (RUSH-2864).
 */
export declare function buildPassthroughForwardedArgs(command: string, allArgs: string[], interactive: boolean): string[];
/**
 * Decide whether a `--device` passthrough should forward over a PLAIN PIPE
 * instead of a PTY, and what color/geometry env to inject when it does.
 *
 * A pure read-only render ({@link RemoteSpec.render}) drawn under a forced
 * `ssh -tt` PTY vanishes on clean exit: the PTY teardown + local-terminal
 * restore (`restoreLocalTerminal` in ssh-exec.ts) wipes the output the command
 * just drew (PHNX-3583). The non-TTY (piped) path never had this problem, so a
 * render command takes it too — but only when a human is actually at a real
 * local terminal (`isTTY` and not `--no-tty`); a genuinely piped local run is
 * already on the pipe path and wants neither color nor forced geometry.
 *
 * A render command's narrow interactive sub-path ({@link RemoteSpec.interactiveWhen},
 * e.g. `view --prune`'s confirm) keeps the PTY. When forwarding over a pipe the
 * remote sees `isTTY=false`, so chalk goes colorless and `terminalWidth()` has no
 * `$COLUMNS` to read; `FORCE_COLOR`/`COLUMNS`/`LINES` restore both. `FORCE_COLOR`
 * is withheld under `--json` so it can never taint machine-readable output.
 */
export declare function renderForwardDecision(command: string, allArgs: string[], io: {
    isTTY: boolean;
    noTty: boolean;
    columns?: number;
    rows?: number;
}): {
    noPty: boolean;
    env?: Record<string, string>;
};
/** Injectable dependencies for {@link runFleetPassthrough} — used by tests. */
export interface FleetPassthroughOptions {
    /** Override the device registry loader (tests). */
    loadDevices?: () => Promise<DeviceRegistry>;
    /** Override the per-device runner (tests). Defaults to `runOnDevice`. */
    runner?: typeof runOnDevice;
    /** Override the local runner for the self device (tests). Defaults to `runLocalCommand`. */
    localRunner?: typeof runLocalCommand;
    /** Override this machine's id (tests). Defaults to `machineId()`. */
    self?: string;
}
/** Run `agents <command> …` across every registered device and render the roster. */
export declare function runFleetPassthrough(command: string, allArgs: string[], spec: RemoteSpec, opts?: FleetPassthroughOptions): Promise<boolean>;
/**
 * Route `agents <command> … --device <name>` to a remote if the command is
 * device-routable and `--device` (or a fleet sentinel `--hosts`/`--devices`) was
 * given. Returns `false` (run locally) when no routing flag is present, the
 * command owns its own device handling, the target is this very machine, or
 * placement flags need the local action. Returns `true` after printing a clear
 * error when the flag is present on a command that is neither routable nor
 * self-handling — so the user never sees commander's raw `unknown option`.
 *
 * @param command the resolved subcommand name (`process.argv`'s first non-flag).
 * @param allArgs `process.argv.slice(2)` — the command name followed by its args.
 */
export declare function maybeRunOnHost(command: string, allArgs: string[], opts?: FleetPassthroughOptions): Promise<boolean>;
/**
 * `--device` passthrough for a **standalone binary** whose command name is fixed by
 * the binary itself (the `browser`/`computer` bins, `dist/browser.js` etc.) rather
 * than being the first argv token.
 *
 * `agents computer … --device <box>` still routes through {@link maybeRunOnHost}
 * in index.ts, but the standalone `browser` / `computer` binaries never enter
 * index.ts. Browser now owns `--device` (start binds the task; later verbs
 * reject it), so this function leaves argv intact for OWN_HOST commands and
 * only strips routing flags on `--help`/`--version`. Other standalone commands
 * still synthesize the implicit command token and delegate to
 * {@link maybeRunOnHost}.
 *
 * @param command the fixed command name the binary stands for (`'browser'`).
 */
export declare function maybeRunStandaloneOnHost(command: string, opts?: FleetPassthroughOptions): Promise<boolean>;
/**
 * Run `agents <forwardedArgs>` on `host` over SSH, streaming its output, and
 * return the exit code. The single place the SSH hop is built, so every remote
 * `agents` invocation carries identical env semantics.
 *
 * Forwards actor provenance (`AGENTS_ACTOR`/`GIT_` vars) across the hop, merged UNDER
 * `extraEnv` so a caller-supplied PATH still wins — without this the remote
 * re-resolves the actor from THIS box's SSH_CONNECTION and mis-credits it
 * (RUSH-2028). Flows to both POSIX (export) and Windows ($env:) dialects.
 * AGENTS_FLEET_REMOTE marks this as a fleet-dispatched run so the far side can
 * gate consent-sensitive actions — the browser consent gate
 * (lib/browser/remote-control.ts) reads it to allow/deny a cross-machine drive.
 */
export declare function streamAgentsOnHost(host: Host, forwardedArgs: string[], opts?: {
    remoteCwd?: string;
    interactive?: boolean;
    extraEnv?: Record<string, string>;
    remoteOs?: string;
    target?: string;
}): number;
export declare function passthroughSshOptions(host: Host, interactive: boolean): {
    tty: boolean;
    multiplex: true;
    extraSshArgs: string[];
};
