Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions app/src/ai/generate_code_review_content/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
// TODO(edward): follow-up — gate callers of this module on both
// 1. an `AISettings` opt-out (mirror `is_shared_block_title_generation_enabled`), and
// 2. a customer-type guard (exclude Enterprise unless Warp plan / dogfood),
// matching the pattern in `terminal/share_block_modal.rs::should_send_title_gen_request`.
// `FeatureFlag::GitOperationsInCodeReview` already gates the surrounding UI,
// but does not address AI-specific privacy / opt-out concerns for sending
// diffs to an LLM.
pub(crate) mod api;
5 changes: 2 additions & 3 deletions app/src/code_review/git_dialog/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,15 @@ fn show_toast(msg: impl Into<String>, ctx: &mut ViewContext<GitDialog>) {
///
/// Folds the parent feature flag, the user's dedicated per-feature AI toggle
/// (which itself requires active AI / auth / remote-session org policy to
/// allow AI), and an enterprise check with the same Warp-plan exception and
/// dogfood override as `share_block_modal.rs::should_send_title_gen_request`.
/// allow AI), and the current team's Git Operations AI tier policy.
///
/// When this returns `false`, call sites skip AI entirely: commit.rs opens
/// with the manual-type placeholder and pr.rs goes straight to
/// `gh pr create --fill`.
fn should_send_git_ops_ai_request(app: &AppContext) -> bool {
FeatureFlag::GitOperationsInCodeReview.is_enabled()
&& AISettings::as_ref(app).is_git_operations_autogen_enabled(app)
&& UserWorkspaces::as_ref(app).ai_allowed_for_current_team()
&& UserWorkspaces::as_ref(app).is_git_operations_ai_enabled()
}

/// Maps a raw git error string to a user-friendly toast message. Known
Expand Down
5 changes: 4 additions & 1 deletion app/src/settings_view/ai_page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2454,6 +2454,9 @@ impl TypedActionView for AISettingsPageView {
ctx.notify();
}
AISettingsPageAction::ToggleGitOperationsAutogen => {
if !UserWorkspaces::as_ref(ctx).is_git_operations_ai_enabled() {
return;
}
match AISettings::handle(ctx).update(ctx, |settings, ctx| {
settings
.git_operations_autogen_enabled_internal
Expand Down Expand Up @@ -3726,7 +3729,7 @@ impl ActiveAIWidget {
&& AISettings::as_ref(app)
.git_operations_autogen_enabled_internal
.is_supported_on_current_platform()
&& UserWorkspaces::as_ref(app).ai_allowed_for_current_team()
&& UserWorkspaces::as_ref(app).is_git_operations_ai_enabled()
}

fn render_next_command_section(
Expand Down
1 change: 1 addition & 0 deletions app/src/workspaces/gql_convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ impl From<GqlWarpAiPolicy> for WarpAiPolicy {
is_code_suggestions_toggleable: gql_warp_ai_policy.is_code_suggestions_toggleable,
is_prompt_suggestions_toggleable: gql_warp_ai_policy.is_prompt_suggestions_toggleable,
is_next_command_enabled: gql_warp_ai_policy.is_next_command_enabled,
is_git_operations_ai_enabled: gql_warp_ai_policy.is_git_operations_ai_enabled,
is_voice_enabled: gql_warp_ai_policy.is_voice_enabled,
}
}
Expand Down
16 changes: 15 additions & 1 deletion app/src/workspaces/user_workspaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ impl UserWorkspaces {
/// Returns `true` if active AI is allowed for the current workspace, based on billing config.
///
/// In the future, we should store active AI enablement on the policy directly. For now, we
/// proxy whether active AI by checking if prompt suggestions, next command, or code suggestions are enabled.
/// proxy whether active AI by checking whether any active AI feature is enabled.
pub fn is_active_ai_allowed(&self) -> bool {
self.current_team().is_none_or(|team| {
team.billing_metadata
Expand All @@ -397,6 +397,7 @@ impl UserWorkspaces {
policy.is_prompt_suggestions_toggleable
|| policy.is_next_command_enabled
|| policy.is_code_suggestions_toggleable
|| policy.is_git_operations_ai_enabled
})
})
}
Expand Down Expand Up @@ -454,6 +455,19 @@ impl UserWorkspaces {
})
}

/// Whether Git Operations AI is enabled for the current user, based on the active policies.
/// Note that the value may be incorrect if called before the team's billing metadata has been fetched.
pub fn is_git_operations_ai_enabled(&self) -> bool {
self.current_team()
// If the user has no team, they can toggle Git Operations AI (no restrictions).
.is_none_or(|team| {
team.billing_metadata
.tier
.warp_ai_policy
.is_some_and(|policy| policy.is_git_operations_ai_enabled)
})
}

/// Whether voice input should be toggleable for the current user, based on the active policies.
/// Note that the value may be incorrect if called before the team's billing metadata has been fetched.
/// If voice input support is not compiled into this build, always returns `false`.
Expand Down
2 changes: 2 additions & 0 deletions app/src/workspaces/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,8 @@ pub struct WarpAiPolicy {
pub is_code_suggestions_toggleable: bool,
pub is_prompt_suggestions_toggleable: bool,
pub is_next_command_enabled: bool,
#[serde(default)]
pub is_git_operations_ai_enabled: bool,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] Existing billing_metadata_json cache rows can contain warp_ai_policy without this new field; without a serde default, deserializing the cached BillingMetadata fails and drops all cached billing policy data until refresh.

Suggested change
pub is_git_operations_ai_enabled: bool,
#[serde(default)]
pub is_git_operations_ai_enabled: bool,

pub is_voice_enabled: bool,
}
#[derive(Clone, Debug, Copy, Serialize, Deserialize)]
Expand Down
1 change: 1 addition & 0 deletions crates/graphql/src/api/billing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ pub struct WarpAiPolicy {
pub is_code_suggestions_toggleable: bool,
pub is_prompt_suggestions_toggleable: bool,
pub is_next_command_enabled: bool,
pub is_git_operations_ai_enabled: bool,
pub is_voice_enabled: bool,
}

Expand Down
1 change: 1 addition & 0 deletions crates/graphql/src/api/mutations/create_team.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ mutation CreateTeam($input: CreateTeamInput!, $request_context: RequestContext!)
isCodeSuggestionsToggleable
isPromptSuggestionsToggleable
isNextCommandEnabled
isGitOperationsAiEnabled
isVoiceEnabled
}
teamSizePolicy {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ query GetWorkspacesMetadataForUser($requestContext: RequestContext!) {
isCodeSuggestionsToggleable
isPromptSuggestionsToggleable
isNextCommandEnabled
isGitOperationsAiEnabled
isVoiceEnabled
}
teamSizePolicy {
Expand Down
1 change: 1 addition & 0 deletions crates/warp_graphql_schema/api/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -3917,6 +3917,7 @@ type WarpAiPolicy {
acceptedAutosuggestionsLimit: Int!
disablePremiumModels: Boolean!
isCodeSuggestionsToggleable: Boolean!
isGitOperationsAiEnabled: Boolean!
isNextCommandEnabled: Boolean!
isPromptSuggestionsToggleable: Boolean!
isUnlimited: Boolean!
Expand Down
Loading