Skip to content

Commit bd133bd

Browse files
committed
feat: enhance user message styling and improve session banner rendering
1 parent 4e7c9ee commit bd133bd

File tree

6 files changed

+51
-74
lines changed

6 files changed

+51
-74
lines changed

docs/project/TODO.md

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -280,19 +280,3 @@ The project aims for clean, maintainable, and testable code through these archit
280280
---
281281

282282
explore and use parking_lot for better performance in multithreaded scenarios. Replace standard library synchronization primitives (like Mutex and RwLock) with their parking_lot counterparts where appropriate. Ensure that the transition maintains thread safety and correctness while improving performance. Update documentation to reflect the use of parking_lot and any changes in synchronization behavior.
283-
284-
---
285-
286-
- `/command <program> [args...]` — run a shell command via `run_terminal_cmd`
287-
--> also add "!" to toggle command and normal mode.
288-
289-
press ! -> command mode
290-
press ! again -> normal mode.
291-
292-
note:
293-
294-
- on command mode only execute `run_terminal_cmd` only no tool call
295-
- on normal mode, full chat agent loop with tools call
296-
- on command mode, update the info and visual of the repl
297-
298-
---

src/agent/runloop/gemini.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ pub(crate) async fn run_single_agent_loop_gemini(
9696
}
9797
placeholder_shown = true;
9898
}
99-
let prompt_style = theme::active_styles().primary;
100-
renderer.inline_with_style(prompt_style, "❯ ")?;
99+
let styles = theme::active_styles();
100+
renderer.inline_with_style(styles.primary, "❯ ")?;
101101
let mut input = String::new();
102102
io::stdin().read_line(&mut input)?;
103103
let input = input.trim();
@@ -179,6 +179,8 @@ pub(crate) async fn run_single_agent_loop_gemini(
179179
}
180180
}
181181

182+
renderer.line(MessageStyle::User, input)?;
183+
182184
conversation_history.push(Content::user_text(input));
183185
let _pruned_tools = prune_gemini_tool_responses(
184186
&mut conversation_history,

src/agent/runloop/ui.rs

Lines changed: 29 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use anyhow::Result;
22
use chrono::Local;
3+
use pathdiff::diff_paths;
34
use sysinfo::System;
45
use vtagent_core::config::types::AgentConfig as CoreAgentConfig;
56
use vtagent_core::tool_policy::{ToolPolicy, ToolPolicyManager};
@@ -13,36 +14,19 @@ pub(crate) fn render_session_banner(
1314
config: &CoreAgentConfig,
1415
session_bootstrap: &SessionBootstrap,
1516
) -> Result<()> {
16-
const VT_ASCII: &[&str] = &[
17-
r"__ _______ _____ _ ",
18-
r"\ \ / /__ __| / ____| | | ",
19-
r" \ \ / / | | ______ | | ___ __| | ___ ___ ",
20-
r" \ \/ / | | |______|| | / _ \ / _` |/ _ \/ __|",
21-
r" \ / | | | |___| (_) | (_| | __/\__ \",
22-
r" \/ |_| \_____/\___/ \__,_|\___||___/",
23-
];
17+
let styles = theme::active_styles();
18+
renderer.line_with_style(styles.primary, "Welcome to VT Code!")?;
2419

25-
for line in VT_ASCII {
26-
renderer.line(MessageStyle::Info, line)?;
27-
}
28-
renderer.line(MessageStyle::Output, "")?;
29-
30-
renderer.line(MessageStyle::Info, "Interactive chat (tools)")?;
31-
renderer.line(MessageStyle::Output, &format!("Model: {}", config.model))?;
32-
renderer.line(
33-
MessageStyle::Output,
34-
&format!("Workspace: {}", config.workspace.display()),
35-
)?;
36-
renderer.line(
37-
MessageStyle::Output,
38-
&format!("Theme: {}", theme::active_theme_label()),
39-
)?;
20+
let mut bullets = Vec::new();
21+
bullets.push(format!("- Model: {}", config.model));
22+
bullets.push(format!("- Workspace: {}", config.workspace.display()));
23+
bullets.push(format!("- Theme: {}", theme::active_theme_label()));
4024

4125
let now = Local::now();
42-
renderer.line(
43-
MessageStyle::Output,
44-
&format!("Local time: {}", now.format("%Y-%m-%d %H:%M:%S %Z")),
45-
)?;
26+
bullets.push(format!(
27+
"- Local time: {}",
28+
now.format("%Y-%m-%d %H:%M:%S %Z")
29+
));
4630

4731
let mut sys = System::new_all();
4832
sys.refresh_all();
@@ -55,17 +39,11 @@ pub(crate) fn render_session_banner(
5539
.max(1);
5640
let total_mem_gb = sys.total_memory() as f64 / 1024.0 / 1024.0;
5741
let used_mem_gb = sys.used_memory() as f64 / 1024.0 / 1024.0;
58-
renderer.line(
59-
MessageStyle::Output,
60-
&format!("System: {} (kernel {})", os_label, kernel),
61-
)?;
62-
renderer.line(
63-
MessageStyle::Output,
64-
&format!(
65-
"Resources: {:.1} GB used / {:.1} GB total, {} cores",
66-
used_mem_gb, total_mem_gb, cpu_count
67-
),
68-
)?;
42+
bullets.push(format!("- System: {} · kernel {}", os_label, kernel));
43+
bullets.push(format!(
44+
"- Resources: {:.1}/{:.1} GB RAM · {} cores",
45+
used_mem_gb, total_mem_gb, cpu_count
46+
));
6947

7048
match ToolPolicyManager::new_with_workspace(&config.workspace) {
7149
Ok(manager) => {
@@ -80,28 +58,25 @@ pub(crate) fn render_session_banner(
8058
ToolPolicy::Deny => deny += 1,
8159
}
8260
}
83-
let policy_line = format!(
84-
"Tool policy: allow {}, prompt {}, deny {} ({})",
85-
allow,
86-
prompt,
87-
deny,
88-
manager.config_path().display()
89-
);
90-
renderer.line(MessageStyle::Output, &policy_line)?;
61+
let policy_path = diff_paths(manager.config_path(), &config.workspace)
62+
.and_then(|p| p.to_str().map(|s| s.to_string()))
63+
.unwrap_or_else(|| manager.config_path().display().to_string());
64+
bullets.push(format!(
65+
"- Tool policy: allow {} · prompt {} · deny {} ({})",
66+
allow, prompt, deny, policy_path
67+
));
9168
}
9269
Err(err) => {
93-
renderer.line(
94-
MessageStyle::Error,
95-
&format!("Tool policy unavailable: {}", err),
96-
)?;
70+
bullets.push(format!("- Tool policy: unavailable ({})", err));
9771
}
9872
}
9973

10074
if let Some(summary) = session_bootstrap.language_summary.as_deref() {
101-
renderer.line(
102-
MessageStyle::Output,
103-
&format!("Detected languages: {}", summary),
104-
)?;
75+
bullets.push(format!("- Languages: {}", summary));
76+
}
77+
78+
for line in bullets {
79+
renderer.line(MessageStyle::Output, &line)?;
10580
}
10681

10782
renderer.line(MessageStyle::Output, "")?;

src/agent/runloop/unified.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,16 @@ pub(crate) async fn run_single_agent_loop_unified(
9090
}
9191
placeholder_shown = true;
9292
}
93-
let prompt_style = theme::active_styles().primary;
94-
renderer.inline_with_style(prompt_style, "❯ ")?;
93+
let styles = theme::active_styles();
94+
renderer.inline_with_style(styles.primary, "❯ ")?;
9595
let mut input = String::new();
9696
io::stdin().read_line(&mut input)?;
9797
let input = input.trim();
9898

99+
if input.is_empty() {
100+
continue;
101+
}
102+
99103
match input {
100104
"" => continue,
101105
"exit" | "quit" => {
@@ -173,6 +177,8 @@ pub(crate) async fn run_single_agent_loop_unified(
173177
}
174178
}
175179

180+
renderer.line(MessageStyle::User, input)?;
181+
176182
let refined_user = refine_user_prompt_if_enabled(input, config, vt_cfg).await;
177183
conversation_history.push(uni::Message::user(refined_user));
178184
let _pruned_tools = prune_unified_tool_responses(

vtagent-core/src/ui/theme.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ impl ThemePalette {
6262
MIN_CONTRAST,
6363
&[lighten(text_color, 0.15), fallback_light],
6464
);
65+
let user_color = ensure_contrast(
66+
lighten(primary, 0.25),
67+
background,
68+
MIN_CONTRAST,
69+
&[lighten(secondary, 0.15), info_color, text_color],
70+
);
6571
let alert_color = ensure_contrast(
6672
self.alert,
6773
background,
@@ -75,6 +81,7 @@ impl ThemePalette {
7581
output: Self::style_from(text_color, false),
7682
response: Self::style_from(response_color, false),
7783
tool: Self::style_from(tool_color, true),
84+
user: Self::style_from(user_color, false),
7885
primary: Self::style_from(primary, false),
7986
secondary: Self::style_from(secondary, false),
8087
background: Color::Rgb(background),
@@ -91,6 +98,7 @@ pub struct ThemeStyles {
9198
pub output: Style,
9299
pub response: Style,
93100
pub tool: Style,
101+
pub user: Style,
94102
pub primary: Style,
95103
pub secondary: Style,
96104
pub background: Color,

vtagent-core/src/utils/ansi.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub enum MessageStyle {
1313
Output,
1414
Response,
1515
Tool,
16+
User,
1617
}
1718

1819
impl MessageStyle {
@@ -24,6 +25,7 @@ impl MessageStyle {
2425
Self::Output => styles.output,
2526
Self::Response => styles.response,
2627
Self::Tool => styles.tool,
28+
Self::User => styles.user,
2729
}
2830
}
2931

0 commit comments

Comments
 (0)