Skip to content

Commit 9e4cc82

Browse files
feat: add /experiment slash command for toggling experimental features (#2711)
* feat: add /experiment slash command for toggling experimental features - Add new /experiment command - Toggle selection interface with colored On/Off status indicators - Include experiment descriptions and disclaimer about experimental features - Include documentation so its available in instrospect tool * Visual apperance fix * Format fix --------- Co-authored-by: Kenneth S. <[email protected]>
1 parent 1432845 commit 9e4cc82

File tree

6 files changed

+241
-3
lines changed

6 files changed

+241
-3
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
// ABOUTME: Implements the /experiment slash command for toggling experimental features
2+
// ABOUTME: Provides interactive selection interface similar to /model command
3+
4+
use clap::Args;
5+
use crossterm::style::{
6+
self,
7+
Color,
8+
};
9+
use crossterm::{
10+
execute,
11+
queue,
12+
};
13+
use dialoguer::Select;
14+
15+
use crate::cli::chat::{
16+
ChatError,
17+
ChatSession,
18+
ChatState,
19+
};
20+
use crate::database::settings::Setting;
21+
use crate::os::Os;
22+
23+
/// Represents an experimental feature that can be toggled
24+
#[derive(Debug, Clone)]
25+
struct Experiment {
26+
name: &'static str,
27+
description: &'static str,
28+
setting_key: Setting,
29+
}
30+
31+
static AVAILABLE_EXPERIMENTS: &[Experiment] = &[
32+
Experiment {
33+
name: "Knowledge",
34+
description: "Enables persistent context storage and retrieval across chat sessions (/knowledge)",
35+
setting_key: Setting::EnabledKnowledge,
36+
},
37+
Experiment {
38+
name: "Thinking",
39+
description: "Enables complex reasoning with step-by-step thought processes",
40+
setting_key: Setting::EnabledThinking,
41+
},
42+
];
43+
44+
#[derive(Debug, PartialEq, Args)]
45+
pub struct ExperimentArgs;
46+
impl ExperimentArgs {
47+
pub async fn execute(self, os: &mut Os, session: &mut ChatSession) -> Result<ChatState, ChatError> {
48+
Ok(select_experiment(os, session).await?.unwrap_or(ChatState::PromptUser {
49+
skip_printing_tools: false,
50+
}))
51+
}
52+
}
53+
54+
async fn select_experiment(os: &mut Os, session: &mut ChatSession) -> Result<Option<ChatState>, ChatError> {
55+
// Get current experiment status
56+
let mut experiment_labels = Vec::new();
57+
let mut current_states = Vec::new();
58+
59+
for experiment in AVAILABLE_EXPERIMENTS {
60+
let is_enabled = os.database.settings.get_bool(experiment.setting_key).unwrap_or(false);
61+
62+
current_states.push(is_enabled);
63+
// Create clean single-line format: "Knowledge [ON] - Description"
64+
let status_indicator = if is_enabled {
65+
style::Stylize::green("[ON] ")
66+
} else {
67+
style::Stylize::grey("[OFF]")
68+
};
69+
let label = format!(
70+
"{:<18} {} - {}",
71+
experiment.name,
72+
status_indicator,
73+
style::Stylize::dark_grey(experiment.description)
74+
);
75+
experiment_labels.push(label);
76+
}
77+
78+
experiment_labels.push(String::new());
79+
experiment_labels.push(format!(
80+
"{}",
81+
style::Stylize::white("⚠ Experimental features may be changed or removed at any time")
82+
));
83+
84+
let selection: Option<_> = match Select::with_theme(&crate::util::dialoguer_theme())
85+
.with_prompt("Select an experiment to toggle")
86+
.items(&experiment_labels)
87+
.default(0)
88+
.interact_on_opt(&dialoguer::console::Term::stdout())
89+
{
90+
Ok(sel) => {
91+
let _ = crossterm::execute!(
92+
std::io::stdout(),
93+
crossterm::style::SetForegroundColor(crossterm::style::Color::Magenta)
94+
);
95+
sel
96+
},
97+
// Ctrl‑C -> Err(Interrupted)
98+
Err(dialoguer::Error::IO(ref e)) if e.kind() == std::io::ErrorKind::Interrupted => return Ok(None),
99+
Err(e) => return Err(ChatError::Custom(format!("Failed to choose experiment: {e}").into())),
100+
};
101+
102+
queue!(session.stderr, style::ResetColor)?;
103+
104+
if let Some(index) = selection {
105+
// Clear the dialoguer selection line to avoid showing old status
106+
queue!(
107+
session.stderr,
108+
crossterm::cursor::MoveUp(1),
109+
crossterm::terminal::Clear(crossterm::terminal::ClearType::CurrentLine),
110+
)?;
111+
112+
// Skip if user selected disclaimer or empty line
113+
if index >= AVAILABLE_EXPERIMENTS.len() {
114+
return Ok(Some(ChatState::PromptUser {
115+
skip_printing_tools: false,
116+
}));
117+
}
118+
119+
let experiment = &AVAILABLE_EXPERIMENTS[index];
120+
let current_state = current_states[index];
121+
let new_state = !current_state;
122+
123+
// Update the setting
124+
os.database
125+
.settings
126+
.set(experiment.setting_key, new_state)
127+
.await
128+
.map_err(|e| ChatError::Custom(format!("Failed to update experiment setting: {e}").into()))?;
129+
130+
// Reload tools to reflect the experiment change
131+
let _ = session
132+
.conversation
133+
.tool_manager
134+
.load_tools(os, &mut session.stderr)
135+
.await;
136+
137+
let status_text = if new_state { "enabled" } else { "disabled" };
138+
139+
queue!(
140+
session.stderr,
141+
style::Print("\n"),
142+
style::SetForegroundColor(Color::Green),
143+
style::Print(format!(" {} experiment {}\n\n", experiment.name, status_text)),
144+
style::ResetColor,
145+
style::SetForegroundColor(Color::Reset),
146+
style::SetBackgroundColor(Color::Reset),
147+
)?;
148+
}
149+
150+
execute!(session.stderr, style::ResetColor)?;
151+
152+
Ok(Some(ChatState::PromptUser {
153+
skip_printing_tools: false,
154+
}))
155+
}

crates/chat-cli/src/cli/chat/cli/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ pub mod clear;
22
pub mod compact;
33
pub mod context;
44
pub mod editor;
5+
pub mod experiment;
56
pub mod hooks;
67
pub mod knowledge;
78
pub mod mcp;
@@ -20,6 +21,7 @@ use clear::ClearArgs;
2021
use compact::CompactArgs;
2122
use context::ContextSubcommand;
2223
use editor::EditorArgs;
24+
use experiment::ExperimentArgs;
2325
use hooks::HooksArgs;
2426
use knowledge::KnowledgeSubcommand;
2527
use mcp::McpArgs;
@@ -83,6 +85,8 @@ pub enum SlashCommand {
8385
Mcp(McpArgs),
8486
/// Select a model for the current conversation session
8587
Model(ModelArgs),
88+
/// Toggle experimental features
89+
Experiment(ExperimentArgs),
8690
/// Upgrade to a Q Developer Pro subscription for increased query limits
8791
Subscribe(SubscribeArgs),
8892
/// Toggle tangent mode for isolated conversations
@@ -144,6 +148,7 @@ impl SlashCommand {
144148
Self::Usage(args) => args.execute(os, session).await,
145149
Self::Mcp(args) => args.execute(session).await,
146150
Self::Model(args) => args.execute(os, session).await,
151+
Self::Experiment(args) => args.execute(os, session).await,
147152
Self::Subscribe(args) => args.execute(os, session).await,
148153
Self::Tangent(args) => args.execute(os, session).await,
149154
Self::Persist(subcommand) => subcommand.execute(os, session).await,
@@ -177,6 +182,7 @@ impl SlashCommand {
177182
Self::Usage(_) => "usage",
178183
Self::Mcp(_) => "mcp",
179184
Self::Model(_) => "model",
185+
Self::Experiment(_) => "experiment",
180186
Self::Subscribe(_) => "subscribe",
181187
Self::Tangent(_) => "tangent",
182188
Self::Persist(sub) => match sub {

crates/chat-cli/src/cli/chat/prompt.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ pub const COMMANDS: &[&str] = &[
5858
"/tools reset",
5959
"/mcp",
6060
"/model",
61+
"/experiment",
6162
"/agent",
6263
"/agent help",
6364
"/agent list",

crates/chat-cli/src/cli/chat/tools/introspect.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ impl Introspect {
5656
documentation.push_str("\n\n--- docs/built-in-tools.md ---\n");
5757
documentation.push_str(include_str!("../../../../../../docs/built-in-tools.md"));
5858

59+
documentation.push_str("\n\n--- docs/experiments.md ---\n");
60+
documentation.push_str(include_str!("../../../../../../docs/experiments.md"));
61+
5962
documentation.push_str("\n\n--- docs/agent-file-locations.md ---\n");
6063
documentation.push_str(include_str!("../../../../../../docs/agent-file-locations.md"));
6164

@@ -84,6 +87,8 @@ impl Introspect {
8487
documentation.push_str(
8588
"• Built-in Tools: https://github.com/aws/amazon-q-developer-cli/blob/main/docs/built-in-tools.md\n",
8689
);
90+
documentation
91+
.push_str("• Experiments: https://github.com/aws/amazon-q-developer-cli/blob/main/docs/experiments.md\n");
8792
documentation.push_str("• Agent File Locations: https://github.com/aws/amazon-q-developer-cli/blob/main/docs/agent-file-locations.md\n");
8893
documentation
8994
.push_str("• Contributing: https://github.com/aws/amazon-q-developer-cli/blob/main/CONTRIBUTING.md\n");
@@ -129,12 +134,11 @@ impl Introspect {
129134
})
130135
}
131136

132-
pub fn queue_description(&self, output: &mut impl Write) -> Result<()> {
137+
pub fn queue_description(output: &mut impl Write) -> Result<()> {
133138
use crossterm::{
134139
queue,
135140
style,
136141
};
137-
_ = self;
138142
queue!(output, style::Print("Introspecting to get you the right information"))?;
139143
Ok(())
140144
}

crates/chat-cli/src/cli/chat/tools/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ impl Tool {
155155
Tool::UseAws(use_aws) => use_aws.queue_description(output),
156156
Tool::Custom(custom_tool) => custom_tool.queue_description(output),
157157
Tool::GhIssue(gh_issue) => gh_issue.queue_description(output),
158-
Tool::Introspect(introspect) => introspect.queue_description(output),
158+
Tool::Introspect(_) => Introspect::queue_description(output),
159159
Tool::Knowledge(knowledge) => knowledge.queue_description(os, output).await,
160160
Tool::Thinking(thinking) => thinking.queue_description(output),
161161
Tool::Todo(_) => Ok(()),

docs/experiments.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Experimental Features
2+
3+
Amazon Q CLI includes experimental features that can be toggled on/off using the `/experiment` command. These features are in active development and may change or be removed at any time.
4+
5+
## Available Experiments
6+
7+
### Knowledge
8+
**Command:** `/knowledge`
9+
**Description:** Enables persistent context storage and retrieval across chat sessions
10+
11+
**Features:**
12+
- Store and search through files, directories, and text content
13+
- Semantic search capabilities for better context retrieval
14+
- Persistent knowledge base across chat sessions
15+
- Add/remove/search knowledge contexts
16+
17+
**Usage:**
18+
```
19+
/knowledge add <path> # Add files or directories to knowledge base
20+
/knowledge show # Display knowledge base contents
21+
/knowledge remove <path> # Remove knowledge base entry by path
22+
/knowledge update <path> # Update a file or directory in knowledge base
23+
/knowledge clear # Remove all knowledge base entries
24+
/knowledge status # Show background operation status
25+
/knowledge cancel # Cancel background operation
26+
```
27+
28+
### Thinking
29+
**Description:** Enables complex reasoning with step-by-step thought processes
30+
31+
**Features:**
32+
- Shows AI reasoning process for complex problems
33+
- Helps understand how conclusions are reached
34+
- Useful for debugging and learning
35+
- Transparent decision-making process
36+
37+
**When enabled:** The AI will show its thinking process when working through complex problems or multi-step reasoning.
38+
39+
## Managing Experiments
40+
41+
Use the `/experiment` command to toggle experimental features:
42+
43+
```
44+
/experiment
45+
```
46+
47+
This will show an interactive menu where you can:
48+
- See current status of each experiment (ON/OFF)
49+
- Toggle experiments by selecting them
50+
- View descriptions of what each experiment does
51+
52+
## Important Notes
53+
54+
⚠️ **Experimental features may be changed or removed at any time**
55+
⚠️ **Experience might not be perfect**
56+
⚠️ **Use at your own discretion in production workflows**
57+
58+
These features are provided to gather feedback and test new capabilities. Please report any issues or feedback through the `/issue` command.
59+
60+
## Fuzzy Search Support
61+
62+
All experimental commands are available in the fuzzy search (Ctrl+S):
63+
- `/experiment` - Manage experimental features
64+
- `/knowledge` - Knowledge base commands (when enabled)
65+
66+
## Settings Integration
67+
68+
Experiments are stored as settings and persist across sessions:
69+
- `EnabledKnowledge` - Knowledge experiment state
70+
- `EnabledThinking` - Thinking experiment state
71+
72+
You can also manage these through the settings system if needed.

0 commit comments

Comments
 (0)