bot_forge/model/output.rs
1//! Public preview and execution-result contracts.
2//!
3//! These presentation-neutral DTOs are shared by execution, CLI output, final report persistence,
4//! and library callers. Serialized enum names are machine-output contracts.
5
6use std::path::PathBuf;
7
8use serde::Serialize;
9
10use crate::model::{Agent, RegistryEntry};
11
12#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
13/// Detection and installation status for one configured tool.
14pub struct ToolStatus {
15 /// Canonical component name.
16 pub name: String,
17 /// Optional human-readable component name.
18 pub display_name: Option<String>,
19 /// Whether interactive selection may omit the tool.
20 pub optional: bool,
21 /// Whether configured detection currently succeeds.
22 pub installed: bool,
23 /// Detected version text, when the check produces one.
24 pub version: Option<String>,
25 /// Version offered by the current configuration, when it is comparable.
26 pub required_version: Option<String>,
27 /// Whether the detected version is older than the configured offered version.
28 pub outdated: bool,
29 /// Whether the configuration supplies an installation backend.
30 pub installable: bool,
31}
32
33#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
34/// Detection and installation status for one configured skill and agent.
35pub struct SkillStatus {
36 /// Canonical skill name.
37 pub name: String,
38 /// Optional human-readable skill name.
39 pub display_name: Option<String>,
40 /// Whether interactive selection may omit the skill.
41 pub optional: bool,
42 /// Agent whose destination was inspected.
43 pub agent: Agent,
44 /// Existing agent skill directory, when available.
45 pub agent_dir: Option<PathBuf>,
46 /// Whether the skill payload already exists at the destination.
47 pub installed: bool,
48 /// Whether the configuration supplies a non-empty source.
49 pub installable: bool,
50}
51
52#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
53/// Presentation-neutral detection snapshot produced before execution.
54pub struct InstallPreview {
55 /// Tool statuses in canonical configuration order.
56 pub tools: Vec<ToolStatus>,
57 /// Skill statuses in canonical skill-and-agent order.
58 pub skills: Vec<SkillStatus>,
59}
60
61#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
62/// Final execution result, committed registry entries, and post-install detection state.
63pub struct InstallReport {
64 /// Registry entries committed by this run.
65 pub entries: Vec<RegistryEntry>,
66 /// Detection state observed after execution.
67 pub final_preview: InstallPreview,
68 /// Per-tool outcomes in plan order.
69 pub tools: Vec<ToolInstallResult>,
70 /// Aggregate run outcome.
71 pub outcome: InstallOutcome,
72 /// End-to-end run duration in milliseconds.
73 pub duration_ms: u128,
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
77#[serde(rename_all = "snake_case")]
78/// Result of processing one tool during an installation run.
79pub enum ToolInstallOutcome {
80 /// Detection showed the requested tool was already installed.
81 AlreadyPresent,
82 /// Installation and verification completed successfully.
83 Installed,
84 /// Processing stopped in response to cancellation.
85 Cancelled,
86 /// Installation ran but the configured verification did not succeed.
87 VerificationFailed,
88}
89
90#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
91/// Named per-tool outcome included in [`InstallReport`].
92pub struct ToolInstallResult {
93 /// Canonical component name.
94 pub name: String,
95 /// Terminal tool outcome.
96 pub outcome: ToolInstallOutcome,
97 /// Optional diagnostic or status detail.
98 pub message: Option<String>,
99}
100
101#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
102#[serde(rename_all = "snake_case")]
103/// Aggregate terminal state of an installation run.
104pub enum InstallOutcome {
105 /// Every selected operation reached an accepted terminal state.
106 Success,
107 /// The run stopped in response to cancellation.
108 Cancelled,
109 /// At least one selected operation failed.
110 Failed,
111}
112
113impl InstallPreview {
114 /// Return tools that are not currently detected as installed.
115 pub fn missing_tools(&self) -> Vec<&ToolStatus> {
116 self.tools
117 .iter()
118 .filter(|status| !status.installed)
119 .collect()
120 }
121
122 /// Return missing skills that have an installable agent destination.
123 pub fn missing_skills(&self) -> Vec<&SkillStatus> {
124 self.skills
125 .iter()
126 .filter(|status| !status.installed && status.installable)
127 .collect()
128 }
129}