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 resume: None,
192 },
193 on_event,
194 )
195 .map_err(|e| e.to_string())?;
196
197 // One normalized stream — same as for any built-in harness.
198 for ev in rx {
199 match ev {
200 RunEvent::Session { model, .. } => println!("[session] model={model:?}"),
201 RunEvent::Text { delta, .. } => println!("[answer] {delta}"),
202 RunEvent::Exited { exit_code, .. } => {
203 println!("[exited] {exit_code:?}");
204 break;
205 }
206 other => println!("{other:?}"),
207 }
208 }
209 Ok(())
210}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 resume: None,
192 },
193 on_event,
194 )
195 .map_err(|e| e.to_string())?;
196
197 // One normalized stream — same as for any built-in harness.
198 for ev in rx {
199 match ev {
200 RunEvent::Session { model, .. } => println!("[session] model={model:?}"),
201 RunEvent::Text { delta, .. } => println!("[answer] {delta}"),
202 RunEvent::Exited { exit_code, .. } => {
203 println!("[exited] {exit_code:?}");
204 break;
205 }
206 other => println!("{other:?}"),
207 }
208 }
209 Ok(())
210}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 resume: None,
192 },
193 on_event,
194 )
195 .map_err(|e| e.to_string())?;
196
197 // One normalized stream — same as for any built-in harness.
198 for ev in rx {
199 match ev {
200 RunEvent::Session { model, .. } => println!("[session] model={model:?}"),
201 RunEvent::Text { delta, .. } => println!("[answer] {delta}"),
202 RunEvent::Exited { exit_code, .. } => {
203 println!("[exited] {exit_code:?}");
204 break;
205 }
206 other => println!("{other:?}"),
207 }
208 }
209 Ok(())
210}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 resume: None,
46 },
47 on_event,
48 )
49 .map_err(|e| e.to_string())?;
50
51 let (mut session, mut tool_input, mut tool_output, mut usage) = (false, false, false, false);
52 for ev in rx {
53 print_event(&ev);
54 match &ev {
55 RunEvent::Session { session_id, model, .. } => {
56 session = session_id.is_some() || model.is_some();
57 }
58 RunEvent::ToolStart { input, .. } => tool_input |= input.is_some(),
59 RunEvent::ToolEnd { output, .. } => tool_output |= output.is_some(),
60 RunEvent::Usage { input_tokens, output_tokens, total_tokens, .. } => {
61 usage = input_tokens.is_some() || output_tokens.is_some() || total_tokens.is_some();
62 }
63 RunEvent::Exited { .. } => break,
64 _ => {}
65 }
66 }
67 eprintln!(
68 "\n── enrichment seen from real {id}: session={session} tool_input={tool_input} tool_output={tool_output} usage={usage}"
69 );
70 Ok(())
71}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 !RefUnwindSafe for Registry
impl !UnwindSafe for Registry
impl Freeze for Registry
impl Send for Registry
impl Sync for Registry
impl Unpin for Registry
impl UnsafeUnpin 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