Agents for developpement added + frontend add + backend added. Git viewer created + agent and template creator + layout and project creator
93 lines
2.6 KiB
Rust
93 lines
2.6 KiB
Rust
//! Agent templates (global IDE store) and their monotonic versioning.
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::error::DomainError;
|
|
use crate::ids::{ProfileId, TemplateId};
|
|
use crate::markdown::MarkdownDoc;
|
|
|
|
/// Monotonically increasing template version.
|
|
///
|
|
/// Invariant (enforced via [`TemplateVersion::next`]): a version only ever
|
|
/// increases by one when the template content changes (ARCHITECTURE §8.1).
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
|
#[serde(transparent)]
|
|
pub struct TemplateVersion(pub u64);
|
|
|
|
impl TemplateVersion {
|
|
/// The initial version assigned to a freshly created template.
|
|
pub const INITIAL: Self = Self(1);
|
|
|
|
/// Returns the next version (current + 1).
|
|
#[must_use]
|
|
pub const fn next(self) -> Self {
|
|
Self(self.0 + 1)
|
|
}
|
|
|
|
/// Returns the raw version number.
|
|
#[must_use]
|
|
pub const fn get(self) -> u64 {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
impl Default for TemplateVersion {
|
|
fn default() -> Self {
|
|
Self::INITIAL
|
|
}
|
|
}
|
|
|
|
/// A reusable agent template stored in the global IDE store.
|
|
///
|
|
/// Invariants:
|
|
/// - `name` non-empty,
|
|
/// - `version` is monotonic; bumping is done via [`AgentTemplate::with_updated_content`].
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct AgentTemplate {
|
|
/// Stable identifier.
|
|
pub id: TemplateId,
|
|
/// Display name.
|
|
pub name: String,
|
|
/// Markdown content.
|
|
pub content_md: MarkdownDoc,
|
|
/// Current version.
|
|
pub version: TemplateVersion,
|
|
/// Default runtime profile for agents created from this template.
|
|
pub default_profile_id: ProfileId,
|
|
}
|
|
|
|
impl AgentTemplate {
|
|
/// Builds a validated template at [`TemplateVersion::INITIAL`].
|
|
///
|
|
/// # Errors
|
|
/// Returns [`DomainError::EmptyField`] if `name` is empty.
|
|
pub fn new(
|
|
id: TemplateId,
|
|
name: impl Into<String>,
|
|
content_md: MarkdownDoc,
|
|
default_profile_id: ProfileId,
|
|
) -> Result<Self, DomainError> {
|
|
let name = name.into();
|
|
crate::validation::non_empty(&name, "template.name")?;
|
|
Ok(Self {
|
|
id,
|
|
name,
|
|
content_md,
|
|
version: TemplateVersion::INITIAL,
|
|
default_profile_id,
|
|
})
|
|
}
|
|
|
|
/// Returns a copy of this template with new content and the version bumped
|
|
/// by one, preserving the monotonic-version invariant.
|
|
#[must_use]
|
|
pub fn with_updated_content(&self, content_md: MarkdownDoc) -> Self {
|
|
Self {
|
|
content_md,
|
|
version: self.version.next(),
|
|
..self.clone()
|
|
}
|
|
}
|
|
}
|