use tau_proto::{ProviderResponseFinished, ProviderStopReason, ToolCallId, ToolName};
#[derive(Clone, Debug, Eq, PartialEq)]
pub(super) struct TerminalToolCall {
pub(super) call_id: ToolCallId,
pub(super) name: ToolName,
pub(super) admitted: bool,
}
#[derive(Clone, Debug)]
pub(super) struct TerminalToolCalls {
calls: Vec<TerminalToolCall>,
work: TerminalToolCallWork,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub(super) struct TerminalToolCallWork {
pub(super) output_items_visited: usize,
pub(super) metadata_buffers_allocated: usize,
pub(super) metadata_slots_reserved: usize,
pub(super) metadata_fields_cloned: usize,
}
impl TerminalToolCalls {
pub(super) fn from_finished(finished: &ProviderResponseFinished) -> Self {
let admitted = finished.stop_reason != ProviderStopReason::Length;
let mut calls = Vec::new();
let mut work = TerminalToolCallWork::default();
for (index, item) in finished.output_items.iter().enumerate() {
work.output_items_visited += 1;
let tau_proto::ContextItem::ToolCall(call) = item else {
continue;
};
if calls.is_empty() {
let slots = finished.output_items.len() - index;
calls.reserve_exact(slots);
work.metadata_buffers_allocated = 1;
work.metadata_slots_reserved = slots;
}
calls.push(TerminalToolCall {
call_id: call.call_id.clone(),
name: call.name.clone(),
admitted,
});
work.metadata_fields_cloned += 2;
}
observe_terminal_tool_call_work(work);
Self { calls, work }
}
pub(super) fn is_empty(&self) -> bool {
self.calls.is_empty()
}
pub(super) fn len(&self) -> usize {
self.calls.len()
}
pub(super) fn admitted_len(&self) -> usize {
self.calls.iter().filter(|call| call.admitted).count()
}
pub(super) fn iter(&self) -> impl ExactSizeIterator<Item = &TerminalToolCall> {
self.calls.iter()
}
pub(super) fn call_ids(&self) -> impl ExactSizeIterator<Item = &ToolCallId> {
self.calls.iter().map(|call| &call.call_id)
}
pub(super) fn work(&self) -> TerminalToolCallWork {
self.work
}
}
#[cfg(test)]
type TerminalToolCallWorkObserver = Box<dyn FnMut(TerminalToolCallWork)>;
#[cfg(test)]
thread_local! {
static TERMINAL_TOOL_CALL_WORK_OBSERVER:
std::cell::RefCell<Option<TerminalToolCallWorkObserver>> =
const { std::cell::RefCell::new(None) };
}
fn observe_terminal_tool_call_work(work: TerminalToolCallWork) {
#[cfg(test)]
TERMINAL_TOOL_CALL_WORK_OBSERVER.with(|observer| {
if let Some(observer) = observer.borrow_mut().as_mut() {
observer(work);
}
});
#[cfg(not(test))]
let _ = work;
}
#[cfg(test)]
pub(super) fn with_terminal_tool_call_work_observer<T>(
observer: impl FnMut(TerminalToolCallWork) + 'static,
run: impl FnOnce() -> T,
) -> T {
struct ObserverReset;
impl Drop for ObserverReset {
fn drop(&mut self) {
TERMINAL_TOOL_CALL_WORK_OBSERVER.with(|slot| {
slot.borrow_mut().take();
});
}
}
TERMINAL_TOOL_CALL_WORK_OBSERVER.with(|slot| {
assert!(
slot.borrow().is_none(),
"projection observer already installed"
);
*slot.borrow_mut() = Some(Box::new(observer));
});
let _reset = ObserverReset;
run()
}