Agents for developpement added + frontend add + backend added. Git viewer created + agent and template creator + layout and project creator
106 lines
2.8 KiB
Rust
106 lines
2.8 KiB
Rust
//! Terminal session entity and supporting value objects.
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::error::DomainError;
|
|
use crate::ids::{AgentId, NodeId, SessionId};
|
|
use crate::project::ProjectPath;
|
|
|
|
/// Dimensions of a pseudo-terminal, in character cells.
|
|
///
|
|
/// Invariant: `rows > 0 && cols > 0`.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct PtySize {
|
|
/// Number of rows.
|
|
pub rows: u16,
|
|
/// Number of columns.
|
|
pub cols: u16,
|
|
}
|
|
|
|
impl PtySize {
|
|
/// Builds a validated PTY size.
|
|
///
|
|
/// # Errors
|
|
/// Returns [`DomainError::InvalidPtySize`] if either dimension is zero.
|
|
pub fn new(rows: u16, cols: u16) -> Result<Self, DomainError> {
|
|
if rows == 0 || cols == 0 {
|
|
return Err(DomainError::InvalidPtySize { rows, cols });
|
|
}
|
|
Ok(Self { rows, cols })
|
|
}
|
|
}
|
|
|
|
/// What a terminal session is running.
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
#[serde(rename_all = "camelCase", tag = "type")]
|
|
pub enum SessionKind {
|
|
/// A plain shell terminal.
|
|
Plain,
|
|
/// A terminal launched for a specific agent.
|
|
#[serde(rename_all = "camelCase")]
|
|
Agent {
|
|
/// The agent driving this session.
|
|
agent_id: AgentId,
|
|
},
|
|
}
|
|
|
|
/// Lifecycle status of a terminal session.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
|
#[serde(rename_all = "camelCase", tag = "state")]
|
|
pub enum SessionStatus {
|
|
/// Spawn requested, not yet confirmed running.
|
|
Starting,
|
|
/// Running.
|
|
Running,
|
|
/// Exited with a code.
|
|
Exited {
|
|
/// Process exit code.
|
|
code: i32,
|
|
},
|
|
}
|
|
|
|
/// A terminal session hosted by a layout leaf cell.
|
|
///
|
|
/// Invariants:
|
|
/// - `pty_size` is valid (`rows>0 && cols>0`),
|
|
/// - "at most one active session per leaf" is a *layout* invariant enforced in
|
|
/// [`crate::layout`], not here (a session does not own the leaf).
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct TerminalSession {
|
|
/// Stable identifier.
|
|
pub id: SessionId,
|
|
/// Layout leaf hosting this session.
|
|
pub node_id: NodeId,
|
|
/// Working directory.
|
|
pub cwd: ProjectPath,
|
|
/// What the session runs.
|
|
pub kind: SessionKind,
|
|
/// Current terminal size.
|
|
pub pty_size: PtySize,
|
|
/// Lifecycle status.
|
|
pub status: SessionStatus,
|
|
}
|
|
|
|
impl TerminalSession {
|
|
/// Builds a terminal session (in `Starting` state).
|
|
#[must_use]
|
|
pub fn starting(
|
|
id: SessionId,
|
|
node_id: NodeId,
|
|
cwd: ProjectPath,
|
|
kind: SessionKind,
|
|
pty_size: PtySize,
|
|
) -> Self {
|
|
Self {
|
|
id,
|
|
node_id,
|
|
cwd,
|
|
kind,
|
|
pty_size,
|
|
status: SessionStatus::Starting,
|
|
}
|
|
}
|
|
}
|