mirror of
https://github.com/aljazceru/goose.git
synced 2025-12-18 06:34:26 +01:00
feat(goose-cli): theme persistence & selection (#1693)
Co-authored-by: Bradley Axen <baxen@squareup.com>
This commit is contained in:
@@ -11,6 +11,7 @@ pub enum InputResult {
|
||||
AddExtension(String),
|
||||
AddBuiltin(String),
|
||||
ToggleTheme,
|
||||
SelectTheme(String),
|
||||
Retry,
|
||||
ListPrompts(Option<String>),
|
||||
PromptCommand(PromptCommandOptions),
|
||||
@@ -103,6 +104,22 @@ fn handle_slash_command(input: &str) -> Option<InputResult> {
|
||||
Some(InputResult::Retry)
|
||||
}
|
||||
"/t" => Some(InputResult::ToggleTheme),
|
||||
s if s.starts_with("/t ") => {
|
||||
let t = s
|
||||
.strip_prefix("/t ")
|
||||
.unwrap_or_default()
|
||||
.trim()
|
||||
.to_lowercase();
|
||||
if ["light", "dark", "ansi"].contains(&t.as_str()) {
|
||||
Some(InputResult::SelectTheme(t))
|
||||
} else {
|
||||
println!(
|
||||
"Theme Unavailable: {} Available themes are: light, dark, ansi",
|
||||
t
|
||||
);
|
||||
Some(InputResult::Retry)
|
||||
}
|
||||
}
|
||||
"/prompts" => Some(InputResult::ListPrompts(None)),
|
||||
s if s.starts_with(CMD_PROMPTS) => {
|
||||
// Parse arguments for /prompts command
|
||||
@@ -234,6 +251,7 @@ fn print_help() {
|
||||
"Available commands:
|
||||
/exit or /quit - Exit the session
|
||||
/t - Toggle Light/Dark/Ansi theme
|
||||
/t <name> - Set theme directly (light, dark, ansi)
|
||||
/extension <command> - Add a stdio extension (format: ENV1=val1 command args...)
|
||||
/builtin <names> - Add builtin extensions by name (comma-separated)
|
||||
/prompts [--extension <name>] - List all available prompts, optionally filtered by extension
|
||||
|
||||
@@ -499,6 +499,28 @@ impl Session {
|
||||
output::set_theme(new_theme);
|
||||
continue;
|
||||
}
|
||||
|
||||
input::InputResult::SelectTheme(theme_name) => {
|
||||
save_history(&mut editor);
|
||||
|
||||
let new_theme = match theme_name.as_str() {
|
||||
"light" => {
|
||||
println!("Switching to Light theme");
|
||||
output::Theme::Light
|
||||
}
|
||||
"dark" => {
|
||||
println!("Switching to Dark theme");
|
||||
output::Theme::Dark
|
||||
}
|
||||
"ansi" => {
|
||||
println!("Switching to Ansi theme");
|
||||
output::Theme::Ansi
|
||||
}
|
||||
_ => output::Theme::Dark,
|
||||
};
|
||||
output::set_theme(new_theme);
|
||||
continue;
|
||||
}
|
||||
input::InputResult::Retry => continue,
|
||||
input::InputResult::ListPrompts(extension) => {
|
||||
save_history(&mut editor);
|
||||
|
||||
@@ -67,6 +67,17 @@ pub fn set_theme(theme: Theme) {
|
||||
.set_param("GOOSE_CLI_THEME", Value::String(theme.as_config_string()))
|
||||
.expect("Failed to set theme");
|
||||
CURRENT_THEME.with(|t| *t.borrow_mut() = theme);
|
||||
|
||||
let config = Config::global();
|
||||
let theme_str = match theme {
|
||||
Theme::Light => "light",
|
||||
Theme::Dark => "dark",
|
||||
Theme::Ansi => "ansi",
|
||||
};
|
||||
|
||||
if let Err(e) = config.set_param("GOOSE_CLI_THEME", Value::String(theme_str.to_string())) {
|
||||
eprintln!("Failed to save theme setting to config: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_theme() -> Theme {
|
||||
|
||||
@@ -556,6 +556,14 @@ All commands support tab completion. Press `<Tab>` after a slash (/) to cycle th
|
||||
|
||||
Goose CLI supports several shortcuts and built-in commands for easier navigation.
|
||||
|
||||
### Keyboard Navigation
|
||||
|
||||
- **`Ctrl+C`** - Interrupt the current request
|
||||
- **`Ctrl+J`** - Add a newline
|
||||
- **`Cmd+Up/Down arrows`** - Navigate through command history
|
||||
- **`Cmd+Up/Down arrows`** - Navigate through command history
|
||||
|
||||
### Slash Commands
|
||||
- **`/exit` or `/quit`** - Exit the session
|
||||
- **`/t`** - Toggle between Light/Dark/Ansi themes
|
||||
- **`/t <theme>`** - Set theme directly (`/t light`, `/t dark`, or `/t ansi`)
|
||||
- **`/?` or `/help`** - Display the help menu
|
||||
|
||||
@@ -317,15 +317,16 @@ export function useMessageStream({
|
||||
const lastMessage = currentMessages[currentMessages.length - 1];
|
||||
onFinish(lastMessage, parsedEvent.reason);
|
||||
}
|
||||
|
||||
|
||||
// Fetch updated session metadata with token counts
|
||||
const sessionId = (extraMetadataRef.current.body as Record<string, unknown>)?.session_id as string;
|
||||
const sessionId = (extraMetadataRef.current.body as Record<string, unknown>)
|
||||
?.session_id as string;
|
||||
if (sessionId) {
|
||||
try {
|
||||
const sessionResponse = await getSessionHistory({
|
||||
path: { session_id: sessionId },
|
||||
});
|
||||
|
||||
|
||||
if (sessionResponse.data?.metadata) {
|
||||
setSessionMetadata({
|
||||
workingDir: sessionResponse.data.metadata.working_dir,
|
||||
@@ -335,9 +336,12 @@ export function useMessageStream({
|
||||
totalTokens: sessionResponse.data.metadata.total_tokens || null,
|
||||
inputTokens: sessionResponse.data.metadata.input_tokens || null,
|
||||
outputTokens: sessionResponse.data.metadata.output_tokens || null,
|
||||
accumulatedTotalTokens: sessionResponse.data.metadata.accumulated_total_tokens || null,
|
||||
accumulatedInputTokens: sessionResponse.data.metadata.accumulated_input_tokens || null,
|
||||
accumulatedOutputTokens: sessionResponse.data.metadata.accumulated_output_tokens || null,
|
||||
accumulatedTotalTokens:
|
||||
sessionResponse.data.metadata.accumulated_total_tokens || null,
|
||||
accumulatedInputTokens:
|
||||
sessionResponse.data.metadata.accumulated_input_tokens || null,
|
||||
accumulatedOutputTokens:
|
||||
sessionResponse.data.metadata.accumulated_output_tokens || null,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user