#[allow(unused_imports)]
use crate::sync_util::LockExt;
use std::time::Instant;
use crossterm::style::Color;
use crate::ui::agent_io::{RENDER_FRAME, render_agent_stream, should_render_token};
use crate::ui::avatar;
use crate::ui::colors::c_agent;
use crate::ui::events::sanitize_output;
use crate::ui::run_handlers::RunCtx;
#[cfg(feature = "plugin")]
use crate::plugin::PluginManager;
#[cfg(feature = "plugin")]
use crate::ui::streaming::TokenBatcher;
#[cfg(feature = "plugin")]
use std::sync::{Arc, Mutex};
pub(crate) fn handle_reasoning(
ctx: &mut RunCtx<'_>,
text: &str,
was_reasoning: &mut bool,
) -> anyhow::Result<()> {
let safe = sanitize_output(text);
ctx.reasoning_buf.push_str(&safe);
render_agent_stream(
ctx.reasoning_buf,
ctx.reasoning_start_line,
crate::ui::theme::thinking(),
ctx.renderer,
)?;
*ctx.agent_line_started = true;
*was_reasoning = true;
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn handle_token(
ctx: &mut RunCtx<'_>,
text: &str,
was_reasoning: &mut bool,
last_token_render: &mut Option<Instant>,
pending: usize,
#[cfg(feature = "plugin")] plugin_manager: Option<&Arc<Mutex<PluginManager>>>,
#[cfg(feature = "plugin")] token_batcher: &mut TokenBatcher,
#[cfg(feature = "plugin")] current_turn_text: &mut String,
#[cfg(feature = "plugin")] current_turn_index: u32,
) -> anyhow::Result<()> {
ctx.renderer.set_avatar_state(avatar::AvatarState::Speaking);
if *was_reasoning {
ctx.renderer.write_line("", Color::White)?;
*was_reasoning = false;
ctx.response_buf.clear();
*ctx.response_start_line = None;
ctx.end_reasoning();
*ctx.reasoning_start_line = None;
}
let safe = sanitize_output(text);
ctx.response_buf.push_str(&safe);
#[cfg(feature = "plugin")]
if let Some(pm) = plugin_manager {
current_turn_text.push_str(text);
if token_batcher.push(text).is_some() {
let mut mgr = pm.lock_ignore_poison();
let _ = mgr.dispatch(
"on-message-update",
&format!(
"@{{:index {} :partial \"{}\"}}",
current_turn_index,
crate::plugin::escape_janet_string(current_turn_text),
),
);
}
}
let since = last_token_render.map_or(RENDER_FRAME, |t| t.elapsed());
if should_render_token(pending, since, RENDER_FRAME) {
render_agent_stream(
ctx.response_buf,
ctx.response_start_line,
c_agent(),
ctx.renderer,
)?;
*last_token_render = Some(Instant::now());
}
*ctx.agent_line_started = true;
Ok(())
}