/**
 * Agent-host provider contract.
 *
 * A `HostProvider` answers "what are my hosts, and how do I reach them?" — the
 * pluggable directory/metadata/reachability layer. Shipped providers: `local`
 * (ssh-config ∪ inline registry) and `devices` (the Tailscale fleet from
 * `agents devices`); `rush`/`crabbox` remain additive fast-follows behind this
 * same contract. Capability-gated so partial providers are first-class
 * (mirrors the cloud provider registry).
 */
/**
 * Thrown when a device resolves but can't be used as an offload target because
 * it authenticates with a password. The offload path runs over `sshExec`, whose
 * `SSH_OPTS` force `BatchMode=yes` (no password prompts), so only key / ssh-config
 * auth can carry a `--device` run. Named so the top-level catch prints the message
 * cleanly instead of a stack trace. (Lives here, not registry.ts, so providers
 * can throw it without a circular import; registry.ts re-exports it.)
 */
export class DeviceOffloadUnsupportedError extends Error {
    constructor(name) {
        super(`Device "${name}" uses password auth, which --device offload can't use yet ` +
            `(runs go over ssh with BatchMode=yes). Switch it to key auth with ` +
            `\`agents devices config ${name} ssh.auth key\`.`);
        this.name = 'DeviceOffloadUnsupportedError';
    }
}
/**
 * The ssh target string for a host: the bare name for ssh-config hosts (ssh
 * resolves HostName/User/Port/Identity), else `user@address` (or `address`).
 */
export function sshTargetFor(host) {
    if (host.source === 'ssh-config')
        return host.name;
    if (!host.address) {
        throw new Error(`Host "${host.name}" is inline but has no address.`);
    }
    return host.user ? `${host.user}@${host.address}` : host.address;
}
export function hostIdentityArgs(host) {
    return host.identityFile ? ['-i', host.identityFile, '-o', 'IdentitiesOnly=yes'] : [];
}
