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 +4 -4
- data/lib/clacky/agent.rb +29 -19
- data/lib/clacky/cli.rb +16 -6
- data/lib/clacky/progress_indicator.rb +1 -0
- data/lib/clacky/ui/prompt.rb +17 -15
- data/lib/clacky/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 52ab39c40c69d821b45d01ed1d14086a50446309421891e9cd6724a9b32864cf
|
|
4
|
+
data.tar.gz: 0d61ef02a23f8a04157f8b7b2308a4f0c68fd37bba1407894b9841cd707c6873
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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 "
|
|
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
|
|
863
|
-
|
|
862
|
+
# Use TTY::Prompt for better input handling
|
|
863
|
+
tty_prompt = TTY::Prompt.new(interrupt: :exit)
|
|
864
864
|
|
|
865
|
-
|
|
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
|
|
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
|
-
#
|
|
873
|
-
if
|
|
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
|
|
662
|
-
|
|
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
|
|
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
|
data/lib/clacky/ui/prompt.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "
|
|
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
|
|
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
|
|
26
|
-
padding = " " *
|
|
27
|
-
puts @pastel.dim("
|
|
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
|
|
38
|
-
prompt_text = @pastel.bright_blue("#{prefix}
|
|
39
|
-
input =
|
|
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
|
|
63
|
-
|
|
64
|
-
|
|
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
|
data/lib/clacky/version.rb
CHANGED