/**
 * Runtime Adapter Layer
 *
 * Provides a unified, pluggable interface for managing AI runtime sessions.
 * Each adapter encapsulates the full lifecycle of a specific runtime (Claude Code,
 * Gemini CLI, Codex): starting a session, writing input, reading output, and stopping.
 *
 * This replaces the need to coordinate between ISessionBackend, SessionCommandHelper,
 * and RuntimeAgentService manually — the adapter handles it all.
 *
 * @module services/runtime-adapter
 */
import { RUNTIME_TYPES, RUNTIME_COMPACT_COMMANDS } from '../constants.js';
import { RuntimeServiceFactory } from './agent/runtime-service.factory.js';
import { getSessionBackendSync, createSessionCommandHelper, } from './session/index.js';
// ========================= Base Adapter =========================
/**
 * Base adapter that delegates to the existing RuntimeAgentService and ISessionBackend.
 *
 * Concrete adapters extend this class and provide their runtime type.
 * The base handles all common operations — subclasses only need to override
 * behavior that differs from the default.
 */
class BaseRuntimeAdapter {
    sessionBackend;
    sessionHelper;
    runtimeService;
    constructor(sessionBackend, sessionHelper, runtimeService) {
        this.sessionBackend = sessionBackend;
        this.sessionHelper = sessionHelper;
        this.runtimeService = runtimeService;
    }
    /**
     * Start a new agent session with the runtime CLI.
     *
     * Creates a PTY shell, sets environment variables, and executes the
     * runtime initialization script.
     *
     * @param config - Session start configuration
     */
    async start(config) {
        const { sessionName, projectPath, runtimeFlags, promptFilePath, env } = config;
        // Create PTY session
        await this.sessionHelper.createSession(sessionName, projectPath);
        // Set environment variables
        if (env) {
            for (const [key, value] of Object.entries(env)) {
                await this.sessionHelper.setEnvironmentVariable(sessionName, key, value);
            }
        }
        // Execute runtime-specific initialization
        await this.runtimeService.executeRuntimeInitScript(sessionName, projectPath, runtimeFlags, promptFilePath);
    }
    /** @inheritdoc */
    async stop(sessionName) {
        await this.sessionBackend.killSession(sessionName);
    }
    /** @inheritdoc */
    async write(sessionName, data) {
        await this.sessionHelper.sendMessage(sessionName, data);
    }
    /** @inheritdoc */
    async getOutput(sessionName, lines) {
        return this.sessionHelper.capturePane(sessionName, lines);
    }
    /** @inheritdoc */
    isRunning(sessionName) {
        return this.sessionBackend.sessionExists(sessionName);
    }
    /** @inheritdoc */
    async waitForReady(sessionName, timeout = 60000) {
        return this.runtimeService.waitForRuntimeReady(sessionName, timeout);
    }
    /** @inheritdoc */
    async detectRuntime(sessionName) {
        return this.runtimeService.detectRuntimeWithCommand(sessionName, true);
    }
    /**
     * Send the runtime-specific compact command to the session.
     *
     * @param sessionName - Name of the session to compact
     * @returns True if the compact command was sent successfully
     */
    async compact(sessionName) {
        if (!this.sessionBackend.sessionExists(sessionName)) {
            return false;
        }
        const command = RUNTIME_COMPACT_COMMANDS[this.runtimeType];
        if (!command) {
            return false;
        }
        const session = this.sessionBackend.getSession(sessionName);
        if (!session) {
            return false;
        }
        session.write(command + '\r');
        return true;
    }
}
// ========================= Concrete Adapters =========================
/**
 * Adapter for Anthropic's Claude Code CLI.
 *
 * Full implementation — Claude Code is the default runtime.
 * Handles Claude-specific initialization, detection (slash command palette),
 * and MCP configuration.
 */
export class ClaudeCodeAdapter extends BaseRuntimeAdapter {
    runtimeType = RUNTIME_TYPES.CLAUDE_CODE;
    displayName = 'Claude Code';
    /**
     * Start a Claude Code session.
     *
     * Extends the base start with Claude-specific post-initialization
     * (MCP server configuration).
     *
     * @param config - Session start configuration
     */
    async start(config) {
        await super.start(config);
        await this.runtimeService.postInitialize(config.sessionName, config.projectPath);
    }
}
/**
 * Adapter for Google's Gemini CLI.
 *
 * Stub implementation — basic structure in place for future development.
 * Uses the base adapter behavior which delegates to GeminiRuntimeService.
 */
export class GeminiCliAdapter extends BaseRuntimeAdapter {
    runtimeType = RUNTIME_TYPES.GEMINI_CLI;
    displayName = 'Gemini CLI';
}
/**
 * Adapter for OpenAI's Codex CLI.
 *
 * Stub implementation — basic structure in place for future development.
 * Uses the base adapter behavior which delegates to CodexRuntimeService.
 */
export class CodexAdapter extends BaseRuntimeAdapter {
    runtimeType = RUNTIME_TYPES.CODEX_CLI;
    displayName = 'OpenAI Codex';
}
// ========================= Factory =========================
/**
 * Creates a RuntimeAdapter for the specified runtime type.
 *
 * Uses the existing RuntimeServiceFactory and session backend to construct
 * the appropriate adapter. Requires the session backend to be initialized
 * first (via createSessionBackend()).
 *
 * @param runtimeType - The runtime type ('claude-code', 'gemini-cli', 'codex-cli')
 * @param projectRoot - The project root directory (for runtime config resolution)
 * @returns A RuntimeAdapter instance for the specified runtime
 * @throws Error if session backend is not initialized or runtime type is unknown
 *
 * @example
 * ```typescript
 * const adapter = getRuntimeAdapter('claude-code', '/home/user/project');
 * await adapter.start({ sessionName: 'agent-1', projectPath: '/project' });
 * ```
 */
export function getRuntimeAdapter(runtimeType, projectRoot) {
    const backend = getSessionBackendSync();
    if (!backend) {
        throw new Error('Session backend not initialized. Call createSessionBackend() before getRuntimeAdapter().');
    }
    const sessionHelper = createSessionCommandHelper(backend);
    const runtimeService = RuntimeServiceFactory.createWithHelper(runtimeType, sessionHelper, projectRoot);
    switch (runtimeType) {
        case RUNTIME_TYPES.CLAUDE_CODE:
            return new ClaudeCodeAdapter(backend, sessionHelper, runtimeService);
        case RUNTIME_TYPES.GEMINI_CLI:
            return new GeminiCliAdapter(backend, sessionHelper, runtimeService);
        case RUNTIME_TYPES.CODEX_CLI:
            return new CodexAdapter(backend, sessionHelper, runtimeService);
        default: {
            // Fallback to Claude Code for unrecognized types
            const fallbackService = RuntimeServiceFactory.createWithHelper(RUNTIME_TYPES.CLAUDE_CODE, sessionHelper, projectRoot);
            return new ClaudeCodeAdapter(backend, sessionHelper, fallbackService);
        }
    }
}
/**
 * Returns the list of all supported runtime types.
 *
 * @returns Array of RuntimeType values
 */
export function getSupportedRuntimeTypes() {
    return RuntimeServiceFactory.getAvailableRuntimeTypes();
}
/**
 * Checks whether a given string is a supported runtime type.
 *
 * @param value - The string to check
 * @returns True if the value is a valid RuntimeType
 */
export function isSupportedRuntime(value) {
    return RuntimeServiceFactory.isRuntimeTypeSupported(value);
}
//# sourceMappingURL=runtime-adapter.js.map