Skip to main content

ViewSurface

Struct ViewSurface 

Source
pub struct ViewSurface {
    workspace: Arc<Workspace>,
    usage_cache: Mutex<Option<(Instant, UsageReport)>>,
    pricing_refill: AtomicBool,
    usage_scan: Mutex<()>,
    usage_scans: AtomicU64,
    usage_gate: Mutex<Option<Arc<Barrier>>>,
}
Expand description

A view’s read handle on the core.

Fields§

§workspace: Arc<Workspace>§usage_cache: Mutex<Option<(Instant, UsageReport)>>

The pool’s last scan and when it was taken, so a reader asking twice inside the window does not walk it twice. A Mutex rather than a second cache type: one report, one window.

§pricing_refill: AtomicBool

Whether a pricing refresh is already out. The fetch crosses the network, so the ask that finds one running is not a reason for a second.

§usage_scan: Mutex<()>

The one scan a cold cache runs: a second reader waits here rather than walking the pool beside the first.

§usage_scans: AtomicU64

How many scans were started, so a test can prove two misses ran one.

§usage_gate: Mutex<Option<Arc<Barrier>>>

Holds every miss at one point, so the race the guard covers is a barrier rather than a large pool that might finish first.

Implementations§

Source§

impl ViewSurface

Source

pub fn accounts(&self) -> AccountPoolView

The pool as the home snapshot and AccountsChanged both state it.

Delegated rather than rebuilt. The frame’s payload and the snapshot’s field must be one builder’s answer, or a client folding the frame and a client reading the snapshot can disagree (rule 25).

Source§

impl ViewSurface

Source

pub fn agents(&self) -> Agents

Every project’s agents: its lead, then its workers.

Source

pub fn failed_turn(&self, slot: &SessionSlot) -> Option<SystemTime>

When slot’s newest turn ended in failure, or None when nothing failed or a newer turn has since been committed.

The same fact a row carries, read for one seat: showing the seat spends that mark, and whether there was one to spend decides whether the home needs re-encoding for the connection that attached.

Source

pub fn seat_shown(&self, slot: &SessionSlot) -> bool

A client has slot on screen, which is this view saying the seat was shown: a death the reader had not been shown is spent with it - the mark and its reason leave the row - so a crash nobody watched is the durable trace until someone looks. Answers whether anything was spent, which is the connection’s cue to re-encode the home it holds.

Called when the connection’s showing and its subscription meet, from whichever half lands second. Both clients subscribe first on a resume, but the route effect that sends Showing races the page’s mount, so a showing alone is remembered rather than spent until the seat is actually watched.

Called after the seat’s own snapshot was encoded, deliberately: the read that spends the mark is the read that shows it.

Source§

impl ViewSurface

Source

pub fn biometric_enrolments(&self) -> Result<Vec<BiometricEnrolment>, String>

Every device’s enrolment, with no wrapped blob in it: a view draws which purposes a device enrolled and when each was last released, and the bytes stay behind a release.

A store that cannot be read is an error rather than an empty list, so the page can tell “no device is enrolled” from “the list could not be read”.

Source§

impl ViewSurface

Source

pub fn board_rows(&self, project: &str) -> Vec<BoardRow>

project’s live rows, with their derived facts.

Source

pub fn fleet(&self) -> Vec<FleetRow>

One row per project, for the fleet page.

Source§

impl ViewSurface

Source

pub fn slash_commands(&self, slot: &SessionSlot) -> Vec<AvailableCommand>

The slash commands the CLI last advertised for slot, named as they are typed. Empty for a seat whose session has not connected, and for one whose CLI advertised none.

The core retains them from the init frame each turn and from commands_changed, so a view that arrived after the turn started reads them here rather than waiting a whole turn for the next frame.

The wire carries the names bare, so the leading slash is added here: a caller renders name as it comes back.

Forge’s own commands are not in this list. A view rendering the / dropdown reads those from Self::forge_commands, and a name in both is drawn from the catalogue rather than the CLI’s copy.

Source

pub fn forge_commands() -> &'static [ForgeCommand]

forge’s own commands, which a view offers beside the ones the CLI advertises: a / dropdown is built from this table and Self::slash_commands together, so the two views cannot show different lists.

A name here shadows the CLI’s row for the same name (crate::commands::is_forge_command), so one row is drawn, with the catalogue’s words.

Source

pub fn subagents(&self, slot: &SessionSlot) -> Vec<AvailableAgent>

The subagents the CLI last advertised for slot, retained by the same frames and empty in the same two cases as Self::slash_commands.

Source

pub async fn resumable_sessions( &self, slot: &SessionSlot, ) -> Vec<SDKSessionInfo>

The sessions slot can jump back to with /resume, newest first, which is what the seat’s own claude --resume can find from the directory it runs in. See forge_workspace::Workspace::resumable_sessions for the set a lead and a worker each get.

Source

pub fn subagent_cards(&self, slot: &SessionSlot) -> Vec<SubagentCard>

The sub-agent instances the session at slot has folded, as the list it pushes when the list moves.

A record that folded the conversation’s messages itself would answer with whatever window of them it holds, which is not the conversation the cards describe.

Source

pub fn file_index(&self, slot: &SessionSlot) -> Option<Arc<FileIndex>>

The seat’s file index, as the seat’s own loop last walked it, or None until the first walk lands.

Held rather than walked here. The walk is a whole tree, and the seat’s loop is the one that takes it - throttled, and announced as FileIndexChanged when it moves - so this answers the store the loop writes rather than paying for a walk of its own.

Source

pub async fn file_index_for_record(&self, slot: &SessionSlot) -> Arc<FileIndex> ⓘ

The record’s file index for slot: the store, or the walk the seat’s loop would take, under the same gate - so the snapshot’s fallback and the first pass are one walk rather than two of the same tree.

Source

pub fn walk_file_index(&self, root: &Path) -> FileIndex

One working tree’s files, walked on demand. root is the session’s own scan cwd, which a git worker’s worktree overrides.

A page’s own walk. A page that holds no seat - nothing subscribes on its behalf, so no seat’s loop runs for it - has no store to read, and walks where it stands.

Source

pub fn respect_gitignore(&self) -> bool

The user’s own respectGitignore, the preference Self::walk_file_index runs with. Read on each call from the CLI’s per-user preferences document, so a flip reaches the next walk.

Source§

impl ViewSurface

Source

pub fn connectors(&self, project: Option<&str>) -> ConnectorsView

project scopes the subscription lists to that project’s own. None reports only the connection status, the way an unstamped session reads.

Source§

impl ViewSurface

Source

pub fn dictate_close(&self, key: &SessionSlot, initiator: u64) -> bool

The connection that was streaming a take for key has gone: drop the take it started and free the seat for the next one.

A connection’s own lifecycle rather than a user action, which is why it is a verb here and not a command: nothing a view dispatches means “the client went away”.

Source

pub fn dictate_axes(&self) -> DictateAxes

The axes a client that captures starts on and resets to: the [dictate] keys over the crate’s own defaults.

Source

pub fn dictate_push( &self, key: &SessionSlot, samples: &[f32], initiator: Option<u64>, ) -> bool

Push one frame of client-captured audio into a seat’s live take, answering whether the samples were kept. The take must belong to initiator: a seat’s live take can be another connection’s, and its audio is not the pushing connection’s to feed.

A data plane rather than a command: a client sends this ~50 times a second for as long as it talks, and the command bus’s dispatch is for the actions a view takes on the user’s behalf, not for the audio itself.

Source

pub fn dictate_read_aloud_push( &self, samples: &[f32], initiator: Option<u64>, ) -> bool

Self::dictate_push for the read-aloud recording, which belongs to no seat: the same data plane, kept only where the recording is the pushing connection’s.

Source

pub fn dictate(&self) -> DictateView

Source

pub fn dictate_models(&self) -> DictateModelsSnapshot

The models page’s whole read: the pinned models, the catalogue check, what the feed proposes, and every row it carries.

Read when the page subscribes and again from each forge_workspace::SessionUpdate::DictateModelsChanged; the check it reports on is started by the core at boot and by Command::DictateCatalogueCheck.

Source

pub fn dictate_bind(&self) -> DictateBind

The [dictate] bind key, as forge.toml declares it. A client draws the keyboard the record carries rather than hardcoding one.

Source

pub fn dictate_mode(&self) -> DictateMode

How a press maps onto a take, as forge.toml declares it.

Source§

impl ViewSurface

Source

pub async fn extensions(&self) -> ExtensionsView

Source§

impl ViewSurface

Source

pub fn header(&self, slot: &SessionSlot) -> SessionHeader

The session’s header facts: model, effort, permission mode and context usage.

One call rather than four, because a header renders them together and each read takes the session’s lock.

Source

pub fn mcp_servers(&self, slot: &SessionSlot) -> Option<McpServers>

The MCP servers the session’s bridge last reported, and the failure standing beside them when the read did not complete.

MCP is configured per session rather than per account, so this is the session’s own set. None until the first snapshot lands, as opposed to a snapshot that carries none.

Source

pub fn processes(&self, slot: &SessionSlot) -> Option<ProcessSnapshot>

The last OS walk of the session’s process tree.

The walk is driven by whoever owns the tick that performs it and the core holds its answer, so this neither performs one nor waits for the next: a slot nothing has walked reads as None.

The snapshot carries the instant it was taken, and a view draws it: a walk is only ever taken for the session a view is looking at, so the answer here can be arbitrarily old and must not be drawn as though it were taken now.

Source

pub async fn work( &self, slot: &SessionSlot, cwd: &Path, review: bool, ) -> WorkSnapshot

The seat’s working tree, read on the loop’s own rule: the stored scan while it is inside the snapshot window, a new one past it.

The record’s read is the seat’s first read, and the loop’s too. A held seat’s snapshot takes the tree under the same gate the watch’s first pass uses, so the two are one scan: whichever gets there first stores, and the other answers that store rather than reading the tree again. A seat nobody holds has no loop to race and reads unguarded.

The window is what keeps the record self-consistent. The record carries the scan’s hunks beside its branch and count; serving an arbitrarily old scan would put its hunks beside a row the first pass has since moved, so a store past the window is re-read here rather than carried.

Source

pub async fn refresh_diff_base( &self, slot: &SessionSlot, held: &WorkSnapshot, ) -> Option<BaseRefresh>

Answer the base the seat’s drawn branch diff is measured against, and keep it fresh off the read.

None when no branch layer is drawn: the default branch, a detached HEAD, or no resolved default. Only the read that draws the diff calls this, so the check it reports is the one that read drew.

A seat with no session waits for its own check. No watch runs for one, so a kicked refresh would land in a store nothing pushes to the page: this read is the only path that can carry the answer.

Source

pub async fn diff_scan( &self, slot: &SessionSlot, cwd: &Path, refresh: &BaseRefresh, ) -> Option<WorkSnapshot>

The scan a drawing read must take: pinned to the base revision the refresh resolved, and gate-awaited so it cannot serve a store written before the base moved. Local only.

None when the scan could not be taken - no session behind the seat, or its gate held past the read’s bound (which scan_work_pinned logs with the slot and the wait). The caller must then re-read locally (Self::work_pinned_local) at the same sha: the store’s count predates the base the refresh moved, and a scan against the ref’s name cannot be paired with content read at the sha this read resolved.

The refresh’s state rides the stored row, so the base beside a pinned ahead is that base’s own measurement rather than the last watch’s.

Source

pub async fn work_pinned_local( &self, slot: &SessionSlot, cwd: &Path, base: Option<&str>, refresh: Option<&BaseRefresh>, ) -> WorkSnapshot

The local re-read a drawing read takes when its pin could not be: the count and the chain must describe the ref the content is read at, and that ref is the one the refresh just left. Pinned to the same sha the content read takes, so a fetch that moves the ref between the two cannot straddle two bases; the refresh’s own state rides it, so the row’s base and the diff’s agree. Never fetches, and takes no gate.

Source

pub fn store_work_snapshot(&self, slot: &SessionSlot, snapshot: WorkSnapshot)

Store a scan’s answer, which is the write half of Self::work.

A fixture’s door, and the same store the seat’s own loop writes: one store means a record read and a pushed row cannot disagree.

Source

pub fn hold_seat(&self, slot: &SessionSlot)

Show a seat: this view is looking at it, which is what keeps its working tree scanned while the view holds it. A sessionless seat is held too - its watch waits for the session - so every call takes a hold, and a caller must release it exactly once.

The caller owes Self::note_record_read once its record is built. That mark is what starts the watch’s first pass; a view that holds without it has a watch that waits and scans nothing.

Source

pub fn note_record_read(&self, slot: &SessionSlot)

Mark the seat’s record read, so its watch’s first pass starts from the stores the snapshot carried.

Source

pub fn release_seat(&self, slot: &SessionSlot)

Stop showing a seat, which is what lets its scan go when nobody else is holding it.

Source

pub fn refresh_context_usage( &self, slot: &SessionSlot, ) -> Result<(), DispatchError>

Ask the core for a fresh context reading on slot, which its bridge answers with SessionUpdate::ContextUsageSnapshot.

The ask rather than the read, because the reading only exists once the CLI has computed it: a view asks for the seat it is addressing, and the socket asks for the seat a client reads, so both reach the one probe rather than each holding a way to reach the CLI.

§Errors

DispatchError::UnknownSession when the seat has no agent to ask or has not stamped a session id yet, and DispatchError::SessionClosed when the ask could not be handed to that agent.

Source

pub fn refresh_mcp_snapshot( &self, slot: &SessionSlot, ) -> Result<(), DispatchError>

Ask the session’s bridge for a fresh MCP snapshot, which it answers with SessionUpdate::McpSnapshot.

The ask rather than the read, for the same reason as Self::refresh_context_usage: the snapshot only exists once the bridge has answered one, and the socket asks for the seat a client reads the way a view asks for the seat it is addressing.

§Errors

See Self::refresh_context_usage.

Source

pub fn monitors(&self, slot: &SessionSlot) -> Vec<MonitorRecord>

The monitors the session has running, and the ones that settled while it did, folded from the wire.

Empty when nothing is running, however many monitors have been and gone: the set drains once every entry in it is terminal, which is the rule a view applies to its own copy.

Source

pub fn background_tasks(&self, slot: &SessionSlot) -> Vec<BackgroundTask>

The seat’s live tasks, each entry with the command its own card carried: the CLI’s background registry plus the long foreground calls it announced, which never enter that registry.

Empty when nothing is running. A view draws the processes feed’s leading rows from this: the tasks are held on the session so a view that attached after the snapshot arrived still reads them, and the command is what tells it whether the OS walk has already adopted the process behind one.

Source§

impl ViewSurface

Source

pub fn plugins(&self) -> PluginsView

Source§

impl ViewSurface

Source

pub fn reviews(&self, project: &str, branch: &str) -> ReviewsView

Source

pub fn tree_reviews(&self, seat: &SessionSlot) -> TreeReviewsView

The seat’s tree-scope reviews, each thread placed against the seat’s working files by line content and neighbours - one bounded read per commented file, zero threads meaning zero reads.

Source

fn place_tree_threads( &self, seat: &SessionSlot, threads: Vec<ReviewThread>, ) -> Vec<PlacedThread>

Place every seated thread by line content and neighbours against the file it was written on, read from the seat’s tree NOW.

Each commented file is read once per call, through the same bounded document read a viewer’s route uses (the ceiling, the escape check, the UTF-8 answer); zero threads means zero reads. A file the read refused leaves its threads unplaced rather than dropping them - a vanished file must not erase the comments about it.

Source

pub fn place_document_threads( &self, threads: Vec<ReviewThread>, lines: Option<&[String]>, ) -> Vec<PlacedThread>

A document’s threads, each placed against the document’s own current lines by its first captured line - the code review’s re-anchoring rule, over a whole document rather than a diff.

None when the read’s bytes are not text: a viewer that draws no source lines has no line to place a thread on.

Source§

impl ViewSurface

Source

pub fn handoff_in_flight(&self, slot: &SessionSlot) -> bool

Whether a handoff owns this seat: its judgment turn is running, or the swap it opened is still building or spawning.

From the moment the judgment prompt is sent until the successor connects, the seat has no composer to take input for - which is what tells the page to stand down. A handoff merely parked on a running turn is not this: the person still has the seat until the boundary, when it begins for real.

Source§

impl ViewSurface

Source

pub async fn usage(self: &Arc<Self>) -> Result<UsageReport>

Scan the shared session-JSONL pool into the four windows a usage view drew.

The scan walks the pool and parses every file behind it, so it runs on the blocking pool rather than on the task that serves a socket: a connection must not wait on a disk walk, and neither must a render.

A scan that panicked is an error rather than an empty report - an all-zero report reads as a pool with no usage in it, which is a different answer from “the scan did not run”.

A scan also kicks the pricing refill (refill_pricing): the answer that goes out carries costs from whatever table was cached, the first-open behaviour a view has, and the priced report lands in the cache for the next ask.

Source

fn refill_pricing(self: &Arc<Self>)

Refresh the pricing table in the background, and re-scan once it lands, so the next ask answers priced figures.

The fetch must not be waited on. It crosses the network and can take seconds - up to the litellm timeout - and a subject’s ask is answered inside its connection’s own loop, where a wait on one ask stalls every other message on that socket. This is a view’s move instead (scan now, re-price when the fetch lands), with the re-scan replacing the held report so the re-ask finds it.

Workspace::refresh_pricing answers false for a cache that is still fresh, so a kick costs a redb read when there is nothing to fetch - and the once-a-day fetch happens on the first scan after the window lapsed, whatever view asked.

Source

fn held_usage(&self) -> Option<UsageReport>

The last scan, while it is inside USAGE_WINDOW.

Source

fn remember_usage(&self, report: &UsageReport)

Source§

impl ViewSurface

Source

pub fn vault_state(&self) -> Option<VaultState>

The shared vault session as the settings page draws it, or None when no [vault] is configured.

Source§

impl ViewSurface

Source

pub fn voices(&self) -> TtsView

The [tts] section’s own read: on or off, and where its model lands. No seat, because neither fact varies by one.

Source

pub fn voice_release(&self, client: u64) -> Vec<SessionSlot>

A connection has left: every seat it was listening to drops it, and each seat’s subscribers hear the count it left behind.

Source§

impl ViewSurface

Source

pub fn new(workspace: Arc<Workspace>) -> Self

Source

pub fn terminal_attach_or_open( &self, seat: &SessionSlot, id: Option<u16>, ) -> Result<Arc<TerminalEntry>, String>

The terminal a client asked to view, with this connection counted as a viewer. An attach naming a terminal the seat no longer has is refused; an attach naming none opens the seat’s terminal, which is the person’s door on a seat no agent has touched.

Source

pub fn take_terminal_control( &self, seat: &SessionSlot, id: u16, viewer: u64, ) -> Result<(), String>

The person’s own take: always explicit, and landing even during a parked hand-off, whose surface opens as a viewer’s.

Source

pub fn terminal_close(&self, seat: &SessionSlot, id: u16) -> Result<(), String>

The person’s close door: end the terminal’s process group.

Source

pub fn terminal_resize( &self, seat: &SessionSlot, id: u16, cols: u16, rows: u16, ) -> Result<(), String>

The attached surface changed size.

Source

pub fn terminal_write( &self, seat: &SessionSlot, id: u16, bytes: &[u8], ) -> Result<(), String>

The person’s own keystrokes, written to the PTY. They are not logged or forwarded, but the shell may echo them onto the screen the terminal tools read once the hand-off resolves.

Source

pub fn terminal_held(&self, seat: &SessionSlot) -> bool

Whether a hand-off parked on the seat’s terminal owns its input.

Source

pub fn terminal(&self, seat: &SessionSlot) -> Option<TerminalSummary>

The seat’s terminal as the record draws it, when it has one.

Source

pub fn test_usage_scans(&self) -> u64

How many pool scans this surface started. Test-only: the single-flight guard’s whole claim is that two concurrent misses start one.

Source

pub fn seed_test_usage_gate(&self, gate: Arc<Barrier>)

Hold every usage miss here until the test lets it go. Test-only, and None outside the tests that seed one.

Source

async fn pass_test_usage_gate(&self)

Source

pub fn tool_record_cap_bytes(&self) -> usize

The byte cap one frame’s tool_use_result may reach in a served page (#2374): [server] tool_record_cap_kb, with 0 meaning whole.

Source

pub fn first_frame_cap_bytes(&self) -> usize

The conversation bytes a session’s first snapshot may carry: [server] first_frame_cap_kb, with 0 meaning the turn count alone decides the page.

Source

pub fn more_page_cap_bytes(&self) -> usize

The conversation bytes a more page may carry: [server] more_page_cap_kb, with 0 meaning the turn count alone decides the page.

Source

pub fn dispatch(&self, command: Command) -> Result<(), DispatchError>

Dispatch one command to the core, which is how a view acts rather than only reads.

A verb rather than an accessor, on purpose: a second view is handed the writes it needs and not the whole core, so nothing here grows a way to reach the workspace itself.

Source

pub fn fatal_error(&self) -> Option<AppError>

The last fatal error, or None when nothing has failed fatally.

App-level rather than the seat’s: it names a startup that could not happen. It is held because the update carries no state of its own, so a view that attached afterwards has no other way to learn of it.

Source

pub fn service_status(&self) -> Option<ServiceIssue>

The statuspage’s last answer, or None.

App-level: the answer is the same for every viewer, so the core probes it once and every view reads this rather than fetching its own. None covers both a healthy statuspage and one that could not be reached, which is the fetch’s own contract.

Source

pub fn pending_asks(&self, slot: &SessionSlot) -> Vec<PendingAsk>

What the seat at slot is holding, with a draft leading and the rest oldest first, so a view that attached after a prompt landed still draws what it offers. Empty when the seat is holding nothing.

Source

pub fn subscribe_mirror(&self) -> UnboundedReceiver<SeatUpdate>

The core’s own update stream for a consumer that reads it WITHOUT answering.

The caller this exists for is a process-wide fold. It folds into state of its own and never replies, so the answering role would park a permission, question or Slack draft waiting on an answer nobody sends.

A view with a dock to answer from takes Self::subscribe_client.

Source

pub fn subscribe_client(&self, answering: bool) -> UnboundedReceiver<SeatUpdate>

The core’s stream for a connecting client, registered with the role that client declared.

A stream carries what follows its own subscribe and nothing before it, whatever the role: a client that attaches late reads what it missed from the subject’s snapshot.

The role decides one thing: whether the core may park a prompt on this connection’s reply. answering is the client’s own statement that it can show and answer a prompt.

Source

pub fn roster(&self) -> Roster

The projects, their sessions, and the per-project lists the home page renders.

Source

pub fn session(&self, slot: &SessionSlot, cwd_raw: &Path) -> SessionState

One session’s operational state. cwd_raw is the caller’s own cwd for the session, which a git worker’s worktree overrides.

Source

pub fn seat_next_seq(&self, slot: &SessionSlot) -> u64

The number slot’s next frame will be minted under: the read a client makes when it attaches. It belongs to the epoch its occupant names - a seat whose occupant changed starts over at 1 - so the two are read together.

Source

pub fn seat_frames_between( &self, slot: &SessionSlot, from: u64, to: u64, ) -> Vec<SeatUpdate>

The frames slot’s stream emitted under the numbers in from..=to, oldest first: the answer to a client’s range ask while the seat’s own window holds them.

Source

pub fn seat_oldest_kept_seq(&self, slot: &SessionSlot) -> Option<u64>

The oldest number slot’s window still holds, None for a seat that has emitted nothing: what tells a range answered from memory from one that has to be read off the transcript.

Source

pub fn seat_unringed_between( &self, slot: &SessionSlot, from: u64, to: u64, ) -> u64

How many of the numbers in from..=to on slot’s stream no window holds: the frames that close an epoch are numbered but kept out of the ring, so a reader measuring whether a copy covers a stretch leaves them out of what it must account for.

Source

pub fn seat_epoch_opened_with_rows(&self, slot: &SessionSlot) -> bool

Whether slot’s latest epoch-opening seal carried rows, which no ring holds.

Source

pub fn workers(&self) -> Workers

The live workers, per project.

Source

pub fn cli_version(&self) -> Option<CliVersionInfo>

The installed and npm-published claude CLI versions. The same answer for every viewer, so the core holds it and a change arrives as SessionUpdate::CliVersionChanged; None until the boot probe lands.

Source

pub fn client_attached(&self)

Register this connection as an attached client for as long as it lives, so a document hand-off can tell a viewer exists to open on. The transport’s per-connection guard calls these two.

Source

pub fn client_detached(&self)

The counterpart of Self::client_attached.

Source

pub fn server_config(&self) -> ServerConfig

The live [server] snapshot, read by the socket’s origin gate on every upgrade so a reload’s new allowances apply to the next connection without a restart.

Source

pub fn client_config(&self) -> ClientConfig

The [client] settings a connection greets with. Read when the connection opens, so an edit applies to the next connection.

Source

pub fn save_settings( &self, fingerprint: &str, edits: &[SettingsEditRequest], ) -> Result<(), SettingsSaveError>

Apply a batched settings save. The refusal is answered by the connection that asked, on the settings refusal frame.

Source

pub fn read_document( &self, seat: &SessionSlot, path: &str, reviewable: bool, ) -> Result<DocumentRead, String>

One document, read out of the seat’s own tree for a viewer’s route.

path resolves against the session’s working directory and reviewable is what the hand-off flagged; both go to the read in forge_agent::env::documents, whose refusals are the sentences a route draws and a refused hand-off returns. The seat’s project’s document_roots go with them, so a document the hand-off accepted opens here too. The read is blocking (a file off disk), so a caller offloads it rather than running it in a handler.

Source

pub fn document_max_bytes(&self) -> u64

The byte ceiling every whole-file read takes, which the record’s whole-file anchor fallback shares with the review page’s expansion.

Source

pub async fn file_content( &self, seat: &SessionSlot, path: &str, sha: Option<&str>, ) -> Result<FileLines, String>

One file’s whole content at a revision, for a review page’s between-hunk expansion.

sha names the revision - a commit’s own tree for a commit scope - and None reads the seat’s branch tip, which is the new side of the all-changes diff. The read is bounded by the same ceiling a document read is, and a file cut at that ceiling answers the lines it carried, flagged, rather than refusing: the gaps those lines reach are still worth drawing.

None is the branch tip read NOW, and it is stated rather than pinned for want of anything to pin it to. The record’s diff was scanned from this same seat, but it carries no revision for its branch layer - its commit chain names only the commits ahead of the default - so a branch that moves between the record’s read and the reader’s ask can draw newer lines against frozen hunks. The window is the record’s age, the page draws its own controls only for lines the read reaches, and the alternative (carrying the scanned revision on the record, and a wire field with it) buys a race nobody has hit for a field every reader would pay.

Source

pub fn conversation( &self, slot: &SessionSlot, cwd_raw: &Path, ) -> ConversationHistory

The conversation the session at slot holds, read from its own transcript on disk: the same read a resume performs, for a view that arrived after the session was already running or one opening a seat that is asleep (the id is the live occupant’s when there is one, and the store’s own row otherwise - transcript_place resolves it).

Subscribe first, then call this. The read is the baseline the stream is applied on top of, so a message may be in both: a view resolves that by dropping the stream’s copy when the read already carries its id, and reading first instead would lose whatever arrived in between, which no later read brings back.

The one class the two halves cannot reconcile by id is the prompts the workspace injects. A cron, a Gotify delivery, a Slack bundle or a peer comm reaches the stream as text alone (CronPromptAppended, GotifyNotificationAppended, SlackMessageAppended) and reaches this read as the envelope-wrapped row the CLI persisted, with no id shared between them, so a view holding both has to match on the envelope’s source and body instead.

This reads a whole transcript off disk on the calling thread, with no size cap: a real session costs milliseconds, and the largest transcript on this machine 2.5 s in a release build. A caller must offload it rather than run it in a handler, the way this project’s other async work does with a spawned task on its own channel.

cwd_raw is the session’s own cwd, which a git worker’s worktree overrides. An empty cwd_raw resolves to the slot’s recorded path, because the read’s no-directory arm walks every projects/ directory for the first file named after the session: that pays the walk per call and takes whichever copy of the same session it meets first. A slot with no live session, or one whose cwd no record places, reads as an empty conversation, and records which of the two it was, so a view drawing nothing can say which of them it met rather than only that it has nothing to draw.

This is the surface’s read for a view that does not hold its own, and the transport reads it only for a seat it holds nothing for. A live seat’s conversation is the one the session task seeds, so no request walks a file for it; a sleeping one has no task to ask and this read is what answers it (transport::wire::seed_from_transcript). A view keeps its own copy in session state. The verb’s other callers are the surface’s own tests and the measurement harness, which is what a surface test is for rather than a sign it is unused.

Source

pub fn cron_names( &self, slot: &SessionSlot, uuids: &[&str], ) -> BTreeMap<String, CronName>

The schedules the fired prompts in uuids came from, keyed by the prompt’s own id: the read half of the pairing the delivery frame carries once.

Source

pub fn transcript_rows( &self, slot: &SessionSlot, cwd_raw: &Path, below: Option<&TranscriptAnchor>, rows: usize, ) -> Option<TranscriptSpan>

The rows of slot’s transcript that sit strictly before below, for a paging read that has walked below the held window’s floor.

A bounded row read. below is the row the page above stopped at - the id it carries and, once a read has seen it, the byte it starts at - and None reads the file’s own newest rows, which is what a walk asks for on a window that holds no row to name. None when the transcript cannot answer: no session for the slot, no file, or an anchor the file does not carry.

Source

fn transcript_place( &self, slot: &SessionSlot, cwd_raw: &Path, ) -> Option<(String, String)>

The session id and the working directory a transcript read for slot needs, each unmet case recorded as it was met.

The id is the live occupant’s when there is one, and the store’s own row otherwise. A sleeping seat still has a session - the one a wake resumes - and its transcript is what a view opening on it reads, so a read that resolved only pooled sessions drew a sleeping seat empty.

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
§

impl<T> Any for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

§

fn type_name(&self) -> &'static str

§

impl<T> AnySync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send> ⓘ

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
§

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

§

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

§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<S> FromSample<S> for S

§

fn from_sample_(s: S) -> S

§

impl<T> Instrument for T

§

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

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

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
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

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

Initializes a with the given initializer. Read more
§

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

Dereferences the given pointer. Read more
§

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

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

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

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

§

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
§

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
§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

§

fn to_sample_(self) -> U

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, !>

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.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

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