use crate::error::Result;
use crate::protocol::FileChange;
use async_trait::async_trait;
use serde::Serialize;
use std::borrow::Cow;
#[derive(Debug, Clone, Serialize)]
pub struct RuntimeStatus {
pub explanations_available: bool,
pub workspace_root: String,
pub connected: bool,
pub turns_available: bool,
pub mutations_allowed: bool,
pub checks_allowed: bool,
pub approval_authority: Cow<'static, str>,
}
#[derive(Debug, Clone, Serialize)]
pub struct WorkspaceFile {
pub path: String,
pub size_bytes: u64,
pub digest: String,
}
#[derive(Debug, Clone, Serialize)]
pub struct FileSnapshot {
pub path: String,
pub content: String,
pub digest: String,
}
#[derive(Debug, Clone, Serialize)]
pub struct PatchProposal {
pub proposal_id: String,
pub changes: Vec<FileChange>,
pub unified_diff: String,
}
#[derive(Debug, Clone, Serialize)]
pub struct AppliedChange {
pub change_id: String,
pub paths: Vec<String>,
}
#[derive(Debug, Clone, Serialize)]
pub struct CheckResult {
pub command: String,
pub exit_code: Option<i32>,
pub stdout: String,
pub stderr: String,
}
#[derive(Debug, Clone, Serialize)]
pub struct TurnResult {
pub turn_id: String,
pub accepted: bool,
}
#[async_trait]
pub trait RuntimeAdapter: Send + Sync {
async fn explanation_get(
&self,
_scope: vtcode_memory::explanation::ExplanationScope,
_offset: usize,
) -> Result<vtcode_memory::explanation::ExplanationPage> {
Err(crate::WebmcpError::Unsupported("execution explanations".into()))
}
async fn explanation_evidence(
&self,
_reference: vtcode_memory::explanation::EvidenceRef,
_offset: usize,
) -> Result<vtcode_memory::explanation::EvidencePage> {
Err(crate::WebmcpError::Unsupported("execution evidence".into()))
}
async fn explanation_navigate(&self, _reference: vtcode_memory::explanation::EvidenceRef) -> Result<bool> {
Err(crate::WebmcpError::Unsupported("execution navigation".into()))
}
async fn status(&self) -> Result<RuntimeStatus>;
async fn list_files(&self) -> Result<Vec<WorkspaceFile>>;
async fn read_file(&self, path: &str) -> Result<FileSnapshot>;
async fn propose_changes(&self, changes: Vec<FileChange>) -> Result<PatchProposal>;
async fn apply_proposal(&self, proposal_id: &str) -> Result<AppliedChange>;
async fn run_checks(&self, command: &str) -> Result<CheckResult>;
async fn revert_last_change(&self, change_id: &str) -> Result<AppliedChange>;
async fn request_turn(&self, prompt: &str, proposal_id: Option<&str>) -> Result<TurnResult>;
async fn cancel(&self, _target_id: &str) -> Result<bool> {
Ok(false)
}
}