Skip to main content

AppState

Struct AppState 

Source
pub struct AppState { /* private fields */ }
Expand description

The shared, cheaply cloned handle every route works through.

Implementations§

Source§

impl AppState

Source

pub fn new(store: Arc<dyn EventStore>, factory: AgentFactory) -> Self

Builds server state over store, using factory to turn submitted definitions into live agents. Auth is off and the clock and random source are the runtime defaults until set with the with_* methods.

Source

pub fn with_client_lease_ttl(self, ttl: Duration) -> Self

Sets how long a client-driven run’s lease stays current without the driver presenting its token again (default 60s). Past this, the run reports no attached driver and a re-open may take it from the driver that has gone quiet. Additive and off-default; a test or a seed shortens it to make a driverless client run observable quickly, exactly as with_poll_interval shortens the stream poll. salvor serve reads it from SALVOR_CLIENT_LEASE_TTL_SECS.

Source

pub fn with_auth_token(self, token: impl Into<String>) -> Self

Requires Authorization: Bearer <token> on every request. Without this, the server trusts its caller (the reverse-proxy posture).

Source

pub fn with_model_executor(self, executor: Arc<dyn ModelExecutor>) -> Self

Injects the general model executor the server performs a client-driven run’s model step through. Additive and off by default (the existing new leaves it unset), so no caller that predates it changes behavior. salvor serve wires a default here; another host injects its own, exactly as it supplies its own AgentFactory.

Source

pub fn with_tool_registry(self, registry: Arc<ToolRegistry>) -> Self

Injects the general tool registry the server performs a client-driven run’s tool step through. Additive and off by default (the existing new leaves it unset), so no caller that predates it changes behavior. salvor serve wires an empty registry here; another host injects one holding its own tools, exactly as it supplies its own AgentFactory and ModelExecutor.

Source

pub fn with_client_tools(self, decls: Arc<ClientToolRegistry>) -> Self

Loads the client-performed tool declarations this server answers client-tool intents against. Additive and empty by default, so no caller that predates it changes behavior: without a declaration, every client-tool intent is a clean unknown_tool and nothing is written.

This is the ONLY way declarations enter the process. There is no endpoint that accepts one, on purpose: a declaration fixes the effect class, and a client that could declare its own would be choosing whether its own write is subject to the write-ahead rule. See crate::client_tools for the full argument.

Source

pub fn with_hooks(self, clock: ClockFn, random: RandomFn) -> Self

Injects the clock and random source every Runtime this state builds uses. Deterministic tests pass fixed functions so full logs compare equal across a control run and a recovered one.

Source

pub fn with_poll_interval(self, interval: Duration) -> Self

Sets how often the event stream polls the store for new events (default 50ms). Tests shorten it so a streamed run completes quickly.

Source

pub fn with_wake_interval(self, interval: Duration) -> Self

Sets how often the wake sweeper looks for runs whose durable timer has come due (default DEFAULT_WAKE_INTERVAL). Duration::ZERO turns the sweeper off entirely, for a host that wakes runs some other way.

Same shape as with_poll_interval, and a test shortens it for the same reason: to make a sweep observable without waiting on a wall clock.

Source

pub fn store(&self) -> Arc<dyn EventStore>

The event store every request reads from and writes through.

Source

pub fn auth_token(&self) -> Option<&str>

The expected bearer token, when auth is required.

Source

pub fn poll_interval(&self) -> Duration

How often the event stream polls for new events.

Source

pub fn wake_interval(&self) -> Duration

How often the wake sweeper looks for due timers. Duration::ZERO means no sweeper runs on this server.

Source

pub fn model_executor(&self) -> Option<Arc<dyn ModelExecutor>>

The injected model executor, if a host wired one. None means the server cannot perform a model step and the endpoint says so.

Source

pub fn tool_registry(&self) -> Option<Arc<ToolRegistry>>

The injected tool registry, if a host wired one. None means the server cannot perform a tool step and the endpoint says so; a wired-but-empty registry instead reports each tool as unknown_tool.

Source

pub fn client_tools(&self) -> Arc<ClientToolRegistry>

The client-performed tool declarations the operator loaded. Empty unless with_client_tools was called, and an empty set answers every client-tool intent with unknown_tool.

Source

pub fn now(&self) -> OffsetDateTime

Reads the current instant from this state’s injected clock, or the real UTC clock when none was injected. This stamps envelopes the server records itself (the model-step intent and completion), the same clock edge a Runtime would use, so deterministic tests still compare logs.

Source

pub fn runtime(&self) -> Runtime

A fresh runtime over the shared store, with this state’s clock and random source.

Source

pub async fn build_agent( &self, definition: AgentDefinition, ) -> Result<BuiltAgent, String>

Builds a live agent from a submitted definition, through the factory.

§Errors

The factory’s human message when the definition will not build.

Source

pub fn register_agent(&self, registered: RegisteredAgent) -> String

Records a registered agent under its content hash, returning that hash.

Source

pub fn agent(&self, hash: &str) -> Option<RegisteredAgent>

The definition registered under hash, if any.

Source

pub fn agent_hashes(&self) -> Vec<String>

Every registered agent’s hash, sorted for a stable listing.

Source

pub fn store_graph(&self, hash: String, graph: Graph) -> bool

Records a validated graph document under hash, returning whether it was newly stored (true) or already present (false). Re-storing the identical document is idempotent: the second call keeps the first and reports false, the graph counterpart of an agent register’s created.

Source

pub fn graph(&self, hash: &str) -> Option<Graph>

The graph document stored under hash, if any. None is the unknown_graph case.

Source

pub fn graph_hashes(&self) -> Vec<String>

Every stored graph’s hash, sorted for a stable listing.

Source

pub fn run_ctx( &self, run_id: RunId, log: Vec<EventEnvelope>, ) -> Result<RunCtx, RuntimeError>

Builds a per-run RunCtx over log, with this state’s clock and random source, so the graph engine can drive a run through the same durability substrate the built-in loop uses. This is the graph counterpart of runtime: the built-in loop reaches the store through a Runtime; the graph engine reaches it through a RunCtx it drives directly, and both share the exact clock/random hooks so a deterministic test’s logs still compare equal.

§Errors

RuntimeError::Replay when log is not a well-formed run history.

Source

pub fn begin_run(&self, run_id: RunId)

Marks a run as being driven. Call this synchronously before spawning the driver task, so a stream opened at the same instant sees the run as active rather than racing the task’s first store write.

Source

pub fn set_handle(&self, run_id: RunId, handle: JoinHandle<()>)

Records the driver task’s handle, for aborting at shutdown.

Source

pub fn end_run(&self, run_id: RunId)

Marks a run’s drive as ended and drops its handle. The task calls this as its last act, whether it completed, parked, or errored.

Source

pub fn is_run_active(&self, run_id: RunId) -> bool

Whether a run is still being driven by a task in this process.

Source

pub fn lease_client_run(&self, run_id: RunId, record_prompts: bool) -> String

Records (or re-leases) a client-driven run, returning a fresh drive token. Called by the open endpoint for a new run, and for a re-open the open endpoint has already decided is allowed: no lease stands, or the one that does has lapsed, or the run is finished. Minting here is unconditional, so it must never be reached while another driver’s lease is current; that is the whole point of the check in client_runs::open, which reads current_client_lease first.

Source

pub fn touch_client_run(&self, run_id: RunId)

Refreshes a client-driven run’s last_seen to now, the driver’s proof of life. Called by the lease gate on every guarded operation (the driver presented its token, so it is alive); a no-op for a run this process holds no lease for.

Source

pub fn current_client_lease( &self, run_id: RunId, ) -> Option<(ClientRunLease, Duration)>

A client-driven run’s lease and how long is left before it lapses, when this process holds one whose driver has proved it is alive within the lease TTL. None covers both “no lease here” (a fresh process, a run this server never opened) and “the lease lapsed” (the tab closed, the SDK exited, the driver crashed), because to everything downstream those are the same fact: nobody is driving this run.

This is the one place the TTL comparison happens, so the liveness field on GET /v1/runs and the re-open refusal in client_runs::open can never disagree about whether a driver is still attached. The remaining time comes back with the lease because the refusal has to tell the second caller when to try again, and computing it twice would invite the two answers to drift.

Source

pub fn client_run_driver_live(&self, run_id: RunId) -> bool

Whether a live driver is currently attached to a client-driven run: this process holds a lease for it AND the driver presented its token within the lease TTL. A lapsed lease (the tab closed, the SDK exited) reports false: the client-driven half of the liveness evidence GET /v1/runs carries.

Source

pub fn client_run(&self, run_id: RunId) -> Option<ClientRunLease>

The lease for a client-driven run, if this process opened one under run_id, whether or not its driver has been heard from lately. The drive-token gate wants exactly this: a driver that went quiet for longer than the TTL and then presents its token again is still the run’s writer, as long as nobody took the run away from it in the meantime. Ask current_client_lease instead when the question is whether someone is driving right now.

Source

pub fn client_lease_ttl(&self) -> Duration

How long a client-driven run’s lease stays current without the driver presenting its token again, the TTL every freshness judgment here is made against. Read by the heartbeat endpoint, which answers with it so a driver about to be busy for a while knows how often it has to beat.

Source

pub fn release_client_run( &self, run_id: RunId, presented: Option<&str>, ) -> LeaseRelease

Hands a client-driven run’s lease back when presented is the token holding it, so the next open takes the run immediately instead of waiting out the TTL.

The token check and the removal happen under one lock, so a release can only ever drop the lease the caller was actually holding, never one minted in between by a driver that took the run over.

Only the lease goes. Nothing about the run itself changes, its recorded driven_by: client included, so a later open adopts it back exactly as it would after a restart.

Source

pub fn clear_client_lease(&self, run_id: RunId, keep: Option<&str>) -> bool

Drops a client-driven run’s lease unless keep is the token that holds it, reporting whether a lease went. What a resolve calls: recording a dangling write by hand says the driver that opened that write never came back, so the lease it left behind is holding the run for nobody and the next open should not have to wait out the TTL for it.

keep is how the client-driven resolve keeps its own lease. That caller presented its current token to get in, which is the driver saying it is right here, so the lease is not a dead one and taking it away would strand a driver mid-run. Every other resolve passes None, because no token was presented and nothing says a driver is still attached.

Source

pub fn is_client_run(&self, run_id: RunId) -> bool

Whether run_id names a client-driven run this process opened.

Source

pub fn mark_unwakeable_warned(&self, run_id: RunId) -> bool

Records that the wake sweeper has warned about this run being unwakeable here. Returns true the first time (the caller logs at WARN) and false on every later call for the same run while the record stands (the caller logs the same fields at DEBUG instead).

Source

pub fn unwakeable_warned(&self, run_id: RunId) -> bool

Whether the sweeper has already warned about this run. Read-only, unlike mark_unwakeable_warned, which always records a sighting; a test uses this to check the record without flipping it.

Source

pub fn clear_unwakeable_warned(&self, run_id: RunId)

Clears a run’s unwakeable-warned record: it woke, so the next time it naps and cannot be rebuilt here is a fresh first sighting.

Source

pub fn prune_unwakeable_warned(&self, still_due: &HashSet<RunId>)

Drops every unwakeable-warned record for a run not in still_due. Called once per sweep pass before processing, so a run that leaves the due set some other way than being driven (the only other way its record could go stale) does not carry a warning into a future nap that has nothing to do with this one.

Source

pub fn abort_all(&self)

Aborts every in-flight driver task. Durability is unaffected: each event was persisted before the task moved on, so an aborted run is recoverable exactly as after a kill -9.

Trait Implementations§

Source§

impl Clone for AppState

Source§

fn clone(&self) -> AppState

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

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> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + 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: Sized + 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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

type Error = !

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