huskies: merge 1183 story Config parse error hints at misplaced top-level keys after [[component]]

This commit is contained in:
Huskies Agent
2026-07-17 10:35:40 +00:00
parent faa7825799
commit ae47dd29e8
2 changed files with 101 additions and 1 deletions
+21 -1
View File
@@ -506,7 +506,7 @@ impl ProjectConfig {
Err(_) => {
// New format failed — try legacy
let legacy: LegacyProjectConfig =
toml::from_str(content).map_err(|e| format!("Parse config: {e}"))?;
toml::from_str(content).map_err(|e| format_parse_error(&e))?;
if let Some(agent) = legacy.agent {
slog!(
"[config] Warning: [agent] table is deprecated. \
@@ -659,6 +659,26 @@ impl ProjectConfig {
}
}
/// Format a `toml::de::Error` for display, appending a hint when the error is
/// an "unknown field" rejection (raised by `ComponentConfig`'s
/// `deny_unknown_fields`). Such errors most commonly happen when a top-level
/// setting is placed after the last `[[component]]` header — TOML attaches
/// trailing bare keys to the table above them, so the setting silently lands
/// inside `ComponentConfig` instead of `ProjectConfig`. The same hint is also
/// shown for a genuine typo'd field inside `[[component]]`, since the error
/// text can't distinguish the two cases.
fn format_parse_error(e: &toml::de::Error) -> String {
let mut msg = format!("Parse config: {e}");
if e.to_string().contains("unknown field") {
msg.push_str(
"\n\nhint: top-level settings must appear before the first `[[component]]` \
section in project.toml — keys placed after a `[[component]]` table are \
attached to that component instead of the project.",
);
}
msg
}
/// Validate agent configs: no duplicate names, no empty names, positive budgets/turns.
fn validate_agents(agents: &[AgentConfig]) -> Result<(), String> {
let mut names = HashSet::new();