Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion crates/goose/src/prompts/session_name.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Generate a short title (four words or less) that describes the topic of the user's messages. Reply with only the title, nothing else.
Generate a short title (four words or less) that describes the topic of the user's messages.
Reply with only the title, nothing else. Do not show your reasoning.

Examples:
- "how do I reverse a list in python?" → Python list reversal
Expand Down
100 changes: 99 additions & 1 deletion crates/goose/src/providers/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,60 @@
TAG_RE.replace_all(&pass1, "").into_owned()
}

fn extract_short_title(text: &str) -> String {
let word_count = text.split_whitespace().count();
if word_count <= 8 {
return text.to_string();
}

{
let mut results = Vec::new();
let mut quote_char: Option<char> = None;
let mut current = String::new();
let mut prev_char: Option<char> = None;

for ch in text.chars() {
match quote_char {

Check warning on line 49 in crates/goose/src/providers/base.rs

View workflow job for this annotation

GitHub Actions / Check Rust Code Format

Diff in /home/runner/work/goose/goose/crates/goose/src/providers/base.rs
None => {
if matches!(ch, '"' | '\'' | '`') {
let after_alnum = prev_char
.map(|p| p.is_alphanumeric())
.unwrap_or(false);
if !after_alnum {
quote_char = Some(ch);
current.clear();
}
}
}
Some(q) => {
if ch == q {
let trimmed = current.trim().to_string();
let wc = trimmed.split_whitespace().count();
if wc >= 2 && wc <= 8 {

Check failure on line 65 in crates/goose/src/providers/base.rs

View workflow job for this annotation

GitHub Actions / Lint Rust Code

manual `RangeInclusive::contains` implementation
results.push(trimmed);
}
quote_char = None;
current.clear();
} else {
current.push(ch);
}
}
}
prev_char = Some(ch);
}

if let Some(title) = results.last() {
return title.clone();
}
}

if let Some(last) = text.lines().rev().find(|l| !l.trim().is_empty()) {
return last.trim().to_string();
}

text.to_string()
}

/// A global store for the current model being used, we use this as when a provider returns, it tells us the real model, not an alias
pub static CURRENT_MODEL: Lazy<Mutex<Option<String>>> = Lazy::new(|| Mutex::new(None));

Expand Down Expand Up @@ -629,10 +683,12 @@
.collect();
let description = strip_xml_tags(&raw)
.split_whitespace()
.collect::<Vec<_>>()

Check warning on line 686 in crates/goose/src/providers/base.rs

View workflow job for this annotation

GitHub Actions / Check Rust Code Format

Diff in /home/runner/work/goose/goose/crates/goose/src/providers/base.rs
.join(" ");

Ok(safe_truncate(&description, 100))


Ok(safe_truncate(&extract_short_title(&description), 100))
}

/// Configure OAuth authentication for this provider
Expand Down Expand Up @@ -752,6 +808,48 @@
);
}

#[test]
fn test_extract_short_title() {

Check warning on line 812 in crates/goose/src/providers/base.rs

View workflow job for this annotation

GitHub Actions / Check Rust Code Format

Diff in /home/runner/work/goose/goose/crates/goose/src/providers/base.rs
assert_eq!(extract_short_title("List files"), "List files");
assert_eq!(
extract_short_title(r#"blah blah blah blah blah blah blah blah blah "List files in folder""#),
"List files in folder"
);
assert_eq!(
extract_short_title("blah blah blah blah blah blah blah blah blah `View current files`"),

Check warning on line 819 in crates/goose/src/providers/base.rs

View workflow job for this annotation

GitHub Actions / Check Rust Code Format

Diff in /home/runner/work/goose/goose/crates/goose/src/providers/base.rs
"View current files"
);
assert_eq!(
extract_short_title(r#"stuff stuff stuff stuff stuff stuff stuff stuff "Abc title" "Zzz title""#),

Check warning on line 823 in crates/goose/src/providers/base.rs

View workflow job for this annotation

GitHub Actions / Check Rust Code Format

Diff in /home/runner/work/goose/goose/crates/goose/src/providers/base.rs
"Zzz title"
);
assert_eq!(
extract_short_title("long long long long long long long long long\nList files in folder"),

Check warning on line 827 in crates/goose/src/providers/base.rs

View workflow job for this annotation

GitHub Actions / Check Rust Code Format

Diff in /home/runner/work/goose/goose/crates/goose/src/providers/base.rs
"List files in folder"
);
assert_eq!(
extract_short_title(r#"lots of words here and there and more and more "single" final line here"#),

Check warning on line 831 in crates/goose/src/providers/base.rs

View workflow job for this annotation

GitHub Actions / Check Rust Code Format

Diff in /home/runner/work/goose/goose/crates/goose/src/providers/base.rs
"lots of words here and there and more and more \"single\" final line here"
);
assert_eq!(extract_short_title("Hello world"), "Hello world");
assert_eq!(
extract_short_title(
r#"1. Analyze the request. 2. The user's message says list files. 3. "List current folder files" fits perfectly. Result: List current folder files"#
),
"List current folder files"
);
assert_eq!(
extract_short_title(
r#"the user's phrasing is about listing files and the user's intent is clear. "List folder files" is best"#
),
"List folder files"

Check warning on line 845 in crates/goose/src/providers/base.rs

View workflow job for this annotation

GitHub Actions / Check Rust Code Format

Diff in /home/runner/work/goose/goose/crates/goose/src/providers/base.rs
);
assert_eq!(
extract_short_title("lots of reasoning here about what to call it\nList current folder files"),
"List current folder files"
);
}

#[test]
fn test_usage_creation() {
let usage = Usage::new(Some(10), Some(20), Some(30));
Expand Down
Loading