- 1001
let api = self.api.clone(); - 1002
let rt = tokio::runtime::Handle::current(); - 1003
rt.spawn(async move { - 1004
let _ = api.set_permission_mode("WorkspaceWrite").await; - 1005
}); - 1006
} else if (11..=13).contains(&y) { - 1007
self.selected_permission_mode = "ReadOnly".into(); - 1008
let api = self.api.clone(); - 1009
let rt = tokio::runtime::Handle::current(); - 1010
rt.spawn(async move { - 1011
let _ = api.set_permission_mode("ReadOnly").await; - 1012
}); - 1013
} else if (14..=16).contains(&y) { - 1014
// FullAccess: explicit human trust decision — - 1015
// do NOT auto-escalate from a click. Send to - 1016
// approval gate instead. - 1017
self.dispatch_approval(HilOutcome::ApproveOnce { - 1018
modified_command: None, - 1019
}); - 1020
} - 1021
} - 1022
if (17..=19).contains(&y) { - 1023
if (15..=25).contains(&x) { - 1024
self.approval_mode = "Ask".into(); - 1025
} else if (26..=45).contains(&x) { - 1026
self.approval_mode = "AutoApprove".into(); - 1027
} - 1028
} - 1029
// Pending Authorization Queue buttons - 1030
if x >= 55 && (16..=20).contains(&y) { - 1031
if (55..=75).contains(&x) { - 1032
self.pending_chat_status = Some(true); - 1033
self.dispatch_approval_from_chat(true, false); - 1034
} else if (76..=95).contains(&x) { - 1035
self.pending_chat_status = Some(false); - 1036
self.dispatch_approval_from_chat(false, false); - 1037
} - 1038
} - 1039
} - 1040
ActiveTab::Inbox => { - 1041
if (1..=4).contains(&y) && (60..=75).contains(&x) { - 1042
self.alert_acknowledged = true; - 1043
} - 1044
if (5..=9).contains(&y) && (40..=65).contains(&x) { - 1045
self.watchdog_restarted = true; - 1046
} - 1047
if (15..=20).contains(&y) && x >= 60 { - 1048
self.skill_promoted = true; - 1049
} - 1050
} - 1051
ActiveTab::Studio => { - 1052
if (8..=11).contains(&y) - 1053
&& (2..=32).contains(&x) - 1054
&& let Some(port) = self - 1055
.launch_servers - 1056
.iter() - 1057
.find(|s| s.running && s.port.is_some()) - 1058
.and_then(|s| s.port) - 1059
{ - 1060
let url = format!("http://localhost:{port}"); - 1061
let _ = std::process::Command::new("open").arg(&url).spawn(); - 1062
} - 1063
if (11..=15).contains(&y) && x < 60 { - 1064
self.card_expanded = !self.card_expanded; - 1065
} - 1066
} - 1067
ActiveTab::Observability => {} - 1068
} - 1069
} - 1070
MouseEventKind::ScrollDown => { - 1071
self.scroll_offset = self.scroll_offset.saturating_add(1); - 1072
} - 1073
MouseEventKind::ScrollUp => { - 1074
self.scroll_offset = self.scroll_offset.saturating_sub(1); - 1075
} - 1076
_ => {} - 1077
} - 1078
} - 1079
- 1080
pub fn quit_requested(&self) -> bool { - 1081
self.should_quit - 1082
} - 1083
- 1084
pub fn detach_requested(&self) -> bool { - 1085
self.should_detach - 1086
} - 1087
- 1088
/// Render the full terminal UI. All data comes from the real - 1089
/// API-backed fields, never from hardcoded values. - 1090
pub fn render_to(&self, area: Rect, buf: &mut Buffer) { - 1091
let chunks = Layout::default() - 1092
.direction(Direction::Vertical) - 1093
.constraints([ - 1094
Constraint::Length(1), // Header tab bar - 1095
Constraint::Min(10), // Active deck view - 1096
Constraint::Length(4), // Pinned bottom composer - 1097
]) - 1098
.split(area); - 1099
- 1100
// 1. Header View (real session, model, server, spend) - 1101
let header = HeaderView { - 1102
active_tab: self.active_tab, - 1103
session_name: &self.session_id, - 1104
model_name: &self.model_name, - 1105
host_endpoint: &self.host_endpoint, - 1106
spend_usd: 0.0, - 1107
connected: self.connected, - 1108
error: self.telemetry.last_error.clone(), - 1109
theme: &self.theme, - 1110
}; - 1111
header.render(chunks[0], buf); - 1112
- 1113
// 2. Active Screen View - 1114
match self.active_tab { - 1115
ActiveTab::Studio => { - 1116
let launch_url = self - 1117
.launch_servers - 1118
.iter() - 1119
.find(|s| s.running && s.port.is_some()) - 1120
.and_then(|s| s.port.map(|port| format!("http://localhost:{port}"))); - 1121
let view = StudioView { - 1122
telemetry: &self.telemetry, - 1123
theme: &self.theme, - 1124
is_running: self.control_state.running, - 1125
deck_focus: self.deck_focus, - 1126
card_expanded: self.card_expanded, - 1127
presentation_items: &self.presentation_items, - 1128
launch_url: launch_url.as_deref(), - 1129
sandbox_name: &self.health.sandbox, - 1130
cwd: &self.health.cwd, - 1131
}; - 1132
view.render(chunks[1], buf); - 1133
} - 1134
ActiveTab::Observability => { - 1135
let view = OpsView { - 1136
telemetry: &self.telemetry, - 1137
theme: &self.theme, - 1138
deck_focus: self.deck_focus, - 1139
incidents: &self.incidents, - 1140
audit_entries: &self.audit_entries, - 1141
merkle_nodes: &self.merkle_nodes, - 1142
health: &self.health, - 1143
}; - 1144
view.render(chunks[1], buf); - 1145
} - 1146
ActiveTab::Admin => { - 1147
let view = AdminView { - 1148
theme: &self.theme, - 1149
selected_permission_mode: &self.selected_permission_mode, - 1150
approval_mode: &self.approval_mode, - 1151
workspace_name: &self.workspace_name, - 1152
deck_focus: self.deck_focus, - 1153
pending_chat_status: self.pending_chat_status, - 1154
mcp_rows: &self.mcp_rows, - 1155
mcp_servers: &self.mcp_servers, - 1156
gateway: &self.gateway, - 1157
sessions: &self.sessions, - 1158
pending_chats: &self.pending_chats, - 1159
health: &self.health, - 1160
connected: self.connected, - 1161
}; - 1162
view.render(chunks[1], buf); - 1163
} - 1164
ActiveTab::Inbox => { - 1165
let view = InboxView { - 1166
theme: &self.theme, - 1167
deck_focus: self.deck_focus, - 1168
alert_acknowledged: self.alert_acknowledged, - 1169
skill_promoted: self.skill_promoted, - 1170
watchdog_restarted: self.watchdog_restarted, - 1171
inbox_entries: &self.inbox_entries, - 1172
health: &self.health, - 1173
}; - 1174
view.render(chunks[1], buf); - 1175
} - 1176
} - 1177
- 1178
// 3. Pinned Bottom Composer - 1179
let composer_view = ComposerView { - 1180
composer: &self.composer, - 1181
theme: &self.theme, - 1182
connected: self.connected, - 1183
error: self.telemetry.last_error.clone(), - 1184
}; - 1185
composer_view.render(chunks[2], buf); - 1186
- 1187
// 4. Floating HIL Approval Modal (if active) - 1188
if let Some(ref hil) = self.hil_state { - 1189
let modal_view = HilModalView { - 1190
state: hil, - 1191
theme: &self.theme, - 1192
remember: hil.remember, - 1193
}; - 1194
modal_view.render(area, buf); - 1195
} - 1196
} - 1197
} - 1198
- 1199
impl Widget for &TerminalApp { - 1200
fn render(self, area: Rect, buf: &mut Buffer) { - 1201
self.render_to(area, buf); - 1202
} - 1203
} - 1204
Indexing the workspace…
Vakyartha documentation is discovering safe artifacts, anchors, and source references.