first pass of merging in warp (doesn't build)

This commit is contained in:
Ryan Ward
2026-07-01 16:08:58 -05:00
parent 2f64909469
commit 4770ac06b5
3662 changed files with 414574 additions and 89772 deletions
@@ -1,40 +1,34 @@
use std::sync::Arc;
use galaxy_core::ui::{appearance::Appearance, theme::color::internal_colors, Icon};
use pathfinder_geometry::vector::vec2f;
use galaxy_core::features::FeatureFlag;
use galaxy_core::ui::appearance::Appearance;
use galaxy_core::ui::theme::color::internal_colors;
use galaxy_core::ui::Icon;
use galaxyui::elements::{
Border, ChildAnchor, ChildView, ConstrainedBox, Container, CornerRadius, CrossAxisAlignment,
Empty, Fill, Flex, Hoverable, MouseStateHandle, OffsetPositioning, ParentAnchor, ParentElement,
ParentOffsetBounds, Radius, SavePosition, Stack, Text, DEFAULT_UI_LINE_HEIGHT_RATIO,
};
use galaxyui::fonts::{Properties, Weight};
use galaxyui::platform::Cursor;
use galaxyui::ui_components::components::UiComponent;
use galaxyui::{
elements::{
Border, ChildAnchor, ChildView, ConstrainedBox, Container, CornerRadius,
CrossAxisAlignment, Empty, Fill, Flex, Hoverable, MouseStateHandle, OffsetPositioning,
ParentAnchor, Radius, SavePosition, Stack, Text, DEFAULT_UI_LINE_HEIGHT_RATIO,
},
platform::Cursor,
AppContext, Element, Entity, EntityId, ModelHandle, SingletonEntity as _, TypedActionView,
View, ViewContext, ViewHandle,
};
use galaxyui::{
elements::{ParentElement, ParentOffsetBounds},
ui_components::components::UiComponent,
};
use pathfinder_geometry::vector::vec2f;
use galaxy_core::features::FeatureFlag;
use crate::{
ai::{
agent::{
icons::todo_list_icon,
todos::popup::{AgentTodosPopupEvent, AgentTodosPopupView},
},
blocklist::{BlocklistAIContextEvent, BlocklistAIContextModel, BlocklistAIHistoryEvent},
document::ai_document_model::{
AIDocumentId, AIDocumentModel, AIDocumentModelEvent, AIDocumentVersion,
},
},
terminal::input::{MenuPositioning, MenuPositioningProvider},
ui_components::blended_colors,
AIAgentTodoList, BlocklistAIHistoryModel,
use crate::ai::agent::icons::todo_list_icon;
use crate::ai::agent::todos::popup::{AgentTodosPopupEvent, AgentTodosPopupView};
use crate::ai::blocklist::{
BlocklistAIContextEvent, BlocklistAIContextModel, BlocklistAIHistoryEvent,
};
use galaxyui::fonts::{Properties, Weight};
use crate::ai::document::ai_document_model::{
AIDocumentId, AIDocumentModel, AIDocumentModelEvent, AIDocumentVersion,
};
use crate::terminal::input::{MenuPositioning, MenuPositioningProvider};
use crate::ui_components::blended_colors;
use crate::{AIAgentTodoList, BlocklistAIHistoryModel};
const TODO_BUTTON_SAVE_POSITION_ID: &str = "plan_and_todo_list::todo_button";
@@ -92,10 +86,10 @@ impl PlanAndTodoListView {
ctx.notify();
}
}
AIDocumentModelEvent::DocumentSaveStatusUpdated { .. } => {}
AIDocumentModelEvent::DocumentUpdated { .. } => {}
AIDocumentModelEvent::StreamingDocumentsCleared(..) => {}
AIDocumentModelEvent::DocumentVisibilityChanged(_) => {}
AIDocumentModelEvent::DocumentSaveStatusUpdated { .. }
| AIDocumentModelEvent::DocumentUpdated { .. }
| AIDocumentModelEvent::StreamingDocumentsCleared(..)
| AIDocumentModelEvent::DocumentVisibilityChanged(_) => {}
},
);
@@ -103,7 +97,7 @@ impl PlanAndTodoListView {
&BlocklistAIHistoryModel::handle(ctx),
|me, _, event, ctx| {
if event
.terminal_view_id()
.terminal_surface_id()
.is_some_and(|id| id != me.terminal_view_id)
{
return;
@@ -114,7 +108,7 @@ impl PlanAndTodoListView {
match event.clone() {
BlocklistAIHistoryEvent::StartedNewConversation { .. }
| BlocklistAIHistoryEvent::SetActiveConversation { .. }
| BlocklistAIHistoryEvent::ClearedConversationsInTerminalView { .. }
| BlocklistAIHistoryEvent::ClearedConversationsForTerminalSurface { .. }
| BlocklistAIHistoryEvent::AppendedExchange { .. }
| BlocklistAIHistoryEvent::UpdatedTodoList { .. } => {
ctx.notify();
+18 -83
View File
@@ -1,32 +1,24 @@
use galaxy_core::ui::appearance::Appearance;
use galaxyui::{
elements::{
ConstrainedBox, Container, CrossAxisAlignment, Flex, FormattedTextElement,
HighlightedHyperlink, HyperlinkLens, MainAxisAlignment, MainAxisSize, ParentElement,
},
AppContext, Element, Entity, SingletonEntity, TypedActionView, View, ViewContext,
};
use markdown_parser::{FormattedText, FormattedTextFragment, FormattedTextLine};
use crate::{
ai::{blocklist::error_color, AIRequestUsageModel},
auth::AuthStateProvider,
network::NetworkStatus,
server::ids::ServerId,
settings::PrivacySettings,
settings_view::SettingsSection,
ui_components::icons::Icon,
workspace::WorkspaceAction,
workspaces::user_workspaces::UserWorkspaces,
};
use ai::api_keys::ApiKeyManager;
use markdown_parser::{FormattedText, FormattedTextFragment, FormattedTextLine};
use galaxy_core::ui::appearance::Appearance;
use galaxyui::elements::{
ConstrainedBox, Container, CrossAxisAlignment, Flex, FormattedTextElement,
HighlightedHyperlink, HyperlinkLens, MainAxisAlignment, MainAxisSize, ParentElement,
};
use galaxyui::{AppContext, Element, Entity, SingletonEntity, TypedActionView, View, ViewContext};
use crate::ai::blocklist::error_color;
use crate::ai::AIRequestUsageModel;
use crate::auth::AuthStateProvider;
use crate::network::NetworkStatus;
use crate::server::ids::ServerId;
use crate::settings_view::SettingsSection;
use crate::ui_components::icons::Icon;
use crate::workspace::WorkspaceAction;
use crate::workspaces::user_workspaces::UserWorkspaces;
const ANONYMOUS_USER_REQUEST_LIMIT_SOFT_GATE_PERCENTAGE: f32 = 0.5;
const TELEMETRY_DISABLED_PRIMARY_TEXT: &str = "To use AI features,";
const ENABLE_ANALYTICS_ACTION_TEXT: &str = "enable analytics";
const UPGRADE_TO_BUILD_ACTION_TEXT: &str = "upgrade";
const NO_CONNECTION_PRIMARY_TEXT: &str = "No internet connection";
const ANONYMOUS_USER_REQUEST_LIMIT_SOFT_GATE_PRIMARY_TEXT: &str = "";
const ANONYMOUS_USER_REQUEST_LIMIT_HARD_GATE_PRIMARY_TEXT: &str = "At Limit -";
@@ -49,7 +41,6 @@ const NON_ADMIN_ASK_ADMIN_TO_INCREASE_OVERAGES_TEXT: &str =
pub enum PromptAlertAction {
SignUpClickedForAnonymousUser,
OpenSettingsClicked,
OpenPrivacySettingsClicked,
ManageBillingClicked { team_uid: ServerId },
}
@@ -57,7 +48,6 @@ pub enum PromptAlertAction {
pub enum PromptAlertEvent {
SignupAnonymousUser,
OpenBillingAndUsagePage,
OpenPrivacyPage,
OpenBillingPortal { team_uid: ServerId },
}
@@ -66,9 +56,6 @@ pub enum PromptAlertEvent {
pub enum PromptAlertState {
/// The user is offline (no connection).
NoConnection,
/// Telemetry is disabled and the user is on a free tier.
/// Free tier users must enable telemetry or upgrade to use AI features.
TelemetryDisabledOnFreeTier,
/// An anonymous user has reached a certain percentage of requests used.
/// This doesn't use a primary text to avoid being too in-your-face.
AnonymousUserRequestLimitSoftGate,
@@ -96,7 +83,6 @@ impl PromptAlertView {
let request_usage_model = AIRequestUsageModel::handle(ctx);
let user_workspaces = UserWorkspaces::handle(ctx);
let network_status = NetworkStatus::handle(ctx);
let privacy_settings = PrivacySettings::handle(ctx);
let api_key_manager = ApiKeyManager::handle(ctx);
ctx.subscribe_to_model(&request_usage_model, |me, _, _, ctx| {
@@ -114,11 +100,6 @@ impl PromptAlertView {
ctx.notify();
});
ctx.subscribe_to_model(&privacy_settings, |me, _, _, ctx| {
me.state = Self::determine_state(ctx);
ctx.notify();
});
ctx.subscribe_to_model(&api_key_manager, |me, _, _, ctx| {
me.state = Self::determine_state(ctx);
ctx.notify();
@@ -136,21 +117,6 @@ impl PromptAlertView {
return PromptAlertState::NoConnection;
}
// Check if telemetry is disabled for free tier users.
// Free tier users must enable telemetry or upgrade to use AI features.
let privacy_settings = PrivacySettings::as_ref(app);
if !privacy_settings.is_telemetry_enabled {
// Fail safe: if billing status is unknown, assume paid to avoid showing confusing message to paying users
let is_on_paid_plan = UserWorkspaces::as_ref(app)
.current_workspace()
.map(|w| w.billing_metadata.is_user_on_paid_plan())
.unwrap_or(true);
if !is_on_paid_plan {
return PromptAlertState::TelemetryDisabledOnFreeTier;
}
}
let request_usage_model = AIRequestUsageModel::as_ref(app);
let has_requests_remaining = request_usage_model.has_requests_remaining();
let auth_state = AuthStateProvider::as_ref(app).get();
@@ -229,11 +195,6 @@ impl PromptAlertView {
NO_CONNECTION_PRIMARY_TEXT,
));
}
PromptAlertState::TelemetryDisabledOnFreeTier => {
text_fragments.push(FormattedTextFragment::plain_text(
TELEMETRY_DISABLED_PRIMARY_TEXT,
));
}
PromptAlertState::AnonymousUserRequestLimitSoftGate => {
text_fragments.push(FormattedTextFragment::plain_text(
ANONYMOUS_USER_REQUEST_LIMIT_SOFT_GATE_PRIMARY_TEXT,
@@ -274,28 +235,6 @@ impl PromptAlertView {
match state {
PromptAlertState::NoConnection => {}
PromptAlertState::TelemetryDisabledOnFreeTier => {
// Show "enable analytics" action link
text_fragments.push(FormattedTextFragment::plain_text(" "));
text_fragments.push(FormattedTextFragment::hyperlink_action(
ENABLE_ANALYTICS_ACTION_TEXT,
PromptAlertAction::OpenPrivacySettingsClicked,
));
// Show "or upgrade to Build" link
text_fragments.push(FormattedTextFragment::plain_text(" or "));
let upgrade_url = if let Some(team) = UserWorkspaces::as_ref(app).current_team() {
UserWorkspaces::upgrade_link_for_team(team.uid)
} else {
let user_id = auth_state.user_id().unwrap_or_default();
UserWorkspaces::upgrade_link(user_id)
};
text_fragments.push(FormattedTextFragment::hyperlink(
UPGRADE_TO_BUILD_ACTION_TEXT,
upgrade_url,
));
text_fragments.push(FormattedTextFragment::plain_text("."));
}
PromptAlertState::AnonymousUserRequestLimitSoftGate
| PromptAlertState::AnonymousUserRequestLimitHardGate => {
text_fragments.push(FormattedTextFragment::plain_text(" "));
@@ -385,7 +324,7 @@ impl PromptAlertView {
};
text_fragments.push(FormattedTextFragment::hyperlink(label, upgrade_url));
}
if UserWorkspaces::as_ref(app).is_byo_api_key_enabled() {
if UserWorkspaces::as_ref(app).is_byo_api_key_enabled(app) {
text_fragments.push(FormattedTextFragment::plain_text(" or "));
text_fragments.push(FormattedTextFragment::hyperlink_action(
"use your own API keys",
@@ -405,7 +344,6 @@ fn does_alert_block_ai_requests(state: &PromptAlertState) -> bool {
match state {
PromptAlertState::AnonymousUserRequestLimitSoftGate | PromptAlertState::NoAlert => false,
PromptAlertState::NoConnection
| PromptAlertState::TelemetryDisabledOnFreeTier
| PromptAlertState::AnonymousUserRequestLimitHardGate
| PromptAlertState::DelinquentDueToPaymentIssue
| PromptAlertState::OveragesToggleableButNotEnabled
@@ -527,9 +465,6 @@ impl TypedActionView for PromptAlertView {
PromptAlertAction::OpenSettingsClicked => {
ctx.emit(PromptAlertEvent::OpenBillingAndUsagePage);
}
PromptAlertAction::OpenPrivacySettingsClicked => {
ctx.emit(PromptAlertEvent::OpenPrivacyPage);
}
PromptAlertAction::ManageBillingClicked { team_uid } => {
ctx.emit(PromptAlertEvent::OpenBillingPortal {
team_uid: *team_uid,