/**
 * Pure argv helpers for `--device` passthrough — build the remote `agents …`
 * invocation and strip the local-only routing flags before forwarding.
 *
 * Kept free of any SSH/process side effects so the two-layer quoting and the
 * flag-stripping edge cases (glued short forms, `=value`, variadic) are unit
 * testable without a live host. The transport itself lives in `ssh-exec.ts`
 * (`sshExec`/`sshStream`); orchestration lives in `passthrough.ts`.
 */
/** A flag to strip from a forwarded argv, with whether it consumes a value. */
export interface StripSpec {
    /** Long form without leading dashes, e.g. `host`, `remote-cwd`. */
    long: string;
    /** Optional single-letter short form without the dash, e.g. `H`. */
    short?: string;
    /** True when the flag takes a following value token (`--device <name>`). */
    takesValue: boolean;
}
/**
 * Remove routing flags (and their values) from a command's args, leaving the
 * rest untouched and in order so they forward verbatim to the remote binary.
 * Handles every form commander accepts: `--host h`, `--host=h`, `-H h`, `-H=h`,
 * and the glued short form `-Hh`.
 *
 * @param args the command's args (already past the command name).
 */
export declare function stripRoutingFlags(args: string[], specs: StripSpec[]): string[];
/**
 * The routing flags every `--device`-capable command shares. Stripped before
 * forwarding so the flag never leaks to the remote binary (which would
 * re-trigger routing). `--host`/`-H` are kept for backward-compat strip only
 * (they are no longer user-facing routing flags).
 */
export declare const HOST_ROUTING_SPECS: StripSpec[];
/** How one `agents run` option behaves when the run is offloaded with `--device`. */
export type RunOptionForwarding = 
/** Appended to the remote `agents run` argv — same behavior local or remote. */
'forward'
/** Refused with an actionable error BEFORE dispatch — never silently dropped. */
 | 'reject'
/** Consumed by the dispatching side (routing, follow rendering, cwd portability). */
 | 'local-only';
/**
 * The forwarding contract for `agents run … --device`: every option of the `run`
 * command is classified here, keyed by its commander attribute name. A
 * commander-introspection test (run-forwarding.test.ts) fails when a run
 * option is missing from this table, so a new option can never silently drop
 * at the SSH boundary again — the exact bug this table exists to prevent
 * (--secrets/--effort/--env/--timeout historically vanished on --host runs
 * with no error).
 *
 * Rejections are value-aware at the call site (exec.ts): `--secrets` only
 * rejects when a bundle was actually passed, `--resume` only when bare.
 */
export declare const RUN_OPTION_FORWARDING: Record<string, RunOptionForwarding>;
/** Actionable messages for value-aware rejections, keyed by attribute name. */
export declare const RUN_OPTION_REJECT_MESSAGES: Record<string, string>;
/**
 * Build the single command string for `ssh <target> <cmd>`. The forwarded args
 * are quoted for the inner login shell, then the whole `agents …` invocation is
 * quoted again so it survives `bash -lc <...>` — `bash -lc` so the remote login
 * PATH resolves `agents`. An optional `cd` runs first for `--remote-cwd`.
 *
 * `os` selects the remote shell dialect: a Windows target gets a PowerShell
 * invocation instead (ssh lands in cmd.exe/PowerShell there, where `bash -lc`
 * does not exist). Anything else — including an unknown/absent OS — keeps the
 * POSIX form, so linux/macos are byte-for-byte unchanged.
 */
export declare function buildRemoteAgentsInvocation(forwardedArgs: string[], remoteCwd?: string, os?: string, env?: Record<string, string>): string;
/**
 * Build a POSIX `export K=V; …` prefix from an env map — empty string when the
 * map is missing or empty. Values are rendered as shell LITERALS by default
 * (single-quoted via {@link shellQuote}), so a `$(...)` or backtick in a value
 * can never execute on the SSH target. Only {@link EXPAND_KEYS} (`PATH`) keep the
 * expanding double-quote form (`\` and `"` escaped) so the remote `$HOME`/`$PATH`
 * still resolve. Shared by {@link buildRemoteAgentsInvocation} and the
 * detached/interactive dispatch builders (dispatch.ts) so every remote path
 * exports env identically.
 */
export declare function posixEnvExports(env?: Record<string, string>): string;
/** The two remote shell dialects we build commands for. */
export type RemoteShell = 'posix' | 'powershell';
/**
 * Pick the remote shell dialect from a recorded OS/platform string. A Windows
 * host (device-registry `platform: 'windows'`, or an enrolled `HostEntry.os`
 * that reads `windows`/`Windows`/`win32`/…) speaks PowerShell; everything else,
 * including `undefined`/unknown, defaults to POSIX so linux/macos never regress.
 */
export declare function remoteShellFor(os: string | undefined): RemoteShell;
/**
 * PowerShell single-quoted literal: wrap in `'…'` and double any embedded `'`.
 * Single-quoted PS strings are fully literal (no `$var`, no backtick escapes),
 * so this neutralises every metacharacter the same way POSIX `shellQuote` does.
 */
export declare function powershellQuote(s: string): string;
/**
 * Encode a PowerShell script for `powershell -EncodedCommand`: base64 of its
 * UTF-16LE bytes. The payload is a bare base64 word (no spaces or shell
 * metacharacters), so it survives being handed to ssh as a single argument and
 * re-parsed by the remote's cmd.exe/PowerShell with zero quoting hazards —
 * the robust way to ship a complex command to a Windows box over SSH.
 */
export declare function encodePowershell(script: string): string;
/** Inverse of {@link encodePowershell} — decode an `-EncodedCommand` payload
 * back to its script. Used by tests to assert on the built command. */
export declare function decodePowershell(encoded: string): string;
/** A single `agents …` invocation to run on a Windows remote. */
export interface WindowsAgentsCommand {
    /** `agents` argv (command name NOT included; `agents` is prepended). */
    args: string[];
    /** Env vars scoped to this invocation (POSIX `VAR=val` ↔ PS `$env:VAR=…`). */
    env?: Record<string, string>;
    /** Directory to enter before running (`--remote-cwd`). */
    cwd?: string;
    /**
     * Append `exit $LASTEXITCODE` so a native `agents` exit code propagates out
     * through `powershell.exe` (which otherwise exits 0 regardless). Default true;
     * pass false for probes whose reachability keys off a sentinel, not the code.
     */
    propagateExit?: boolean;
    /** Remap a reached peer command's 255 to 254 so SSH's own 255 stays unambiguous. */
    remapExit255?: boolean;
}
/**
 * The PowerShell script (pre-encoding) that {@link buildWindowsAgentsCommand}
 * runs. Exposed so tests can decode the `-EncodedCommand` payload and compare
 * against the exact script, without needing PowerShell on the test host.
 *
 * `& agents …` invokes the CLI from the machine PATH (Windows has no login
 * shell, so there is no `bash -lc` equivalent — the shim is simply on PATH).
 */
/**
 * PowerShell prelude that silences the progress stream. PowerShell 5.1 serializes
 * progress records ("Preparing modules for first use.") to CLIXML when stderr is a
 * redirected pipe (an ssh capture, not a console), so a remote `agents …` result
 * otherwise comes back wrapped in a raw `#< CLIXML <Objs …>` blob — unreadable to
 * humans and to the JSON parsers that consume doctor / fleet-status output. Prepend
 * this to EVERY Windows script that invokes `agents` (there is more than one builder
 * in this file). Verified against a live win-mini (PowerShell 5.1): this clears it.
 * (`-OutputFormat Text` does NOT — it governs success-stream object serialization,
 * not the progress stream.)
 */
export declare const POWERSHELL_PROGRESS_SILENCE = "$ProgressPreference = 'SilentlyContinue'";
/**
 * Strip a PowerShell CLIXML wrapper from stdout relayed off a Windows host.
 *
 * PowerShell 5.1 serializes progress / error / verbose records to CLIXML when a
 * stream is a redirected pipe (an ssh capture, not a console): a `#< CLIXML`
 * banner followed by one or more `<Objs …>…</Objs>` elements. {@link
 * POWERSHELL_PROGRESS_SILENCE} suppresses the common "Preparing modules for
 * first use." progress record at the source, but a Windows peer reached WITHOUT
 * that prelude — a raw `agents ssh <win> 'agents … --json'`, an older peer, or a
 * record on a stream we did not silence — can still emit the banner ahead of the
 * real payload, which breaks a naive `JSON.parse` of the relayed `--json`
 * (RUSH-2286). Remove the banner and every self-contained `<Objs …>…</Objs>`
 * block, leaving the genuine payload untouched. A no-op (returns the input
 * unchanged) when no `#< CLIXML` marker is present, so it is safe to apply on
 * every remote-JSON boundary regardless of the peer's OS.
 */
export declare function stripClixml(stdout: string): string;
export declare function windowsAgentsScript(cmd: WindowsAgentsCommand): string;
/**
 * Build the `ssh <target> <cmd>` string for one `agents …` invocation on a
 * Windows remote: a `powershell -NoProfile -EncodedCommand <base64>` call. The
 * Windows counterpart of `bash -lc '<...>'`, shared by every `--device` site.
 */
export declare function buildWindowsAgentsCommand(cmd: WindowsAgentsCommand): string;
/**
 * Build the `ssh <target> <cmd>` string for `agents secrets import` on a Windows
 * remote where the `.env` is piped over ssh stdin.
 *
 * We can't just run `agents secrets import <bundle> --from -`: the npm
 * `agents.ps1` shim does NOT forward the ssh-piped stdin down to the underlying
 * node process, so a raw fd-0 read (`--from -`) hangs forever (observed: the
 * push to a Windows host times out). PowerShell ITSELF can read the pipe, so we
 * read stdin into a temp file in PowerShell, import `--from <file>` (a plain
 * file read, which the shim handles fine), and delete the temp file afterwards
 * — success or failure. Backend defaults to the platform native store
 * (Credential Manager, or the headless file store when there's no logon
 * session), matching a local `agents secrets import`.
 */
/**
 * Run `agents <args> --from <tmp>` on a Windows peer, feeding the ssh-piped stdin
 * through a temp file — the `agents.ps1` shim does not forward piped stdin to the
 * node process, so a verb that reads stdin must be handed a file instead. The
 * generic sibling of {@link buildWindowsStdinImportCommand}; the receiving verb
 * MUST accept `--from <path>` (see `usage-ingest.ts`). The temp file is removed in
 * a `finally` so a throw mid-run never leaves the payload behind.
 */
export declare function buildWindowsStdinAgentsCommand(args: string[]): string;
export declare function buildWindowsStdinImportCommand(bundle: string, opts?: {
    force?: boolean;
    policyNever?: boolean;
}): string;
