pub trait WorkerFacade: Send + Sync {
// Required methods
fn caller_project(&self, caller: &SessionSlot) -> Option<CallerProject>;
fn spawn_worker<'life0, 'life1, 'async_trait>(
&'life0 self,
caller: &'life1 SessionSlot,
label: String,
charter: String,
kick: Option<String>,
resume_kick: Option<String>,
interactive: bool,
resume_session: bool,
mcp_families: Option<Vec<String>>,
cwd: Option<String>,
) -> Pin<Box<dyn Future<Output = Result<WorkerSpawnReply, WorkerSpawnError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn update_worker(
&self,
caller: &SessionSlot,
label: &str,
charter: Option<String>,
kick: Option<String>,
resume_kick: Option<String>,
mcp_families: Option<Vec<String>>,
) -> Result<(), WorkerUpdateError>;
fn despawn_worker<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
caller: &'life1 SessionSlot,
label: &'life2 str,
force: bool,
) -> Pin<Box<dyn Future<Output = Result<DespawnOutcome, WorkerDespawnError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn list_workers(&self, caller: &SessionSlot) -> Vec<WorkerStatus>;
fn list_all_workers(&self) -> Vec<WorkerStatus>;
fn capacity(&self, caller: &SessionSlot) -> Option<WorkerCapacity>;
fn deliver_worker_prompt<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
caller: &'life1 SessionSlot,
target_label: &'life2 str,
wrapped: WrappedPrompt,
) -> Pin<Box<dyn Future<Output = Result<WorkerTargetStatus, WorkerDeliverError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn deliver_worker_prompt_to_project<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
&'life0 self,
caller: &'life1 SessionSlot,
org: &'life2 str,
project: &'life3 str,
target_label: &'life4 str,
wrapped: WrappedPrompt,
) -> Pin<Box<dyn Future<Output = Result<WorkerTargetStatus, WorkerDeliverError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait;
fn deliver_prompt_to_lead<'life0, 'life1, 'async_trait>(
&'life0 self,
caller: &'life1 SessionSlot,
wrapped: WrappedPrompt,
) -> Pin<Box<dyn Future<Output = Result<WorkerTargetStatus, WorkerLeadDeliverError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
}Expand description
The narrow workspace-state surface workers MCP Tool impls depend on.
spawn_worker is async because the production impl awaits a
oneshot receiver wired into Command::SpawnWorker. The remaining
methods are synchronous (one mutex acquire over in-memory state).
Required Methods§
Sourcefn caller_project(&self, caller: &SessionSlot) -> Option<CallerProject>
fn caller_project(&self, caller: &SessionSlot) -> Option<CallerProject>
Resolve the caller’s project key + lead/worker flag.
Returns None when caller matches no known session.
Sourcefn spawn_worker<'life0, 'life1, 'async_trait>(
&'life0 self,
caller: &'life1 SessionSlot,
label: String,
charter: String,
kick: Option<String>,
resume_kick: Option<String>,
interactive: bool,
resume_session: bool,
mcp_families: Option<Vec<String>>,
cwd: Option<String>,
) -> Pin<Box<dyn Future<Output = Result<WorkerSpawnReply, WorkerSpawnError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn spawn_worker<'life0, 'life1, 'async_trait>(
&'life0 self,
caller: &'life1 SessionSlot,
label: String,
charter: String,
kick: Option<String>,
resume_kick: Option<String>,
interactive: bool,
resume_session: bool,
mcp_families: Option<Vec<String>>,
cwd: Option<String>,
) -> Pin<Box<dyn Future<Output = Result<WorkerSpawnReply, WorkerSpawnError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Dispatch a Command::SpawnWorker and await its synchronous
reply. Gating (lead-only, non-empty label, non-empty charter)
happens before dispatch. resume_kick is persisted rather than
delivered now; it replaces the generic restart note when this
worker resumes after a forge restart with a turn that was cut off.
A worker that was idle when forge stopped resumes with nothing
delivered. interactive keeps the built-in
AskUserQuestion tool, which every other worker is denied.
resume_session resumes the label’s most recent prior session
instead of starting fresh. A label with none resolves to
ResumeTarget::None, which starts a fresh session and says so in
the reply’s SessionChoice; only a lookup that failed is an
error.
cwd names the tree the worker should run in when it is not the
project’s own - an absolute or ~-prefixed path, resolved to its
repo root. None keeps the project’s path for a fresh spawn, and
adopts the row’s recorded tree for a resume that states none.
Sourcefn update_worker(
&self,
caller: &SessionSlot,
label: &str,
charter: Option<String>,
kick: Option<String>,
resume_kick: Option<String>,
mcp_families: Option<Vec<String>>,
) -> Result<(), WorkerUpdateError>
fn update_worker( &self, caller: &SessionSlot, label: &str, charter: Option<String>, kick: Option<String>, resume_kick: Option<String>, mcp_families: Option<Vec<String>>, ) -> Result<(), WorkerUpdateError>
Merge the supplied fields onto the stored dynamic-worker row for
label in the caller’s project, leaving a None field at its
stored value. Errors with NoSuchWorker when no row exists:
update revises an existing worker, it never creates one. Takes
effect on that worker’s next respawn, since a session’s system
prompt and tool list are fixed when the session spawns.
mcp_families follows the same contract: None leaves the
stored selection alone, Some(names) replaces it - canonicalised
by the tool - and Some(empty) resets it to every family.
Sourcefn despawn_worker<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
caller: &'life1 SessionSlot,
label: &'life2 str,
force: bool,
) -> Pin<Box<dyn Future<Output = Result<DespawnOutcome, WorkerDespawnError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn despawn_worker<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
caller: &'life1 SessionSlot,
label: &'life2 str,
force: bool,
) -> Pin<Box<dyn Future<Output = Result<DespawnOutcome, WorkerDespawnError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Dispatch a Command::DespawnWorker and await its result.
Gating (lead-only, non-empty label) happens before dispatch.
force removes a dirty worktree; without it a dirty worktree
blocks the despawn (DespawnOutcome::Blocked).
Sourcefn list_workers(&self, caller: &SessionSlot) -> Vec<WorkerStatus>
fn list_workers(&self, caller: &SessionSlot) -> Vec<WorkerStatus>
Snapshot of every worker in the caller’s project. Returns an empty Vec when the caller resolves to no project.
Sourcefn list_all_workers(&self) -> Vec<WorkerStatus>
fn list_all_workers(&self) -> Vec<WorkerStatus>
Snapshot of every project’s workers: the real workspace walks
list_projects in config order, the mock sorts its project keys.
Sourcefn capacity(&self, caller: &SessionSlot) -> Option<WorkerCapacity>
fn capacity(&self, caller: &SessionSlot) -> Option<WorkerCapacity>
The caller’s project worker capacity: the cap the spawn path
enforces (max_workers in the project’s [[orgs.projects]]
entry, else DEFAULT_MAX_WORKERS_PER_PROJECT) paired with the
live count.
A plain data read - the same one the spawn path’s cap check
performs. Returns None when the caller resolves to no
project.
Sourcefn deliver_worker_prompt<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
caller: &'life1 SessionSlot,
target_label: &'life2 str,
wrapped: WrappedPrompt,
) -> Pin<Box<dyn Future<Output = Result<WorkerTargetStatus, WorkerDeliverError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn deliver_worker_prompt<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
caller: &'life1 SessionSlot,
target_label: &'life2 str,
wrapped: WrappedPrompt,
) -> Pin<Box<dyn Future<Output = Result<WorkerTargetStatus, WorkerDeliverError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Dispatch a worker-bound wrapped prompt. Delivered means the
prompt was accepted - handed to the target’s session queue, held
for its turn end, or parked for its connect - which is the whole
claim the sender’s ack makes; anything that reached no session is
an error. UnknownLabel when no live worker matches.
Sourcefn deliver_worker_prompt_to_project<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
&'life0 self,
caller: &'life1 SessionSlot,
org: &'life2 str,
project: &'life3 str,
target_label: &'life4 str,
wrapped: WrappedPrompt,
) -> Pin<Box<dyn Future<Output = Result<WorkerTargetStatus, WorkerDeliverError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
fn deliver_worker_prompt_to_project<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
&'life0 self,
caller: &'life1 SessionSlot,
org: &'life2 str,
project: &'life3 str,
target_label: &'life4 str,
wrapped: WrappedPrompt,
) -> Pin<Box<dyn Future<Output = Result<WorkerTargetStatus, WorkerDeliverError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
Dispatch a worker-bound wrapped prompt to a project named by
its (org, project) pair rather than the caller’s own. The
caller lives in another project, so the target cannot be
resolved from it. Mirrors deliver_worker_prompt otherwise:
an unknown label is an error and a sleeping target is not
auto-spawned.
Sourcefn deliver_prompt_to_lead<'life0, 'life1, 'async_trait>(
&'life0 self,
caller: &'life1 SessionSlot,
wrapped: WrappedPrompt,
) -> Pin<Box<dyn Future<Output = Result<WorkerTargetStatus, WorkerLeadDeliverError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn deliver_prompt_to_lead<'life0, 'life1, 'async_trait>(
&'life0 self,
caller: &'life1 SessionSlot,
wrapped: WrappedPrompt,
) -> Pin<Box<dyn Future<Output = Result<WorkerTargetStatus, WorkerLeadDeliverError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Dispatch a wrapped prompt from a worker back to its lead.
Caller MUST be a worker. The target lead is resolved from the
caller’s WorkerEntry::spawned_by_session_id. Same
wire-shape contract as deliver_worker_prompt: Delivered
means the lead’s session accepted it, and one the session could
not take is an error.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".