onlyne_client/backend/
port.rs1use super::*;
2
3pub trait SessionBackend: Send + Sync {
4 fn name(&self) -> &'static str;
5 fn capabilities(&self) -> Capabilities;
6 fn available(&self) -> Result<bool>;
7 fn spawn(&self, spec: SpawnSpec) -> Result<SessionRef>;
8 fn attach(&self, session: &SessionRef) -> Result<SessionRef>;
9 fn probe(&self, session: &SessionRef) -> Result<ResourceProbe>;
10 fn close(&self, session: &SessionRef, reason: CloseReason, force: bool) -> Result<()>;
11 fn rename(&self, _session: &SessionRef, _title: &str) -> Result<()> {
12 Err(unsupported(
13 self.name(),
14 "rename",
15 "backend does not expose rename",
16 ))
17 }
18 fn focus(&self, _session: &SessionRef) -> Result<()> {
19 Err(unsupported(
20 self.name(),
21 "focus",
22 "backend does not expose focus",
23 ))
24 }
25
26 fn self_driven(&self) -> bool {
31 false
32 }
33
34 fn deliver(&self, _session: &SessionRef, _task_id: &str, _prompt: &str) -> Result<()> {
39 Err(unsupported(
40 self.name(),
41 "deliver",
42 "backend delivers through an adapter socket",
43 ))
44 }
45
46 fn nudge(&self, _session: &SessionRef, _task_id: &str, _text: &str) -> Result<()> {
56 Err(unsupported(
57 self.name(),
58 "nudge",
59 "backend has no channel to hand the sentence to",
60 ))
61 }
62
63 fn set_content_sink(&self, _sink: Arc<dyn crate::content::ContentSink>) {}
66
67 fn outcomes(&self) -> Option<OutcomeFeed> {
70 None
71 }
72}
73
74#[derive(Debug, Clone, PartialEq, Eq)]
75pub struct CommandOutput {
76 pub status: i32,
77 pub stdout: Vec<u8>,
78 pub stderr: Vec<u8>,
79}
80
81pub trait Runner: Send + Sync {
82 fn run(
83 &self,
84 program: &str,
85 args: &[String],
86 cwd: Option<&Path>,
87 env: &BTreeMap<String, String>,
88 ) -> Result<CommandOutput>;
89}
90
91#[derive(Debug, Default, Clone, Copy)]
92pub struct ProcessRunner;
93
94impl Runner for ProcessRunner {
95 fn run(
96 &self,
97 program: &str,
98 args: &[String],
99 cwd: Option<&Path>,
100 env: &BTreeMap<String, String>,
101 ) -> Result<CommandOutput> {
102 let mut command = std::process::Command::new(program);
103 command.args(args);
104 if let Some(cwd) = cwd {
105 command.current_dir(cwd);
106 }
107 command.envs(env);
108 let output = command.output()?;
109 Ok(CommandOutput {
110 status: output.status.code().unwrap_or(-1),
111 stdout: output.stdout,
112 stderr: output.stderr,
113 })
114 }
115}