diff --git a/crates/agent-gui/src-tauri/src/commands/config/settings/system.rs b/crates/agent-gui/src-tauri/src/commands/config/settings/system.rs index 8508f2ab8..7a3eea389 100644 --- a/crates/agent-gui/src-tauri/src/commands/config/settings/system.rs +++ b/crates/agent-gui/src-tauri/src/commands/config/settings/system.rs @@ -244,7 +244,20 @@ fn normalize_workspace_resource_settings(raw: Option<&Value>) -> Value { .get("updatedAt") .and_then(Value::as_u64) .unwrap_or(0); + let project_prompt = entry + .get("projectPrompt") + .and_then(Value::as_str) + .map(str::trim) + .unwrap_or_default(); + let project_prompt_strategy = match entry + .get("projectPromptStrategy") + .and_then(Value::as_str) + { + Some("replace") => "replace", + _ => "append", + }; if mode == "inherit" + && project_prompt.is_empty() && updated_at > 0 && now.saturating_sub(updated_at) > WORKSPACE_RESOURCE_TOMBSTONE_TTL_MS { @@ -264,6 +277,8 @@ fn normalize_workspace_resource_settings(raw: Option<&Value>) -> Value { } else { Value::Array(Vec::new()) }, + "projectPrompt": project_prompt, + "projectPromptStrategy": project_prompt_strategy, "stateVersion": state_version, "writerId": writer_id, "updatedAt": updated_at, @@ -272,8 +287,14 @@ fn normalize_workspace_resource_settings(raw: Option<&Value>) -> Value { } let mut normalized_entries = normalized_by_path.into_iter().collect::>(); normalized_entries.sort_by(|(path_a, entry_a), (path_b, entry_b)| { - let active_a = entry_a["mode"] != "inherit"; - let active_b = entry_b["mode"] != "inherit"; + let entry_active = |entry: &Value| { + entry["mode"] != "inherit" + || entry["projectPrompt"] + .as_str() + .is_some_and(|prompt| !prompt.is_empty()) + }; + let active_a = entry_active(entry_a); + let active_b = entry_active(entry_b); active_b .cmp(&active_a) .then_with(|| { diff --git a/crates/agent-gui/src-tauri/src/commands/config/settings/tests.rs b/crates/agent-gui/src-tauri/src/commands/config/settings/tests.rs index 0b0cade55..a65847b7d 100644 --- a/crates/agent-gui/src-tauri/src/commands/config/settings/tests.rs +++ b/crates/agent-gui/src-tauri/src/commands/config/settings/tests.rs @@ -1323,6 +1323,8 @@ mod tests { "mode": "custom", "skillNames": ["review", "review", ""], "mcpServerIds": ["github", "github", 42], + "projectPrompt": " Review this project. ", + "projectPromptStrategy": "replace", "stateVersion": 3, "writerId": " client-a ", "updatedAt": 100 @@ -1331,6 +1333,8 @@ mod tests { "mode": "inherit", "skillNames": ["ignored"], "mcpServerIds": ["ignored"], + "projectPrompt": 42, + "projectPromptStrategy": "invalid", "stateVersion": 4, "writerId": "client-b", "updatedAt": now @@ -1351,6 +1355,8 @@ mod tests { "mode": "custom", "skillNames": ["review"], "mcpServerIds": ["github"], + "projectPrompt": "Review this project.", + "projectPromptStrategy": "replace", "stateVersion": 3, "writerId": "client-a", "updatedAt": 100 @@ -1359,6 +1365,8 @@ mod tests { "mode": "inherit", "skillNames": [], "mcpServerIds": [], + "projectPrompt": "", + "projectPromptStrategy": "append", "stateVersion": 4, "writerId": "client-b", "updatedAt": now @@ -1421,6 +1429,13 @@ mod tests { "mode": "inherit", "stateVersion": 1, "updatedAt": now + }, + "/tmp/project-prompt": { + "mode": "inherit", + "projectPrompt": " Keep project context ", + "projectPromptStrategy": "replace", + "stateVersion": 1, + "updatedAt": old } }))); let normalized = normalized.as_object().expect("normalized workspace resources"); @@ -1428,6 +1443,14 @@ mod tests { assert_eq!(normalized["/tmp/custom"]["mode"], "custom"); assert_eq!(normalized["/tmp/off"]["mode"], "off"); assert_eq!(normalized["/tmp/recent-tombstone"]["mode"], "inherit"); + assert_eq!( + normalized["/tmp/project-prompt"]["projectPrompt"], + "Keep project context" + ); + assert_eq!( + normalized["/tmp/project-prompt"]["projectPromptStrategy"], + "replace" + ); } #[test] @@ -1458,14 +1481,25 @@ mod tests { }), ); } + entries.insert( + "/tmp/project-prompt".to_string(), + json!({ + "mode": "inherit", + "projectPrompt": "Keep project context", + "projectPromptStrategy": "append", + "stateVersion": 1, + "updatedAt": 1 + }), + ); let normalized = normalize_workspace_resource_settings(Some(&Value::Object(entries))); let normalized = normalized.as_object().expect("normalized workspace resources"); assert_eq!(normalized.len(), MAX_WORKSPACE_RESOURCE_SETTINGS); for index in 0..20 { assert!(normalized.contains_key(&format!("/tmp/custom-{index:02}"))); } - assert!(normalized.contains_key("/tmp/tombstone-235")); - assert!(!normalized.contains_key("/tmp/tombstone-236")); + assert!(normalized.contains_key("/tmp/project-prompt")); + assert!(normalized.contains_key("/tmp/tombstone-234")); + assert!(!normalized.contains_key("/tmp/tombstone-235")); } #[test]