configurable stream timeout, show per-call timer in status bar
Stream chunk timeout is now api_stream_timeout_secs in config (default 60s). Status bar shows total turn time and per-call time with timeout: "thinking... 45s, 12/60s". Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
13d9cc962e
commit
156626ae53
3 changed files with 24 additions and 5 deletions
|
|
@ -305,7 +305,7 @@ impl SseReader {
|
||||||
pub(crate) fn new(ui_tx: &UiSender) -> Self {
|
pub(crate) fn new(ui_tx: &UiSender) -> Self {
|
||||||
Self {
|
Self {
|
||||||
line_buf: String::new(),
|
line_buf: String::new(),
|
||||||
chunk_timeout: Duration::from_secs(60),
|
chunk_timeout: Duration::from_secs(crate::config::get().api_stream_timeout_secs),
|
||||||
stream_start: Instant::now(),
|
stream_start: Instant::now(),
|
||||||
chunks_received: 0,
|
chunks_received: 0,
|
||||||
sse_lines_parsed: 0,
|
sse_lines_parsed: 0,
|
||||||
|
|
|
||||||
|
|
@ -311,6 +311,10 @@ pub struct App {
|
||||||
activity: String,
|
activity: String,
|
||||||
/// When the current turn started (for elapsed timer).
|
/// When the current turn started (for elapsed timer).
|
||||||
turn_started: Option<std::time::Instant>,
|
turn_started: Option<std::time::Instant>,
|
||||||
|
/// When the current LLM call started (for per-call timer).
|
||||||
|
call_started: Option<std::time::Instant>,
|
||||||
|
/// Stream timeout for the current call (for display).
|
||||||
|
call_timeout_secs: u64,
|
||||||
/// Whether to emit a ● marker before the next assistant TextDelta.
|
/// Whether to emit a ● marker before the next assistant TextDelta.
|
||||||
needs_assistant_marker: bool,
|
needs_assistant_marker: bool,
|
||||||
/// Number of running child processes (updated by main loop).
|
/// Number of running child processes (updated by main loop).
|
||||||
|
|
@ -392,6 +396,8 @@ impl App {
|
||||||
},
|
},
|
||||||
activity: String::new(),
|
activity: String::new(),
|
||||||
turn_started: None,
|
turn_started: None,
|
||||||
|
call_started: None,
|
||||||
|
call_timeout_secs: 60,
|
||||||
needs_assistant_marker: false,
|
needs_assistant_marker: false,
|
||||||
running_processes: 0,
|
running_processes: 0,
|
||||||
reasoning_effort: "none".to_string(),
|
reasoning_effort: "none".to_string(),
|
||||||
|
|
@ -485,6 +491,12 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UiMessage::Activity(text) => {
|
UiMessage::Activity(text) => {
|
||||||
|
if text.is_empty() {
|
||||||
|
self.call_started = None;
|
||||||
|
} else if self.activity.is_empty() || self.call_started.is_none() {
|
||||||
|
self.call_started = Some(std::time::Instant::now());
|
||||||
|
self.call_timeout_secs = crate::config::get().api_stream_timeout_secs;
|
||||||
|
}
|
||||||
self.activity = text;
|
self.activity = text;
|
||||||
}
|
}
|
||||||
UiMessage::Reasoning(text) => {
|
UiMessage::Reasoning(text) => {
|
||||||
|
|
@ -874,10 +886,12 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw status bar with live activity indicator
|
// Draw status bar with live activity indicator
|
||||||
let elapsed = self.turn_started.map(|t| t.elapsed());
|
let timer = if !self.activity.is_empty() {
|
||||||
let timer = match elapsed {
|
let total = self.turn_started.map(|t| t.elapsed().as_secs()).unwrap_or(0);
|
||||||
Some(d) if !self.activity.is_empty() => format!(" {:.0}s", d.as_secs_f64()),
|
let call = self.call_started.map(|t| t.elapsed().as_secs()).unwrap_or(0);
|
||||||
_ => String::new(),
|
format!(" {}s, {}/{}s", total, call, self.call_timeout_secs)
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
};
|
};
|
||||||
let tools_info = if self.status.turn_tools > 0 {
|
let tools_info = if self.status.turn_tools > 0 {
|
||||||
format!(" ({}t)", self.status.turn_tools)
|
format!(" ({}t)", self.status.turn_tools)
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ pub struct ContextGroup {
|
||||||
|
|
||||||
fn default_true() -> bool { true }
|
fn default_true() -> bool { true }
|
||||||
fn default_context_window() -> usize { 128_000 }
|
fn default_context_window() -> usize { 128_000 }
|
||||||
|
fn default_stream_timeout() -> u64 { 60 }
|
||||||
fn default_identity_dir() -> PathBuf {
|
fn default_identity_dir() -> PathBuf {
|
||||||
PathBuf::from(std::env::var("HOME").expect("HOME not set")).join(".consciousness/identity")
|
PathBuf::from(std::env::var("HOME").expect("HOME not set")).join(".consciousness/identity")
|
||||||
}
|
}
|
||||||
|
|
@ -91,6 +92,9 @@ pub struct Config {
|
||||||
/// Used to resolve API settings, not stored on Config
|
/// Used to resolve API settings, not stored on Config
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
agent_model: Option<String>,
|
agent_model: Option<String>,
|
||||||
|
/// Stream chunk timeout in seconds (no data = timeout).
|
||||||
|
#[serde(default = "default_stream_timeout")]
|
||||||
|
pub api_stream_timeout_secs: u64,
|
||||||
pub api_reasoning: String,
|
pub api_reasoning: String,
|
||||||
pub agent_types: Vec<String>,
|
pub agent_types: Vec<String>,
|
||||||
/// Surface agent timeout in seconds.
|
/// Surface agent timeout in seconds.
|
||||||
|
|
@ -138,6 +142,7 @@ impl Default for Config {
|
||||||
api_key: None,
|
api_key: None,
|
||||||
api_model: None,
|
api_model: None,
|
||||||
api_context_window: default_context_window(),
|
api_context_window: default_context_window(),
|
||||||
|
api_stream_timeout_secs: default_stream_timeout(),
|
||||||
agent_model: None,
|
agent_model: None,
|
||||||
api_reasoning: "high".to_string(),
|
api_reasoning: "high".to_string(),
|
||||||
agent_types: vec![
|
agent_types: vec![
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue