rig_harness/workspace.rs
1//! The workspace the agent works in: [`ProjectWorkspace`].
2
3use std::sync::Arc;
4
5use bevy_ecs::prelude::*;
6use rig_tools::workspace::{Local, Workspace};
7
8/// The workspace the tools act on: this machine's ([`Local`]) unless a
9/// plugin puts another in while the app is built, such as one reached over
10/// SSH. Paths in [`ProjectRoot`](crate::services::ProjectRoot),
11/// [`WorkDir`](crate::services::WorkDir) and tools' facts
12/// ([`FilesRead`](rig_core::tool::FilesRead),
13/// [`FilesChanged`](rig_core::tool::FilesChanged)) are in it. Run project
14/// commands, such as `git`, with its [`spawn`](Workspace::spawn), so they
15/// follow it; other plugins learn it is not this machine from its
16/// [`host`](Workspace::host).
17///
18/// **The main-thread rule.** Tools call it inside
19/// [`blocking`](rig_tools::blocking). A system calls it inline only when
20/// `host()` is `None`; for another workspace it reads as
21/// [`Running::spawn`](rig_ecs::tasks::Running::spawn) work, under a hold
22/// ([`HoldOf`](rig_ecs::stage::HoldOf)) on what waits for it, so a remote
23/// workspace never blocks a frame and a local one keeps its timing.
24///
25/// ```
26/// use std::sync::Arc;
27/// use rig_harness::prelude::*;
28/// use rig_harness::rig_tools::workspace::Local;
29///
30/// let mut app = App::new();
31/// // A plugin of another workspace inserts its own in `build`, with the
32/// // project's path there.
33/// app.insert_resource(ProjectWorkspace(Arc::new(Local)))
34/// .insert_resource(ProjectRoot("/srv/app".into()));
35/// assert!(app.world().resource::<ProjectWorkspace>().0.host().is_none());
36/// ```
37#[derive(Resource, Clone, Debug)]
38pub struct ProjectWorkspace(pub Arc<dyn Workspace>);
39
40/// This machine.
41impl Default for ProjectWorkspace {
42 fn default() -> Self {
43 Self(Arc::new(Local))
44 }
45}