Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 3 additions & 3 deletions .repository-projection.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"projection": "deixic-code",
"projectionSchemaVersion": 1,
"sourceRepository": "dx-corp/mono",
"sourceSha": "d86f17d9fc24cbabd645f27a7dbc3d861d57acb7",
"sourceSha": "0c4999b07bdbd4132282664256240c97cca5f8e6",
"destinationRepository": "dx-corp/code",
"priorProjectedBase": "9610ff4cc0f57cd58d5d334d46b875b766f6b2e2",
"priorProjectedBase": "01cbd80c5f6e9b39311ae3ead51074bf34eee588",
"definitionDigest": "82936441c776e3e8edb5d215a75007ec9714a233f489d460075d79d5ef5ba32f",
"toolDigest": "89cbdbe1d79917bad52655817aab0eb545b89183915380eaedc3217f014e6715",
"contentDigest": "bf569f56d06fbd6cd2c5de9cd3b3d699dbc019417492e2493ec4da8b9ab6202e",
"contentDigest": "9d42748e8e0da39268d1af21ef1b2d7d4f71ba4814e1541f9cf2246dee33a956",
"publicationEligible": true
}
1 change: 1 addition & 0 deletions packages/local-host-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ pub mod tool_output;
pub mod tools;
pub mod transcript;
pub mod ui_prefs;
pub mod ui_wake;
pub mod video;
pub mod workflow_runtime;
pub use sandbox::SandboxPolicy;
Expand Down
1 change: 1 addition & 0 deletions packages/local-host-rs/src/local_models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ fn spawn_local_model_discovery_with_client_factory(
{
break;
}
crate::ui_wake::wake();
}
})
.expect("local model discovery thread should start");
Expand Down
3 changes: 3 additions & 0 deletions packages/local-host-rs/src/mcp/notifications.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ impl NotificationQueue {
.position(|method| *method == notification.method)
{
self.0.lock().unwrap().invalidated[index] = true;
crate::ui_wake::wake();
return true;
}
let Ok(serialized) = serde_json::to_vec(&notification) else {
Expand All @@ -58,6 +59,8 @@ impl NotificationQueue {
}
pending.bytes += bytes;
pending.events.push_back((notification, bytes));
drop(pending);
crate::ui_wake::wake();
true
}

Expand Down
1 change: 1 addition & 0 deletions packages/local-host-rs/src/subagents/lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,7 @@ impl SubagentManager {
record.id
)
})?;
crate::ui_wake::wake();
record.lifecycle_notification_published = true;
self.write_record(record)
}
Expand Down
5 changes: 5 additions & 0 deletions packages/local-host-rs/src/tools/background_tasks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ fn emit_task_lifecycle(task_id: &str, command: &str, status: &str, exit_code: Op
});
}
persist_running_snapshot();
crate::ui_wake::wake();
}

/// Drain process exit/stop notifications for the UI (and optional agent nudge).
Expand Down Expand Up @@ -564,6 +565,7 @@ fn emit_monitor_matches(task_id: &str, stream: &'static str, line: &str) {
});
}
}
let had_events = !matched.is_empty();
for event in matched {
if let Ok(mut events) = MONITOR_EVENTS.write() {
if events.len() >= MAX_MONITOR_EVENTS {
Expand All @@ -578,6 +580,9 @@ fn emit_monitor_matches(task_id: &str, stream: &'static str, line: &str) {
history.push_back(event);
}
}
if had_events {
crate::ui_wake::wake();
}
}

fn remove_task_monitors(task_id: &str) {
Expand Down
26 changes: 26 additions & 0 deletions packages/local-host-rs/src/ui_wake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//! Process-wide wake hook for the Deixic Code terminal event loop.
//!
//! Producers that enqueue work from another crate, a sync thread, or a
//! file-watcher callback cannot hold the TUI's [`tokio::sync::Notify`].
//! They call [`wake`] after the enqueue. The TUI installs one hook for the
//! lifetime of its main loop; other processes leave the hook empty.

use std::sync::{Arc, Mutex};

static HOOK: Mutex<Option<Arc<dyn Fn() + Send + Sync>>> = Mutex::new(None);

/// Install or clear the UI wake hook. The TUI sets this while its loop runs.
pub fn set_hook(hook: Option<Arc<dyn Fn() + Send + Sync>>) {
*HOOK.lock().unwrap_or_else(std::sync::PoisonError::into_inner) = hook;
}

/// Wake the installed UI loop, if any. Safe to call when no hook is set.
pub fn wake() {
let hook = HOOK
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.clone();
if let Some(hook) = hook {
hook();
}
}
Loading
Loading