anveesa 0.3.8 → 0.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Cargo.lock CHANGED
@@ -60,7 +60,7 @@ dependencies = [
60
60
 
61
61
  [[package]]
62
62
  name = "anveesa"
63
- version = "0.3.8"
63
+ version = "0.3.9"
64
64
  dependencies = [
65
65
  "anyhow",
66
66
  "base64",
package/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "anveesa"
3
- version = "0.3.8"
3
+ version = "0.3.9"
4
4
  edition = "2024"
5
5
  default-run = "anveesa"
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anveesa",
3
- "version": "0.3.8",
3
+ "version": "0.3.9",
4
4
  "description": "A terminal CLI that wraps AI providers (OpenAI-compatible APIs and local CLIs) into a single unified command",
5
5
  "main": "bin/anveesa.js",
6
6
  "bin": {
package/src/tui.rs CHANGED
@@ -44,12 +44,17 @@ pub enum TuiEvent {
44
44
  enum Msg {
45
45
  User { text: String },
46
46
  Assistant { text: String },
47
- Tool { icon: &'static str, text: String, ok: bool },
47
+ Tool { done: bool, ok: bool, text: String },
48
48
  FileOp { verb: String, path: String, added: usize, removed: usize },
49
49
  Error(String),
50
50
  System(String),
51
51
  }
52
52
 
53
+ #[derive(Debug)]
54
+ struct PendingTool {
55
+ summary: String,
56
+ }
57
+
53
58
  #[derive(Debug)]
54
59
  struct PendingConfirm {
55
60
  summary: String,
@@ -69,7 +74,8 @@ pub struct App {
69
74
  // conversation display
70
75
  messages: Vec<Msg>,
71
76
  streaming_buf: String,
72
- accumulated_response: String, // full assistant text across tool calls
77
+ accumulated_response: String,
78
+ pending_tool: Option<PendingTool>, // currently-running tool (not yet committed)
73
79
  tool_status: String,
74
80
  plan_tasks: Vec<String>,
75
81
  plan_done: Vec<bool>,
@@ -151,6 +157,7 @@ impl App {
151
157
  messages,
152
158
  streaming_buf: String::new(),
153
159
  accumulated_response: String::new(),
160
+ pending_tool: None,
154
161
  tool_status: String::new(),
155
162
  plan_tasks: vec![],
156
163
  plan_done: vec![],
@@ -636,22 +643,25 @@ async fn handle_stream_event(app: &mut App, ev: TuiEvent) {
636
643
  }
637
644
  TuiEvent::ToolCall(summary) => {
638
645
  flush_streaming_buf(app);
639
- app.messages.push(Msg::Tool { icon: "⚙", text: summary, ok: true });
640
- app.tool_status = "Running".to_string();
646
+ // Commit any previous pending tool (shouldn't happen, but be safe)
647
+ commit_pending_tool(app, true);
648
+ app.pending_tool = Some(PendingTool { summary: summary.clone() });
649
+ app.tool_status = summary;
641
650
  }
642
651
  TuiEvent::ToolDone { summary, ok } => {
643
- if let Some(Msg::Tool { text, ok: tool_ok, .. }) = app.messages.last_mut() {
644
- *text = summary;
645
- *tool_ok = ok;
646
- }
652
+ // Commit the pending tool with its final status
653
+ app.pending_tool = Some(PendingTool { summary });
654
+ commit_pending_tool(app, ok);
647
655
  app.tool_status = "Thinking".to_string();
648
656
  }
649
657
  TuiEvent::FileOp { verb, path, added, removed } => {
650
658
  flush_streaming_buf(app);
659
+ commit_pending_tool(app, true);
651
660
  app.messages.push(Msg::FileOp { verb, path, added, removed });
652
661
  }
653
662
  TuiEvent::Confirm { summary, reply } => {
654
663
  flush_streaming_buf(app);
664
+ commit_pending_tool(app, true);
655
665
  app.confirm = Some(PendingConfirm { summary, reply });
656
666
  app.mode = Mode::Confirming;
657
667
  }
@@ -688,8 +698,16 @@ fn flush_streaming_buf(app: &mut App) {
688
698
  }
689
699
  }
690
700
 
701
+ /// Commit a pending tool call to the message history with its final status.
702
+ fn commit_pending_tool(app: &mut App, ok: bool) {
703
+ if let Some(tool) = app.pending_tool.take() {
704
+ app.messages.push(Msg::Tool { done: true, ok, text: tool.summary });
705
+ }
706
+ }
707
+
691
708
  /// Commit the completed turn to history and save session.
692
709
  fn finish_turn(app: &mut App) {
710
+ commit_pending_tool(app, true);
693
711
  flush_streaming_buf(app);
694
712
  let response = std::mem::take(&mut app.accumulated_response);
695
713
  if !response.is_empty() {
@@ -767,8 +785,14 @@ fn render_messages(frame: &mut Frame, area: Rect, app: &mut App) {
767
785
  }
768
786
  lines.push(Line::from(""));
769
787
  }
770
- Msg::Tool { icon, text, ok } => {
771
- let color = if *ok { Color::Rgb(229, 192, 123) } else { Color::Rgb(224, 108, 117) };
788
+ Msg::Tool { done, ok, text } => {
789
+ let (icon, color) = if !done {
790
+ ("⠋", Color::DarkGray)
791
+ } else if *ok {
792
+ ("✓", Color::Rgb(152, 195, 121))
793
+ } else {
794
+ ("✗", Color::Rgb(224, 108, 117))
795
+ };
772
796
  lines.push(Line::from(Span::styled(
773
797
  format!(" {icon} {text}"),
774
798
  Style::default().fg(color),
@@ -804,8 +828,19 @@ fn render_messages(frame: &mut Frame, area: Rect, app: &mut App) {
804
828
  }
805
829
  }
806
830
 
831
+ // Live pending tool (running, not yet committed)
832
+ if let Some(tool) = &app.pending_tool {
833
+ let dots = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
834
+ let dot = dots[app.spinner_frame % dots.len()];
835
+ lines.push(Line::from(Span::styled(
836
+ format!(" {dot} {}", tool.summary),
837
+ Style::default().fg(Color::DarkGray),
838
+ )));
839
+ lines.push(Line::from(""));
840
+ }
841
+
807
842
  // In-progress streaming
808
- if !app.streaming_buf.is_empty() || app.mode == Mode::Streaming {
843
+ if !app.streaming_buf.is_empty() || (app.mode == Mode::Streaming && app.pending_tool.is_none()) {
809
844
  lines.push(assistant_header(&app.model));
810
845
  if !app.streaming_buf.is_empty() {
811
846
  for l in format_assistant_lines(&app.streaming_buf, width) {