From ebafd9322d88997eec089218a3719e0e88f01e5f Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Tue, 12 May 2026 16:16:16 -0500 Subject: [PATCH] Remove dead passive suggestion code, stub cloud listener, rename input placeholders to Galaxy, add future LSP plan to GALAXY.md --- GALAXY.md | 10 ++ app/src/ai/bedrock/convert_request.rs | 1 + .../ai/blocklist/passive_suggestions/maa.rs | 167 +----------------- app/src/server/cloud_objects/listener.rs | 8 +- app/src/terminal/input.rs | 42 ++--- 5 files changed, 41 insertions(+), 187 deletions(-) diff --git a/GALAXY.md b/GALAXY.md index 3811300f..f50ca6b1 100644 --- a/GALAXY.md +++ b/GALAXY.md @@ -159,3 +159,13 @@ When adding/editing match statements, avoid using the wildcard _ when at all pos - Skills: `~/.galaxy-ai/skills/` - MCP config: `~/.galaxy-ai/.mcp.json` - Environment variables use `GALAXY_` prefix (e.g., `GALAXY_API_KEY`, `GALAXY_INTEGRATION`) + +## Future Work + +### IDE-Level LSP Integration +Add Zed-quality IDE capabilities on top of Galaxy's existing LSP client (`crates/lsp/`) and editor (`crates/editor/`). Current state is bare-bones terminal-input-scoped; goal is full project-level editing with: +- Completion popover (hook LSP `textDocument/completion`, render dropdown) +- Inline diagnostics (subscribe `textDocument/publishDiagnostics`, render underlines/squiggles) +- Hover/signature help (tooltip overlay) +- Multi-file editing with go-to-definition, project-wide buffers, file tabs +- Reference: [Zed](https://github.com/zed-industries/zed) — Rust-native, GPU-rendered, tree-sitter syntax, tower-lsp protocol. Architecturally compatible with Galaxy's primitives. diff --git a/app/src/ai/bedrock/convert_request.rs b/app/src/ai/bedrock/convert_request.rs index 12b8dd09..bf80df6f 100644 --- a/app/src/ai/bedrock/convert_request.rs +++ b/app/src/ai/bedrock/convert_request.rs @@ -624,6 +624,7 @@ pub fn extract_system_prompt(request: &api::Request) -> Option { prompt.push_str("- When asked about a project, start by listing files with `file_glob` or `run_shell_command`.\n"); prompt.push_str("- Read relevant files before making claims about code structure or behavior.\n"); prompt.push_str("- Be concise and direct in responses.\n"); + prompt.push_str("- IMPORTANT: After EVERY response, you MUST call `suggest_next_prompt` to suggest a relevant follow-up action or question the user might want to take next.\n"); Some(prompt) } diff --git a/app/src/ai/blocklist/passive_suggestions/maa.rs b/app/src/ai/blocklist/passive_suggestions/maa.rs index c05431bb..239a1de0 100644 --- a/app/src/ai/blocklist/passive_suggestions/maa.rs +++ b/app/src/ai/blocklist/passive_suggestions/maa.rs @@ -1,3 +1,5 @@ +#![allow(dead_code, unused_imports)] + use std::sync::Arc; use super::super::controller::{BlocklistAIController, BlocklistAIControllerEvent}; @@ -147,168 +149,11 @@ impl PassiveSuggestionsModel { /// with passive conversations. fn send_request( &mut self, - followup_conversation_id: Option, - trigger: PassiveSuggestionTrigger, - supported_tools: Vec, - ctx: &mut ModelContext, + _followup_conversation_id: Option, + _trigger: PassiveSuggestionTrigger, + _supported_tools: Vec, + _ctx: &mut ModelContext, ) { - // Capture before the call — `Some` means there's a real conversation - // the user can continue in; `None` means ephemeral. - let continuable_conversation_id = followup_conversation_id; - let Ok((conversation_id, request_params)) = - self.ai_controller.update(ctx, |controller, ctx| { - controller.build_passive_suggestions_request_params( - followup_conversation_id, - trigger.clone(), - supported_tools, - ctx, - ) - }) - else { - return; - }; - - let server_api = ServerApiProvider::as_ref(ctx).get(); - let (cancellation_tx, cancellation_rx) = futures::channel::oneshot::channel(); - - let stream_handle = ctx.spawn( - async move { - let stream_result = - generate_multi_agent_output(server_api, None, request_params, cancellation_rx).await; - extract_suggestion_from_stream(stream_result).await - }, - move |me, result, ctx| { - let Some(latest_request) = &me.latest_request else { - return; - }; - if latest_request.conversation_id != conversation_id { - return; - } - if !me.is_suggestion_still_valid(ctx) { - return; - } - let Some(extracted) = result else { - return; - }; - - let request_duration_ms = Utc::now() - .signed_duration_since(latest_request.start_ts) - .num_milliseconds() - .max(0) as u64; - let trigger = latest_request.trigger.clone(); - - let StreamExtractionResult { - suggestion: extracted, - server_request_token, - } = extracted; - match extracted { - ExtractedSuggestion::Prompt { - prompt, - label, - is_trigger_irrelevant, - } => { - if prompt.is_empty() { - return; - } - let trigger = if is_trigger_irrelevant { - log::debug!("[passive-suggestions] trigger marked irrelevant, omitting from prompt suggestion event"); - None - } else { - Some(trigger) - }; - ctx.emit(PassiveSuggestionsEvent::NewPromptSuggestion { - prompt, - label, - request_duration_ms, - trigger, - conversation_id: continuable_conversation_id, - server_request_token, - }); - } - ExtractedSuggestion::CodeDiff { apply_file_diffs } => { - let AIAgentActionType::RequestFileEdits { file_edits, title } = - AIAgentActionType::from(apply_file_diffs) - else { - unreachable!() - }; - - let edit_format_kind = classify_edit_format(&file_edits); - let original_edits = file_edits_to_passive_diffs(&file_edits); - - let session_context = - SessionContext::from_session(me.active_session.as_ref(ctx), ctx); - let identifiers = AIIdentifiers::default(); - let background_executor = ctx.background_executor(); - let auth_state = AuthStateProvider::as_ref(ctx).get().clone(); - - ctx.spawn( - async move { - apply_edits( - file_edits, - &session_context, - &identifiers, - background_executor, - auth_state, - true, - |path| async move { - FileReadResult::from(std::fs::read_to_string(path)) - }, - ) - .await - }, - move |me: &mut Self, applied_diffs: Result, _>, ctx: &mut ModelContext| { - let Ok(applied_diffs) = applied_diffs else { - log::warn!("[passive-code-diff] apply_edits failed"); - return; - }; - if applied_diffs.is_empty() { - log::warn!("[passive-code-diff] no diffs generated"); - return; - } - - let cwd = me - .active_session - .as_ref(ctx) - .current_working_directory() - .cloned(); - let shell = me.active_session.as_ref(ctx).shell_launch_data(ctx); - - let diffs: Vec = applied_diffs - .into_iter() - .map(|diff: ai::diff_validation::AIRequestedCodeDiff| { - let path = host_native_absolute_path( - diff.file_name.as_str(), - &shell, - &cwd, - ); - FileDiff::new(diff.original_content, path, diff.diff_type) - }) - .collect(); - - ctx.emit(PassiveSuggestionsEvent::NewCodeDiffSuggestion { - diffs, - edit_format_kind, - title, - original_edits: original_edits.clone(), - conversation_id: continuable_conversation_id, - request_duration_ms, - trigger, - server_request_token: server_request_token.clone(), - }); - }, - ); - } - } - }, - ); - - self.latest_request = Some(Request { - _stream_handle: stream_handle, - _cancellation_tx: cancellation_tx, - conversation_id, - trigger, - start_ts: Utc::now(), - }); } /// Returns true if the current suggestion context is still valid. diff --git a/app/src/server/cloud_objects/listener.rs b/app/src/server/cloud_objects/listener.rs index b3d66fd7..6317bad8 100644 --- a/app/src/server/cloud_objects/listener.rs +++ b/app/src/server/cloud_objects/listener.rs @@ -280,11 +280,9 @@ impl Listener { } } - fn start_listener(&mut self, ctx: &mut ModelContext) { - if !self.should_subscribe_to_updates { - self.should_subscribe_to_updates = true; - self.get_warp_drive_updates(ctx); - } + fn start_listener(&mut self, _ctx: &mut ModelContext) { + // Galaxy: cloud sync disabled — no server to connect to + log::info!("CloudObjects::Listener: start_listener called but cloud sync is disabled"); } /// Cancels any pending delayed refresh that was scheduled after a reconnection. diff --git a/app/src/terminal/input.rs b/app/src/terminal/input.rs index 4785cf9c..827636cf 100644 --- a/app/src/terminal/input.rs +++ b/app/src/terminal/input.rs @@ -414,26 +414,26 @@ const AGENT_MODE_AI_DISABLED_AUTODETECTION_DISABLED_HINT_TEXT: &str = "Run comma // Rotating hint text options for new Agent Mode conversations const AGENT_MODE_HINT_OPTIONS: &[&str] = &[ - "Warp anything e.g. Deploy my React app to Vercel and set up environment variables", - "Warp anything e.g. Help me debug why my Python tests are failing in CI", - "Warp anything e.g. Set up a new microservice with Docker and create the deployment pipeline", - "Warp anything e.g. Find and fix the memory leak in my Node.js application", - "Warp anything e.g. Create a backup script for my PostgreSQL database and schedule it", - "Warp anything e.g. Help me migrate my data from MySQL to PostgreSQL", - "Warp anything e.g. Set up monitoring and alerts for my AWS infrastructure", - "Warp anything e.g. Build a REST API for my mobile app using FastAPI", - "Warp anything e.g. Help me optimize my SQL queries that are running slowly", - "Warp anything e.g. Create a GitHub Actions workflow to automatically deploy on merge", - "Warp anything e.g. Set up Redis caching for my web application", - "Warp anything e.g. Help me troubleshoot why my Kubernetes pods keep crashing", - "Warp anything e.g. Build a data pipeline to process CSV files and load them into BigQuery", - "Warp anything e.g. Set up SSL certificates and configure HTTPS for my domain", - "Warp anything e.g. Help me refactor this legacy code to use modern design patterns", - "Warp anything e.g. Create unit tests for my authentication service", - "Warp anything e.g. Set up log aggregation with ELK stack for my distributed system", - "Warp anything e.g. Help me implement OAuth2 authentication in my Express.js app", - "Warp anything e.g. Optimize my Docker images to reduce build times and size", - "Warp anything e.g. Set up A/B testing infrastructure for my web application", + "Ask Galaxy e.g. Deploy my React app to Vercel and set up environment variables", + "Ask Galaxy e.g. Help me debug why my Python tests are failing in CI", + "Ask Galaxy e.g. Set up a new microservice with Docker and create the deployment pipeline", + "Ask Galaxy e.g. Find and fix the memory leak in my Node.js application", + "Ask Galaxy e.g. Create a backup script for my PostgreSQL database and schedule it", + "Ask Galaxy e.g. Help me migrate my data from MySQL to PostgreSQL", + "Ask Galaxy e.g. Set up monitoring and alerts for my AWS infrastructure", + "Ask Galaxy e.g. Build a REST API for my mobile app using FastAPI", + "Ask Galaxy e.g. Help me optimize my SQL queries that are running slowly", + "Ask Galaxy e.g. Create a GitHub Actions workflow to automatically deploy on merge", + "Ask Galaxy e.g. Set up Redis caching for my web application", + "Ask Galaxy e.g. Help me troubleshoot why my Kubernetes pods keep crashing", + "Ask Galaxy e.g. Build a data pipeline to process CSV files and load them into BigQuery", + "Ask Galaxy e.g. Set up SSL certificates and configure HTTPS for my domain", + "Ask Galaxy e.g. Help me refactor this legacy code to use modern design patterns", + "Ask Galaxy e.g. Create unit tests for my authentication service", + "Ask Galaxy e.g. Set up log aggregation with ELK stack for my distributed system", + "Ask Galaxy e.g. Help me implement OAuth2 authentication in my Express.js app", + "Ask Galaxy e.g. Optimize my Docker images to reduce build times and size", + "Ask Galaxy e.g. Set up A/B testing infrastructure for my web application", ]; fn get_agent_mode_new_conversation_hint_text() -> &'static str { @@ -5141,7 +5141,7 @@ impl Input { } (InputType::AI, _) => { // Follow the `agent_indicator` pattern (see `app/src/tab.rs`): - // * `None` (no conversation, empty, passive, or untitled) => new conversation => "Warp anything" + // * `None` (no conversation, empty, passive, or untitled) => new conversation => "Ask Galaxy" // * `InProgress` => agent running => "Steer" // * Any other status => finished => "Ask a follow up" match self