Apply local updates and test/build fixes

This commit is contained in:
Ryan Ward
2026-05-13 15:56:40 -05:00
parent cee61e2af0
commit b61d6bcbce
36 changed files with 567 additions and 327 deletions
+1 -1
View File
@@ -260,7 +260,7 @@ pub async fn generate_multi_agent_output(
format!("MultiPart[{}]", part_descs.join(", "))
}
};
log::debug!(
log::info!(
"[bedrock] msg[{}]: role={:?}, content={}",
i,
msg.role,
+12 -11
View File
@@ -14,7 +14,7 @@ use crate::terminal::model::block::{
};
use crate::ai::agent::api::convert_conversation::{
ConvertToExchanges, compute_time_to_first_token_ms_from_messages,
compute_time_to_first_token_ms_from_messages, ConvertToExchanges,
};
use ai::document::AIDocumentId;
use chrono::{DateTime, Local, TimeZone};
@@ -29,8 +29,8 @@ use galaxy_core::execution_mode::AppExecutionMode;
use galaxy_core::features::FeatureFlag;
use galaxy_core::send_telemetry_from_ctx;
use galaxy_core::ui::appearance::Appearance;
use galaxy_core::ui::theme::WarpTheme;
use galaxy_core::ui::theme::color::internal_colors;
use galaxy_core::ui::theme::WarpTheme;
use galaxyui::color::ColorU;
use galaxyui::{EntityId, ModelContext, SingletonEntity};
use uuid::Uuid;
@@ -40,35 +40,36 @@ use warp_multi_agent_api::{self as api, response_event::stream_finished::TokenUs
use crate::ai::agent::{AIIdentifiers, CancellationReason};
use crate::{
BlocklistAIHistoryModel, GlobalResourceHandlesProvider,
ai::{
agent::{
AIAgentOutputMessage, AIAgentOutputMessageType, MessageToAIAgentOutputMessageError,
icons::{
failed_icon, gray_stop_icon, in_progress_icon, succeeded_icon, yellow_stop_icon,
},
todos::AIAgentTodoList,
AIAgentOutputMessage, AIAgentOutputMessageType, MessageToAIAgentOutputMessageError,
},
blocklist::BlocklistAIHistoryEvent,
},
persistence::{
ModelEvent,
model::{AgentConversationData, PersistedAutoexecuteMode},
ModelEvent,
},
ui_components::icons::Icon,
BlocklistAIHistoryModel, GlobalResourceHandlesProvider,
};
use super::task::{ExtractMessagesError, UpdateTaskError, UpgradeOptimisticTaskError};
use super::{
api::ServerConversationToken,
task::{
derive_todo_lists_from_root_task,
helper::*,
transaction::{SavedTask, Transaction},
Task, TaskId,
},
AIAgentAction, AIAgentActionId, AIAgentContext, AIAgentExchange, AIAgentExchangeId,
AIAgentInput, AIAgentOutputStatus, AIAgentTodo, AIAgentTodoId, FinishedAIAgentOutput,
MessageId, RenderableAIError, RequestCost,
api::ServerConversationToken,
task::{
Task, TaskId, derive_todo_lists_from_root_task,
helper::*,
transaction::{SavedTask, Transaction},
},
};
use super::{
AIAgentOutput, OutputModelInfo, ServerOutputId, Shared, SuggestedLoggingId, Suggestions,
+1 -1
View File
@@ -1,7 +1,7 @@
use std::collections::HashMap;
use super::{
AIConversation, AIConversationAutoexecuteMode, AIConversationId, artifact_from_fork_proto,
artifact_from_fork_proto, AIConversation, AIConversationAutoexecuteMode, AIConversationId,
};
use crate::ai::artifacts::Artifact;
use crate::persistence::model::AgentConversationData;
+20 -2
View File
@@ -577,10 +577,17 @@ fn ensure_tool_results_paired(messages: &mut Vec<ConversationMessage>) {
let insert_idx = i + 1;
// If the next message is already a user message, merge synthetic results into it.
// IMPORTANT: ToolResult blocks must come BEFORE text content in a user message
// that follows an assistant tool_use. The Bedrock/Anthropic API validates this
// ordering and rejects requests where text precedes tool_result.
if insert_idx < messages.len() && messages[insert_idx].role == MessageRole::User {
match &mut messages[insert_idx].content {
MessageContent::MultiPart(parts) => {
// Prepend synthetic results before existing parts so
// tool_result blocks appear first in the content.
let existing = std::mem::take(parts);
parts.extend(synthetic_results);
parts.extend(existing);
}
existing => {
// Convert existing single content + synthetic results into MultiPart.
@@ -607,11 +614,18 @@ fn ensure_tool_results_paired(messages: &mut Vec<ConversationMessage>) {
},
MessageContent::MultiPart(_) => unreachable!(),
};
let mut parts = vec![existing_part];
parts.extend(synthetic_results);
// Synthetic tool_result blocks come first, then the
// original content (text), matching the Bedrock API
// requirement that tool_result precedes other content.
let mut parts = synthetic_results;
parts.push(existing_part);
*existing = MessageContent::MultiPart(parts);
}
}
log::info!(
"[bedrock] Merged synthetic tool_result(s) into existing user message at index {}",
insert_idx
);
} else {
// No user message follows — insert a new one.
let content = if synthetic_results.len() == 1 {
@@ -1272,3 +1286,7 @@ fn format_tool_call_result(result: &api::message::ToolCallResult) -> String {
"Tool completed.".to_string()
}
}
#[cfg(test)]
#[path = "convert_request_tests.rs"]
mod tests;
@@ -0,0 +1,47 @@
use serde_json::json;
use super::super::convert::{ContentPart, ConversationMessage, MessageContent, MessageRole};
use super::sanitize_messages_for_bedrock;
#[test]
fn test_sanitize_messages_prepends_synthetic_tool_result_before_existing_user_text() {
let tool_use_id = "tooluse_Pzmn1QfoWgJsA8sb4RHTM3".to_string();
let existing_user_text = "What happened?".to_string();
let mut messages = vec![
ConversationMessage {
role: MessageRole::User,
content: MessageContent::Text("Run a command.".to_string()),
},
ConversationMessage {
role: MessageRole::Assistant,
content: MessageContent::ToolUse {
tool_use_id: tool_use_id.clone(),
name: "run_shell_command".to_string(),
input: json!({ "command": "ls" }),
},
},
ConversationMessage {
role: MessageRole::User,
content: MessageContent::Text(existing_user_text.clone()),
},
];
sanitize_messages_for_bedrock(&mut messages);
assert_eq!(messages.len(), 3);
let parts = match &messages[2].content {
MessageContent::MultiPart(parts) => parts,
other => panic!("Expected MultiPart content, got: {:?}", other),
};
assert_eq!(parts.len(), 2);
assert!(
matches!(&parts[0], ContentPart::ToolResult { tool_use_id: id, .. } if id == &tool_use_id)
);
assert!(matches!(
&parts[1],
ContentPart::Text(text) if text == &existing_user_text
));
}
+26 -5
View File
@@ -555,6 +555,7 @@ impl AgentSimulation {
8192,
None,
false,
None,
Arc::new(Mutex::new(Vec::new())),
)
.await
@@ -1140,6 +1141,7 @@ async fn test_reasoning_model_produces_substantial_output() {
8192,
None,
false,
None,
Arc::new(Mutex::new(Vec::new())),
)
.await
@@ -1261,6 +1263,7 @@ async fn test_event_sequence_matches_controller_expectations() {
100,
None,
false,
None,
Arc::new(Mutex::new(Vec::new())),
)
.await
@@ -1374,6 +1377,7 @@ async fn test_followup_turn_does_not_send_create_task() {
100,
None,
false,
None,
Arc::new(Mutex::new(Vec::new())),
)
.await
@@ -1438,7 +1442,11 @@ async fn run_slash_command_test(
let task_id = uuid::Uuid::new_v4().to_string();
println!(
"\n{}\n[SLASH CMD TEST] {}\n[SLASH CMD TEST] Model: {}\n[SLASH CMD TEST] Message: {:.100}\n{}",
"=".repeat(80), test_name, model, user_message, "=".repeat(80)
"=".repeat(80),
test_name,
model,
user_message,
"=".repeat(80)
);
let stream = client
@@ -1452,6 +1460,7 @@ async fn run_slash_command_test(
4096,
None,
true,
None,
Arc::new(Mutex::new(Vec::new())),
)
.await
@@ -1678,6 +1687,7 @@ async fn test_slash_resume_conversation() {
256,
None,
true,
None,
Arc::new(Mutex::new(Vec::new())),
)
.await
@@ -1788,6 +1798,7 @@ async fn test_empty_messages_safety_check() {
100,
None,
true,
None,
Arc::new(Mutex::new(Vec::new())),
)
.await
@@ -1829,17 +1840,26 @@ async fn test_full_proto_round_trip_with_tool_history() {
let request = make_request(
&task_id,
vec![
make_user_query_message("msg-1", &task_id, "List all files in the current directory."),
make_user_query_message(
"msg-1",
&task_id,
"List all files in the current directory.",
),
make_tool_call_run_shell(tool_call_id_1, &task_id, tool_call_id_1, "ls -la"),
make_tool_call_read_files(tool_call_id_2, &task_id, tool_call_id_2, "README.md"),
make_tool_result_shell(
"msg-result-1", &task_id, tool_call_id_1,
"msg-result-1",
&task_id,
tool_call_id_1,
"total 16\ndrwxr-xr-x 5 user staff 160 May 6 10:00 .\n-rw-r--r-- 1 user staff 100 May 6 10:00 README.md\n-rw-r--r-- 1 user staff 200 May 6 10:00 Cargo.toml",
0,
),
make_tool_result_read_files(
"msg-result-2", &task_id, tool_call_id_2,
"README.md", "# Sample Project\nA test project.",
"msg-result-2",
&task_id,
tool_call_id_2,
"README.md",
"# Sample Project\nA test project.",
),
],
make_user_inputs_input("Now summarize what you found in one sentence."),
@@ -1938,6 +1958,7 @@ async fn test_full_proto_round_trip_with_tool_history() {
1024,
None,
true,
None,
Arc::new(Mutex::new(Vec::new())),
)
.await;
+1
View File
@@ -64,6 +64,7 @@ async fn collect_stream_output(
8192,
None,
false,
None,
Arc::new(Mutex::new(Vec::new())),
)
.await
+30 -24
View File
@@ -1,25 +1,26 @@
#[cfg(target_family = "wasm")]
use crate::uri::web_intent_parser::open_url_on_desktop;
use crate::{
ObjectActions,
ai::{
document::ai_document_model::AIDocumentId,
facts::{AIFact, AIMemory},
},
appearance::Appearance,
auth::{
AuthStateProvider,
auth_manager::{AuthManager, LoginGatedFeature},
auth_state::AuthState,
auth_view_modal::AuthViewVariant,
AuthStateProvider,
},
cloud_object::{
CloudObject, CloudObjectEventEntrypoint, CloudObjectLocation, CloudObjectSyncStatus,
GenericCloudObject, GenericStringObjectFormat, JsonObjectType, NumInFlightRequests,
ObjectType, Space,
model::{
persistence::{CloudModel, CloudModelEvent},
view::{CloudViewModel, CloudViewModelEvent, UpdateTimestamp},
},
CloudObject, CloudObjectEventEntrypoint, CloudObjectLocation, CloudObjectSyncStatus,
GenericCloudObject, GenericStringObjectFormat, JsonObjectType, NumInFlightRequests,
ObjectType, Space,
},
editor::{EditorView, Event as EditorEvent, SingleLineEditorOptions},
env_vars::CloudEnvVarCollection,
@@ -38,8 +39,8 @@ use crate::{
ui_components::{
blended_colors,
buttons::{highlight, icon_button},
icons::{Icon, ICON_DIMENSIONS},
menu_button::{icon_button_with_context_menu, MenuDirection},
icons::{ICON_DIMENSIONS, Icon},
menu_button::{MenuDirection, icon_button_with_context_menu},
},
util::{color::coloru_with_opacity, sync::Condition},
view_components::{Dropdown, DropdownItem},
@@ -48,10 +49,10 @@ use crate::{
workspaces::{
update_manager::TeamUpdateManager, user_workspaces::UserWorkspaces, workspace::WorkspaceUid,
},
ObjectActions,
};
use super::{
CloudObjectTypeAndId, DriveObjectType, DriveSortOrder,
cloud_object_naming_dialog::CloudObjectNamingDialog,
drive_helpers::{
has_feature_gated_anonymous_user_reached_env_var_limit,
@@ -61,17 +62,16 @@ use super::{
empty_trash_confirmation_dialog::{EmptyTrashConfirmationDialog, EmptyTrashConfirmationEvent},
folders::CloudFolder,
items::{
ai_fact_collection::WarpDriveAIFactCollection,
item::{tools_panel_menu_direction, ItemStates, WarpDriveRow},
mcp_server_collection::WarpDriveMCPServerCollection,
WarpDriveItemId,
ai_fact_collection::WarpDriveAIFactCollection,
item::{ItemStates, WarpDriveRow, tools_panel_menu_direction},
mcp_server_collection::WarpDriveMCPServerCollection,
},
settings::WarpDriveSettings,
sharing::{
dialog::{SharingDialog, SharingDialogEvent},
ContentEditability, ShareableObject,
dialog::{SharingDialog, SharingDialogEvent},
},
CloudObjectTypeAndId, DriveObjectType, DriveSortOrder,
};
use crate::drive::panel::DrivePanelAction;
use crate::server::cloud_objects::update_manager::InitiatedBy;
@@ -80,6 +80,8 @@ use galaxy_core::{
context_flag::ContextFlag, settings::Setting, ui::theme::color::internal_colors,
};
use galaxyui::{
AppContext, BlurContext, Element, Entity, ModelHandle, SingletonEntity, TypedActionView,
UpdateView, View, ViewContext, ViewHandle, WindowId,
clipboard::ClipboardContent,
elements::{
Align, AnchorPair, Border, ChildAnchor, ChildView, ClippedScrollStateHandle,
@@ -98,12 +100,10 @@ use galaxyui::{
components::{Coords, UiComponent, UiComponentStyles},
},
units::IntoPixels,
AppContext, BlurContext, Element, Entity, ModelHandle, SingletonEntity, TypedActionView,
UpdateView, View, ViewContext, ViewHandle, WindowId,
};
use itertools::Itertools;
use pathfinder_color::ColorU;
use pathfinder_geometry::vector::{vec2f, Vector2F};
use pathfinder_geometry::vector::{Vector2F, vec2f};
use std::{any::Any, collections::HashMap, sync::Arc};
use url::Url;
@@ -651,7 +651,7 @@ impl DriveIndex {
.as_ref(ctx)
.num_trashed_cloud_objects_per_space(spaces.iter(), ctx),
};
let mut sections = spaces
let sections = spaces
.iter()
.map(|space| DriveIndexSection::Space(*space))
.collect::<Vec<_>>();
@@ -1254,7 +1254,9 @@ impl DriveIndex {
{
self.expand_section_for_object(&id.uid().clone(), ctx);
} else {
log::warn!("unknown GenericStringObject type found while trying to manually expand drive section. {object_id:?}");
log::warn!(
"unknown GenericStringObject type found while trying to manually expand drive section. {object_id:?}"
);
}
}
};
@@ -4906,12 +4908,14 @@ impl DriveIndex {
space: *space,
offset,
});
let menu_items = vec![MenuItemFields::new("Collapse all")
.with_on_select_action(DriveIndexAction::CollapseAllInLocation(
CloudObjectLocation::Space(*space),
))
.with_icon(Icon::ListCollapsed)
.into_item()];
let menu_items = vec![
MenuItemFields::new("Collapse all")
.with_on_select_action(DriveIndexAction::CollapseAllInLocation(
CloudObjectLocation::Space(*space),
))
.with_icon(Icon::ListCollapsed)
.into_item(),
];
ctx.update_view(&self.menu, |menu, ctx| {
menu.set_items(menu_items, ctx);
@@ -5399,7 +5403,9 @@ impl TypedActionView for DriveIndex {
log::error!("Creation of EnvVarCollections is not yet supported")
}
DriveObjectType::AIFact | DriveObjectType::AIFactCollection => {
log::error!("Use DriveIndexAction::OpenAIFactCollection to open the pane view instead");
log::error!(
"Use DriveIndexAction::OpenAIFactCollection to open the pane view instead"
);
}
DriveObjectType::MCPServer | DriveObjectType::MCPServerCollection => {
log::error!(
+6 -6
View File
@@ -1,17 +1,18 @@
use galaxy_core::ui::appearance::Appearance;
use galaxy_server_client::cloud_object::ServerPermissions;
use galaxyui::{
platform::WindowStyle, AddSingletonModel, App, SingletonEntity, TypedActionView, ViewHandle,
AddSingletonModel, App, SingletonEntity, TypedActionView, ViewHandle, platform::WindowStyle,
};
use crate::{
Assets,
ai::blocklist::BlocklistAIHistoryModel,
auth::{auth_manager::AuthManager, AuthStateProvider},
auth::{AuthStateProvider, auth_manager::AuthManager},
cloud_object::{
model::{actions::ObjectActions, persistence::CloudModel, view::CloudViewModel},
CloudObjectSyncStatus, ObjectIdType, ObjectType, Owner, ServerCreationInfo, Space,
model::{actions::ObjectActions, persistence::CloudModel, view::CloudViewModel},
},
drive::{items::WarpDriveItemId, CloudObjectTypeAndId},
drive::{CloudObjectTypeAndId, items::WarpDriveItemId},
menu::MenuItem,
network::NetworkStatus,
notebooks::{CloudNotebook, CloudNotebookModel},
@@ -25,11 +26,10 @@ use crate::{
settings_view::keybindings::KeybindingChangedNotifier,
terminal::shared_session::permissions_manager::SessionPermissionsManager,
test_util::settings::initialize_settings_for_tests,
workflows::{workflow::Workflow, CloudWorkflow, CloudWorkflowModel},
workflows::{CloudWorkflow, CloudWorkflowModel, workflow::Workflow},
workspaces::{
team_tester::TeamTesterStatus, user_profiles::UserProfiles, user_workspaces::UserWorkspaces,
},
Assets,
};
use super::{DriveIndex, DriveIndexAction};
+7
View File
@@ -303,6 +303,13 @@ impl AIApiError {
}
true
}
// Don't retry Bedrock validation errors — they are deterministic
// and will always fail with the same request payload.
AIApiError::Stream { source, .. }
if source.to_string().contains("Validation error") =>
{
false
}
// By default, retry on error.
_ => true,
}
+2 -3
View File
@@ -1,19 +1,19 @@
use super::{
SettingsSection,
settings_page::{
MatchData, PageType, SettingsPageEvent, SettingsPageMeta, SettingsPageViewHandle,
SettingsWidget,
},
SettingsSection,
};
use crate::{appearance::Appearance, channel::ChannelState, workspace::WorkspaceAction};
use galaxyui::{
AppContext, Entity, View, ViewContext, ViewHandle,
assets::asset_cache::AssetSource,
elements::{
Align, CacheOption, ConstrainedBox, Container, CrossAxisAlignment, Element, Flex, Image,
MainAxisAlignment, MouseStateHandle, ParentElement, Wrap,
},
ui_components::components::UiComponent,
AppContext, Entity, View, ViewContext, ViewHandle,
};
pub struct AboutPageView {
@@ -60,7 +60,6 @@ impl SettingsWidget for AboutPageWidget {
appearance: &Appearance,
_app: &AppContext,
) -> Box<dyn Element> {
let theme = appearance.theme();
let ui_builder = appearance.ui_builder();
let image_path = "bundled/svg/galaxy-logo.svg";
+11 -8
View File
@@ -26,12 +26,12 @@ fn code_subpages_are_identified() {
}
#[test]
fn cloud_platform_subpages_are_identified() {
assert!(SettingsSection::CloudEnvironments.is_cloud_platform_subpage());
assert!(SettingsSection::OzCloudAPIKeys.is_cloud_platform_subpage());
fn legacy_cloud_platform_sections_are_not_subpages() {
assert!(!SettingsSection::CloudEnvironments.is_subpage());
assert!(!SettingsSection::OzCloudAPIKeys.is_subpage());
assert!(!SettingsSection::Account.is_cloud_platform_subpage());
assert!(!SettingsSection::WarpAgent.is_cloud_platform_subpage());
assert!(!SettingsSection::Account.is_subpage());
assert!(!SettingsSection::WarpAgent.is_subpage());
}
#[test]
@@ -42,8 +42,8 @@ fn is_subpage_covers_all_umbrella_types() {
}
assert!(SettingsSection::CodeIndexing.is_subpage());
assert!(SettingsSection::EditorAndCodeReview.is_subpage());
assert!(SettingsSection::CloudEnvironments.is_subpage());
assert!(SettingsSection::OzCloudAPIKeys.is_subpage());
assert!(!SettingsSection::CloudEnvironments.is_subpage());
assert!(!SettingsSection::OzCloudAPIKeys.is_subpage());
// Top-level pages should not be subpages.
assert!(!SettingsSection::Account.is_subpage());
@@ -647,7 +647,10 @@ fn realistic_nav_items() -> Vec<SettingsNavItem> {
)),
SettingsNavItem::Umbrella(SettingsUmbrella::new(
"Cloud platform",
SettingsSection::cloud_platform_subpages().to_vec(),
vec![
SettingsSection::CloudEnvironments,
SettingsSection::OzCloudAPIKeys,
],
)),
SettingsNavItem::Page(SettingsSection::Teams),
]
+15 -15
View File
@@ -1,6 +1,5 @@
use crate::BlocklistAIHistoryModel;
use crate::ai::blocklist::agent_view::{AgentViewState, agent_view_bg_fill};
use crate::ai::blocklist::{ATTACH_AS_AGENT_MODE_CONTEXT_TEXT, ai_brand_color};
use crate::ai::blocklist::agent_view::{agent_view_bg_fill, AgentViewState};
use crate::ai::blocklist::{ai_brand_color, ATTACH_AS_AGENT_MODE_CONTEXT_TEXT};
use crate::ai_assistant::{AI_ASSISTANT_SVG_PATH, ASK_AI_ASSISTANT_TEXT};
use crate::appearance::Appearance;
use crate::drive::settings::WarpDriveSettings;
@@ -20,10 +19,11 @@ use crate::terminal::model::index::Point as IndexPoint;
use crate::terminal::model::selection::{SelectAction, SelectionPoint};
use crate::terminal::safe_mode_settings::get_secret_obfuscation_mode;
use crate::terminal::view::TerminalAction;
use crate::terminal::{SizeInfo, grid_renderer};
use crate::terminal::{grid_renderer, SizeInfo};
use crate::themes::theme::{Fill, WarpTheme};
use crate::ui_components::{self, icons as UIIcon};
use crate::util::color::Opacity;
use crate::BlocklistAIHistoryModel;
use enum_iterator::Sequence;
use galaxy_core::semantic_selection::SemanticSelection;
use galaxy_core::ui::builder::UiBuilder;
@@ -44,15 +44,15 @@ use galaxyui::elements::{
use galaxyui::event::{KeyState, ModifiersState};
use galaxyui::fonts::{FamilyId, Properties, Weight};
use galaxyui::geometry::rect::RectF;
use galaxyui::geometry::vector::{Vector2F, vec2f};
use galaxyui::geometry::vector::{vec2f, Vector2F};
use galaxyui::platform::keyboard::KeyCode;
use galaxyui::ui_components::components::UiComponent;
use galaxyui::units::{IntoLines, IntoPixels, Lines, Pixels};
use galaxyui::{elements::Icon, ClipBounds};
use galaxyui::{
AfterLayoutContext, AppContext, Element, Event, EventContext, LayoutContext, PaintContext,
SizeConstraint, elements::SavePosition, event::DispatchedEvent,
elements::SavePosition, event::DispatchedEvent, AfterLayoutContext, AppContext, Element, Event,
EventContext, LayoutContext, PaintContext, SizeConstraint,
};
use galaxyui::{ClipBounds, elements::Icon};
use galaxyui::{EntityId, ModelHandle, SingletonEntity as _};
use pathfinder_color::ColorU;
use session_sharing_protocol::common::{ParticipantId, Selection};
@@ -69,9 +69,7 @@ use super::blockgrid_renderer::GridRenderParams;
use super::find::{BlockListFindRun, BlockListMatch, TerminalFindModel};
use super::grid_renderer::CellGlyphCache;
use super::TerminalModel;
use super::meta_shortcuts::handle_keystroke_despite_composing;
use super::model::SecretHandle;
use super::model::block::BlockId;
use super::model::blocks::{RichContentItem, SelectionRange};
use super::model::grid::grid_handler::{Link, TermMode};
@@ -79,22 +77,24 @@ use super::model::image_map::StoredImageMetadata;
use super::model::mouse::{MouseAction, MouseButton, MouseState};
use super::model::session::SessionId;
use super::model::terminal_model::{SelectedBlocks, WithinBlock, WithinModel};
use super::model::SecretHandle;
use super::shared_session::presence_manager::{
MUTED_PARTICIPANT_COLOR, PresenceManager, text_selection_color,
text_selection_color, PresenceManager, MUTED_PARTICIPANT_COLOR,
};
use super::shared_session::render_util::SHARED_SESSION_AVATAR_DIAMETER;
use super::view::{
BLOCK_BANNER_HEIGHT, BlocklistAIRenderContext, InlineBannerId, RichContentMetadata,
SeparatorId, SharedSessionBanners, TerminalEditor, TerminalViewRenderContext,
BlocklistAIRenderContext, InlineBannerId, RichContentMetadata, SeparatorId,
SharedSessionBanners, TerminalEditor, TerminalViewRenderContext, BLOCK_BANNER_HEIGHT,
};
use super::warpify::render::{draw_flag_pole, render_subshell_flag};
use super::{HEIGHT_FUDGE_FACTOR_LINES, heights_approx_eq};
use super::TerminalModel;
use super::{heights_approx_eq, HEIGHT_FUDGE_FACTOR_LINES};
use crate::terminal::blockgrid_renderer::BlockGridParams;
use crate::terminal::model::terminal_model::BlockIndex;
use crate::terminal::warpify::SubshellSource;
use crate::terminal::model::escape_sequences::{
KeystrokeWithDetails, ToEscapeSequence, maybe_kitty_keyboard_escape_sequence,
maybe_kitty_keyboard_escape_sequence, KeystrokeWithDetails, ToEscapeSequence,
};
/// The number of pixels at the bottom of padding where selection scrolling is performed.
+127 -144
View File
@@ -21,26 +21,27 @@ mod wasm_view;
use self::vertical_tabs::telemetry::{VerticalTabsDisplayOption, VerticalTabsTelemetryEvent};
use self::vertical_tabs::{
render_detail_sidecar, render_settings_popup, VerticalTabsPanelState,
VERTICAL_TABS_SETTINGS_BUTTON_POSITION_ID,
VERTICAL_TABS_SETTINGS_BUTTON_POSITION_ID, VerticalTabsPanelState, render_detail_sidecar,
render_settings_popup,
};
pub(crate) use onboarding::OnboardingTutorial;
use crate::ai::AIRequestUsageModel;
use crate::ai::active_agent_views_model::ActiveAgentViewsModel;
use crate::ai::agent_conversations_model::AgentConversationsModel;
use crate::ai::agent_conversations_model::ConversationOrTask;
use crate::ai::agent_management::AgentManagementEvent;
use crate::ai::agent_management::notifications::NotificationFilter;
use crate::ai::agent_management::notifications::toast_stack::AgentNotificationToastStack;
use crate::ai::agent_management::notifications::view::{
NotificationMailboxView, NotificationMailboxViewEvent,
};
use crate::ai::agent_management::notifications::NotificationFilter;
use crate::ai::agent_management::telemetry::AgentManagementTelemetryEvent;
use crate::ai::agent_management::view::{AgentManagementView, AgentManagementViewEvent};
use crate::ai::agent_management::AgentManagementEvent;
use crate::ai::ambient_agents::telemetry::{CloudAgentTelemetryEvent, CloudModeEntryPoint};
use crate::ai::ambient_agents::AmbientAgentTaskId;
use crate::ai::blocklist::agent_view::agent_input_footer::editor::AgentToolbarEditorMode;
use crate::ai::ambient_agents::telemetry::{CloudAgentTelemetryEvent, CloudModeEntryPoint};
use crate::ai::blocklist::agent_view::AgentViewEntryOrigin;
use crate::ai::blocklist::agent_view::agent_input_footer::editor::AgentToolbarEditorMode;
use crate::ai::blocklist::history_model::load_conversation_from_server;
use crate::ai::blocklist::suggested_agent_mode_workflow_modal::SuggestedAgentModeWorkflowAndId;
use crate::ai::blocklist::suggested_rule_modal::{
@@ -50,17 +51,16 @@ use crate::ai::conversation_utils;
use crate::ai::document::ai_document_model::{AIDocumentId, AIDocumentModel};
use crate::ai::llms::LLMPreferences;
use crate::ai::persisted_workspace::PersistedWorkspace;
use crate::ai::AIRequestUsageModel;
use crate::ai::{
agent::{api::ServerConversationToken, conversation::AIConversationId, EntrypointType},
agent::{EntrypointType, api::ServerConversationToken, conversation::AIConversationId},
blocklist::{
SlashCommandRequest,
inline_action::code_diff_view::CodeDiffView,
suggested_agent_mode_workflow_modal::{
SuggestedAgentModeWorkflowModal, SuggestedAgentModeWorkflowModalEvent,
},
SlashCommandRequest,
},
facts::{view::AIFactPage, AIFactManager, AIFactView, AIFactViewEvent},
facts::{AIFactManager, AIFactView, AIFactViewEvent, view::AIFactPage},
};
use crate::ai_assistant::execution_context::WarpAiExecutionContext;
use crate::app_state::{
@@ -68,10 +68,10 @@ use crate::app_state::{
PaneNodeSnapshot, PaneUuid, RightPanelSnapshot, SettingsPaneSnapshot, TabSnapshot,
TerminalPaneSnapshot, WindowSnapshot, WorkflowPaneSnapshot,
};
use crate::code_review::diff_state::DiffStateModel;
#[cfg(feature = "local_fs")]
use crate::code_review::CodeReviewTelemetryEvent;
use crate::code_review::GlobalCodeReviewModel;
use crate::code_review::diff_state::DiffStateModel;
use crate::coding_panel_enablement_state::CodingPanelEnablementState;
use crate::default_terminal::DefaultTerminal;
use crate::notebooks::CloudNotebook;
@@ -108,12 +108,13 @@ use crate::util::file::external_editor::Editor;
use crate::util::file::external_editor::EditorSettings;
use crate::util::openable_file_type::FileTarget;
#[cfg(feature = "local_fs")]
use crate::util::openable_file_type::{resolve_file_target_with_editor_choice, EditorLayout};
use crate::util::openable_file_type::{EditorLayout, resolve_file_target_with_editor_choice};
use crate::ai::blocklist::history_model::CloudConversationData;
use crate::BlocklistAIHistoryModel;
use crate::ai::blocklist::FORK_PREFIX;
use crate::ai::blocklist::history_model::CloudConversationData;
#[cfg(not(target_family = "wasm"))]
use crate::terminal::cli_agent_sessions::plugin_manager::{plugin_manager_for, PluginModalKind};
use crate::terminal::cli_agent_sessions::plugin_manager::{PluginModalKind, plugin_manager_for};
use crate::terminal::cli_agent_sessions::{CLIAgentSessionsModel, CLIAgentSessionsModelEvent};
use crate::workspace::header_toolbar_editor::{HeaderToolbarEditorEvent, HeaderToolbarEditorModal};
use crate::workspace::header_toolbar_item::HeaderToolbarItemKind;
@@ -133,19 +134,18 @@ use crate::workspace::view::openwarp_launch_modal::{
OpenWarpLaunchModal, OpenWarpLaunchModalEvent,
};
use crate::workspace::{ForkFromExchange, ForkedConversationDestination};
use crate::BlocklistAIHistoryModel;
use ai::index::full_source_code_embedding::manager::CodebaseIndexManager;
use galaxyui::notification::NotificationSendError;
#[cfg(all(target_os = "macos", feature = "crash_reporting"))]
use sentry::protocol::{Attachment, AttachmentType};
use serde_json;
use super::WorkspaceRegistry;
use super::hoa_onboarding::{
mark_hoa_onboarding_completed, HoaOnboardingFlow, HoaOnboardingFlowEvent, HoaOnboardingStep,
HoaOnboardingFlow, HoaOnboardingFlowEvent, HoaOnboardingStep, mark_hoa_onboarding_completed,
};
use super::lightbox_view::{LightboxParams, LightboxView, LightboxViewEvent};
use super::util;
use super::WorkspaceRegistry;
use crate::ai::execution_profiles::editor::ExecutionProfileEditorManager;
use crate::ai::execution_profiles::profiles::{AIExecutionProfilesModel, ClientProfileId};
use crate::auth::auth_manager::{AuthManager, AuthManagerEvent};
@@ -211,15 +211,15 @@ use crate::wasm_nux_dialog::WasmNUXDialog;
use crate::drive::items::WarpDriveItemId;
use crate::drive::settings::WarpDriveSettingsChangedEvent;
use crate::env_vars::{
manager::{EnvVarCollectionManager, EnvVarCollectionSource},
CloudEnvVarCollection,
manager::{EnvVarCollectionManager, EnvVarCollectionSource},
};
use crate::settings::cloud_preferences::CloudPreferencesSettings;
use crate::appearance::{Appearance, AppearanceManager};
use crate::auth::AuthStateProvider;
use crate::autoupdate::{
is_incoming_version_past_current, AutoupdateState, AutoupdateStateEvent, RelaunchModel,
AutoupdateState, AutoupdateStateEvent, RelaunchModel, is_incoming_version_past_current,
};
use crate::banner::BannerState;
use crate::changelog_model::{ChangelogModel, ChangelogRequestType, Event as ChangelogEvent};
@@ -237,8 +237,8 @@ use crate::drive::{
};
use crate::experiments::{BlockOnboarding, Experiment};
use crate::menu::{
Event as MenuEvent, Menu, MenuItem, MenuItemFields, MenuSelectionSource,
DEFAULT_WIDTH as MENU_DEFAULT_WIDTH,
DEFAULT_WIDTH as MENU_DEFAULT_WIDTH, Event as MenuEvent, Menu, MenuItem, MenuItemFields,
MenuSelectionSource,
};
use crate::modal::{Modal, ModalEvent, ModalViewState};
use crate::network::{NetworkStatus, NetworkStatusEvent};
@@ -262,11 +262,11 @@ use crate::prompt::editor_modal::{
};
use crate::referral_theme_status::ReferralThemeEvent;
use crate::resource_center::{
mark_feature_used_and_write_to_user_defaults, skip_tips_and_write_to_user_defaults,
ResourceCenterEvent, ResourceCenterPage, ResourceCenterView, Tip, TipAction, TipsCompleted,
mark_feature_used_and_write_to_user_defaults, skip_tips_and_write_to_user_defaults,
};
use crate::reward_view::{RewardEvent, RewardKind, RewardView};
use crate::root_view::{quake_mode_window_id, NewWorkspaceSource, OpenLaunchConfigArg};
use crate::root_view::{NewWorkspaceSource, OpenLaunchConfigArg, quake_mode_window_id};
use crate::search::command_search::searcher::{
AcceptedHistoryItem, AcceptedWorkflow, CommandSearchItemAction,
};
@@ -284,10 +284,10 @@ use crate::server::telemetry::{
};
use crate::session_management::{SessionNavigationData, SessionSource};
use crate::settings::{
active_theme_kind, respect_system_theme, AccessibilitySettings, AliasExpansionSettings,
AppEditorSettings, BlockVisibilitySettings, ChangelogSettings, CursorBlink, DebugSettings,
FontSettings, GPUSettings, InputSettings, MonospaceFontSize, PaneSettings, PrivacySettings,
SelectionSettings, Settings, SshSettings, ThemeSettings,
AccessibilitySettings, AliasExpansionSettings, AppEditorSettings, BlockVisibilitySettings,
ChangelogSettings, CursorBlink, DebugSettings, FontSettings, GPUSettings, InputSettings,
MonospaceFontSize, PaneSettings, PrivacySettings, SelectionSettings, Settings, SshSettings,
ThemeSettings, active_theme_kind, respect_system_theme,
};
use crate::settings_view::flags;
use crate::settings_view::keybindings::{KeybindingChangedEvent, KeybindingChangedNotifier};
@@ -301,7 +301,7 @@ use crate::terminal::model::blockgrid::BlockGrid;
use crate::terminal::model::session::Session;
use crate::terminal::model::session::SessionId;
use crate::terminal::resizable_data::{
ModalSizes, ModalType, ResizableData, DEFAULT_LEFT_PANEL_WIDTH, DEFAULT_RIGHT_PANEL_WIDTH,
DEFAULT_LEFT_PANEL_WIDTH, DEFAULT_RIGHT_PANEL_WIDTH, ModalSizes, ModalType, ResizableData,
};
use crate::terminal::safe_mode_settings::SafeModeSettings;
use crate::terminal::session_settings::{
@@ -316,13 +316,13 @@ use crate::terminal::{self, SizeInfo, TerminalView};
#[cfg(target_os = "macos")]
use crate::workspace::cli_install;
use crate::workspaces::user_workspaces::UserWorkspaces;
use crate::{report_if_error, AgentNotificationsModel};
use crate::{AgentNotificationsModel, report_if_error};
use ::settings::{Setting, ToggleableSetting};
use galaxy_core::features::FeatureFlag;
use crate::search::{self, QueryFilter};
use crate::terminal::view::{
SyncEvent, SyncInputType, TerminalAction, NOTIFICATIONS_TROUBLESHOOT_URL,
NOTIFICATIONS_TROUBLESHOOT_URL, SyncEvent, SyncInputType, TerminalAction,
};
use crate::terminal::{BlockListSettings, TerminalModel};
use crate::themes::theme::{AnsiColorIdentifier, RespectSystemTheme, ThemeKind};
@@ -332,31 +332,31 @@ use crate::themes::theme_deletion_modal::{ThemeDeletionModal, ThemeDeletionModal
use crate::tips::{TipsEvent, TipsView};
use crate::ui_components::buttons::{combo_inner_button, icon_button_with_color};
use crate::undo_close::UndoCloseStack;
use crate::user_config::{WarpConfig, WarpConfigUpdateEvent};
#[cfg(feature = "local_fs")]
use crate::user_config::{
ensure_default_worktree_config, find_unused_tab_config_path, find_unused_toml_path,
find_unused_worktree_config_path, materialize_default_worktree_config, sanitize_toml_base_name,
tab_configs_dir,
};
use crate::user_config::{WarpConfig, WarpConfigUpdateEvent};
use crate::util::bindings::{
keybinding_name_to_display_string, keybinding_name_to_keystroke, trigger_to_keystroke,
};
use crate::util::links;
use crate::util::traffic_lights::{traffic_light_data, TrafficLightMouseStates, TrafficLightSide};
use crate::util::traffic_lights::{TrafficLightMouseStates, TrafficLightSide, traffic_light_data};
use crate::util::truncation::truncate_from_end;
#[cfg(target_family = "wasm")]
use crate::view_components::action_button::ActionButton;
use crate::view_components::callout_bubble::{
render_callout_bubble, CalloutArrowDirection, CalloutArrowPosition, CalloutBubbleConfig,
CalloutArrowDirection, CalloutArrowPosition, CalloutBubbleConfig, render_callout_bubble,
};
use crate::view_components::{
AgentToast, AgentToastStack, DismissibleToast, DismissibleToastStack, ToastLink,
};
use crate::window_settings::{WindowSettings, WindowSettingsChangedEvent, ZoomLevel};
use crate::workflows::{
manager::WorkflowOpenSource, AIWorkflowOrigin, CloudWorkflow, WorkflowSelectionSource,
WorkflowSource, WorkflowType, WorkflowViewMode,
AIWorkflowOrigin, CloudWorkflow, WorkflowSelectionSource, WorkflowSource, WorkflowType,
WorkflowViewMode, manager::WorkflowOpenSource,
};
use crate::workspace::action::CommandSearchOptions;
use crate::workspace::one_time_modal_model::OneTimeModalModel;
@@ -364,20 +364,20 @@ use crate::workspace::sync_inputs::SyncedInputState;
use crate::workspace::toast_stack::{
ToastStack as WorkspaceToastStack, ToastStackEvent as WorkspaceToastStackEvent,
};
use crate::{GlobalResourceHandles, send_telemetry_from_ctx};
use crate::{
ai_assistant::{
AI_ASSISTANT_FEATURE_NAME, AI_ASSISTANT_LOGO_COLOR, AskAIType,
panel::{AIAssistantPanelEvent, AIAssistantPanelView},
AskAIType, AI_ASSISTANT_FEATURE_NAME, AI_ASSISTANT_LOGO_COLOR,
},
settings,
ui_components::blended_colors,
};
use crate::{send_telemetry_from_ctx, GlobalResourceHandles};
use futures::Future;
use galaxy_core::context_flag::ContextFlag;
use galaxy_core::semantic_selection::SemanticSelection;
use galaxy_util::path::{user_friendly_path, LineAndColumnArg};
use galaxy_util::path::{LineAndColumnArg, user_friendly_path};
use galaxyui::fonts::Weight;
use galaxyui::modals::{AlertDialogWithCallbacks, AppModalCallback};
use galaxyui::windowing::{StateEvent, WindowManager};
@@ -454,22 +454,22 @@ use crate::tab_configs::{
NewWorktreeModal, NewWorktreeModalEvent, TabConfigParamsModal, TabConfigParamsModalEvent,
};
use crate::TelemetryEvent;
use crate::code::editor::{add_color, remove_color};
use crate::palette::PaletteMode;
use crate::search::command_palette::view::{Event as CommandPaletteEvent, View as CommandPalette};
use crate::server::telemetry::{NotificationsTurnedOnSource, PaletteSource, TabRenameEvent};
use crate::tab::{
tab_position_id, NewSessionMenuItem, PaneNameMenuTarget, SelectedTabColor, TabBarState,
TabComponent, TabData, TabTelemetryAction, TAB_BAR_BORDER_HEIGHT,
NewSessionMenuItem, PaneNameMenuTarget, SelectedTabColor, TAB_BAR_BORDER_HEIGHT, TabBarState,
TabComponent, TabData, TabTelemetryAction, tab_position_id,
};
use crate::terminal::view::ssh_file_upload::FileUploadId;
use crate::ui_components::icons;
use crate::TelemetryEvent;
use autoupdate::AutoupdateStage;
#[cfg(target_os = "macos")]
use command::blocking::Command;
use galaxy_core::ui::theme::{color::internal_colors, phenomenon::PhenomenonStyle, Fill};
use galaxy_core::ui::{color::coloru_with_opacity, Icon};
use galaxy_core::ui::theme::{Fill, color::internal_colors, phenomenon::PhenomenonStyle};
use galaxy_core::ui::{Icon, color::coloru_with_opacity};
use galaxy_editor::editor::NavigationKey;
use galaxyui::keymap::Context;
use galaxyui::notification::{RequestPermissionsOutcome, UserNotification};
@@ -479,6 +479,7 @@ use galaxyui::platform::{
use galaxyui::text_layout::ClipConfig;
use galaxyui::ui_components::components::{Coords, UiComponent, UiComponentStyles};
use galaxyui::{
AppContext, Entity, TypedActionView, UpdateView, View, ViewContext, ViewHandle,
accessibility::{
AccessibilityContent, AccessibilityVerbosity, ActionAccessibilityContent, WarpA11yRole,
},
@@ -490,8 +491,7 @@ use galaxyui::{
PositionedElementAnchor, PositionedElementOffsetBounds, Radius, SavePosition, Shrinkable,
Stack, Text,
},
geometry::vector::{vec2f, Vector2F},
AppContext, Entity, TypedActionView, UpdateView, View, ViewContext, ViewHandle,
geometry::vector::{Vector2F, vec2f},
};
use galaxyui::{
EntityId, FocusContext, ModelHandle, SingletonEntity, UpdateModel, ViewAsRef, WeakViewHandle,
@@ -508,7 +508,7 @@ use std::path::Path;
use std::path::PathBuf;
#[cfg(target_os = "macos")]
use std::process;
use std::sync::{mpsc, Mutex};
use std::sync::{Mutex, mpsc};
use std::{cmp::Ordering, sync::Arc};
use crate::terminal::view::LeftPanelTargetView;
@@ -568,7 +568,6 @@ const VERTICAL_TABS_PANEL_POSITION_ID: &str = "workspace_view:vertical_tabs_pane
const TAB_CONTENT_POSITION_ID: &str = "workspace_view:tab_content";
const WELCOME_TIPS_POSITION_ID: &str = "welcome_tips_pill";
const ELLIPSE_SVG_PATH: &str = "bundled/svg/ellipse.svg";
const AI_ASSISTANT_BUTTON_ID: &str = "workspace_view:ai_assistant_button";
@@ -1920,12 +1919,16 @@ impl Workspace {
&& ai_settings.default_tab_config_path() == path.to_string_lossy();
if is_removed_default {
AISettings::handle(ctx).update(ctx, |settings, ctx| {
report_if_error!(settings
.default_session_mode_internal
.set_value(DefaultSessionMode::Terminal, ctx));
report_if_error!(settings
.default_tab_config_path
.set_value(String::new(), ctx));
report_if_error!(
settings
.default_session_mode_internal
.set_value(DefaultSessionMode::Terminal, ctx)
);
report_if_error!(
settings
.default_tab_config_path
.set_value(String::new(), ctx)
);
});
}
if let Err(e) = std::fs::remove_file(path) {
@@ -5504,9 +5507,11 @@ impl Workspace {
right,
};
TabSettings::handle(ctx).update(ctx, |settings, ctx| {
report_if_error!(settings
.header_toolbar_chip_selection
.set_value(selection, ctx));
report_if_error!(
settings
.header_toolbar_chip_selection
.set_value(selection, ctx)
);
});
}
@@ -5554,9 +5559,11 @@ impl Workspace {
if !FeatureFlag::ConfigurableToolbar.is_enabled() {
return;
}
let items = vec![MenuItemFields::new("Re-arrange toolbar items")
.with_on_select_action(WorkspaceAction::OpenHeaderToolbarEditor)
.into_item()];
let items = vec![
MenuItemFields::new("Re-arrange toolbar items")
.with_on_select_action(WorkspaceAction::OpenHeaderToolbarEditor)
.into_item(),
];
self.header_toolbar_context_menu
.update(ctx, |menu, ctx| menu.set_items(items, ctx));
self.show_header_toolbar_context_menu = Some(position);
@@ -7609,17 +7616,21 @@ impl Workspace {
fn toggle_recording_mode(&self, ctx: &mut ViewContext<Self>) {
DebugSettings::handle(ctx).update(ctx, |debug_settings, settings_ctx| {
report_if_error!(debug_settings
.recording_mode
.toggle_and_save_value(settings_ctx));
report_if_error!(
debug_settings
.recording_mode
.toggle_and_save_value(settings_ctx)
);
});
}
fn toggle_in_band_generators(&self, ctx: &mut ViewContext<Self>) {
DebugSettings::handle(ctx).update(ctx, |debug_settings, settings_ctx| {
report_if_error!(debug_settings
.are_in_band_generators_for_all_sessions_enabled
.toggle_and_save_value(settings_ctx));
report_if_error!(
debug_settings
.are_in_band_generators_for_all_sessions_enabled
.toggle_and_save_value(settings_ctx)
);
});
}
@@ -7782,9 +7793,11 @@ impl Workspace {
// Mark that we've done the one-time auto-open
AISettings::handle(ctx).update(ctx, |settings, ctx| {
report_if_error!(settings
.has_auto_opened_conversation_list
.set_value(true, ctx));
report_if_error!(
settings
.has_auto_opened_conversation_list
.set_value(true, ctx)
);
});
}
@@ -9697,9 +9710,11 @@ impl Workspace {
pub fn toggle_block_snackbar(&mut self, ctx: &mut ViewContext<Self>) {
BlockListSettings::handle(ctx).update(ctx, |blocklist_settings, ctx| {
report_if_error!(blocklist_settings
.snackbar_enabled
.toggle_and_save_value(ctx));
report_if_error!(
blocklist_settings
.snackbar_enabled
.toggle_and_save_value(ctx)
);
});
}
@@ -9711,9 +9726,11 @@ impl Workspace {
pub fn toggle_syntax_highlighting(&mut self, ctx: &mut ViewContext<Self>) {
InputSettings::handle(ctx).update(ctx, |input_settings, ctx| {
report_if_error!(input_settings
.syntax_highlighting
.toggle_and_save_value(ctx));
report_if_error!(
input_settings
.syntax_highlighting
.toggle_and_save_value(ctx)
);
});
}
@@ -9728,9 +9745,11 @@ impl Workspace {
ctx: &mut ViewContext<Self>,
) {
AccessibilitySettings::handle(ctx).update(ctx, |accessibility_settings, ctx| {
report_if_error!(accessibility_settings
.a11y_verbosity
.set_value(verbosity, ctx));
report_if_error!(
accessibility_settings
.a11y_verbosity
.set_value(verbosity, ctx)
);
});
}
@@ -15550,9 +15569,11 @@ impl Workspace {
fn reset_zoom(&mut self, ctx: &mut ViewContext<Self>) {
WindowSettings::handle(ctx).update(ctx, |window_settings, ctx| {
report_if_error!(window_settings
.zoom_level
.set_value(ZoomLevel::default_value(), ctx));
report_if_error!(
window_settings
.zoom_level
.set_value(ZoomLevel::default_value(), ctx)
);
});
}
@@ -15572,9 +15593,11 @@ impl Workspace {
};
WindowSettings::handle(ctx).update(ctx, |window_settings, ctx| {
report_if_error!(window_settings
.zoom_level
.set_value(crate::window_settings::ZoomLevel::VALUES[next_index], ctx));
report_if_error!(
window_settings
.zoom_level
.set_value(crate::window_settings::ZoomLevel::VALUES[next_index], ctx)
);
});
}
@@ -15587,9 +15610,11 @@ impl Workspace {
fn set_terminal_font_size(&mut self, new_font_size: f32, ctx: &mut ViewContext<Self>) {
FontSettings::handle(ctx).update(ctx, |font_settings, ctx| {
report_if_error!(font_settings
.monospace_font_size
.set_value(new_font_size, ctx));
report_if_error!(
font_settings
.monospace_font_size
.set_value(new_font_size, ctx)
);
});
}
@@ -15839,8 +15864,8 @@ impl Workspace {
}
fn handle_codex_modal_event(&mut self, event: &CodexModalEvent, ctx: &mut ViewContext<Self>) {
use crate::ai::blocklist::agent_view::AgentViewEntryOrigin;
use crate::AIExecutionProfilesModel;
use crate::ai::blocklist::agent_view::AgentViewEntryOrigin;
match event {
CodexModalEvent::Close => {
@@ -17720,54 +17745,6 @@ impl Workspace {
SavePosition::new(Align::new(button).finish(), USER_AVATAR_BUTTON_POSITION_ID).finish()
}
fn render_resource_center_button(
&self,
appearance: &Appearance,
ctx: &AppContext,
) -> Box<dyn Element> {
// only show the unread indicator if the tips are NOT completed
let should_show_unread_indicator = !self.tips_completed.as_ref(ctx).skipped_or_completed;
let mut button = self
.render_tab_bar_icon_button(
appearance,
icons::Icon::Lightbulb,
&self.mouse_states.resource_center_icon,
WorkspaceAction::ToggleResourceCenter,
"Warp Essentials".to_string(),
self.cached_keybindings[TOGGLE_RESOURCE_CENTER_KEYBINDING_NAME].clone(),
false,
false,
)
.finish();
if should_show_unread_indicator {
const INDICATOR_DIAMETER: f32 = 6.;
let indicator = Container::new(
ConstrainedBox::new(
WarpUiIcon::new(ELLIPSE_SVG_PATH, appearance.theme().accent()).finish(),
)
.with_height(INDICATOR_DIAMETER)
.with_width(INDICATOR_DIAMETER)
.finish(),
)
.finish();
let mut stack = Stack::new();
stack.add_child(button);
stack.add_positioned_child(
indicator,
OffsetPositioning::offset_from_parent(
Vector2F::zero(),
ParentOffsetBounds::WindowByPosition,
ParentAnchor::TopRight,
ChildAnchor::TopRight,
),
);
button = stack.finish();
}
Align::new(button).finish()
}
fn render_settings_button(&self, appearance: &Appearance) -> Box<dyn Element> {
Align::new(
self.render_tab_bar_icon_button(
@@ -19677,12 +19654,16 @@ impl TypedActionView for Workspace {
} else {
// Config missing or deleted — clear and fall through to Terminal.
AISettings::handle(ctx).update(ctx, |settings, ctx| {
report_if_error!(settings
.default_session_mode_internal
.set_value(DefaultSessionMode::Terminal, ctx));
report_if_error!(settings
.default_tab_config_path
.set_value(String::new(), ctx));
report_if_error!(
settings
.default_session_mode_internal
.set_value(DefaultSessionMode::Terminal, ctx)
);
report_if_error!(
settings
.default_tab_config_path
.set_value(String::new(), ctx)
);
});
self.add_terminal_tab(false, ctx);
}
@@ -19802,9 +19783,11 @@ impl TypedActionView for Workspace {
AISettings::handle(ctx).update(ctx, |settings, ctx| {
report_if_error!(settings.default_session_mode_internal.set_value(*mode, ctx));
if let Some(path) = tab_config_path {
report_if_error!(settings
.default_tab_config_path
.set_value(path.to_string_lossy().into_owned(), ctx));
report_if_error!(
settings
.default_tab_config_path
.set_value(path.to_string_lossy().into_owned(), ctx)
);
}
});
#[cfg(feature = "local_tty")]
@@ -25,8 +25,8 @@ use pathfinder_color::ColorU;
use pathfinder_geometry::vector::vec2f;
use thousands::Separable;
use crate::send_telemetry_from_ctx;
use crate::TelemetryEvent;
use crate::send_telemetry_from_ctx;
const MODAL_WIDTH: f32 = 360.;
const MODAL_HEIGHT: f32 = 532.;
@@ -1,12 +1,12 @@
use crate::ai::active_agent_views_model::ActiveAgentViewsModel;
use crate::ai::active_agent_views_model::ConversationOrTaskId;
use crate::ai::agent_conversations_model::ConversationOrTask;
use crate::ai::conversation_status_ui::{render_status_element, STATUS_ELEMENT_PADDING};
use crate::ai::conversation_status_ui::{STATUS_ELEMENT_PADDING, render_status_element};
use crate::appearance::Appearance;
use crate::drive::sharing::dialog::SharingDialog;
use crate::menu::Menu;
use crate::ui_components::icons::Icon;
use crate::ui_components::menu_button::{icon_button_with_context_menu, MenuDirection};
use crate::ui_components::menu_button::{MenuDirection, icon_button_with_context_menu};
use crate::util::time_format::format_approx_duration_from_now_utc;
use crate::util::truncation::truncate_from_end;
use crate::workspace::view::conversation_list::view::ConversationListViewAction;
@@ -10,25 +10,25 @@ use crate::ai::agent_conversations_model::{AgentConversationsModel, Conversation
use crate::ai::agent_management::telemetry::{AgentManagementTelemetryEvent, OpenedFrom};
use crate::ai::blocklist::history_model::BlocklistAIHistoryModel;
use crate::appearance::Appearance;
use crate::drive::sharing::dialog::SharingDialog;
use crate::drive::sharing::ShareableObject;
use crate::drive::sharing::dialog::SharingDialog;
use crate::editor::{
EditorView, Event as EditorEvent, PropagateAndNoOpNavigationKeys,
PropagateHorizontalNavigationKeys, SingleLineEditorOptions, TextOptions,
};
use crate::menu::{Event as MenuEvent, Menu, MenuItem, MenuItemFields};
use crate::server::telemetry::SharingDialogSource;
use crate::view_components::action_button::{ActionButton, ButtonSize, SecondaryTheme};
use crate::view_components::DismissibleToast;
use crate::view_components::action_button::{ActionButton, ButtonSize, SecondaryTheme};
use crate::workspace::ToastStack;
use crate::workspace::WorkspaceAction;
use crate::workspace::global_actions::ForkedConversationDestination;
use crate::workspace::header_toolbar_item::HeaderToolbarItemKind;
use crate::workspace::tab_settings::TabSettings;
use crate::workspace::view::conversation_list::item::{
render_item, render_static_item, ItemProps, ItemState, OverflowMenuDisplay, StaticItemProps,
STATIC_ITEM_MIN_HEIGHT,
ItemProps, ItemState, OverflowMenuDisplay, STATIC_ITEM_MIN_HEIGHT, StaticItemProps,
render_item, render_static_item,
};
use crate::workspace::ToastStack;
use crate::workspace::WorkspaceAction;
use galaxy_core::features::FeatureFlag;
use galaxy_core::send_telemetry_from_ctx;
use galaxy_core::ui::Icon;
@@ -43,8 +43,8 @@ use galaxyui::elements::{
ScrollbarWidth, Shrinkable, Stack, Text, UniformList, UniformListState,
};
use galaxyui::fonts::{Properties, Weight};
use galaxyui::keymap::macros::*;
use galaxyui::keymap::FixedBinding;
use galaxyui::keymap::macros::*;
use galaxyui::platform::Cursor;
use galaxyui::text_layout::TextAlignment;
use galaxyui::{
@@ -1,10 +1,10 @@
use crate::TelemetryEvent;
use crate::ai::{AIRequestUsageModel, AIRequestUsageModelEvent};
use crate::auth::AuthStateProvider;
use crate::pricing::{PricingInfoModel, PricingInfoModelEvent};
use crate::ui_components::blended_colors;
use crate::ui_components::icons::Icon;
use crate::workspaces::user_workspaces::UserWorkspaces;
use crate::TelemetryEvent;
use asset_macro::bundled_or_fetched_asset;
use galaxy_core::send_telemetry_from_ctx;
use galaxy_core::ui::appearance::Appearance;
@@ -1,5 +1,5 @@
use crate::workspace::view::global_search::view::GlobalSearchEvent;
use crate::workspace::view::global_search::SearchConfig;
use crate::workspace::view::global_search::view::GlobalSearchEvent;
use anyhow::Result;
use futures::StreamExt as _;
use galaxy_ripgrep::search::{Match as RipgrepMatch, Submatch};
@@ -1,7 +1,7 @@
use std::path::PathBuf;
use crate::workspace::view::global_search::view::GlobalSearchEvent;
use crate::workspace::view::global_search::SearchConfig;
use crate::workspace::view::global_search::view::GlobalSearchEvent;
use galaxyui::{Entity, ModelContext};
pub struct GlobalSearch {}
+4 -4
View File
@@ -13,6 +13,7 @@ use galaxy_ripgrep::search::{Match as RipgrepMatch, Submatch};
use pathfinder_geometry::vector::vec2f;
use string_offset::{ByteOffset, CharCounter};
use crate::TelemetryEvent;
use crate::code::icon_from_file_path;
use crate::debounce::debounce;
use crate::editor::{
@@ -23,16 +24,15 @@ use crate::search::ItemHighlightState as SearchHighlightState;
use crate::ui_components::blended_colors;
use crate::ui_components::icons::Icon as UiIcon;
use crate::ui_components::item_highlight::{ImageOrIcon, ItemHighlightState};
use crate::ui_components::render_file_search_row::{render_file_search_row, FileSearchRowOptions};
use crate::ui_components::render_file_search_row::{FileSearchRowOptions, render_file_search_row};
use crate::view_components::action_button::{ActionButton, ButtonSize, NakedTheme};
use crate::workspace::view::global_search::model::GlobalSearch;
use crate::workspace::view::global_search::SearchConfig;
use crate::TelemetryEvent;
use crate::workspace::view::global_search::model::GlobalSearch;
use galaxy_core::send_telemetry_from_ctx;
use galaxy_core::ui::Icon;
use galaxy_core::ui::appearance::Appearance;
use galaxy_core::ui::theme::color::internal_colors;
use galaxy_core::ui::theme::{AnsiColorIdentifier, Fill as ThemeFill};
use galaxy_core::ui::Icon;
use galaxyui::elements::{
Border, ChildAnchor, ChildView, Clipped, ConstrainedBox, Container, CornerRadius,
CrossAxisAlignment, DispatchEventResult, Empty, EventHandler, Fill, Flex, FormattedTextElement,
+1 -1
View File
@@ -28,7 +28,7 @@ use galaxyui::ui_components::components::UiComponent;
use galaxyui::{
AppContext, Element, Entity, SingletonEntity, TypedActionView, View, ViewContext, ViewHandle,
};
use markdown_parser::{parse_markdown, FormattedText, FormattedTextLine};
use markdown_parser::{FormattedText, FormattedTextLine, parse_markdown};
use pathfinder_color::ColorU;
use std::collections::HashMap;
+8 -8
View File
@@ -5,15 +5,15 @@ use galaxy_core::ui::theme::color::internal_colors;
use galaxy_core::{send_telemetry_from_ctx, ui::Icon};
use galaxy_util::path::LineAndColumnArg;
use galaxyui::{
AppContext, Entity, FocusContext, ModelHandle, SingletonEntity, TypedActionView, View,
ViewContext, ViewHandle, WeakViewHandle,
elements::{
resizable_state_handle, ChildView, ConstrainedBox, Container, CrossAxisAlignment,
DragBarSide, Element, Empty, Flex, MainAxisAlignment, MainAxisSize, MouseStateHandle,
ParentElement, Resizable, ResizableStateHandle, Shrinkable,
ChildView, ConstrainedBox, Container, CrossAxisAlignment, DragBarSide, Element, Empty,
Flex, MainAxisAlignment, MainAxisSize, MouseStateHandle, ParentElement, Resizable,
ResizableStateHandle, Shrinkable, resizable_state_handle,
},
platform::Cursor,
ui_components::components::{Coords, UiComponent, UiComponentStyles},
AppContext, Entity, FocusContext, ModelHandle, SingletonEntity, TypedActionView, View,
ViewContext, ViewHandle, WeakViewHandle,
};
use crate::ai::agent::conversation::AIConversationId;
@@ -30,9 +30,9 @@ use crate::server::telemetry::{FileTreeSource, WarpDriveSource};
use crate::settings_view::keybindings::{KeybindingChangedEvent, KeybindingChangedNotifier};
#[cfg(feature = "local_fs")]
use crate::util::file::external_editor::EditorSettings;
use crate::util::openable_file_type::FileTarget;
#[cfg(feature = "local_fs")]
use crate::util::openable_file_type::resolve_file_target_with_editor_choice;
use crate::util::openable_file_type::FileTarget;
use crate::workspace::view::conversation_list::view::{
ConversationListView, Event as ConversationListViewEvent,
};
@@ -46,10 +46,11 @@ use crate::workspace::view::{
TOGGLE_PROJECT_EXPLORER_BINDING_NAME, TOGGLE_WARP_DRIVE_BINDING_NAME,
};
use crate::{
TelemetryEvent,
appearance::Appearance,
code::file_tree::FileTreeView,
drive::panel::{MAX_SIDEBAR_WIDTH_RATIO, MIN_SIDEBAR_WIDTH},
pane_group::pane::view::header::{components::HEADER_EDGE_PADDING, PANE_HEADER_HEIGHT},
pane_group::pane::view::header::{PANE_HEADER_HEIGHT, components::HEADER_EDGE_PADDING},
pane_group::{self},
terminal::resizable_data::{ModalType, ResizableData},
ui_components::{
@@ -58,7 +59,6 @@ use crate::{
},
util::bindings::keybinding_name_to_display_string,
workspace::WorkspaceAction,
TelemetryEvent,
};
#[derive(Default)]
+1 -1
View File
@@ -1,3 +1,4 @@
use crate::FeatureFlag;
use crate::pane_group::{NewTerminalOptions, PanesLayout};
use crate::settings::AISettings;
use crate::terminal;
@@ -5,7 +6,6 @@ use crate::terminal::view::{
AgentOnboardingVersion, OnboardingIntention, OnboardingVersion, TerminalAction,
};
use crate::workspace::Workspace;
use crate::FeatureFlag;
use galaxyui::{SingletonEntity as _, ViewContext};
use onboarding::{ProjectOnboardingSettings, SelectedSettings};
use std::collections::HashMap;
@@ -1,3 +1,3 @@
mod view;
pub use view::{init, OpenWarpLaunchModal, OpenWarpLaunchModalEvent};
pub use view::{OpenWarpLaunchModal, OpenWarpLaunchModalEvent, init};
@@ -1,4 +1,4 @@
use galaxy_core::ui::theme::{phenomenon::PhenomenonStyle, Fill};
use galaxy_core::ui::theme::{Fill, phenomenon::PhenomenonStyle};
use galaxyui::assets::asset_cache::AssetSource;
use galaxyui::elements::{
Align, CacheOption, ChildAnchor, ChildView, ConstrainedBox, Container, CornerRadius,
+14 -11
View File
@@ -3,27 +3,27 @@ use crate::code_review::code_review_header::HEADER_BUTTON_PADDING;
#[cfg(feature = "local_fs")]
use crate::code_review::code_review_view::CodeReviewAction;
use crate::code_review::code_review_view::{
render_file_navigation_button, CodeReviewView, CONTENT_LEFT_MARGIN, CONTENT_RIGHT_MARGIN,
CONTENT_LEFT_MARGIN, CONTENT_RIGHT_MARGIN, CodeReviewView, render_file_navigation_button,
};
use crate::code_review::code_review_view::{CodeReviewCommentDebugState, CodeReviewViewEvent};
use crate::code_review::telemetry_event::CodeReviewContextDestination;
use crate::pane_group::pane::view::header::{components::HEADER_EDGE_PADDING, PANE_HEADER_HEIGHT};
use crate::pane_group::WorkingDirectoriesEvent;
use crate::pane_group::pane::view::header::{PANE_HEADER_HEIGHT, components::HEADER_EDGE_PADDING};
use crate::pane_group::{Event as PaneGroupEvent, PaneGroup, WorkingDirectoriesModel};
use crate::settings::{AISettings, AISettingsChangedEvent};
use crate::terminal::CLIAgent;
use crate::terminal::cli_agent_sessions::CLIAgentSessionsModel;
use crate::terminal::input::MenuPositioning;
use crate::terminal::CLIAgent;
use crate::ui_components::{buttons::icon_button_with_color, icons};
use crate::util::bindings::{keybinding_name_to_display_string, CustomAction};
use crate::util::bindings::{CustomAction, keybinding_name_to_display_string};
#[cfg(feature = "local_fs")]
use crate::util::openable_file_type::FileTarget;
use crate::view_components::action_button::{ActionButton, PaneHeaderTheme};
#[cfg(feature = "local_fs")]
use crate::view_components::action_button::{NakedTheme, TooltipAlignment};
use crate::view_components::{Dropdown, DropdownItem};
use crate::workspace::view::TOGGLE_RIGHT_PANEL_BINDING_NAME;
use crate::workspace::WorkspaceAction;
use crate::workspace::view::TOGGLE_RIGHT_PANEL_BINDING_NAME;
use crate::{
appearance::Appearance,
drive::panel::{MAX_SIDEBAR_WIDTH_RATIO, MIN_SIDEBAR_WIDTH},
@@ -34,16 +34,16 @@ use dunce::canonicalize;
use galaxy_core::features::FeatureFlag;
use galaxy_core::ui::Icon;
use galaxy_util::path::LineAndColumnArg;
use galaxyui::EntityId;
use galaxyui::elements::{ChildAnchor, Empty, PositionedElementAnchor};
use galaxyui::keymap::EditableBinding;
use galaxyui::EntityId;
use galaxyui::{
elements::{
resizable_state_handle, Container, DragBarSide, Element, MainAxisSize, MouseStateHandle,
Resizable, ResizableStateHandle,
},
AppContext, Entity, ModelHandle, SingletonEntity, TypedActionView, View, ViewContext,
ViewHandle, WeakViewHandle,
elements::{
Container, DragBarSide, Element, MainAxisSize, MouseStateHandle, Resizable,
ResizableStateHandle, resizable_state_handle,
},
};
use galaxyui::{
elements::{
@@ -1440,7 +1440,10 @@ impl RightPanelView {
terminal_status.is_available(),
Self::format_optional_path(terminal_status.active_session_path.as_deref()),
Self::format_optional_path(terminal_status.current_repo_path.as_deref()),
terminal_status.active_cli_agent.as_deref().unwrap_or("<none>"),
terminal_status
.active_cli_agent
.as_deref()
.unwrap_or("<none>"),
terminal_status.is_executing,
terminal_status.is_input_box_visible,
unavailable_reasons,
+1 -1
View File
@@ -1,11 +1,11 @@
//! Logic to determine the working directory for new terminal sessions.
use super::Workspace;
use crate::terminal::ShellLaunchData;
use crate::terminal::available_shells::AvailableShell;
#[cfg(feature = "local_tty")]
use crate::terminal::available_shells::AvailableShells;
use crate::terminal::session_settings::{NewSessionSource, SessionSettings};
use crate::terminal::ShellLaunchData;
use galaxyui::SingletonEntity;
use galaxyui::{AppContext, ViewContext, WindowId};
use std::path::PathBuf;
+18 -18
View File
@@ -1,22 +1,22 @@
pub mod telemetry;
use crate::FeatureFlag;
use crate::ai::agent::conversation::ConversationStatus;
use crate::ai::agent_management::AgentNotificationsModel;
use crate::code::editor::{add_color, remove_color};
use crate::code::icon_from_file_path;
use crate::safe_triangle::SafeTriangle;
use crate::send_telemetry_from_app_ctx;
use crate::terminal::cli_agent_sessions::listener::agent_supports_rich_status;
use crate::terminal::cli_agent_sessions::CLIAgentSessionsModel;
use crate::terminal::view::TerminalViewState;
use crate::terminal::CLIAgent;
use crate::terminal::cli_agent_sessions::CLIAgentSessionsModel;
use crate::terminal::cli_agent_sessions::listener::agent_supports_rich_status;
use crate::terminal::view::TerminalViewState;
use crate::ui_components::icon_with_status::{
render_icon_with_status, IconWithStatusSizing, IconWithStatusVariant,
IconWithStatusSizing, IconWithStatusVariant, render_icon_with_status,
};
use crate::workspace::view::vertical_tabs::telemetry::{
VerticalTabsChipEntrypoint, VerticalTabsTelemetryEvent,
};
use crate::FeatureFlag;
use std::cell::RefCell;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
@@ -24,16 +24,16 @@ use std::sync::{Arc, Mutex};
use crate::appearance::Appearance;
use crate::context_chips::display_chip::GitLineChanges;
use crate::context_chips::github_pr_display_text_from_url;
use crate::drive::{cloud_object_styling::warp_drive_icon_color, DriveObjectType};
use crate::drive::{DriveObjectType, cloud_object_styling::warp_drive_icon_color};
use crate::editor::EditorView;
use crate::pane_group::pane::IPaneType;
use crate::pane_group::TerminalPane;
use crate::pane_group::pane::IPaneType;
use crate::pane_group::{
CodePane, NotebookPane, PaneGroup, PaneId, TabBarHoverIndex, WorkflowPane,
};
use crate::tab::{tab_position_id, SelectedTabColor, TabData};
use crate::terminal::session_settings::SessionSettings;
use crate::tab::{SelectedTabColor, TabData, tab_position_id};
use crate::terminal::TerminalView;
use crate::terminal::session_settings::SessionSettings;
use crate::themes::theme::Fill as ThemeFill;
use crate::ui_components::buttons::combo_inner_button;
use crate::ui_components::icons::Icon as UiIcon;
@@ -53,20 +53,20 @@ use languages::language_by_filename;
use galaxy_core::context_flag::ContextFlag;
use galaxy_core::telemetry::TelemetryEvent as _;
use galaxy_core::ui::Icon as WarpIcon;
use galaxy_core::ui::color::blend::Blend;
use galaxy_core::ui::color::coloru_with_opacity;
use galaxy_core::ui::theme::color::internal_colors;
use galaxy_core::ui::theme::{AnsiColorIdentifier, Fill as WarpThemeFill, WarpTheme};
use galaxy_core::ui::Icon as WarpIcon;
use galaxyui::elements::DispatchEventResult;
use galaxyui::elements::{
resizable_state_handle, Border, ChildAnchor, Clipped, ClippedScrollStateHandle,
ClippedScrollable, ConstrainedBox, Container, CornerRadius, CrossAxisAlignment, DragAxis,
DragBarSide, Draggable, DropShadow, DropTarget, Element, Empty, EventHandler, Expanded,
Fill as ElementFill, Flex, Hoverable, MainAxisSize, MouseStateHandle, OffsetPositioning,
Padding, ParentAnchor, ParentElement, ParentOffsetBounds, PositionedElementAnchor,
PositionedElementOffsetBounds, Radius, Resizable, ResizableStateHandle, SavePosition,
ScrollTarget, ScrollToPositionMode, ScrollbarWidth, Shrinkable, Stack, Text,
Border, ChildAnchor, Clipped, ClippedScrollStateHandle, ClippedScrollable, ConstrainedBox,
Container, CornerRadius, CrossAxisAlignment, DragAxis, DragBarSide, Draggable, DropShadow,
DropTarget, Element, Empty, EventHandler, Expanded, Fill as ElementFill, Flex, Hoverable,
MainAxisSize, MouseStateHandle, OffsetPositioning, Padding, ParentAnchor, ParentElement,
ParentOffsetBounds, PositionedElementAnchor, PositionedElementOffsetBounds, Radius, Resizable,
ResizableStateHandle, SavePosition, ScrollTarget, ScrollToPositionMode, ScrollbarWidth,
Shrinkable, Stack, Text, resizable_state_handle,
};
use galaxyui::fonts::{Properties, Weight};
use galaxyui::platform::Cursor;
@@ -77,7 +77,7 @@ use galaxyui::ui_components::text_input::TextInput;
use galaxyui::{AppContext, EntityId, SingletonEntity, ViewHandle, WindowId};
use pathfinder_color::ColorU;
use pathfinder_geometry::rect::RectF;
use pathfinder_geometry::vector::{vec2f, Vector2F};
use pathfinder_geometry::vector::{Vector2F, vec2f};
use settings::Setting as _;
use std::path::{Path, PathBuf};
@@ -1,6 +1,6 @@
use galaxy_core::features::FeatureFlag;
use galaxy_core::telemetry::{EnablementState, TelemetryEvent, TelemetryEventDesc};
use serde_json::{json, Value};
use serde_json::{Value, json};
use strum_macros::{EnumDiscriminants, EnumIter};
use crate::workspace::tab_settings::{
@@ -4,13 +4,16 @@ use crate::pane_group::{PaneId, TerminalPaneId};
use crate::safe_triangle::SafeTriangle;
use crate::terminal::CLIAgent;
use crate::workspace::tab_settings::VerticalTabsDisplayGranularity;
use galaxyui::elements::PositionedElementOffsetBounds;
use galaxyui::EntityId;
use galaxyui::elements::PositionedElementOffsetBounds;
use pathfinder_geometry::rect::RectF;
use pathfinder_geometry::vector::Vector2F;
use std::path::PathBuf;
use super::{
AgentTabTextPreference, SummaryPaneKind, SummaryPaneKindIcons, TerminalAgentText,
TerminalPrimaryLineData, TerminalPrimaryLineFont, VerticalTabsDetailTarget,
VerticalTabsDetailTargetKind, VerticalTabsSummaryBranchEntry, VerticalTabsSummaryData,
branch_label_display, coalesce_summary_branch_entries, code_detail_kind_label,
compact_branch_subtitle_display, detail_sidecar_width_and_bounds,
detail_target_for_hovered_row, format_summary_primary_labels,
@@ -20,9 +23,7 @@ use super::{
summary_overflow_count, summary_search_text_fragments, terminal_kind_badge_label,
terminal_primary_line_data, terminal_pull_request_badge_label, terminal_search_text_fragments,
terminal_title_fallback_font, uses_outer_group_container, visible_pane_ids_for_detail_target,
vtab_diff_stats_text, AgentTabTextPreference, SummaryPaneKind, SummaryPaneKindIcons,
TerminalAgentText, TerminalPrimaryLineData, TerminalPrimaryLineFont, VerticalTabsDetailTarget,
VerticalTabsDetailTargetKind, VerticalTabsSummaryBranchEntry, VerticalTabsSummaryData,
vtab_diff_stats_text,
};
fn pane_id() -> PaneId {
+1 -1
View File
@@ -9,6 +9,7 @@ use crate::uri::browser_url_handler::parse_current_url;
use super::PanelPosition;
use crate::BlocklistAIHistoryModel;
use crate::ai::agent_conversations_model::AgentConversationsModel;
use crate::ai::conversation_details_panel::{
ConversationDetailsData, ConversationDetailsPanel, ConversationDetailsPanelEvent,
@@ -21,7 +22,6 @@ use crate::view_components::action_button::{
use crate::wasm_nux_dialog::{WasmNUXDialog, WasmNUXDialogEvent};
use crate::workspace::action::WorkspaceAction;
use crate::workspace::view::{NotebookSource, OpenWarpDriveObjectSettings, Workspace};
use crate::BlocklistAIHistoryModel;
const TRANSCRIPT_PANEL_WIDTH: f32 = 280.0;
+67 -42
View File
@@ -1,4 +1,5 @@
use super::*;
use crate::ai::AIRequestUsageModel;
use crate::ai::blocklist::{BlocklistAIHistoryModel, BlocklistAIPermissions};
use crate::ai::document::ai_document_model::AIDocumentModel;
use crate::ai::execution_profiles::profiles::AIExecutionProfilesModel;
@@ -8,7 +9,6 @@ use crate::ai::outline::RepoOutlines;
use crate::ai::persisted_workspace::PersistedWorkspace;
use crate::ai::restored_conversations::RestoredAgentConversations;
use crate::ai::skills::SkillManager;
use crate::ai::AIRequestUsageModel;
use crate::cloud_object::model::persistence::CloudModel;
use crate::cloud_object::model::view::CloudViewModel;
use crate::context_chips::prompt::Prompt;
@@ -22,12 +22,12 @@ use crate::pricing::PricingInfoModel;
use crate::suggestions::ignored_suggestions_model::IgnoredSuggestionsModel;
#[cfg(feature = "local_fs")]
use crate::user_config::tab_configs_dir;
use repo_metadata::repositories::DetectedRepositories;
use repo_metadata::watcher::DirectoryWatcher;
#[cfg(feature = "local_fs")]
use repo_metadata::CanonicalizedPath;
#[cfg(feature = "local_fs")]
use repo_metadata::RepoMetadataModel;
use repo_metadata::repositories::DetectedRepositories;
use repo_metadata::watcher::DirectoryWatcher;
use session_sharing_protocol::sharer::SessionSourceType;
use std::collections::HashMap;
#[cfg(feature = "local_fs")]
@@ -41,8 +41,8 @@ use crate::server::sync_queue::SyncQueue;
use crate::server::telemetry::context_provider::AppTelemetryContextProvider;
use crate::settings::PrivacySettings;
use crate::settings_view::keybindings::KeybindingChangedNotifier;
use crate::settings_view::DisplayCount;
use crate::settings_view::keybindings::KeybindingChangedNotifier;
use crate::system::SystemStats;
use crate::tab_configs::tab_config::{TabConfigPaneNode, TabConfigPaneType};
use crate::terminal::history::History;
@@ -61,8 +61,8 @@ use crate::ai::active_agent_views_model::ActiveAgentViewsModel;
use crate::ai::agent_conversations_model::AgentConversationsModel;
use crate::ai::ambient_agents::github_auth_notifier::GitHubAuthNotifier;
use crate::ai::mcp::{
gallery::MCPGalleryManager, templatable_manager::TemplatableMCPServerManager,
FileBasedMCPManager, FileMCPWatcher,
FileBasedMCPManager, FileMCPWatcher, gallery::MCPGalleryManager,
templatable_manager::TemplatableMCPServerManager,
};
use crate::resource_center::Tip;
use crate::terminal::cli_agent_sessions::CLIAgentSessionsModel;
@@ -70,15 +70,15 @@ use crate::test_util::settings::initialize_settings_for_tests;
use crate::undo_close::UndoCloseSettings;
use crate::warp_managed_paths_watcher::WarpManagedPathsWatcher;
use crate::workflows::local_workflows::LocalWorkflows;
use crate::{experiments, workspace, GlobalResourceHandlesProvider};
use crate::{AgentNotificationsModel, ObjectActions};
use crate::{GlobalResourceHandlesProvider, experiments, workspace};
use crate::settings::cloud_preferences_syncer::CloudPreferencesSyncer;
use ai::index::full_source_code_embedding::manager::CodebaseIndexManager;
use ai::project_context::model::ProjectContextModel;
use galaxy_editor::editor::NavigationKey;
use galaxyui::AddSingletonModel;
use galaxyui::{platform::WindowStyle, App, ViewHandle};
use galaxyui::{App, ViewHandle, platform::WindowStyle};
use pane_group::{NotebookPane, PaneState, SplitPaneState, TerminalPaneId};
use session_sharing_protocol::common::SessionId;
use terminal::shared_session::permissions_manager::SessionPermissionsManager;
@@ -879,9 +879,11 @@ fn test_workspace_sessions_retrieves_tabs() {
.map(|tab| tab.read(ctx, |tab, _ctx| tab.pane_id_by_index(0).unwrap()))
.expect("WindowId was not retrieved.");
assert!(workspace
.workspace_sessions(ctx.window_id(), ctx)
.any(|x| { x.pane_view_locator().pane_id == pane_id }));
assert!(
workspace
.workspace_sessions(ctx.window_id(), ctx)
.any(|x| { x.pane_view_locator().pane_id == pane_id })
);
// Add a tab and check if workspace_sessions finds the second session from the new tab.
workspace.add_terminal_tab(false, ctx);
@@ -890,9 +892,11 @@ fn test_workspace_sessions_retrieves_tabs() {
.map(|tab| tab.read(ctx, |tab, _ctx| tab.pane_id_by_index(0).unwrap()))
.expect("WindowId was not retrieved.");
assert!(workspace
.workspace_sessions(ctx.window_id(), ctx)
.any(|x| { x.pane_view_locator().pane_id == new_pane_id }));
assert!(
workspace
.workspace_sessions(ctx.window_id(), ctx)
.any(|x| { x.pane_view_locator().pane_id == new_pane_id })
);
});
});
}
@@ -917,9 +921,11 @@ fn test_workspace_sessions_retrieves_panes() {
.get_pane_group_view(0)
.map(|tab| tab.read(ctx, |tab, _ctx| tab.pane_id_by_index(1).unwrap()))
.expect("WindowId was not retrieved.");
assert!(workspace
.workspace_sessions(ctx.window_id(), ctx)
.any(|x| { x.pane_view_locator().pane_id == new_pane_id }));
assert!(
workspace
.workspace_sessions(ctx.window_id(), ctx)
.any(|x| { x.pane_view_locator().pane_id == new_pane_id })
);
});
});
}
@@ -1661,8 +1667,11 @@ fn test_tab_context_menu_share_session_items() {
// for sharing are "Stop sharing" and "Stop sharing all".
workspace.read(&app, |workspace, ctx| {
let items = workspace.tabs[1].menu_items(1, 3, ctx);
assert!(items[0]
.is_approximately_same_item_as(&MenuItemFields::new("Stop sharing").into_item()));
assert!(
items[0].is_approximately_same_item_as(
&MenuItemFields::new("Stop sharing").into_item()
)
);
assert!(items[1].is_approximately_same_item_as(
&MenuItemFields::new("Stop sharing all").into_item()
));
@@ -1682,8 +1691,11 @@ fn test_tab_context_menu_share_session_items() {
// for sharing are "Share session" and "Stop sharing all".
workspace.read(&app, |workspace, ctx| {
let items = workspace.tabs[1].menu_items(1, 3, ctx);
assert!(items[0]
.is_approximately_same_item_as(&MenuItemFields::new("Share session").into_item()));
assert!(
items[0].is_approximately_same_item_as(
&MenuItemFields::new("Share session").into_item()
)
);
assert!(items[1].is_approximately_same_item_as(
&MenuItemFields::new("Stop sharing all").into_item()
));
@@ -1698,8 +1710,11 @@ fn test_tab_context_menu_share_session_items() {
// When there's no shared sessions in a tab, the only option is "Share session".
workspace.read(&app, |workspace, ctx| {
let items = workspace.tabs[1].menu_items(1, 3, ctx);
assert!(items[0]
.is_approximately_same_item_as(&MenuItemFields::new("Share session").into_item()));
assert!(
items[0].is_approximately_same_item_as(
&MenuItemFields::new("Share session").into_item()
)
);
assert!(items[1].is_approximately_same_item_as(&MenuItem::Separator));
});
});
@@ -2676,11 +2691,13 @@ fn test_worktree_sidecar_search_editor_proxies_navigation_and_escape() {
assert!(workspace.show_new_session_dropdown_menu.is_none());
assert!(!workspace.show_new_session_sidecar);
assert!(workspace.worktree_sidecar_search_query.is_empty());
assert!(workspace
.worktree_sidecar_search_editor
.as_ref(ctx)
.buffer_text(ctx)
.is_empty());
assert!(
workspace
.worktree_sidecar_search_editor
.as_ref(ctx)
.buffer_text(ctx)
.is_empty()
);
});
});
}
@@ -2780,9 +2797,11 @@ fn test_vertical_tabs_context_menu_does_not_show_hover_only_tab_bar() {
workspace.update(&mut app, |workspace, ctx| {
TabSettings::handle(ctx).update(ctx, |settings, ctx| {
report_if_error!(settings
.workspace_decoration_visibility
.set_value(WorkspaceDecorationVisibility::OnHover, ctx));
report_if_error!(
settings
.workspace_decoration_visibility
.set_value(WorkspaceDecorationVisibility::OnHover, ctx)
);
report_if_error!(settings.use_vertical_tabs.set_value(true, ctx));
});
workspace.should_show_ai_assistant_warm_welcome = false;
@@ -2807,9 +2826,11 @@ fn test_standard_tab_context_menu_shows_hover_only_tab_bar() {
workspace.update(&mut app, |workspace, ctx| {
TabSettings::handle(ctx).update(ctx, |settings, ctx| {
report_if_error!(settings
.workspace_decoration_visibility
.set_value(WorkspaceDecorationVisibility::OnHover, ctx));
report_if_error!(
settings
.workspace_decoration_visibility
.set_value(WorkspaceDecorationVisibility::OnHover, ctx)
);
});
workspace.should_show_ai_assistant_warm_welcome = false;
@@ -2843,10 +2864,12 @@ fn test_open_cloud_agent_setup_guide_action_opens_management_view_and_is_idempot
.current_workspace_state
.is_agent_management_view_open
);
assert!(workspace
.agent_management_view
.as_ref(ctx)
.is_showing_setup_guide());
assert!(
workspace
.agent_management_view
.as_ref(ctx)
.is_showing_setup_guide()
);
workspace.handle_action(&WorkspaceAction::OpenCloudAgentSetupGuide, ctx);
assert!(
@@ -2854,10 +2877,12 @@ fn test_open_cloud_agent_setup_guide_action_opens_management_view_and_is_idempot
.current_workspace_state
.is_agent_management_view_open
);
assert!(workspace
.agent_management_view
.as_ref(ctx)
.is_showing_setup_guide());
assert!(
workspace
.agent_management_view
.as_ref(ctx)
.is_showing_setup_guide()
);
});
});
}
@@ -0,0 +1 @@
Overwrite content
+123
View File
@@ -0,0 +1,123 @@
#!/usr/bin/env bash
#
# install-galaxy.sh — Clone, build, and install Galaxy.app on macOS.
#
# Usage:
# curl -fsSL https://mng-web-sharing.mini-games.tv/wst-data/ryan-share/galaxy/install-galaxy.sh | bash
# — or —
# ./script/install-galaxy.sh
#
set -euo pipefail
REPO_URL="git@gitlab.com:samnasbo/shared/galaxy.git"
CLONE_DIR="$HOME/.galaxy/source"
APP_NAME="Galaxy.app"
INSTALL_DIR="/Applications"
BUNDLE_BIN="galaxy-oss"
BUNDLE_PKG="galaxy"
# ---------- helpers ----------
info() { printf "\033[1;34m==>\033[0m %s\n" "$1"; }
warn() { printf "\033[1;33m==> WARNING:\033[0m %s\n" "$1"; }
fail() { printf "\033[1;31m==> ERROR:\033[0m %s\n" "$1"; exit 1; }
# ---------- 1. Xcode / CLI tools ----------
info "Checking Xcode and Command Line Tools..."
if ! xcode-select -p &>/dev/null; then
fail "Xcode Command Line Tools are not installed. Run: xcode-select --install"
fi
if ! xcrun --show-sdk-path &>/dev/null; then
fail "Xcode SDK not found. Ensure Xcode or Command Line Tools are properly installed."
fi
if ! xcrun -f metal &>/dev/null; then
warn "Metal compiler not found. Attempting to download Metal toolchain..."
xcodebuild -downloadComponent MetalToolchain || warn "Could not download Metal toolchain — build may fail."
fi
info "Xcode prerequisites look good."
# ---------- 2. Homebrew ----------
if ! command -v brew &>/dev/null; then
info "Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Add brew to PATH for Apple Silicon
if [[ -f /opt/homebrew/bin/brew ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
fi
fi
if ! command -v pkgconf &>/dev/null && ! command -v pkg-config &>/dev/null; then
info "Installing pkgconf via Homebrew..."
brew install pkgconf
fi
# ---------- 3. Rust toolchain ----------
if ! command -v rustup &>/dev/null; then
info "Installing Rust via rustup..."
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source "$HOME/.cargo/env"
fi
info "Syncing Rust toolchain (rust-toolchain.toml will pin the exact version)..."
rustup show active-toolchain &>/dev/null || rustup default stable
# aarch64-apple-darwin target for Apple Silicon
rustup target add aarch64-apple-darwin 2>/dev/null || true
# cargo-bundle for producing the .app
if ! cargo bundle --help &>/dev/null 2>&1; then
info "Installing cargo-bundle..."
cargo install cargo-bundle \
--git=https://github.com/burtonageo/cargo-bundle \
--rev ae4c76e92c08774bf54ff077b1c52e3d1cd6c16d
fi
# ---------- 4. Clone the repo ----------
if [[ -d "$CLONE_DIR/.git" ]]; then
info "Repository already exists at $CLONE_DIR — pulling latest..."
git -C "$CLONE_DIR" pull --ff-only || warn "Pull failed; building with current checkout."
else
info "Cloning Galaxy into $CLONE_DIR..."
mkdir -p "$(dirname "$CLONE_DIR")"
git clone "$REPO_URL" "$CLONE_DIR"
fi
# ---------- 5. Build ----------
info "Building $BUNDLE_BIN (release)..."
cargo build --release --bin "$BUNDLE_BIN" --package "$BUNDLE_PKG" \
--manifest-path "$CLONE_DIR/Cargo.toml"
info "Bundling $APP_NAME..."
# cargo-bundle does not support --manifest-path; run from repo root
pushd "$CLONE_DIR" > /dev/null
cargo bundle --release --bin "$BUNDLE_BIN" --package "$BUNDLE_PKG"
popd > /dev/null
BUILT_APP="$CLONE_DIR/target/release/bundle/osx/$APP_NAME"
if [[ ! -d "$BUILT_APP" ]]; then
fail "Bundle not found at $BUILT_APP — build may have failed."
fi
# ---------- 6. Kill, remove, install, launch ----------
info "Stopping any running Galaxy processes..."
pkill -x "Galaxy" 2>/dev/null && sleep 1 || true
pkill -9 -x "Galaxy" 2>/dev/null || true
INSTALLED_APP="$INSTALL_DIR/$APP_NAME"
if [[ -d "$INSTALLED_APP" ]]; then
info "Removing existing $INSTALLED_APP..."
rm -rf "$INSTALLED_APP"
fi
info "Copying $APP_NAME to $INSTALL_DIR..."
cp -R "$BUILT_APP" "$INSTALL_DIR/"
info "Launching Galaxy..."
open "$INSTALLED_APP"
info "Done! Galaxy is running."