pub struct Registry { /* private fields */ }Expand description
An open set of harnesses. Build it with the ones you want — the
built-ins (Bob/Claude/Codex) and/or your own:
use harness::Registry;
let reg = Registry::new()
.register(harness::Bob::new());
// .register(MyCustomHarness::new()) // your own impl Harness
assert!(reg.by_id("bob").is_some());Implementations§
Source§impl Registry
impl Registry
Sourcepub fn new() -> Self
pub fn new() -> Self
An empty registry.
Examples found in repository?
examples/custom_harness.rs (line 176)
174fn main() -> Result<(), String> {
175 // Register your harness alongside (or instead of) the built-ins — no fork.
176 let reg = Registry::new().register(EchoHarness);
177 let h = reg.by_id(ECHO_ID).expect("registered");
178 println!("harness: {} — {}", h.info().display_name, h.info().description);
179
180 let (tx, rx) = sync_channel::<RunEvent>(64);
181 let on_event: RunCallback = Arc::new(move |ev| {
182 let _ = tx.send(ev);
183 });
184 let _handle = h.run(
185 RunRequest {
186 run_id: "demo".into(),
187 prompt: "hello".into(),
188 cwd: None,
189 mode: RunMode::Ask,
190 tuning: RunTuning::default(),
191 },
192 on_event,
193 )
194 .map_err(|e| e.to_string())?;
195
196 // One normalized stream — same as for any built-in harness.
197 for ev in rx {
198 match ev {
199 RunEvent::Session { model, .. } => println!("[session] model={model:?}"),
200 RunEvent::Text { delta, .. } => println!("[answer] {delta}"),
201 RunEvent::Exited { exit_code, .. } => {
202 println!("[exited] {exit_code:?}");
203 break;
204 }
205 other => println!("{other:?}"),
206 }
207 }
208 Ok(())
209}Sourcepub fn register(self, harness: impl Harness + 'static) -> Self
pub fn register(self, harness: impl Harness + 'static) -> Self
Add a harness. Chainable. Registration order is preserved (it’s the UI display order; the first registered is the conventional default).
Examples found in repository?
examples/custom_harness.rs (line 176)
174fn main() -> Result<(), String> {
175 // Register your harness alongside (or instead of) the built-ins — no fork.
176 let reg = Registry::new().register(EchoHarness);
177 let h = reg.by_id(ECHO_ID).expect("registered");
178 println!("harness: {} — {}", h.info().display_name, h.info().description);
179
180 let (tx, rx) = sync_channel::<RunEvent>(64);
181 let on_event: RunCallback = Arc::new(move |ev| {
182 let _ = tx.send(ev);
183 });
184 let _handle = h.run(
185 RunRequest {
186 run_id: "demo".into(),
187 prompt: "hello".into(),
188 cwd: None,
189 mode: RunMode::Ask,
190 tuning: RunTuning::default(),
191 },
192 on_event,
193 )
194 .map_err(|e| e.to_string())?;
195
196 // One normalized stream — same as for any built-in harness.
197 for ev in rx {
198 match ev {
199 RunEvent::Session { model, .. } => println!("[session] model={model:?}"),
200 RunEvent::Text { delta, .. } => println!("[answer] {delta}"),
201 RunEvent::Exited { exit_code, .. } => {
202 println!("[exited] {exit_code:?}");
203 break;
204 }
205 other => println!("{other:?}"),
206 }
207 }
208 Ok(())
209}Sourcepub fn by_id(&self, id: &str) -> Option<&dyn Harness>
pub fn by_id(&self, id: &str) -> Option<&dyn Harness>
Resolve a harness by its HarnessInfo::id.
Examples found in repository?
examples/custom_harness.rs (line 177)
174fn main() -> Result<(), String> {
175 // Register your harness alongside (or instead of) the built-ins — no fork.
176 let reg = Registry::new().register(EchoHarness);
177 let h = reg.by_id(ECHO_ID).expect("registered");
178 println!("harness: {} — {}", h.info().display_name, h.info().description);
179
180 let (tx, rx) = sync_channel::<RunEvent>(64);
181 let on_event: RunCallback = Arc::new(move |ev| {
182 let _ = tx.send(ev);
183 });
184 let _handle = h.run(
185 RunRequest {
186 run_id: "demo".into(),
187 prompt: "hello".into(),
188 cwd: None,
189 mode: RunMode::Ask,
190 tuning: RunTuning::default(),
191 },
192 on_event,
193 )
194 .map_err(|e| e.to_string())?;
195
196 // One normalized stream — same as for any built-in harness.
197 for ev in rx {
198 match ev {
199 RunEvent::Session { model, .. } => println!("[session] model={model:?}"),
200 RunEvent::Text { delta, .. } => println!("[answer] {delta}"),
201 RunEvent::Exited { exit_code, .. } => {
202 println!("[exited] {exit_code:?}");
203 break;
204 }
205 other => println!("{other:?}"),
206 }
207 }
208 Ok(())
209}More examples
examples/verify_enrichment.rs (line 22)
16fn main() -> Result<(), String> {
17 let id = std::env::args().nth(1).unwrap_or_else(|| "claude".to_owned());
18 let prompt = std::env::args().nth(2).unwrap_or_else(|| default_prompt(&id));
19
20 let reg = default_registry();
21 let h = reg
22 .by_id(&id)
23 .ok_or_else(|| format!("unknown/disabled harness: {id}"))?;
24
25 // Cheapest viable settings (per the "don't burn tokens" rule).
26 let tuning = match id.as_str() {
27 "claude" => RunTuning { model: Some("haiku".to_owned()), ..RunTuning::default() },
28 "codex" => RunTuning { effort: Some(ReasoningEffort::Low), ..RunTuning::default() },
29 _ => RunTuning::default(),
30 };
31
32 let (tx, rx) = sync_channel::<RunEvent>(256);
33 let on_event: RunCallback = Arc::new(move |ev| {
34 let _ = tx.send(ev);
35 });
36
37 eprintln!("── running {id} ──");
38 let _handle = h.run(
39 RunRequest {
40 run_id: "verify".into(),
41 prompt,
42 cwd: Some(std::env::current_dir().map_err(|e| e.to_string())?),
43 mode: RunMode::Ask,
44 tuning,
45 },
46 on_event,
47 )
48 .map_err(|e| e.to_string())?;
49
50 let (mut session, mut tool_input, mut tool_output, mut usage) = (false, false, false, false);
51 for ev in rx {
52 print_event(&ev);
53 match &ev {
54 RunEvent::Session { session_id, model, .. } => {
55 session = session_id.is_some() || model.is_some();
56 }
57 RunEvent::ToolStart { input, .. } => tool_input |= input.is_some(),
58 RunEvent::ToolEnd { output, .. } => tool_output |= output.is_some(),
59 RunEvent::Usage { input_tokens, output_tokens, total_tokens, .. } => {
60 usage = input_tokens.is_some() || output_tokens.is_some() || total_tokens.is_some();
61 }
62 RunEvent::Exited { .. } => break,
63 _ => {}
64 }
65 }
66 eprintln!(
67 "\n── enrichment seen from real {id}: session={session} tool_input={tool_input} tool_output={tool_output} usage={usage}"
68 );
69 Ok(())
70}Sourcepub fn catalog(&self) -> Vec<HarnessInfo>
pub fn catalog(&self) -> Vec<HarnessInfo>
Metadata for every registered harness, in registration order.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Registry
impl !RefUnwindSafe for Registry
impl Send for Registry
impl Sync for Registry
impl Unpin for Registry
impl UnsafeUnpin for Registry
impl !UnwindSafe for Registry
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more