1use crate::error::Result;
2use crate::protocol::FileChange;
3use async_trait::async_trait;
4use serde::Serialize;
5use std::borrow::Cow;
6
7#[derive(Debug, Clone, Serialize)]
9pub struct RuntimeStatus {
10 pub explanations_available: bool,
12 pub workspace_root: String,
14 pub connected: bool,
16 pub turns_available: bool,
18 pub mutations_allowed: bool,
20 pub checks_allowed: bool,
22 pub approval_authority: Cow<'static, str>,
24}
25
26#[derive(Debug, Clone, Serialize)]
28pub struct WorkspaceFile {
29 pub path: String,
31 pub size_bytes: u64,
33 pub digest: String,
35}
36
37#[derive(Debug, Clone, Serialize)]
39pub struct FileSnapshot {
40 pub path: String,
42 pub content: String,
44 pub digest: String,
46}
47
48#[derive(Debug, Clone, Serialize)]
50pub struct PatchProposal {
51 pub proposal_id: String,
53 pub changes: Vec<FileChange>,
55 pub unified_diff: String,
57}
58
59#[derive(Debug, Clone, Serialize)]
61pub struct AppliedChange {
62 pub change_id: String,
64 pub paths: Vec<String>,
66}
67
68#[derive(Debug, Clone, Serialize)]
70pub struct CheckResult {
71 pub command: String,
73 pub exit_code: Option<i32>,
75 pub stdout: String,
77 pub stderr: String,
79}
80
81#[derive(Debug, Clone, Serialize)]
83pub struct TurnResult {
84 pub turn_id: String,
86 pub accepted: bool,
88}
89
90#[async_trait]
92pub trait RuntimeAdapter: Send + Sync {
93 async fn explanation_get(
95 &self,
96 _scope: vtcode_memory::explanation::ExplanationScope,
97 _offset: usize,
98 ) -> Result<vtcode_memory::explanation::ExplanationPage> {
99 Err(crate::WebmcpError::Unsupported("execution explanations".into()))
100 }
101 async fn explanation_evidence(
103 &self,
104 _reference: vtcode_memory::explanation::EvidenceRef,
105 _offset: usize,
106 ) -> Result<vtcode_memory::explanation::EvidencePage> {
107 Err(crate::WebmcpError::Unsupported("execution evidence".into()))
108 }
109 async fn explanation_navigate(&self, _reference: vtcode_memory::explanation::EvidenceRef) -> Result<bool> {
111 Err(crate::WebmcpError::Unsupported("execution navigation".into()))
112 }
113 async fn status(&self) -> Result<RuntimeStatus>;
115
116 async fn list_files(&self) -> Result<Vec<WorkspaceFile>>;
118
119 async fn read_file(&self, path: &str) -> Result<FileSnapshot>;
121
122 async fn propose_changes(&self, changes: Vec<FileChange>) -> Result<PatchProposal>;
124
125 async fn apply_proposal(&self, proposal_id: &str) -> Result<AppliedChange>;
127
128 async fn run_checks(&self, command: &str) -> Result<CheckResult>;
130
131 async fn revert_last_change(&self, change_id: &str) -> Result<AppliedChange>;
133
134 async fn request_turn(&self, prompt: &str, proposal_id: Option<&str>) -> Result<TurnResult>;
136
137 async fn cancel(&self, _target_id: &str) -> Result<bool> {
143 Ok(false)
144 }
145}