pub struct TurnRunner {
pub provider: Arc<dyn LlmProvider>,
pub tools: Arc<ToolRegistry>,
pub context: ToolContext,
pub config: Config,
pub ctx: Arc<dyn CtxBuilder>,
pub permission: Box<dyn PermissionDecider>,
pub recently_edited_files: Vec<String>,
pub hook_executor: Arc<HookExecutor>,
pub loop_guard: LoopGuardState,
}Expand description
Core LLM streaming + tool execution primitive.
Handles exactly one LLM call cycle:
- Build messages from conversation
- Stream LLM response (text deltas + tool calls)
- Execute tool calls (with permission checking)
- Add results to conversation
Does NOT handle: retries, discipline (anti-loop, step limits), or conversation management. The caller (AgentLoop / SubagentLoop) owns those responsibilities.
Fields§
§provider: Arc<dyn LlmProvider>§tools: Arc<ToolRegistry>§context: ToolContext§config: Config§ctx: Arc<dyn CtxBuilder>Context construction strategy. Shared with the parent
AgentLoop::ctx (same Arc) so the turn’s actual send and
the agent’s datalog snapshot go through one ctx — per-model
logic like apply_model_directives lands on both paths.
Rebuilt on AgentCommand::ReloadConfig alongside the agent’s
clone.
permission: Box<dyn PermissionDecider>§recently_edited_files: Vec<String>Files edited during the current session (tracked for context awareness).
hook_executor: Arc<HookExecutor>Hook executor — runs user-configured lifecycle hooks at tool execution boundaries.
loop_guard: LoopGuardStateCross-batch tool-call loop guard. Cleared per user-message by the
agent (see handle_send_message); records every executed tool’s
(name, args, output_hash) triple and short-circuits the third
identical attempt. See loop_guard.rs for the full rationale.
Implementations§
Source§impl TurnRunner
impl TurnRunner
Sourcepub async fn run(
&mut self,
conversation: &mut Conversation,
system_prompt: &str,
event_tx: &UnboundedSender<TurnEvent>,
cancel: CancellationToken,
) -> TurnResult
pub async fn run( &mut self, conversation: &mut Conversation, system_prompt: &str, event_tx: &UnboundedSender<TurnEvent>, cancel: CancellationToken, ) -> TurnResult
Execute one LLM turn: stream response, execute any tool calls, return result.
Sourcepub async fn run_with_filter(
&mut self,
conversation: &mut Conversation,
system_prompt: &str,
turn_reminder: &str,
event_tx: &UnboundedSender<TurnEvent>,
cancel: CancellationToken,
allowed_tools: Option<&[&str]>,
) -> TurnResult
pub async fn run_with_filter( &mut self, conversation: &mut Conversation, system_prompt: &str, turn_reminder: &str, event_tx: &UnboundedSender<TurnEvent>, cancel: CancellationToken, allowed_tools: Option<&[&str]>, ) -> TurnResult
Run with optional tool filter and turn reminder.
turn_reminder is dynamic per-turn context (git status, current task, etc.)
injected as a
Sourcepub async fn run_execute(
&mut self,
file_path: &str,
instruction: &str,
event_tx: &UnboundedSender<TurnEvent>,
cancel: CancellationToken,
) -> TurnResult
pub async fn run_execute( &mut self, file_path: &str, instruction: &str, event_tx: &UnboundedSender<TurnEvent>, cancel: CancellationToken, ) -> TurnResult
EXECUTE mode: run one LLM turn with minimal context. Reads the target file fresh from disk, sends only the file + instruction, and only exposes edit_file. Used for precise, focused edits.
Returns the TurnResult and whether any file was edited.
Auto Trait Implementations§
impl Freeze for TurnRunner
impl !RefUnwindSafe for TurnRunner
impl Send for TurnRunner
impl Sync for TurnRunner
impl Unpin for TurnRunner
impl UnsafeUnpin for TurnRunner
impl !UnwindSafe for TurnRunner
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more