返回 CodeWhale
operate.rs
根目录 / crates / tui / src / tui / setup / operate.rs
1 use crate::config::Config;
2 use crate::tui::app::App;
3
4 #[derive(Debug, Clone, PartialEq, Eq)]
5 pub(super) struct SetupOperateFacts {
6 pub(super) runtime_ready: bool,
7 pub(super) runtime_result: String,
8 pub(super) roster_ready: bool,
9 pub(super) roster_result: String,
10 pub(super) concurrency_result: String,
11 pub(super) result: String,
12 }
13
14 impl Default for SetupOperateFacts {
15 fn default() -> Self {
16 Self {
17 runtime_ready: false,
18 runtime_result: "worker runtime not loaded".to_string(),
19 roster_ready: false,
20 roster_result: "Fleet roster not loaded".to_string(),
21 concurrency_result: "concurrency not loaded".to_string(),
22 result: "operate readiness not loaded".to_string(),
23 }
24 }
25 }
26
27 impl SetupOperateFacts {
28 pub(super) fn from_app_config(app: &App, config: &Config, provider_ready: bool) -> Self {
29 let provider_identity = app.provider_identity_for_persistence();
30 let subagents_enabled = config.subagents_enabled_for_provider(app.api_provider);
31 let max_subagents = config.max_subagents_for_provider(app.api_provider);
32 let launch_concurrency = config.launch_concurrency_for_provider(app.api_provider);
33 let max_admitted = config.max_admitted_subagents_for_provider(app.api_provider);
34 let runtime_disabled_reason = if subagents_enabled {
35 None
36 } else {
37 Some(
38 config
39 .subagents_disabled_reason()
40 .unwrap_or("disabled for active provider"),
41 )
42 };
43 let max_spawn_depth = config.subagent_max_spawn_depth_for_provider(app.api_provider);
44 let runtime_configured =
45 subagents_enabled && max_subagents > 0 && launch_concurrency > 0 && max_spawn_depth > 0;
46 // Conversation and read-only discovery do not require a worker. This
47 // readiness fact describes whether Operate can also dispatch executable
48 // work in the background and report its lifecycle accurately.
49 let runtime_ready = runtime_configured && provider_ready;
50 let runtime_result = if let Some(reason) = runtime_disabled_reason {
51 format!("worker runtime disabled ({reason})")
52 } else if runtime_ready {
53 format!(
54 "worker runtime ready for {}; max_subagents={}, launch_concurrency={}, admission={}, max_spawn_depth={}; background dispatch and completion receipts are available",
55 provider_identity, max_subagents, launch_concurrency, max_admitted, max_spawn_depth
56 )
57 } else if runtime_configured {
58 format!(
59 "worker runtime configured for {}, but the active provider route is not ready; max_subagents={}, launch_concurrency={}, admission={}, max_spawn_depth={}",
60 provider_identity, max_subagents, launch_concurrency, max_admitted, max_spawn_depth
61 )
62 } else {
63 format!(
64 "worker runtime has no launch capacity for {}; max_subagents={}, launch_concurrency={}, admission={}, max_spawn_depth={}",
65 provider_identity, max_subagents, launch_concurrency, max_admitted, max_spawn_depth
66 )
67 };
68
69 let roster =
70 crate::fleet::roster::FleetRoster::load(&config.fleet_config(), &app.workspace);
71 let roster_members = roster.members().len();
72 let origin_count = |origin| {
73 roster
74 .members()
75 .iter()
76 .filter(|member| member.origin == origin)
77 .count()
78 };
79 let config_members = origin_count(crate::fleet::roster::ProfileOrigin::Config);
80 let personal_members = origin_count(crate::fleet::roster::ProfileOrigin::Personal);
81 let project_members = origin_count(crate::fleet::roster::ProfileOrigin::Workspace);
82 let custom_roster_members = config_members + personal_members + project_members;
83 let roster_ready = roster_members > 0;
84 let roster_result = if custom_roster_members > 0 {
85 let origins = [
86 ("config", config_members),
87 ("personal", personal_members),
88 ("project", project_members),
89 ]
90 .into_iter()
91 .filter(|(_, count)| *count > 0)
92 .map(|(label, count)| format!("{label}={count}"))
93 .collect::<Vec<_>>()
94 .join(", ");
95 format!("{roster_members} Fleet members (custom: {origins})")
96 } else {
97 format!("{roster_members} built-in Fleet members; starter roster available")
98 };
99
100 let concurrency_result = format!(
101 "configured launch_concurrency={launch_concurrency}; max_subagents={max_subagents}; admission={max_admitted}; plan limit not probed"
102 );
103 let result = format!(
104 "provider={}, runtime={}, roster={}, concurrency={}",
105 if provider_ready {
106 "ready"
107 } else {
108 "needs_action"
109 },
110 if runtime_ready {
111 "ready"
112 } else {
113 "needs_action"
114 },
115 if roster_ready {
116 "ready"
117 } else {
118 "needs_action"
119 },
120 concurrency_result
121 );
122
123 Self {
124 runtime_ready,
125 runtime_result,
126 roster_ready,
127 roster_result,
128 concurrency_result,
129 result,
130 }
131 }
132 }
133
133 lines RUST