Chat tabs, chat mode, own modes, compaction notice, CLI binaries again
- Terminals and file managers as tabs of a chat; chat terminals keep running on the server (no idle timeout) and re-attach from any device - "Just chat" in New session and a built-in chat mode with a lean prompt and only web tools; custom modes with kind (coding/conversation), read-only and tool picker - Mode selector as a dropdown - The chat shows running compactions (automatic: tokens and share of the limit) and labels summaries - Docker image builds and serves the terminal client binaries again - Fix: atomic session updates; background title/usage writes no longer undo each other (auto compaction triggered one turn late) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
242b80605c
commit
c850586a81
29 files changed
+831
-187
No files matched your search
+23
-3
@@ -46,6 +46,8 @@ pub struct Runtime {
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
/// Serializes read-modify-write of sessions (see `update_session`).
|
||||
session_write: Mutex<()>,
|
||||
config_path: PathBuf,
|
||||
config: RwLock<Arc<Config>>,
|
||||
registry: RwLock<Arc<Registry>>,
|
||||
@@ -101,6 +103,7 @@ impl App {
|
||||
let registry = Registry::build(&cfg).await;
|
||||
let (events, _) = broadcast::channel(4096);
|
||||
let app = Arc::new(Self {
|
||||
session_write: Mutex::new(()),
|
||||
config_path,
|
||||
config: RwLock::new(Arc::new(cfg)),
|
||||
registry: RwLock::new(Arc::new(registry)),
|
||||
@@ -326,10 +329,27 @@ impl App {
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
/// Load, change and save a session atomically: background tasks (title, usage, phase,
|
||||
/// todos) change different fields at the same time and must not undo each other.
|
||||
pub fn update_session(&self, id: &str, f: impl FnOnce(&mut Session)) -> Result<Session> {
|
||||
self.modify_session(id, true, f)
|
||||
}
|
||||
|
||||
/// Like `update_session`; `touch = false` keeps `updated_at` (organising the list).
|
||||
pub fn modify_session(&self, id: &str, touch: bool, f: impl FnOnce(&mut Session)) -> Result<Session> {
|
||||
let _guard = self.session_write.lock().unwrap();
|
||||
let mut s = self.session(id)?;
|
||||
f(&mut s);
|
||||
if touch {
|
||||
return self.save_session(s);
|
||||
}
|
||||
self.store.save_session(&s)?;
|
||||
self.emit(Event::SessionUpdated { session: s.clone() });
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
pub fn set_todos(&self, session_id: &str, todos: Value) -> Result<()> {
|
||||
let mut s = self.session(session_id)?;
|
||||
s.todos = todos;
|
||||
self.save_session(s)?;
|
||||
self.update_session(session_id, |s| s.todos = todos)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user