Skip to main content

harness_core/
world.rs

1use async_trait::async_trait;
2use serde::{Deserialize, Serialize};
3use std::path::{Path, PathBuf};
4use std::sync::Arc;
5
6/// Runtime view of the filesystem / repo the agent operates on.
7#[derive(Debug, Clone)]
8pub struct RepoView {
9    pub root: PathBuf,
10}
11
12/// Things the agent and its sensors can do that aren't covered by a Tool.
13///
14/// This is intentionally tiny — most work flows through Tools.
15pub struct World {
16    pub repo: RepoView,
17    pub runner: Arc<dyn ProcessRunner>,
18    pub clock: Arc<dyn Clock>,
19    pub kv: Arc<dyn KvStore>,
20    /// Ambient information about who's using the agent (name, timezone, locale,
21    /// preferences). Loaded once at world construction. See [`crate::UserProfile`].
22    pub profile: crate::UserProfile,
23}
24
25#[async_trait]
26pub trait ProcessRunner: Send + Sync + 'static {
27    async fn exec(
28        &self,
29        program: &str,
30        args: &[&str],
31        cwd: Option<&Path>,
32    ) -> std::io::Result<ProcessOutput>;
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct ProcessOutput {
37    pub status: i32,
38    pub stdout: String,
39    pub stderr: String,
40}
41
42pub trait Clock: Send + Sync + 'static {
43    /// Unix milliseconds since epoch.
44    fn now_ms(&self) -> i64;
45}
46
47#[async_trait]
48pub trait KvStore: Send + Sync + 'static {
49    async fn get(&self, key: &str) -> Option<Vec<u8>>;
50    async fn set(&self, key: &str, value: Vec<u8>);
51    async fn delete(&self, key: &str);
52}