vtcode 0.141.11

A Rust-based terminal coding agent with modular architecture supporting multiple LLM providers
use std::path::{Path, PathBuf};

use chrono::Utc;
use vtcode_config::loader::VTCodeConfig;
use vtcode_core::core::agent::features::FeatureSet;
use vtcode_core::exec::events::{ThreadEvent, ThreadStartedEvent};

use crate::agent::runloop::unified::inline_events::harness::{
    HARNESS_LOG_MAX_AGE_DAYS, HarnessEventEmitter, default_harness_log_dir, prune_old_harness_logs,
    resolve_event_log_path,
};
use crate::agent::runloop::unified::run_loop_context::TurnRunId;

pub(super) fn initialize_harness(
    vt_cfg: Option<&VTCodeConfig>,
    model: &str,
    turn_run_id: &TurnRunId,
) -> Option<HarnessEventEmitter> {
    let harness_config = vt_cfg.map(|cfg| cfg.agent.harness.clone()).unwrap_or_default();
    let effective_log_path = harness_config
        .event_log_path
        .as_deref()
        .filter(|path| !path.trim().is_empty())
        .map(PathBuf::from)
        .or_else(default_harness_log_dir);
    let Some(log_path) = effective_log_path else {
        tracing::warn!(target: "vtcode.harness", phase = "setup", error = "no log path", "harness setup skipped");
        return None;
    };

    let log_dir = if log_path.extension().is_some() {
        log_path.parent().unwrap_or(Path::new(".")).to_path_buf()
    } else {
        log_path.clone()
    };
    if let Err(error) = prune_old_harness_logs(&log_dir, HARNESS_LOG_MAX_AGE_DAYS) {
        tracing::warn!(target: "vtcode.harness", phase = "harness_prune", path = %log_dir.display(), error = %error, "harness log pruning failed");
    }

    let resolved_path = resolve_event_log_path(&log_path.to_string_lossy(), turn_run_id);
    let emitter = match HarnessEventEmitter::new(resolved_path.clone()) {
        Ok(emitter) => emitter,
        Err(error) => {
            tracing::warn!(target: "vtcode.harness", phase = "setup", path = %resolved_path.display(), error = %error, "harness emitter setup failed");
            return None;
        }
    };

    let features = FeatureSet::from_config(vt_cfg);
    if features.open_responses.emit_events {
        let open_responses_config = vt_cfg.map(|cfg| cfg.agent.open_responses.clone()).unwrap_or_default();
        let parent = log_path.parent().unwrap_or(Path::new("."));
        let timestamp = Utc::now().format("%Y%m%dT%H%M%SZ");
        let output_path = parent.join(format!("open-responses-{}-{}.jsonl", turn_run_id.0, timestamp));
        if let Err(error) = emitter.enable_open_responses(open_responses_config, model, Some(output_path.clone())) {
            tracing::warn!(target: "vtcode.harness", phase = "open_responses_setup", path = %output_path.display(), error = %error, "Open Responses setup failed");
        }
    }

    if vt_cfg.is_some_and(|cfg| cfg.telemetry.atif_enabled) {
        let atif_path =
            log_dir.join(format!("atif-trajectory-{}-{}.json", turn_run_id.0, Utc::now().format("%Y%m%dT%H%M%SZ")));
        if let Err(error) = emitter.enable_atif(model, atif_path.clone()) {
            tracing::warn!(target: "vtcode.harness", phase = "atif_setup", path = %atif_path.display(), error = %error, "ATIF setup failed");
        }
    }

    if let Err(error) =
        emitter.emit(ThreadEvent::ThreadStarted(ThreadStartedEvent { thread_id: turn_run_id.0.clone() }))
    {
        tracing::warn!(target: "vtcode.harness", phase = "thread_start", path = %resolved_path.display(), error = %error, "harness thread-start event failed");
    }
    Some(emitter)
}