/**
 * `olam services` — umbrella verb for managing Olam service containers.
 *
 * Subcommands:
 *   olam services up              — start all service containers (idempotent)
 *   olam services down            — stop all service containers
 *   olam services status          — show state of all service containers
 *   olam services restart <name>  — restart a named service
 *
 * Substrate-aware (D1 — Phase 2 Phase D):
 *   compose    → docker-based lifecycle (AuthContainerController / McpAuth / KgService)
 *   kubernetes → kubectl scale / rollout restart / get deployment
 *
 * `olam auth up/down/status` delegates here with a deprecation warning.
 */
import type { Command } from 'commander';
import { kubectlWrap } from '../lib/kubectl-wrap.js';
type ContainerState = 'running' | 'stopped' | 'missing';
interface ContainerStatus {
    readonly state: ContainerState;
    readonly port: number;
    readonly containerId?: string;
}
export declare class McpAuthContainerController {
    private imageTag;
    status(): ContainerStatus;
    private imageExists;
    start(): void;
    stop(): void;
    remove(): void;
    waitForReady(timeoutMs?: number): Promise<boolean>;
}
export interface ServicesKubernetesDeps {
    readonly kubectlWrapImpl?: typeof kubectlWrap;
    readonly configPath?: string;
}
/**
 * `olam services up` on kubernetes substrate.
 * Scales each peripheral deployment to replicas=1.
 * Applies the manifest if the Deployment is missing (not found).
 */
export declare function servicesUpKubernetes(deps?: ServicesKubernetesDeps): Promise<{
    exitCode: number;
}>;
/**
 * `olam services down` on kubernetes substrate.
 * Scales each peripheral deployment to replicas=0.
 */
export declare function servicesDownKubernetes(deps?: ServicesKubernetesDeps): Promise<{
    exitCode: number;
}>;
/**
 * `olam services status` on kubernetes substrate.
 * Fetches `kubectl get deployment -n olam -o wide` and formats it to match
 * the compose table shape: NAME | STATUS | IMAGE | AGE | RESTARTS.
 */
export declare function servicesStatusKubernetes(deps?: ServicesKubernetesDeps): Promise<void>;
/**
 * Normalize a user-supplied service name to the k8s Deployment name form.
 *
 * All olam peripheral Deployments are named `olam-<short-name>` in the k8s
 * manifests (e.g. `olam-kg-service`, `olam-auth-service`). When the operator
 * types `olam services restart kg-service` the CLI must prepend `olam-` before
 * calling `kubectl rollout restart deployment/olam-kg-service`.
 *
 * Idempotent: if the user already types the full name (`olam-kg-service`), the
 * prefix is NOT doubled → `olam-kg-service` (NOT `olam-olam-kg-service`).
 *
 * Exported for unit testing (C1 — R3-D).
 */
export declare function normalizeK8sDeploymentName(name: string): string;
/**
 * `olam services restart <name>` on kubernetes substrate.
 * Uses `kubectl rollout restart deployment/olam-<name>`.
 * Prepends `olam-` to the user-supplied name (idempotent — no double-prefix).
 */
export declare function servicesRestartKubernetes(name: string, deps?: ServicesKubernetesDeps): Promise<{
    exitCode: number;
}>;
/** Start both auth containers, idempotent. */
/**
 * Dump the last N lines of `docker logs <container>` to stderr so the
 * operator can see why /health didn't respond. Pre-fix, the timeout
 * branch printed only "started but /health did not respond within Ns"
 * and the operator had no way to know whether the container had
 * crashed, was stuck on an env var, or was just genuinely slow.
 */
/**
 * Idempotently ensure `alpine/socat:latest` is present locally.
 *
 * Called during `olam services up` so the first `olam_port_expose` call
 * (which spawns an `alpine/socat` sidecar container via host-cp) doesn't
 * fail opaquely with an image-pull error on hosts where the image isn't
 * cached. See issue #964.
 *
 * Failure-mode contract: NEVER throws. Returns a status object the caller
 * renders as a printSuccess / printInfo / printWarning. If docker isn't
 * installed or the daemon is unreachable, returns `{ dockerAvailable: false }`
 * and the start flow continues — running services may still be useful even
 * when port-expose isn't.
 */
export interface PullSocatImageDeps {
    readonly spawnImpl?: (cmd: string, args: readonly string[], opts?: {
        encoding?: 'utf-8';
        timeout?: number;
    }) => {
        status: number | null;
        stdout: string;
        stderr: string;
    };
}
export interface PullSocatImageResult {
    readonly dockerAvailable: boolean;
    readonly alreadyPresent: boolean;
    readonly pulled: boolean;
    readonly error?: string;
}
export declare function pullSocatImage(deps?: PullSocatImageDeps): PullSocatImageResult;
export declare function servicesUp(): Promise<{
    exitCode: number;
}>;
/** Stop all service containers. */
export declare function servicesDown(): {
    exitCode: number;
};
/** One service container's state in the `--json` projection. */
export interface ServiceStatusEntry {
    /** Stable docker container name (e.g. `olam-auth`). */
    readonly name: string;
    /** Container lifecycle: `running` (up), `stopped` (exists, not running), `missing` (no container). */
    readonly state: ContainerState;
    /** Published host port the service listens on. */
    readonly port: number;
    /**
     * 12-char short container id (matches `docker ps` truncation), or `null`
     * when the container is `missing`. Short — not the full 64-char id — so the
     * payload mirrors what operators see and never doubles as a handle to a
     * full-id-gated operation.
     */
    readonly containerId: string | null;
}
/** Injectable controller surface — just the `.status()` method each controller exposes. */
interface ServiceStatusController {
    status(): {
        state: ContainerState;
        port: number;
        containerId?: string;
    };
}
export interface ServicesStatusDeps {
    readonly auth?: ServiceStatusController;
    readonly mcpAuth?: ServiceStatusController;
    readonly kgService?: ServiceStatusController;
    readonly memoryService?: ServiceStatusController;
}
/**
 * Pure collector: probe each service controller and return a stable, ordered
 * array. Order is fixed (auth, mcp-auth, kg-service, memory-service) so JSON
 * consumers can index positionally AND the human table order is preserved.
 *
 * Controllers are injectable for unit testing (mirrors the kg-doctor deps
 * pattern) — no live docker daemon needed in tests.
 */
export declare function collectServicesStatus(deps?: ServicesStatusDeps): ServiceStatusEntry[];
/** Show container state for all services. */
export declare function servicesStatus(deps?: ServicesStatusDeps): void;
/**
 * `--json` projection of `services status` (compose path). Emits a stable
 * array to stdout. Exit-code contract is unchanged from the human path
 * (always 0 — `services status` has never gated its exit code on container
 * health).
 */
export declare function servicesStatusJson(deps?: ServicesStatusDeps): void;
export declare function registerServices(program: Command): void;
export {};
//# sourceMappingURL=services.d.ts.map