Add Galaxy Decides risk reviews and focus implementation prompts
This commit is contained in:
@@ -96,8 +96,8 @@ use crate::settings::{
|
||||
AIAutoDetectionEnabled, AICommandDenylist, AISettings, AISettingsChangedEvent, AcpEnabled,
|
||||
AcpProviderConfig, AgentModeCodingPermissionsType, AgentModeCommandExecutionDenylist,
|
||||
AgentModeCommandExecutionPredicate, AgentModeQuerySuggestionsEnabled, BedrockAutoLogin,
|
||||
BedrockEnabled, BedrockModelConfig, CodeSettings, CodebaseContextEnabled, CrosscheckEnabled,
|
||||
FileBasedMcpEnabled, GitOperationsAutogenEnabled, IncludeAgentCommandsInHistory, InputSettings,
|
||||
BedrockEnabled, BedrockModelConfig, CodeSettings, CodebaseContextEnabled, FileBasedMcpEnabled,
|
||||
GitOperationsAutogenEnabled, IncludeAgentCommandsInHistory, InputSettings,
|
||||
IntelligentAutosuggestionsEnabled, LongRunningCommandSubmissionMode, MemoryEnabled,
|
||||
NLDInTerminalEnabled, NaturalLanguageAutosuggestionsEnabled, OpenAIModelConfig,
|
||||
OpenAIProviderConfig, OrchestrationMessageDisplayMode, PromptSubmissionMode,
|
||||
@@ -167,8 +167,6 @@ pub enum AISubpage {
|
||||
ProviderBedrock,
|
||||
/// ACP provider settings.
|
||||
ProviderACP,
|
||||
/// Experimental features.
|
||||
Experiments,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
@@ -189,7 +187,6 @@ impl AISubpage {
|
||||
SettingsSection::ProviderChatGPTSubscription => Some(Self::ProviderChatGPTSubscription),
|
||||
SettingsSection::ProviderBedrock => Some(Self::ProviderBedrock),
|
||||
SettingsSection::ProviderACP => Some(Self::ProviderACP),
|
||||
SettingsSection::Experiments => Some(Self::Experiments),
|
||||
// AgentMCPServers renders the standalone MCPServers page, not an AI subpage.
|
||||
_ => None,
|
||||
}
|
||||
@@ -1430,6 +1427,10 @@ impl AISettingsPageView {
|
||||
"Always ask",
|
||||
AISettingsPageAction::SetApplyCodeDiffs(ActionPermission::AlwaysAsk),
|
||||
),
|
||||
DropdownItem::new(
|
||||
"Galaxy Decides",
|
||||
AISettingsPageAction::SetApplyCodeDiffs(ActionPermission::GalaxyDecides),
|
||||
),
|
||||
],
|
||||
ctx,
|
||||
);
|
||||
@@ -1460,6 +1461,10 @@ impl AISettingsPageView {
|
||||
"Always ask",
|
||||
AISettingsPageAction::SetReadFiles(ActionPermission::AlwaysAsk),
|
||||
),
|
||||
DropdownItem::new(
|
||||
"Galaxy Decides",
|
||||
AISettingsPageAction::SetReadFiles(ActionPermission::GalaxyDecides),
|
||||
),
|
||||
],
|
||||
ctx,
|
||||
);
|
||||
@@ -1490,6 +1495,10 @@ impl AISettingsPageView {
|
||||
"Always ask",
|
||||
AISettingsPageAction::SetExecuteCommands(ActionPermission::AlwaysAsk),
|
||||
),
|
||||
DropdownItem::new(
|
||||
"Galaxy Decides",
|
||||
AISettingsPageAction::SetExecuteCommands(ActionPermission::GalaxyDecides),
|
||||
),
|
||||
],
|
||||
ctx,
|
||||
);
|
||||
@@ -1520,6 +1529,10 @@ impl AISettingsPageView {
|
||||
"Ask on first write",
|
||||
AISettingsPageAction::SetWriteToPty(WriteToPtyPermission::AskOnFirstWrite),
|
||||
),
|
||||
DropdownItem::new(
|
||||
"Galaxy Decides",
|
||||
AISettingsPageAction::SetWriteToPty(WriteToPtyPermission::GalaxyDecides),
|
||||
),
|
||||
],
|
||||
ctx,
|
||||
);
|
||||
@@ -1550,6 +1563,10 @@ impl AISettingsPageView {
|
||||
"Always ask",
|
||||
AISettingsPageAction::SetMCPPermissions(ActionPermission::AlwaysAsk),
|
||||
),
|
||||
DropdownItem::new(
|
||||
"Galaxy Decides",
|
||||
AISettingsPageAction::SetMCPPermissions(ActionPermission::GalaxyDecides),
|
||||
),
|
||||
],
|
||||
ctx,
|
||||
);
|
||||
@@ -2214,9 +2231,6 @@ impl AISettingsPageView {
|
||||
ProviderSetupProviderType::Acp,
|
||||
)));
|
||||
}
|
||||
Some(AISubpage::Experiments) => {
|
||||
widgets.push(Box::new(ExperimentsWidget::default()));
|
||||
}
|
||||
}
|
||||
|
||||
// Subpage widgets render their own subheader-sized titles internally,
|
||||
@@ -2598,6 +2612,7 @@ impl AISettingsPageView {
|
||||
ActionPermission::AgentDecides | ActionPermission::Unknown => 0,
|
||||
ActionPermission::AlwaysAllow => 1,
|
||||
ActionPermission::AlwaysAsk => 2,
|
||||
ActionPermission::GalaxyDecides => 3,
|
||||
};
|
||||
|
||||
menu.set_selected_by_index(active, ctx);
|
||||
@@ -2623,6 +2638,7 @@ impl AISettingsPageView {
|
||||
WriteToPtyPermission::AlwaysAllow => 0,
|
||||
WriteToPtyPermission::AlwaysAsk | WriteToPtyPermission::Unknown => 1,
|
||||
WriteToPtyPermission::AskOnFirstWrite => 2,
|
||||
WriteToPtyPermission::GalaxyDecides => 3,
|
||||
};
|
||||
|
||||
menu.set_selected_by_index(active, ctx);
|
||||
@@ -2999,7 +3015,6 @@ pub enum AISettingsPageAction {
|
||||
agent: Option<CLIAgent>,
|
||||
},
|
||||
ToggleCloudAgentComputerUse,
|
||||
ToggleCrosscheckEnabled,
|
||||
}
|
||||
|
||||
impl TypedActionView for AISettingsPageView {
|
||||
@@ -3664,12 +3679,6 @@ impl TypedActionView for AISettingsPageView {
|
||||
});
|
||||
ctx.notify();
|
||||
}
|
||||
AISettingsPageAction::ToggleCrosscheckEnabled => {
|
||||
AISettings::handle(ctx).update(ctx, |settings, ctx| {
|
||||
report_if_error!(settings.crosscheck_enabled.toggle_and_save_value(ctx));
|
||||
});
|
||||
ctx.notify();
|
||||
}
|
||||
AISettingsPageAction::ToggleBedrockEnabled => {
|
||||
AISettings::handle(ctx).update(ctx, |settings, ctx| {
|
||||
if !*settings.bedrock_enabled.value() {
|
||||
@@ -5265,6 +5274,7 @@ impl AgentsWidget {
|
||||
}
|
||||
|
||||
if current_mcp_setting == ActionPermission::AlwaysAllow
|
||||
|| current_mcp_setting == ActionPermission::GalaxyDecides
|
||||
|| current_mcp_setting == ActionPermission::AgentDecides
|
||||
{
|
||||
let denylist = self.render_mcp_list(
|
||||
@@ -8073,75 +8083,6 @@ impl SettingsWidget for CustomModelRoutersWidget {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Experiments widget ──────────────────────────────────────────────────────
|
||||
|
||||
#[derive(Default)]
|
||||
struct ExperimentsWidget {
|
||||
crosscheck_toggle: SwitchStateHandle,
|
||||
}
|
||||
|
||||
impl SettingsWidget for ExperimentsWidget {
|
||||
type View = AISettingsPageView;
|
||||
|
||||
fn search_terms(&self) -> &str {
|
||||
"experiments crosscheck review reviewer sub-agent feedback loop lgtm"
|
||||
}
|
||||
|
||||
fn should_render(&self, _app: &AppContext) -> bool {
|
||||
FeatureFlag::CrosscheckWork.is_enabled()
|
||||
}
|
||||
|
||||
fn render(
|
||||
&self,
|
||||
view: &Self::View,
|
||||
appearance: &Appearance,
|
||||
app: &AppContext,
|
||||
) -> Box<dyn Element> {
|
||||
let ai_settings = AISettings::as_ref(app);
|
||||
let is_any_ai_enabled = ai_settings.is_any_ai_enabled(app);
|
||||
|
||||
let header = build_sub_header(
|
||||
appearance,
|
||||
"Experiments",
|
||||
Some(styles::header_font_color(is_any_ai_enabled, app)),
|
||||
)
|
||||
.with_margin_bottom(HEADER_PADDING)
|
||||
.finish();
|
||||
|
||||
let crosscheck_toggle = render_ai_setting_toggle::<CrosscheckEnabled>(
|
||||
"Crosscheck Work",
|
||||
AISettingsPageAction::ToggleCrosscheckEnabled,
|
||||
*ai_settings.crosscheck_enabled,
|
||||
is_any_ai_enabled,
|
||||
self.crosscheck_toggle.clone(),
|
||||
&view.local_only_icon_tooltip_states,
|
||||
app,
|
||||
);
|
||||
|
||||
let crosscheck_description = render_ai_setting_description(
|
||||
"When enabled, a reviewer agent critiques the main agent's output after each turn. \
|
||||
The feedback loop continues until the reviewer responds with \"LGTM!\" or the \
|
||||
maximum iteration count is reached.",
|
||||
is_any_ai_enabled,
|
||||
app,
|
||||
);
|
||||
|
||||
let model_description = render_ai_setting_description(
|
||||
"Configure the reviewer model and max iterations in settings.toml under \
|
||||
[agents.experiments].",
|
||||
is_any_ai_enabled,
|
||||
app,
|
||||
);
|
||||
|
||||
Flex::column()
|
||||
.with_child(header)
|
||||
.with_child(crosscheck_toggle)
|
||||
.with_child(crosscheck_description)
|
||||
.with_child(model_description)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
mod styles {
|
||||
use galaxy_core::ui::appearance::Appearance;
|
||||
use galaxy_core::ui::theme::Fill;
|
||||
|
||||
@@ -245,7 +245,7 @@ impl View for ExecutionProfileView {
|
||||
));
|
||||
|
||||
match profile.execute_commands {
|
||||
ActionPermission::AlwaysAllow => {
|
||||
ActionPermission::AlwaysAllow | ActionPermission::GalaxyDecides => {
|
||||
permissions_column.add_child(render_command_denylist(
|
||||
&profile,
|
||||
appearance,
|
||||
@@ -325,7 +325,7 @@ impl View for ExecutionProfileView {
|
||||
));
|
||||
|
||||
match profile.mcp_permissions {
|
||||
ActionPermission::AlwaysAllow => {
|
||||
ActionPermission::AlwaysAllow | ActionPermission::GalaxyDecides => {
|
||||
permissions_column.add_child(render_mcp_denylist(
|
||||
&profile,
|
||||
appearance,
|
||||
@@ -700,6 +700,7 @@ fn render_action_permission_line_with_icon(
|
||||
ActionPermission::AgentDecides => "Agent decides",
|
||||
ActionPermission::AlwaysAllow => "Always allow",
|
||||
ActionPermission::AlwaysAsk => "Always ask",
|
||||
ActionPermission::GalaxyDecides => "Galaxy Decides",
|
||||
ActionPermission::Unknown => "Unknown",
|
||||
};
|
||||
render_permission_line_with_icon(icon, label, permission_text, appearance, is_ai_enabled)
|
||||
@@ -715,6 +716,7 @@ fn render_write_to_pty_permission_line_with_icon(
|
||||
let permission_text = match permission {
|
||||
WriteToPtyPermission::AlwaysAllow => "Always allow",
|
||||
WriteToPtyPermission::AlwaysAsk => "Always ask",
|
||||
WriteToPtyPermission::GalaxyDecides => "Galaxy Decides",
|
||||
WriteToPtyPermission::AskOnFirstWrite => "Ask on first write",
|
||||
WriteToPtyPermission::Unknown => "Unknown",
|
||||
};
|
||||
@@ -732,6 +734,7 @@ fn render_computer_use_permission_line_with_icon(
|
||||
crate::ai::execution_profiles::ComputerUsePermission::Never
|
||||
| crate::ai::execution_profiles::ComputerUsePermission::Unknown => "Never",
|
||||
crate::ai::execution_profiles::ComputerUsePermission::AlwaysAsk => "Always ask",
|
||||
crate::ai::execution_profiles::ComputerUsePermission::GalaxyDecides => "Galaxy Decides",
|
||||
crate::ai::execution_profiles::ComputerUsePermission::AlwaysAllow => "Always allow",
|
||||
};
|
||||
render_permission_line_with_icon(icon, label, permission_text, appearance, is_ai_enabled)
|
||||
@@ -765,6 +768,7 @@ fn render_run_agents_permission_line_with_icon(
|
||||
RunAgentsPermission::NeverAllow | RunAgentsPermission::Unknown => "Never",
|
||||
RunAgentsPermission::AlwaysAllow => "Always allow",
|
||||
RunAgentsPermission::AlwaysAsk => "Always ask",
|
||||
RunAgentsPermission::GalaxyDecides => "Galaxy Decides",
|
||||
};
|
||||
render_permission_line_with_icon(icon, label, permission_text, appearance, is_ai_enabled)
|
||||
}
|
||||
|
||||
@@ -246,7 +246,6 @@ pub enum SettingsSection {
|
||||
Knowledge,
|
||||
ThirdPartyCLIAgents,
|
||||
Models,
|
||||
Experiments,
|
||||
// ── Providers umbrella subpages ──
|
||||
ProviderOpenAI,
|
||||
ProviderLiteLLM,
|
||||
@@ -280,7 +279,6 @@ impl Display for SettingsSection {
|
||||
SettingsSection::Knowledge => write!(f, "Knowledge"),
|
||||
SettingsSection::ThirdPartyCLIAgents => write!(f, "Third party CLI agents"),
|
||||
SettingsSection::Models => write!(f, "Models"),
|
||||
SettingsSection::Experiments => write!(f, "Experiments"),
|
||||
SettingsSection::ProviderOpenAI => write!(f, "OpenAI"),
|
||||
SettingsSection::ProviderLiteLLM => write!(f, "LiteLLM"),
|
||||
SettingsSection::ProviderChatGPTSubscription => write!(f, "ChatGPT Subscription"),
|
||||
@@ -310,7 +308,6 @@ impl SettingsSection {
|
||||
| Self::Knowledge
|
||||
| Self::ThirdPartyCLIAgents
|
||||
| Self::Models
|
||||
| Self::Experiments
|
||||
)
|
||||
}
|
||||
|
||||
@@ -335,7 +332,6 @@ impl SettingsSection {
|
||||
| Self::Knowledge
|
||||
| Self::ThirdPartyCLIAgents
|
||||
| Self::Models
|
||||
| Self::Experiments
|
||||
| Self::ProviderOpenAI
|
||||
| Self::ProviderLiteLLM
|
||||
| Self::ProviderChatGPTSubscription
|
||||
@@ -371,7 +367,6 @@ impl SettingsSection {
|
||||
Self::AgentMCPServers,
|
||||
Self::Knowledge,
|
||||
Self::ThirdPartyCLIAgents,
|
||||
Self::Experiments,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -421,7 +416,6 @@ impl FromStr for SettingsSection {
|
||||
"Agent Client Protocol" | "ACP" => Ok(Self::ProviderACP),
|
||||
"Indexing and projects" | "CodeIndexing" => Ok(Self::CodeIndexing),
|
||||
"Editor and Code Review" | "EditorAndCodeReview" => Ok(Self::EditorAndCodeReview),
|
||||
"Experiments" => Ok(Self::Experiments),
|
||||
"Wormhole" => Ok(Self::Wormhole),
|
||||
_ => Err(()),
|
||||
}
|
||||
|
||||
@@ -110,7 +110,6 @@ fn current_settings_display_names_round_trip() {
|
||||
SettingsSection::ThirdPartyCLIAgents,
|
||||
"Third party CLI agents",
|
||||
),
|
||||
(SettingsSection::Experiments, "Experiments"),
|
||||
(SettingsSection::ProviderOpenAI, "OpenAI"),
|
||||
(SettingsSection::ProviderLiteLLM, "LiteLLM"),
|
||||
(
|
||||
@@ -217,7 +216,7 @@ fn collapsed_umbrellas_each_form_one_navigation_stop() {
|
||||
NavStop::CollapsedUmbrella {
|
||||
nav_index: 0,
|
||||
first_subpage: SettingsSection::WarpAgent,
|
||||
last_subpage: SettingsSection::Experiments,
|
||||
last_subpage: SettingsSection::ThirdPartyCLIAgents,
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -272,7 +271,7 @@ fn collapsed_umbrella_uses_first_and_last_visible_subpages() {
|
||||
let stops = build_nav_stops(&nav_items, |section| {
|
||||
!matches!(
|
||||
section,
|
||||
SettingsSection::WarpAgent | SettingsSection::Models | SettingsSection::Experiments
|
||||
SettingsSection::WarpAgent | SettingsSection::Models
|
||||
)
|
||||
});
|
||||
|
||||
@@ -412,7 +411,7 @@ fn cycling_leaves_an_expanded_umbrella_after_its_last_subpage() {
|
||||
simulate_cycle(
|
||||
&nav_items,
|
||||
&stops,
|
||||
SettingsSection::Experiments,
|
||||
SettingsSection::ThirdPartyCLIAgents,
|
||||
CycleDirection::Down,
|
||||
),
|
||||
SettingsSection::ProviderOpenAI
|
||||
|
||||
Reference in New Issue
Block a user