Skip to main content

Crate forge_workspace

Crate forge_workspace 

Source
Expand description

forge-workspace - multi-session orchestrator and view-facing facade.

Pools forge_agent::Agent instances behind a single Workspace handle. One DomainSession per active session holds workspace-internal routing metadata (AgentHandle slot, claude-issued session_id, pending-interaction mailbox). Operational state a view renders (lifecycle, cwd, turn state, account info) stays on the view’s side of the wire; workspace is a thin proxy that reacts to Commands in and emits SessionUpdates out. A per-session actor pumps events from AgentHandle::take_events(), translates them into SessionUpdates, and routes Commands back.

§Communication contract

The view ↔ workspace contract is one entry point in each direction:

  • view → workspace: Workspace::dispatch takes a protocol::Command. One enum, one entry point.
  • workspace → view: Workspace::subscribe_mirror and Workspace::subscribe_answerer return receivers for protocol::SessionUpdate. Every caller gets a stream of its own, so a second view attaches beside the first, and a stream carries what is emitted after it subscribes. The socket’s own fold takes the mirror; each client takes the answering or mirror role it declared, through ViewSurface::subscribe_client. The role decides one thing: whether the core may park a prompt on that subscriber’s reply.

No callback hooks, and no state shared between a view and the core. A view does not hold an Arc<AgentHandle>: every outbound call goes through Workspace::dispatch(Command); query-style refreshes (refresh_context_usage, refresh_mcp_snapshot) and direct accessors (settings_documents, project_memory_path, config_dir_for) live as inherent methods on Workspace. The handle stays on the workspace’s DomainSession.

§Facade scope (intentionally thin)

The MVVM boundary between a view and forge-agent is enforced at the dependency graph level: no view depends on forge-agent; everything routes through forge-workspace. The workspace exposes forge-agent’s submodules verbatim via pass-through pub use (see the env, tooling, translate, user_interaction and userdata modules below). Types reached through them are defined in forge-agent - the workspace just exposes them under the workspace name so a view can keep its dep graph clean.

Re-exports§

pub use dictate::DictateAxes;
pub use dictate::DictateBind;
pub use dictate::DictateFailure;
pub use dictate::DictateMode;
pub use dictate::DictateModel;
pub use dictate::DictateModelState;
pub use dictate::DictateOverrideUpdate;
pub use dictate::DictateOverrides;
pub use dictate::DictateRole;
pub use dictate::DictateSettings;
pub use dictate::DictateSnapshot;
pub use domain_session::ContextUsage;
pub use domain_session::DomainSession;
pub use domain_session::McpServers;
pub use domain_session::TurnLiveness;
pub use domain_session::liveness_of;
pub use error::WorkspaceError;
pub use handoff::ShippedSkill;
pub use handoff::SkillInstall;
pub use handoff::install_skill;
pub use handoff::shipped_skills;
pub use handoff::skill_dir;
pub use handoff::skill_path;
pub use protocol::Command;
pub use protocol::DictateOutcome;
pub use protocol::DispatchError;
pub use protocol::NoticeSeverity;
pub use protocol::PromptSource;
pub use protocol::SessionUpdate;
pub use target::SessionTarget;
pub use tts::TtsSettings;
pub use tts::TtsSnapshot;
pub use tts::TtsView;
pub use update_fanout::SeatUpdate;
pub use vault::VaultState;
pub use views::AccountGatewayView;
pub use views::AccountLoadingRow;
pub use views::AccountPoolView;
pub use views::AccountUsageView;
pub use views::ProjectView;
pub use workspace::testing::set_seat_ring_cap;
pub use workspace::BootWaveTarget;
pub use workspace::LEAD_RESTART_NOTE;
pub use workspace::PendingInteractionKind;
pub use workspace::PricingFetch;
pub use workspace::PricingFetcher;
pub use workspace::SessionChipInfo;
pub use workspace::SessionChipState;
pub use workspace::SettingsSaveError;
pub use workspace::Workspace;
pub use mcp::cron::schedule::next_fire_after;
pub use mcp::gotify::types::GotifyNotification;
pub use mcp::peers::types::MessageId;
pub use mcp::peers::types::WrappedKind;
pub use mcp::peers::types::WrappedPrompt;
pub use mcp::workers::types::LiveWorkerState;
pub use mcp::workers::types::WorkerEntry;
pub use config::BrowserSettings;
pub use config::ConfigReload;
pub use config::PluginSettings;
pub use mcp::agents::build_server as build_agents_server;
pub use mcp::peers::facade::MockWorkspaceFacade;
pub use mcp::peers::types::PeerLiveness;
pub use mcp::peers::types::PeerStatus;
pub use mcp::workers::facade::CallerProject;
pub use mcp::workers::facade::MockWorkerFacade;
pub use mcp::workers::facade::WorkerFacade;

Modules§

account_cache 🔒
Persistent forge state: the per-account usage cache.
account_loader 🔒
Per-account boot-time loading task.
bench
Benching a model on this machine’s own material: which models a run can load, the config each one runs under, and the state and results the page reads.
biometric 🔒
The biometric proxy’s server half: each device’s enrolment, each purpose’s opaque blob, and revocation.
board
The board: one answer for every derived fact a reader of the task list needs.
browser
The browser the sessions drive: the port the tools ask through, and the hand-offs that park on the person.
catalogue
The dictation model catalogue: the feed’s check and the models page’s view.
chase
The chase sweep: the pass that makes the board drive instead of report.
config 🔒
forge.toml schema + loader.
conversation_turns
Where a conversation’s turns open, in the shape the fold reads them.
conversation_window
The window a conversation is cut to when it is held or handed over.
crons 🔒
The cron cluster on Workspace: the durable-cron store accessor and its mutation helpers, the asleep-slot prompt buffers, the fire router, the scheduler task, and the cross-crate seed helper.
dictate 🔒
Dictation - the [dictate] section in forge.toml, and the preflight pass that makes the models usable before forge starts.
documents
The document hand-off’s parked ask: one document handed to the reader, held until their answer.
domain_session 🔒
Workspace-side per-session state.
env
error 🔒
Error types surfaced by Workspace::new and friends.
file_index
One working tree’s files, and the ranking the @ trigger reads a query against.
gotify 🔒
The Gotify seam on Workspace: the forge.toml [gotify] config accessor, subscription CRUD (durable rows in the redb store, ephemeral ones in memory), the subsystem start/stop lifecycle, and the GotifyHost port impl the forge-connectors pump drives.
handoff 🔒
The handoff brief: forge’s own ground truth, and the handing-over session’s judgment.
healing 🔒
Auto-heal for dead seats: the supervisor that brings a durable lead or worker back when its subprocess closes while it should be up.
hub
The Hugging Face Hub calls the speaking model’s install makes: the repository’s current revision, its blobs with their LFS digests, and the download of one pinned file.
idle_sweep
The idle lead sweep: forge injects the board sweep when a project’s lead has nothing in flight.
install
Installing a model from the feed, and resolving which model each role runs: the doc’s own download link, a size-checked fetch into the models directory, the record of what arrived, and the config-key / runtime-pick / compiled-pin order an active model comes from.
launch_settings
The settings a session is spawned with.
mcp 🔒
In-process MCP server forge exposes to every spawned claude subprocess.
output_tail
A command’s own output: the tail of the file the CLI streams it to.
parked 🔒
Payloads that arrived while their slot had no live session, addressed by (org, project, label) - the triple the sessions table is keyed by.
plugins 🔒
Plugin and marketplace actions over the command bus.
prompt
What a composer’s text means at forge’s own boundary.
protocol
Command + SessionUpdate channel envelopes between a view and forge-workspace. A view dispatches Commands; workspace per-session tasks emit SessionUpdates back through the workspace’s fan-out.
provider_probe 🔒
Workspace-side routing of account probes through the forge-gateway backends, shared by the boot loader and the 60 s usage poller.
review 🔒
The review-conversation cluster on Workspace: durable review-thread CRUD over the redb store, review submit / list / get, worker reply + resolve, the per-turn activity drain that notifies the reviewer, and the dead-branch sweep run off the startup path.
session_task 🔒
Per-session actor. Owns one Arc<AgentHandle>’s event drain (AgentHandle::take_events) plus a per-session Command receiver. Translates each AgentEvent into the matching SessionUpdate envelope and emits onto the workspace-wide fan-out, which hands one update to every subscriber. Mutates DomainSession inline before each emit so workspace-side projections stay current.
settings
The class catalogue and the effective-config document.
settings_ask 🔒
The held configuration write.
settings_write 🔒
The comment-preserving writer behind the settings editor.
single_instance 🔒
Single-instance boot guard.
slack 🔒
The Slack seam on Workspace: one client per configured workspace, the subscription records sessions create, and the boot verification that proves each token.
spawn 🔒
App-level spawn command handlers. Called from crate::Workspace::dispatch when an App-level Command::SpawnProject arrives. Each handler resolves the id the session will run under, emits SessionUpdate::Spawning under it, and kicks off the agent spawn. The matching Connected arrives later under the same key.
store
Machine-local embedded database (redb).
subagent_cards
The session’s sub-agent instances, folded as the frames arrive.
systemone 🔒
The System One decision tools’ workspace leg: the boot-time client construction, shared by the real boot and the testing stubs so both agree on trust handling.
target 🔒
Identifiers + the SessionTarget enum used to address sessions.
tasks 🔒
The task cluster on Workspace: the durable task store accessor and its mutation helpers, a second impl block beside crons.rs so every caller keeps its path.
terminal
The per-seat terminals: the registry, the hand-off that parks on the person, and the idle clock.
tooling
translate
tts
The [tts] section: what the speaking role runs, the Hugging Face install that supplies it, and the read the models page and the settings card draw.
update_fanout 🔒
Fan-out for the workspace’s SessionUpdate stream.
user_interaction
Pass-through for the agent’s typed tool-input parsers (AskUserQuestion, Monitor), which the server reads when folding a tool call into the block a view draws.
userdata
vault 🔒
The process-wide vault session and its audit.
vault_ask 🔒
The held vault call.
views 🔒
Read-only views surfaced by crate::Workspace::list_projects.
voice
The per-seat voice service: listeners, the sentence queue, and synthesis.
work
The seat’s working tree: what a scan of it found, when that was, and the loop that keeps it fresh for the seats a view is showing.
workspace 🔒
The orchestrator.

Structs§

AgentHandle
Handle returned by Agent::spawn. Owns the channels + a thin passthrough to the bridge’s direct-return accessors.
BackgroundTask
One of the seat’s live tasks, with the command its own card carried where forge has seen both.
ProjectKey
Project root path key - the canonicalised, sanitised string form produced by forge_agent::userdata::catalog::scan::project_key_for_directory. Equivalent to the directory names you see under <config_dir>/projects/.
SessionLaunchSettings
SessionSlot
The (org, project, label) triple naming one session. org and project are the forge.toml names - the same pair the redb sessions table is keyed by - and label carries the role: LEAD_LABEL for a project’s lead, the worker’s own label otherwise.

Enums§

Context
Destination conventions. Not a domain or vocabulary hint: it will not protect technical terms, which are a Styling concern.
LoadingState
Boot-time loading state for an account. The boot wave and the cron spawn path wait for every account in the map to resolve to Ready or Bailed; the selection walk skips Loading and keeps Bailed as its last resort. A bailed account’s usage is None by construction (the loader clears it on the transition).
PermissionMode
Which permission flow the claude binary should use for tool invocations. Mirrors the upstream CLI’s six-variant set.
RuntimeSessionState
Structure
Whether the model may turn enumerable content into a bulleted list.
Styling
The register the transcript is rewritten into.
TurnErrorClass
Coarse classification of a turn-level error message. The classifier itself lives in forge-agent’s translate::error_handling; this enum is the wire shape it produces.
Unusable
Why an account is held out of the usable tier. Which reason can apply is keyed on the account’s billing kind: only a window-billed account can saturate, so on a spend row an unusable account can only be probe-blocked. A snapshot whose source is not the account backend’s is ignored here, so a cache surviving a forge.toml provider edit cannot saturate the row it landed on.
UsageFetchStatus
Classification of the latest usage-poll attempt outcome for an account. Feeds unusable_reason’s probe-blocked branch and the backoff schedule.

Constants§

LEAD_LABEL
The label reserved for a project’s own agent. A caller addresses it as the label of an agents__send_message target; agents__spawn rejects the label so no live worker can shadow the keyword. Reserved label for a project’s own agent, addressed as the label of an agents__send_message target. agents__spawn rejects it so no live worker can shadow the keyword.

Functions§

has_a_transcript_row
Whether a transcript row carries a frame, which is what tells a copy’s numbering from the file’s when the frames the CLI never wrote are in it. Whether a transcript row carries this frame.
session_history
The messages a session’s transcript holds and the compactions it records. The same read the spawn performs, available for a session that is already running.
session_history_main_thread
session_history over the session’s own rows only: sub-agent sidecars are not opened or folded. The handoff brief takes this one, so it pays for neither the frames nor the parse. A page read does not: a dispatch row draws its sidecar frames (#1763).
transcript_rows
The rows of a session’s transcript that sit strictly before below, for a paging read that has walked below the window a conversation is kept in.