Add hooks, @file mentions, session search/fork/export, follow-scroll
- Hooks ([[hooks]]): pre_tool, post_tool, user_prompt, stop; sandboxed, exit 2 blocks - @file mentions with autocomplete; mentioned files/folders are attached to the prompt - Session full-text search in the sidebar, fork into a copy, export as Markdown/JSON - Chat follows the newest message until the user scrolls up; jump-to-latest button - SVG activity spark and thinking icon instead of Unicode/emoji glyphs - File search ranks name matches first and returns relative paths Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ec1b9b4925
commit
013695722a
17 files changed
+911
-41
No files matched your search
+19
-7
@@ -399,20 +399,32 @@ pub async fn search(Extension(user): Extension<User>, State(app): State<AppState
|
||||
return Ok(Json(json!([])));
|
||||
}
|
||||
let hits = tokio::task::spawn_blocking(move || {
|
||||
let mut out = Vec::new();
|
||||
// Matches on the name or the relative path; name prefix matches first.
|
||||
let mut found: Vec<(u8, usize, Value)> = Vec::new();
|
||||
for e in ignore::WalkBuilder::new(&root).hidden(true).build().flatten() {
|
||||
if e.depth() == 0 {
|
||||
continue;
|
||||
}
|
||||
let name = e.file_name().to_string_lossy().to_lowercase();
|
||||
if name.contains(&needle) {
|
||||
out.push(json!({"path": e.path(), "is_dir": e.file_type().is_some_and(|t| t.is_dir())}));
|
||||
if out.len() >= 200 {
|
||||
break;
|
||||
}
|
||||
let rel = e.path().strip_prefix(&root).unwrap_or(e.path()).to_string_lossy().to_string();
|
||||
let rel_l = rel.to_lowercase();
|
||||
let rank = if name.starts_with(&needle) {
|
||||
0
|
||||
} else if name.contains(&needle) {
|
||||
1
|
||||
} else if rel_l.contains(&needle) {
|
||||
2
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
let is_dir = e.file_type().is_some_and(|t| t.is_dir());
|
||||
found.push((rank, rel.len(), json!({"path": e.path(), "rel": rel, "is_dir": is_dir})));
|
||||
if found.len() >= 2000 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
out
|
||||
found.sort_by_key(|(r, l, _)| (*r, *l));
|
||||
found.into_iter().take(200).map(|(_, _, v)| v).collect::<Vec<_>>()
|
||||
})
|
||||
.await?;
|
||||
Ok(Json(json!(hits)))
|
||||
|
||||
Reference in new issue
Block a user