Skip to main content

ProcessRegistry

Struct ProcessRegistry 

Source
pub struct ProcessRegistry { /* private fields */ }
Expand description

Central registry for managing running agent processes

The ProcessRegistry maintains a thread-safe map of all running processes, providing lifecycle management, monitoring, and termination capabilities.

§Thread Safety

The registry uses async-aware locking (tokio::sync::Mutex) for the process map to avoid blocking async tasks. Process handles use standard std::sync::Mutex for synchronous operations.

§Process Lifecycle

1. Register → Process added to registry with metadata
2. Running  → Process executes, output is captured
3. Kill     → Graceful shutdown attempted, then force kill
4. Cleanup  → Process removed from registry

Implementations§

Source§

impl ProcessRegistry

Source

pub fn new() -> Self

Create a new empty process registry

Initializes the registry with an empty process map and sets the ID counter to start at 1,000,000.

§Example
use bamboo_agent::process::registry::ProcessRegistry;

let registry = ProcessRegistry::new();
Source

pub fn generate_id(&self) -> Result<i64, String>

Generate a unique run ID

Returns the next available run ID and increments the counter. IDs start at 1,000,000 and increase sequentially.

§Errors

Returns an error if the ID counter mutex is poisoned.

§Example
use bamboo_agent::process::registry::ProcessRegistry;

let registry = ProcessRegistry::new();
let id = registry.generate_id().unwrap();
assert!(id >= 1000000);
Source

pub async fn register_process( &self, config: ProcessRegistrationConfig, child: Child, ) -> Result<(), String>

Register a new agent run process

Adds a newly spawned agent process to the registry with its configuration and process handle.

§Arguments
  • config - Registration configuration with agent metadata
  • child - The spawned child process handle
§Returns

Returns Ok(()) if registration succeeds.

§Errors

Returns an error if the process map lock fails.

§Example
use bamboo_agent::process::registry::{ProcessRegistry, ProcessRegistrationConfig};
use tokio::process::Command;

#[tokio::main]
async fn main() -> Result<(), String> {
    let registry = ProcessRegistry::new();

    let mut child = Command::new("agent-binary")
        .spawn()
        .map_err(|e| e.to_string())?;

    let config = ProcessRegistrationConfig {
        run_id: 1000001,
        agent_id: 1,
        agent_name: "MyAgent".to_string(),
        pid: child.id().unwrap_or(0),
        project_path: "/project".to_string(),
        task: "Analyze code".to_string(),
        model: "claude-3-5-sonnet".to_string(),
    };

    registry.register_process(config, child).await
}
Source

pub async fn register_sidecar_process( &self, config: ProcessRegistrationConfig, ) -> Result<(), String>

Register a sidecar process without a direct child handle

Used for processes that are managed externally (e.g., by Tauri) but still need to be tracked in the registry for monitoring.

§Arguments
  • config - Registration configuration with agent metadata
§Returns

Returns Ok(()) if registration succeeds.

§Errors

Returns an error if the process map lock fails.

Source

pub async fn register_claude_session( &self, session_id: String, pid: u32, project_path: String, task: String, model: String, child: Arc<Mutex<Option<Child>>>, ) -> Result<i64, String>

Register a Claude interactive session process

Adds a Claude session to the registry, generating a unique run ID if one isn’t provided.

§Arguments
  • session_id - Claude session identifier
  • pid - Operating system process ID
  • project_path - Project directory path
  • task - Task description
  • model - Model identifier
  • child - Optional child process handle wrapped in Arc
§Returns

Returns the generated or provided run ID on success.

§Errors

Returns an error if ID generation or process map lock fails.

Source

pub async fn get_running_claude_sessions( &self, ) -> Result<Vec<ProcessInfo>, String>

Get all running Claude session processes

Returns a list of all registered Claude sessions that are currently tracked in the registry.

§Returns

Vector of ProcessInfo for all Claude sessions.

§Errors

Returns an error if the process map lock fails.

Source

pub async fn get_claude_session_by_id( &self, session_id: &str, ) -> Result<Option<ProcessInfo>, String>

Find a Claude session by its session ID

Searches the registry for a Claude session matching the provided session identifier.

§Arguments
  • session_id - The Claude session ID to search for
§Returns

Some(ProcessInfo) if found, None otherwise.

§Errors

Returns an error if the process map lock fails.

Source

pub async fn unregister_process(&self, run_id: i64) -> Result<(), String>

Remove a process from the registry

Unregisters a process by its run ID. This does NOT kill the process; it only removes it from tracking.

§Arguments
  • run_id - The run ID of the process to remove
§Returns

Returns Ok(()) whether or not the process existed.

§Errors

Returns an error if the process map lock fails.

Source

pub async fn get_running_processes(&self) -> Result<Vec<ProcessInfo>, String>

Get all registered processes (agent runs and Claude sessions)

Returns a list of all processes currently in the registry.

§Returns

Vector of ProcessInfo for all registered processes.

§Errors

Returns an error if the process map lock fails.

Source

pub async fn get_running_agent_processes( &self, ) -> Result<Vec<ProcessInfo>, String>

Get all running agent run processes

Returns a list of all agent run processes (excluding Claude sessions) currently tracked in the registry.

§Returns

Vector of ProcessInfo for agent run processes.

§Errors

Returns an error if the process map lock fails.

Source

pub async fn get_process( &self, run_id: i64, ) -> Result<Option<ProcessInfo>, String>

Get process information by run ID

Retrieves metadata for a specific process.

§Arguments
  • run_id - The run ID to look up
§Returns

Some(ProcessInfo) if found, None otherwise.

§Errors

Returns an error if the process map lock fails.

Source

pub async fn kill_process(&self, run_id: i64) -> Result<bool, String>

Kill a process by run ID

Attempts graceful shutdown first using the child process handle, then falls back to system-level process termination if needed.

§Process
  1. Send kill signal via child handle
  2. Wait up to 5 seconds for graceful exit
  3. If timeout, use system kill command (kill -KILL or taskkill)
  4. Remove process from registry
§Arguments
  • run_id - The run ID of the process to kill
§Returns

Ok(true) if the process was killed successfully, Ok(false) if the process wasn’t found.

§Errors

Returns an error if process termination fails critically.

§Cross-Platform
  • Unix: Uses SIGTERM first, then SIGKILL if needed
  • Windows: Uses taskkill /F
Source

pub async fn kill_process_by_pid( &self, run_id: i64, pid: u32, ) -> Result<bool, String>

Kill a process by its operating system PID

Uses system commands to terminate a process when the child handle is not available or has already been dropped.

§Arguments
  • run_id - Run ID for registry cleanup
  • pid - Operating system process ID
§Returns

Ok(true) if kill succeeded, Ok(false) if it failed.

§Errors

Returns an error if the kill command cannot be executed.

§Cross-Platform Behavior
  • Unix: Tries SIGTERM first, waits 2 seconds, then SIGKILL
  • Windows: Uses taskkill /F immediately
Source

pub async fn is_process_running(&self, run_id: i64) -> Result<bool, String>

Check if a process is still running

Uses try_wait() to check if the process has exited without blocking.

§Arguments
  • run_id - The run ID to check
§Returns

Ok(true) if the process is still running, Ok(false) if it has exited or doesn’t exist.

§Errors

Returns an error if lock acquisition fails.

Source

pub async fn append_live_output( &self, run_id: i64, output: &str, ) -> Result<(), String>

Append output to a process’s live output buffer

Adds a line of output to the process’s output buffer for later retrieval.

§Arguments
  • run_id - The run ID of the process
  • output - The output text to append
§Returns

Returns Ok(()) whether or not the process exists.

§Errors

Returns an error if lock acquisition fails.

Source

pub async fn get_live_output(&self, run_id: i64) -> Result<String, String>

Retrieve the live output buffer for a process

Gets all captured output for the specified process.

§Arguments
  • run_id - The run ID of the process
§Returns

The accumulated output string, or empty string if process not found.

§Errors

Returns an error if lock acquisition fails.

Source

pub async fn cleanup_finished_processes(&self) -> Result<Vec<i64>, String>

Remove all finished processes from the registry

Checks each registered process and removes those that have exited. Useful for periodic cleanup.

§Returns

Vector of run IDs that were removed.

§Errors

Returns an error if process checks or lock acquisition fails.

Trait Implementations§

Source§

impl Default for ProcessRegistry

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

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

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

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

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

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> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: 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
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: 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
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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

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

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

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

fn with_current_subscriber(self) -> WithDispatch<Self>

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