Skip to main content

Module executor

Module executor 

Source
Expand description

The model-executor seam: the general injection point a host supplies so the server can perform a model call on a client-driven run’s behalf.

§Why it is a seam, not baked in

This mirrors the AgentFactory decision exactly. The server owns the mechanism of a durable model step (append the write-ahead intent, perform the call, append the completion, answer retries from the log), but it must not own the policy of which provider runs, where its credential comes from, or how the request is shaped. Salvor is for anyone building on it, browser or backend; aarg is only the first consumer. So the executor is a trait the embedding binary implements and injects, never a hard-wired provider.

salvor serve wires a default LlmModelExecutor from its own client-construction path, so the feature works out of the box; another host (a future aarg serve) injects its own executor resolving a keychain credential, and nothing consumer-specific leaks into salvor-server.

§The two methods

  • ModelExecutor::execute performs a single call and returns the assembled MessageResponse. This backs the non-streaming model step.
  • ModelExecutor::open_stream opens the provider stream and returns a ModelStream the server pumps: each event feeds a live ticker frame and a [MessageAccumulator], and the assembled completion is recorded once at the end. This backs the server-sent-events model step.

The request crosses the seam as a raw Value (the caller’s canonical request JSON), not a typed MessageRequest, because the server hashes and records exactly those bytes: the hash it recorded is the hash it sent.

An executor error is a plain String, the same human-message convention the agent factory uses. A provider failure maps to the server error envelope without a completion being recorded, so the intent is left dangling (legal, the crash story) and the run stays drivable.

§Naming the key on a 401, the way the CLI already does

A raw 401 from salvor_llm::Error::Api says the request was rejected; it says nothing about where to fix it. The CLI’s contextualize_auth_error (salvor-cli/src/commands.rs) solves this for the agent-driven run/resume path because it still has the agent’s own [llm] api_key_env in scope. This executor has no such per-agent config to read: a client-driven run’s model step is served by the one LlmModelExecutor salvor serve wires for the whole process, built by Config::from_env, which only ever reads ANTHROPIC_API_KEY (see salvor-llm/src/config.rs). So contextualize_401 names that fixed variable directly, and points at the machine running the server rather than the client’s own environment: for a client-driven run the key lives with the server, not the caller driving it over HTTP.

Structs§

LlmModelExecutor
The default ModelExecutor, wrapping a general salvor_llm::Client.

Traits§

ModelExecutor
Performs a model call on behalf of a client-driven run. Injected by the embedding binary, exactly like AgentFactory.
ModelStream
A stream of provider events opened by ModelExecutor::open_stream.