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:
@@ -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:?}"),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user