Skip to main content

KodaSession

Struct KodaSession 

Source
pub struct KodaSession {
    pub id: String,
    pub agent: Arc<KodaAgent>,
    pub db: Database,
    pub provider: Box<dyn LlmProvider>,
    pub mode: TrustMode,
    pub cancel: CancellationToken,
    pub file_tracker: FileTracker,
    pub title_set: bool,
    pub proxy: Option<ProxyHandle>,
    pub socks5_proxy: Option<ProxyHandle>,
    pub bg_agents: Arc<BgAgentRegistry>,
    pub sub_agent_cache: SubAgentCache,
}
Expand description

A single conversation session with its own state.

Each session has its own provider, trust mode, and cancel token. Multiple sessions can share the same Arc<KodaAgent>.

Fields§

§id: String

Unique session identifier.

§agent: Arc<KodaAgent>

Shared agent configuration (tools, system prompt).

§db: Database

Database handle for message persistence.

§provider: Box<dyn LlmProvider>

LLM provider for this session.

§mode: TrustMode

Current trust mode (Plan / Safe / Auto).

§cancel: CancellationToken

Cancellation token for graceful shutdown.

§file_tracker: FileTracker

File lifecycle tracker — tracks files created by Koda (#465).

§title_set: bool

Whether the session title has already been set (first-message guard).

§proxy: Option<ProxyHandle>

Per-session HTTP CONNECT proxy (Phase 3b of #934).

Spawned unconditionally in Self::new with the hardcoded koda_sandbox::DEFAULT_DEV_ALLOWLIST — koda is config-free, so there’s no “opt in” toggle and no user-tunable allowlist (yet; future work: DB-backed slash command for per-project extensions). Always-on means every Bash invocation routes through this proxy and unknown hostnames get a 403 at the CONNECT layer.

Option rather than bare ProxyHandle because spawn can fail (ephemeral-port exhaustion, broken loopback, runtime shutdown). Fail-open: on spawn failure we log + continue with None, matching the contract of koda_sandbox::ExternalProxy::spawn. A broken proxy must never break a session — the kernel sandbox remains the authoritative network boundary anyway.

Held for the session’s lifetime; Drop aborts the proxy task and closes the listener — no manual teardown needed.

§socks5_proxy: Option<ProxyHandle>

Per-session SOCKS5 proxy (Phase 3d.1 of #934). Sibling of Self::proxy for raw-TCP clients (git over ssh, gRPC) that don’t honor HTTPS_PROXY. Same fail-open contract: spawn failure logs a warning and the field stays None. Uses the same hostname allowlist as the HTTP proxy by construction — see koda_sandbox::BuiltInSocks5Proxy.

§bg_agents: Arc<BgAgentRegistry>

Background sub-agent registry (#1022 B12).

Lives on the session, not on inference_loop, so background agents survive across turns. The previous design constructed the registry locally inside inference_loop; when the loop returned (final text, error, hard-stop) the Arc dropped and every still-pending bg task was aborted via tokio_util::task::AbortOnDropHandle — silently discarding any not-yet-completed result. With single-iteration responses (InvokeAgent { background: true } followed by final text in the same turn) this lost the bg result every time.

Owning here means: bg tasks keep running between turns, and the next turn’s first iteration drains anything that completed during the idle gap. Registry abort still happens at Drop — i.e. when the session itself is dropped — which is what users actually mean by “stop”.

Wrapped in Arc because tool dispatch needs to hand the same registry into the recursive execute_sub_agent call (so nested InvokeAgent { background: true } registers in the caller-visible slot, not a fresh per-call one).

§sub_agent_cache: SubAgentCache

Cross-turn sub-agent result cache (#1022 B12).

Same lifetime motivation as Self::bg_agents: was previously re-created per inference_loop invocation, which threw away every cache entry on each turn boundary and made the cache useless for the natural “ask, follow up, ask again” flow. Living on the session means the second turn can hit results computed in the first.

Invalidation still happens on every mutating tool call via crate::tool_dispatch::execute_one_tool — generation bump, cached entries with stale generations are treated as misses. Cross-turn doesn’t change that contract; it just extends the window in which a still-fresh entry can be reused.

Implementations§

Source§

impl KodaSession

Source

pub async fn new( id: String, agent: Arc<KodaAgent>, db: Database, config: &KodaConfig, mode: TrustMode, ) -> Self

Create a new session from an agent, config, and database.

Source

pub async fn run_turn( &mut self, config: &KodaConfig, pending_images: Option<Vec<ImageData>>, sink: &dyn EngineSink, cmd_rx: &mut Receiver<EngineCommand>, ) -> Result<()>

Run one inference turn: prompt → streaming → tool execution → response.

Emits TurnStart and TurnEnd lifecycle events. The loop-cap prompt is handled via EngineEvent::LoopCapReached / EngineCommand::LoopDecision through the cmd_rx channel.

Source

pub fn update_provider(&mut self, config: &KodaConfig)

Replace the provider (e.g., after switching models or providers).

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more