ito_core/harness/
opencode.rs1use super::streaming_cli::CliHarness;
2use super::types::{HarnessName, HarnessRunConfig};
3
4#[derive(Debug, Default)]
18pub struct OpencodeHarness;
19
20impl CliHarness for OpencodeHarness {
21 fn harness_name(&self) -> HarnessName {
22 HarnessName::Opencode
23 }
24
25 fn binary(&self) -> &str {
26 "opencode"
27 }
28
29 fn build_args(&self, config: &HarnessRunConfig) -> Vec<String> {
30 let mut args = vec!["run".to_string()];
31 if let Some(model) = config.model.as_deref() {
32 args.push("-m".to_string());
33 args.push(model.to_string());
34 }
35 args.push(config.prompt.clone());
36 args
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43 use std::collections::BTreeMap;
44
45 enum Allow {
46 #[allow(dead_code)]
47 All,
48 None,
49 }
50
51 fn config(allow: Allow, model: Option<&str>) -> HarnessRunConfig {
52 let allow_all = match allow {
53 Allow::All => true,
54 Allow::None => false,
55 };
56 HarnessRunConfig {
57 prompt: "do stuff".to_string(),
58 model: model.map(String::from),
59 cwd: std::env::temp_dir(),
60 env: BTreeMap::new(),
61 interactive: false,
62 allow_all,
63 inactivity_timeout: None,
64 }
65 }
66
67 #[test]
68 fn harness_name_is_opencode() {
69 let harness = OpencodeHarness;
70 assert_eq!(harness.harness_name(), HarnessName::Opencode);
71 }
72
73 #[test]
74 fn binary_is_opencode() {
75 let harness = OpencodeHarness;
76 assert_eq!(harness.binary(), "opencode");
77 }
78
79 #[test]
80 fn build_args_with_model() {
81 let harness = OpencodeHarness;
82 let cfg = config(Allow::None, Some("gpt-4"));
83 let args = harness.build_args(&cfg);
84 assert_eq!(args, vec!["run", "-m", "gpt-4", "do stuff"]);
85 }
86
87 #[test]
88 fn build_args_without_model() {
89 let harness = OpencodeHarness;
90 let cfg = config(Allow::None, None);
91 let args = harness.build_args(&cfg);
92 assert_eq!(args, vec!["run", "do stuff"]);
93 }
94}