supercode_harness/
startup_prompts.rs1use std::path::Path;
10
11use serde::Deserialize;
12
13#[derive(Deserialize)]
14struct Prompts {
15 startup: Vec<Vec<String>>,
16 unattended: Vec<String>,
17 unattended_chosen_by: Vec<String>,
18}
19
20fn table() -> std::collections::BTreeMap<String, Prompts> {
21 serde_json::from_str(include_str!("startup_prompts.json"))
22 .expect("startup_prompts.json is the harness crate's own table")
23}
24
25pub fn startup_arguments(
29 harness: &str,
30 cwd: Option<&Path>,
31 given: &[String],
32 unattended: bool,
33) -> Vec<String> {
34 let table = table();
35 let Some(prompts) = table.get(harness) else {
36 return Vec::new();
37 };
38 let cwd = cwd.map(|cwd| {
39 serde_json::to_string(cwd.to_string_lossy().as_ref())
40 .expect("a filesystem path always serializes as JSON text")
41 });
42 let mut arguments = Vec::new();
43 for pair in &prompts.startup {
44 let needs_cwd = pair.iter().any(|flag| flag.contains("{cwd}"));
45 if needs_cwd && cwd.is_none() {
46 continue;
47 }
48 let key = pair
49 .last()
50 .and_then(|flag| flag.split('=').next())
51 .unwrap_or_default();
52 if !key.is_empty() && given.iter().any(|argument| argument.contains(key)) {
53 continue;
54 }
55 arguments.extend(pair.iter().map(|flag| match &cwd {
56 Some(cwd) => flag.replace("{cwd}", cwd),
57 None => flag.clone(),
58 }));
59 }
60 let chosen = given.iter().any(|argument| {
61 prompts
62 .unattended_chosen_by
63 .iter()
64 .any(|flag| argument == flag || argument.starts_with(&format!("{flag}=")))
65 });
66 if unattended && !chosen {
67 arguments.extend(prompts.unattended.iter().cloned());
68 }
69 arguments
70}