Port recent Warp terminal and UI improvements

Improve tab-group search, rename focus, history navigation, shell prompt and
completion handling, emoji width promotion, and macOS clipboard support.
Guard unavailable settings/model-selector/undo-close views and forward the
MCP OAuth callback issuer through the existing authentication flow.

Adapt local changes from 14 upstream Warp commits through f571865ca3f2,
reviewed from the latest 200 commits. Preserve Galaxy provider lifecycle,
permissions, storage, and branding; exclude hosted/cloud infrastructure.

Fix existing boolean-assertion lints and use stronger optimization with four
code-generation units for the app test target to fit macOS unwind offsets.
Production and dependency compilation settings remain unchanged.

Validation: two clean builds and a final build; both prescribed Clippy
commands with -D warnings; formatting, shell syntax and completion cleanup;
167 focused regression tests. Galaxy was not launched.
This commit is contained in:
2026-10-06 14:48:09 -05:00
parent d6da089862
commit 75d4965385
23 changed files with 1142 additions and 188 deletions
@@ -40,7 +40,10 @@ fn accepts_a_single_fenced_decision_but_not_empty_output() {
let response = format!("{prefix}\n{{\"risk\":1,\"reason\":\"Scoped local edit\"}}\n```");
assert_eq!(Assessment::parse(&response).unwrap().risk, 1);
}
assert!(Assessment::parse(" \n").unwrap_err().to_string().contains("no decision text"));
assert!(Assessment::parse(" \n")
.unwrap_err()
.to_string()
.contains("no decision text"));
}
fn with_pending_review(
@@ -406,34 +409,61 @@ fn request_history_does_not_drop_intermediate_revocations() {
fn allow_all_skips_model_review_for_unrestricted_actions() {
with_pending_review(|model, conversation, action, ctx| {
set_fixture_mode(model, PermissionMode::AllowAll, ctx);
assert_eq!(model.review_pending_action(&action, conversation, false, ctx), Some(true));
assert_eq!(
model.review_pending_action(&action, conversation, false, ctx),
Some(true)
);
assert!(model.action_reviews.is_empty());
});
}
#[test]
fn explicit_command_approval_applies_in_every_mode_and_denylist_wins() {
for mode in [PermissionMode::ReadOnly, PermissionMode::AskFirst, PermissionMode::GalaxyDecides, PermissionMode::AllowAll] {
for mode in [
PermissionMode::ReadOnly,
PermissionMode::AskFirst,
PermissionMode::GalaxyDecides,
PermissionMode::AllowAll,
] {
with_pending_review(move |model, conversation, mut action, ctx| {
set_fixture_mode(model, mode, ctx);
action.action = AIAgentActionType::RequestCommandOutput {
command: "cargo test".to_string(), is_read_only: None, is_risky: None,
rationale: None, uses_pager: None, wait_until_completion: true, citations: vec![],
command: "cargo test".to_string(),
is_read_only: None,
is_risky: None,
rationale: None,
uses_pager: None,
wait_until_completion: true,
citations: vec![],
};
model.pending_actions.insert(conversation, VecDeque::from([action.clone()]));
model
.pending_actions
.insert(conversation, VecDeque::from([action.clone()]));
model.action_reviews.clear();
let predicate = crate::settings::AgentModeCommandExecutionPredicate::new_regex("^cargo test$").unwrap();
let predicate =
crate::settings::AgentModeCommandExecutionPredicate::new_regex("^cargo test$")
.unwrap();
AIExecutionProfilesModel::handle(ctx).update(ctx, |profiles, ctx| {
let id = *profiles.active_profile(Some(model.terminal_view_id), ctx).id();
let id = *profiles
.active_profile(Some(model.terminal_view_id), ctx)
.id();
profiles.add_to_command_allowlist(id, &predicate, ctx);
});
assert_eq!(model.review_pending_action(&action, conversation, false, ctx), Some(true));
assert_eq!(
model.review_pending_action(&action, conversation, false, ctx),
Some(true)
);
AIExecutionProfilesModel::handle(ctx).update(ctx, |profiles, ctx| {
let id = *profiles.active_profile(Some(model.terminal_view_id), ctx).id();
let id = *profiles
.active_profile(Some(model.terminal_view_id), ctx)
.id();
profiles.add_to_command_denylist(id, &predicate, ctx);
});
assert_eq!(model.is_explicitly_allowlisted_command(&action, ctx), false);
assert_ne!(model.review_pending_action(&action, conversation, false, ctx), Some(true));
assert!(!model.is_explicitly_allowlisted_command(&action, ctx));
assert_ne!(
model.review_pending_action(&action, conversation, false, ctx),
Some(true)
);
});
}
}
@@ -150,6 +150,7 @@ impl TemplatableMCPServerManager {
// Pass the state value through as the CSRF token; rmcp will validate it
// against the token it stored when generating the authorization URL.
csrf_token: state.to_string(),
issuer: query_params.get("iss").map(|issuer| issuer.to_string()),
},
None => CallbackResult::Error {
error: error.map(|e| e.to_string()),
@@ -1887,3 +1888,7 @@ impl TemplatableMCPServerManager {
.contains_key(&installation_hash)
}
}
#[cfg(test)]
#[path = "native_tests.rs"]
mod tests;
@@ -0,0 +1,37 @@
use futures_util::stream::AbortHandle;
use super::*;
#[test]
fn oauth_callback_preserves_decoded_issuer() {
let mut manager = TemplatableMCPServerManager::default();
let installation_uuid = Uuid::new_v4();
let (abort_handle, _) = AbortHandle::new_pair();
let (oauth_result_tx, oauth_result_rx) = async_channel::unbounded();
manager.spawned_servers.insert(
installation_uuid,
SpawnedServerInfo {
abort_handle,
oauth_result_tx,
},
);
manager
.pending_oauth_csrf
.insert("test-state".to_string(), installation_uuid);
let callback_url = Url::parse(
"galaxydev://mcp/oauth2callback?code=test-code&state=test-state&iss=https%3A%2F%2Fmcp.linear.app",
).unwrap();
manager.handle_oauth_callback(&callback_url).unwrap();
match oauth_result_rx.try_recv().unwrap() {
CallbackResult::Success {
code,
csrf_token,
issuer,
} => {
assert_eq!(code, "test-code");
assert_eq!(csrf_token, "test-state");
assert_eq!(issuer.as_deref(), Some("https://mcp.linear.app"));
}
CallbackResult::Error { error } => panic!("unexpected callback error: {error:?}"),
}
}