Compare commits

...

2 Commits

Author SHA1 Message Date
Harish Manikantan
8c2acc376a Merge remote-tracking branch 'origin/main' into harish/selection-quote-replies-feature 2026-03-26 09:14:23 -04:00
Harish Manikantan
f07159def2 Add selection quote replies experimental feature 2026-03-26 08:39:45 -04:00
5 changed files with 51 additions and 1 deletions

View File

@@ -43,6 +43,7 @@ use tracing::warn;
const SUPPORTED_EXPERIMENTAL_FEATURE_ENABLEMENT: &[&str] = &[
"apps",
"plugins",
"selection_quote_replies",
"tool_search",
"tool_suggest",
"tool_call_mcp_elicitation",

View File

@@ -165,6 +165,7 @@ async fn experimental_feature_enablement_set_only_updates_named_features() -> Re
&mut mcp,
BTreeMap::from([
("plugins".to_string(), true),
("selection_quote_replies".to_string(), true),
("tool_search".to_string(), true),
("tool_suggest".to_string(), true),
("tool_call_mcp_elicitation".to_string(), false),
@@ -177,6 +178,7 @@ async fn experimental_feature_enablement_set_only_updates_named_features() -> Re
ExperimentalFeatureEnablementSetResponse {
enablement: BTreeMap::from([
("plugins".to_string(), true),
("selection_quote_replies".to_string(), true),
("tool_search".to_string(), true),
("tool_suggest".to_string(), true),
("tool_call_mcp_elicitation".to_string(), false),
@@ -200,6 +202,13 @@ async fn experimental_feature_enablement_set_only_updates_named_features() -> Re
.and_then(|features| features.get("plugins")),
Some(&json!(true))
);
assert_eq!(
config
.additional
.get("features")
.and_then(|features| features.get("selection_quote_replies")),
Some(&json!(true))
);
assert_eq!(
config
.additional
@@ -283,7 +292,9 @@ async fn experimental_feature_enablement_set_rejects_non_allowlisted_feature() -
assert!(
error
.message
.contains("apps, plugins, tool_search, tool_suggest, tool_call_mcp_elicitation"),
.contains(
"apps, plugins, selection_quote_replies, tool_search, tool_suggest, tool_call_mcp_elicitation"
),
"{}",
error.message
);

View File

@@ -458,6 +458,9 @@
"search_tool": {
"type": "boolean"
},
"selection_quote_replies": {
"type": "boolean"
},
"shell_snapshot": {
"type": "boolean"
},
@@ -2097,6 +2100,9 @@
"search_tool": {
"type": "boolean"
},
"selection_quote_replies": {
"type": "boolean"
},
"shell_snapshot": {
"type": "boolean"
},

View File

@@ -176,6 +176,8 @@ pub enum Feature {
VoiceTranscription,
/// Enable experimental realtime voice conversation mode in the TUI.
RealtimeConversation,
/// Enable selection-based quote replies in app-server clients.
SelectionQuoteReplies,
/// Route interactive startup to the app-server-backed TUI implementation.
TuiAppServer,
/// Prevent idle system sleep while a turn is actively running.
@@ -819,6 +821,16 @@ pub const FEATURES: &[FeatureSpec] = &[
stage: Stage::UnderDevelopment,
default_enabled: false,
},
FeatureSpec {
id: Feature::SelectionQuoteReplies,
key: "selection_quote_replies",
stage: Stage::Experimental {
name: "Selection quote replies",
menu_description: "Show a quote-reply action when you select text in a conversation and insert the selection into the composer as a quoted reply.",
announcement: "",
},
default_enabled: false,
},
FeatureSpec {
id: Feature::TuiAppServer,
key: "tui_app_server",

View File

@@ -150,6 +150,26 @@ fn tool_call_mcp_elicitation_is_stable_and_enabled_by_default() {
assert_eq!(Feature::ToolCallMcpElicitation.default_enabled(), true);
}
#[test]
fn selection_quote_replies_is_experimental_and_user_toggleable() {
let spec = Feature::SelectionQuoteReplies.info();
let stage = spec.stage;
assert!(matches!(stage, Stage::Experimental { .. }));
assert_eq!(
stage.experimental_menu_name(),
Some("Selection quote replies")
);
assert_eq!(
stage.experimental_menu_description(),
Some(
"Show a quote-reply action when you select text in a conversation and insert the selection into the composer as a quoted reply."
)
);
assert_eq!(stage.experimental_announcement(), None);
assert_eq!(Feature::SelectionQuoteReplies.default_enabled(), false);
}
#[test]
fn image_detail_original_feature_is_under_development() {
assert_eq!(