prodex 0.25.0

OpenAI profile pooling and safe auto-rotate for Codex CLI and Claude Code
Documentation
use super::*;

pub(crate) trait RuntimeLaunchStrategy {
    fn runtime_request(&self) -> RuntimeLaunchRequest<'_>;
    fn build_plan(
        &self,
        prepared: &PreparedRuntimeLaunch,
        runtime_proxy: Option<&RuntimeProxyEndpoint>,
    ) -> Result<RuntimeLaunchPlan>;
}

pub(crate) trait RuntimeLaunchPlanFactory {
    fn build_runtime_launch_plan(
        &self,
        prepared: &PreparedRuntimeLaunch,
        runtime_proxy: Option<&RuntimeProxyEndpoint>,
    ) -> Result<RuntimeLaunchPlan>;
}

impl<T> RuntimeLaunchPlanFactory for T
where
    T: RuntimeLaunchStrategy,
{
    fn build_runtime_launch_plan(
        &self,
        prepared: &PreparedRuntimeLaunch,
        runtime_proxy: Option<&RuntimeProxyEndpoint>,
    ) -> Result<RuntimeLaunchPlan> {
        self.build_plan(prepared, runtime_proxy)
    }
}

#[derive(Debug)]
struct RuntimeLaunchExecution {
    plan: RuntimeLaunchPlan,
    runtime_proxy: Option<RuntimeProxyEndpoint>,
}

struct RuntimeLaunchExecutionFactory<'a, F> {
    request: RuntimeLaunchRequest<'a>,
    plan_factory: &'a F,
}

impl<'a, F> RuntimeLaunchExecutionFactory<'a, F>
where
    F: RuntimeLaunchPlanFactory,
{
    fn new(request: RuntimeLaunchRequest<'a>, plan_factory: &'a F) -> Self {
        Self {
            request,
            plan_factory,
        }
    }

    fn build(self) -> Result<RuntimeLaunchExecution> {
        let prepared = prepare_runtime_launch(self.request)?;
        RuntimeLaunchExecutionBuilder::new(prepared, self.plan_factory).build()
    }
}

struct RuntimeLaunchExecutionBuilder<'a, F> {
    prepared: PreparedRuntimeLaunch,
    plan_factory: &'a F,
}

impl<'a, F> RuntimeLaunchExecutionBuilder<'a, F>
where
    F: RuntimeLaunchPlanFactory,
{
    fn new(prepared: PreparedRuntimeLaunch, plan_factory: &'a F) -> Self {
        Self {
            prepared,
            plan_factory,
        }
    }

    fn build(self) -> Result<RuntimeLaunchExecution> {
        let RuntimeLaunchExecutionBuilder {
            prepared,
            plan_factory,
        } = self;
        let plan = {
            let runtime_proxy = prepared.runtime_proxy.as_ref();
            plan_factory.build_runtime_launch_plan(&prepared, runtime_proxy)?
        };
        let runtime_proxy = prepared.runtime_proxy;
        Ok(RuntimeLaunchExecution {
            plan,
            runtime_proxy,
        })
    }
}

pub(crate) fn execute_runtime_launch<S>(strategy: S) -> Result<()>
where
    S: RuntimeLaunchStrategy,
{
    let execution = build_runtime_launch_execution(&strategy)?;
    exit_with_status(run_runtime_launch_execution(execution)?)
}

fn build_runtime_launch_execution<S>(strategy: &S) -> Result<RuntimeLaunchExecution>
where
    S: RuntimeLaunchStrategy,
{
    RuntimeLaunchExecutionFactory::new(strategy.runtime_request(), strategy).build()
}

fn run_runtime_launch_execution(execution: RuntimeLaunchExecution) -> Result<ExitStatus> {
    let RuntimeLaunchExecution {
        plan,
        runtime_proxy,
    } = execution;
    let status = run_child_plan(&plan.child, runtime_proxy.as_ref());
    drop(runtime_proxy);
    cleanup_runtime_launch_plan(&plan);
    status
}