openclacky 0.5.2 → 0.5.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c1d065edf333a21a538aff43effdcefbc1cb9fa9a3c816d2da3943418f502fb
4
- data.tar.gz: d891f1b03ff43bcd237eb510990b74145522404dd4fa3b2bc4b3741f3e495a32
3
+ metadata.gz: 52ab39c40c69d821b45d01ed1d14086a50446309421891e9cd6724a9b32864cf
4
+ data.tar.gz: 0d61ef02a23f8a04157f8b7b2308a4f0c68fd37bba1407894b9841cd707c6873
5
5
  SHA512:
6
- metadata.gz: 5190473333b6c0259ee7ec76bf3127986b03fcbbaeba8face1e0f5bd5ebc60d40b9937df7ef129737eb6364789a214a515970728cfd71b80770cc671e5440004
7
- data.tar.gz: 0a7858fe351e34810bca0b28ab91b3974041758608fe8c446e6f0c555402c990418bb6d3bc4ac071fe61fe3d881a5c190f191258287541b57508a940c2643752
6
+ metadata.gz: d654bd29a093bf23f1e0c162867251e08a28ec722deaae7a9d234f2aed913329d991df29391778612c458c51b6775881ee0867cb2d959c0f7072b14e662d0c38
7
+ data.tar.gz: 8056dff60d1c845751021e2c852e58071360c8d6a6b81cec72be238e647521ae36a211d72af88602239f8abcab5a15b7a345b8efd98e68b62a0a6dfde8a63b23
data/lib/clacky/agent.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "securerandom"
4
4
  require "json"
5
- require "readline"
5
+ require "tty-prompt"
6
6
  require "set"
7
7
  require_relative "utils/arguments_parser"
8
8
 
@@ -97,7 +97,7 @@ module Clacky
97
97
  @working_dir = session_data[:working_dir]
98
98
  @created_at = session_data[:created_at]
99
99
  @total_tasks = session_data.dig(:stats, :total_tasks) || 0
100
-
100
+
101
101
  # Restore cache statistics if available
102
102
  @cache_stats = session_data.dig(:stats, :cache_stats) || {
103
103
  cache_creation_input_tokens: 0,
@@ -138,12 +138,12 @@ module Clacky
138
138
  if @messages.empty?
139
139
  system_prompt = build_system_prompt
140
140
  system_message = { role: "system", content: system_prompt }
141
-
141
+
142
142
  # Enable caching for system prompt if configured and model supports it
143
143
  if @config.enable_prompt_caching
144
144
  system_message[:cache_control] = { type: "ephemeral" }
145
145
  end
146
-
146
+
147
147
  @messages << system_message
148
148
  end
149
149
 
@@ -616,14 +616,14 @@ module Clacky
616
616
  input_cost = (usage[:prompt_tokens] / 1_000_000.0) * PRICING[:input]
617
617
  output_cost = (usage[:completion_tokens] / 1_000_000.0) * PRICING[:output]
618
618
  @total_cost += input_cost + output_cost
619
-
619
+
620
620
  # Track cache usage statistics
621
621
  @cache_stats[:total_requests] += 1
622
-
622
+
623
623
  if usage[:cache_creation_input_tokens]
624
624
  @cache_stats[:cache_creation_input_tokens] += usage[:cache_creation_input_tokens]
625
625
  end
626
-
626
+
627
627
  if usage[:cache_read_input_tokens]
628
628
  @cache_stats[:cache_read_input_tokens] += usage[:cache_read_input_tokens]
629
629
  @cache_stats[:cache_hit_requests] += 1
@@ -669,12 +669,12 @@ module Clacky
669
669
  # Rebuild messages array: [system, summary, recent_messages]
670
670
  # Preserve cache_control on system message if it exists
671
671
  rebuilt_messages = [system_msg, summary, *recent_messages].compact
672
-
672
+
673
673
  # Re-apply cache control to system message if caching is enabled
674
674
  if @config.enable_prompt_caching && rebuilt_messages.first&.dig(:role) == "system"
675
675
  rebuilt_messages.first[:cache_control] = { type: "ephemeral" }
676
676
  end
677
-
677
+
678
678
  @messages = rebuilt_messages
679
679
 
680
680
  final_size = @messages.size
@@ -703,7 +703,7 @@ module Clacky
703
703
 
704
704
  # Track which messages to include
705
705
  messages_to_include = Set.new
706
-
706
+
707
707
  # Start from the end and work backwards
708
708
  i = messages.size - 1
709
709
  messages_collected = 0
@@ -724,13 +724,13 @@ module Clacky
724
724
  # If this is an assistant message with tool_calls, we MUST include ALL corresponding tool results
725
725
  if msg[:role] == "assistant" && msg[:tool_calls]
726
726
  tool_call_ids = msg[:tool_calls].map { |tc| tc[:id] }
727
-
727
+
728
728
  # Find all tool results that belong to this assistant message
729
729
  # They should be in the messages immediately following this assistant message
730
730
  j = i + 1
731
731
  while j < messages.size
732
732
  next_msg = messages[j]
733
-
733
+
734
734
  # If we find a tool result for one of our tool_calls, include it
735
735
  if next_msg[:role] == "tool" && tool_call_ids.include?(next_msg[:tool_call_id])
736
736
  messages_to_include.add(j)
@@ -738,7 +738,7 @@ module Clacky
738
738
  # Stop when we hit a non-tool message (start of next turn)
739
739
  break
740
740
  end
741
-
741
+
742
742
  j += 1
743
743
  end
744
744
  end
@@ -859,18 +859,28 @@ module Clacky
859
859
  prompt_text = format_tool_prompt(call)
860
860
  puts "\n❓ #{prompt_text}"
861
861
 
862
- # Use Readline for better input handling (backspace, arrow keys, etc.)
863
- response = Readline.readline(" (Enter/y to approve, n to deny, or provide feedback): ", true)
862
+ # Use TTY::Prompt for better input handling
863
+ tty_prompt = TTY::Prompt.new(interrupt: :exit)
864
864
 
865
- if response.nil? # Handle EOF/pipe input
865
+ begin
866
+ response = tty_prompt.ask(" (Enter/y to approve, n to deny, or provide feedback):", required: false) do |q|
867
+ q.modify :strip
868
+ end
869
+ rescue TTY::Reader::InputInterrupt
870
+ # Handle Ctrl+C
871
+ puts
866
872
  return { approved: false, feedback: nil }
867
873
  end
868
874
 
869
- response = response.chomp
875
+ # Handle nil response (EOF/pipe input)
876
+ if response.nil? || response.empty?
877
+ return { approved: true, feedback: nil } # Empty means approved
878
+ end
879
+
870
880
  response_lower = response.downcase
871
881
 
872
- # Empty response (just Enter) or "y"/"yes" = approved
873
- if response.empty? || response_lower == "y" || response_lower == "yes"
882
+ # "y"/"yes" = approved
883
+ if response_lower == "y" || response_lower == "yes"
874
884
  return { approved: true, feedback: nil }
875
885
  end
876
886
 
data/lib/clacky/cli.rb CHANGED
@@ -3,7 +3,6 @@
3
3
  require "thor"
4
4
  require "tty-prompt"
5
5
  require "tty-spinner"
6
- require "readline"
7
6
  require_relative "ui/banner"
8
7
  require_relative "ui/prompt"
9
8
  require_relative "ui/statusbar"
@@ -414,7 +413,7 @@ module Clacky
414
413
 
415
414
  break if current_message.nil? || %w[exit quit].include?(current_message&.downcase&.strip)
416
415
  next if current_message.strip.empty?
417
-
416
+
418
417
  # Display user's message after input
419
418
  ui_formatter.user_message(current_message)
420
419
  end
@@ -657,12 +656,23 @@ module Clacky
657
656
  base_url: config.base_url
658
657
  )
659
658
 
659
+ # Use TTY::Prompt for input
660
+ tty_prompt = TTY::Prompt.new(interrupt: :exit)
661
+
660
662
  loop do
661
- # Use Readline for better Unicode/CJK support
662
- message = Readline.readline("You: ", true)
663
+ # Use TTY::Prompt for better input handling
664
+ begin
665
+ message = tty_prompt.ask("You:", required: false) do |q|
666
+ q.modify :strip
667
+ end
668
+ rescue TTY::Reader::InputInterrupt
669
+ # Handle Ctrl+C
670
+ puts
671
+ break
672
+ end
663
673
 
664
- break if message.nil? || %w[exit quit].include?(message.downcase.strip)
665
- next if message.strip.empty?
674
+ break if message.nil? || %w[exit quit].include?(message&.downcase&.strip)
675
+ next if message.nil? || message.strip.empty?
666
676
 
667
677
  spinner = TTY::Spinner.new("[:spinner] Claude is thinking...", format: :dots)
668
678
  spinner.auto_spin
@@ -49,6 +49,7 @@ module Clacky
49
49
  print "\e[u" # Restore cursor position (to after [..] symbol)
50
50
  print "\e[K" # Clear to end of line from cursor
51
51
  print text
52
+ print " "
52
53
  $stdout.flush
53
54
  end
54
55
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "readline"
3
+ require "tty-prompt"
4
4
  require "pastel"
5
5
  require "tty-screen"
6
6
 
@@ -10,11 +10,12 @@ module Clacky
10
10
  class Prompt
11
11
  def initialize
12
12
  @pastel = Pastel.new
13
+ @tty_prompt = TTY::Prompt.new(interrupt: :exit)
13
14
  end
14
15
 
15
16
  # Read user input with enhanced prompt box
16
17
  # @param prefix [String] Prompt prefix (default: "You:")
17
- # @param placeholder [String] Placeholder text (not shown when using Readline)
18
+ # @param placeholder [String] Placeholder text (not shown when using TTY::Prompt)
18
19
  # @return [String, nil] User input or nil on EOF
19
20
  def read_input(prefix: "You:", placeholder: nil)
20
21
  width = [TTY::Screen.width - 5, 70].min
@@ -22,9 +23,9 @@ module Clacky
22
23
  # Display complete box frame first
23
24
  puts @pastel.dim("╭" + "─" * width + "╮")
24
25
 
25
- # Empty input line with borders (width - 2 for left/right padding)
26
- padding = " " * (width - 2)
27
- puts @pastel.dim("#{padding} │")
26
+ # Empty input line - NO left border, just spaces and right border
27
+ padding = " " * width
28
+ puts @pastel.dim("#{padding} │")
28
29
 
29
30
  # Bottom border
30
31
  puts @pastel.dim("╰" + "─" * width + "╯")
@@ -32,36 +33,37 @@ module Clacky
32
33
  # Move cursor back up to input line (2 lines up)
33
34
  print "\e[2A" # Move up 2 lines
34
35
  print "\r" # Move to beginning of line
35
- print "\e[2C" # Move right 2 chars to after "│ "
36
36
 
37
- # Read input with Readline
38
- prompt_text = @pastel.bright_blue("#{prefix} ")
39
- input = read_with_readline(prompt_text)
37
+ # Read input with TTY::Prompt
38
+ prompt_text = @pastel.bright_blue("#{prefix}")
39
+ input = read_with_tty_prompt(prompt_text)
40
40
 
41
41
  # After input, clear the input box completely
42
42
  # Move cursor up 2 lines to the top of the box
43
43
  print "\e[2A"
44
44
  print "\r"
45
-
45
+
46
46
  # Clear all 3 lines of the box
47
47
  3.times do
48
48
  print "\e[2K" # Clear entire line
49
49
  print "\e[1B" # Move down 1 line
50
50
  print "\r" # Move to beginning of line
51
51
  end
52
-
52
+
53
53
  # Move cursor back up to where the box started
54
54
  print "\e[3A"
55
55
  print "\r"
56
-
56
+
57
57
  input
58
58
  end
59
59
 
60
60
  private
61
61
 
62
- def read_with_readline(prompt)
63
- Readline.readline(prompt, true)
64
- rescue Interrupt
62
+ def read_with_tty_prompt(prompt)
63
+ @tty_prompt.ask(prompt, required: false, echo: true) do |q|
64
+ q.modify :strip
65
+ end
66
+ rescue TTY::Reader::InputInterrupt
65
67
  puts
66
68
  nil
67
69
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Clacky
4
- VERSION = "0.5.2"
4
+ VERSION = "0.5.3"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openclacky
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - windy