openclacky 0.6.2 → 0.6.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.
@@ -32,7 +32,7 @@ module Clacky
32
32
  user: [:white, :white],
33
33
  assistant: [:bright_green, :white],
34
34
  tool_call: [:bright_cyan, :cyan],
35
- tool_result: [:cyan, :white],
35
+ tool_result: [:bright_cyan, :cyan],
36
36
  tool_denied: [:bright_yellow, :yellow],
37
37
  tool_planned: [:bright_cyan, :cyan],
38
38
  tool_error: [:bright_red, :red],
@@ -29,7 +29,7 @@ module Clacky
29
29
  user: [:white, :white],
30
30
  assistant: [:green, :white],
31
31
  tool_call: [:cyan, :cyan],
32
- tool_result: [:white, :white],
32
+ tool_result: [:cyan, :cyan],
33
33
  tool_denied: [:yellow, :yellow],
34
34
  tool_planned: [:cyan, :cyan],
35
35
  tool_error: [:red, :red],
@@ -147,6 +147,12 @@ module Clacky
147
147
  @mode_toggle_callback = block
148
148
  end
149
149
 
150
+ # Set skill loader for command suggestions
151
+ # @param skill_loader [Clacky::SkillLoader] The skill loader instance
152
+ def set_skill_loader(skill_loader)
153
+ @input_area.set_skill_loader(skill_loader)
154
+ end
155
+
150
156
  # Append output to the output area
151
157
  # @param content [String] Content to append
152
158
  def append_output(content)
@@ -214,7 +220,7 @@ module Clacky
214
220
 
215
221
  # Delta tokens with color coding (green/yellow/red + dim)
216
222
  delta_tokens = token_data[:delta_tokens]
217
- delta_str = "+#{delta_tokens}"
223
+ delta_str = delta_tokens.negative? ? "#{delta_tokens}" : "+#{delta_tokens}"
218
224
  color_style = if delta_tokens > 10000
219
225
  :red
220
226
  elsif delta_tokens > 5000
@@ -222,7 +228,11 @@ module Clacky
222
228
  else
223
229
  :green
224
230
  end
225
- colored_delta = pastel.decorate(delta_str, color_style, :dim)
231
+ colored_delta = if delta_tokens.negative?
232
+ pastel.cyan(delta_str)
233
+ else
234
+ pastel.decorate(delta_str, color_style, :dim)
235
+ end
226
236
  token_info << colored_delta
227
237
 
228
238
  # Cache status indicator (using theme)
@@ -342,10 +352,13 @@ module Clacky
342
352
 
343
353
  # Remove <think>...</think> blocks (multiline, case-insensitive)
344
354
  # Also handles variations like <thinking>...</thinking>
345
- filtered = content.gsub(%r{<think(?:ing)?>\s*.*?\s*</think(?:ing)?>}mi, '')
355
+ filtered = content.gsub(%r{<think(?:ing)?>[\s\S]*?</think(?:ing)?>}mi, '')
356
+
357
+ # Clean up multiple empty lines left behind (max 2 consecutive newlines)
358
+ filtered.gsub!(/\n{3,}/, "\n\n")
346
359
 
347
- # Clean up extra whitespace left behind
348
- filtered.gsub(/\n{3,}/, "\n\n").strip
360
+ # Remove leading and trailing whitespace
361
+ filtered.strip
349
362
  end
350
363
 
351
364
  # Show tool call
@@ -556,8 +569,9 @@ module Clacky
556
569
  # Collect input (blocks until user presses Enter)
557
570
  result_text = inline_input.collect
558
571
 
559
- # Clean up - remove the inline input line (use layout to track position)
560
- @layout.remove_last_line
572
+ # Clean up - remove the inline input lines (handle wrapped lines)
573
+ line_count = inline_input.line_count
574
+ @layout.remove_last_line(line_count)
561
575
 
562
576
  # Append the final response to output
563
577
  if result_text.nil?
@@ -594,41 +608,15 @@ module Clacky
594
608
  require 'diffy'
595
609
 
596
610
  diff = Diffy::Diff.new(old_content, new_content, context: 3)
597
- all_lines = diff.to_s(:color).lines
598
- plain_lines = diff.to_s.lines
599
-
600
- # Add line numbers to diff output
601
- old_line_num = 0
602
- new_line_num = 0
603
-
604
- numbered_lines = all_lines.each_with_index.map do |line, index|
605
- # Use plain text to detect line type (remove ANSI codes)
606
- plain_line = plain_lines[index]&.chomp || line.gsub(/\e\[[0-9;]*m/, '').chomp
607
-
608
- # Remove trailing newline from colored line to avoid double newlines
609
- colored_line = line.chomp
610
-
611
- # Determine line type and number (use single line number for simplicity)
612
- if plain_line.start_with?('+') || plain_line.start_with?('-') || plain_line.start_with?(' ')
613
- new_line_num += 1
614
- sprintf("%4d | %s", new_line_num, colored_line)
615
- elsif plain_line.start_with?('@@')
616
- # Diff header: extract line numbers from @@ -old_start,old_count +new_start,new_count @@
617
- if plain_line =~ /@@ -(\d+)(?:,\d+)? (\d+)(?:,\d+)? @@/
618
- new_line_num = $2.to_i - 1
619
- end
620
- sprintf("%4s | %s", "", colored_line)
621
- else
622
- # Other lines (headers, etc.)
623
- sprintf("%4s | %s", "", colored_line)
624
- end
625
- end
611
+ diff_lines = diff.to_s(:color).lines
626
612
 
627
- display_lines = numbered_lines.first(max_lines)
628
- display_lines.each { |line| append_output(line) }
613
+ # Show diff without line numbers
614
+ diff_lines.take(max_lines).each do |line|
615
+ append_output(line.chomp)
616
+ end
629
617
 
630
- if all_lines.size > max_lines
631
- append_output("\n... (#{all_lines.size - max_lines} more lines, diff truncated)")
618
+ if diff_lines.size > max_lines
619
+ append_output("\n... (#{diff_lines.size - max_lines} more lines, diff truncated)")
632
620
  end
633
621
  rescue LoadError
634
622
  # Fallback if diffy is not available
@@ -788,16 +776,19 @@ module Clacky
788
776
 
789
777
  # Handle key input for InlineInput
790
778
  def handle_inline_input_key(key)
779
+ # Get old line count BEFORE modification
780
+ old_line_count = @inline_input.line_count
781
+
791
782
  result = @inline_input.handle_key(key)
792
783
 
793
784
  case result[:action]
794
785
  when :update
795
- # Update the last line of output with current input (use layout to track position)
796
- @layout.update_last_line(@inline_input.render)
786
+ # Update the output area with current input (considering wrapped lines)
787
+ @layout.update_last_line(@inline_input.render, old_line_count)
797
788
  # Position cursor for inline input
798
789
  @layout.position_inline_input_cursor(@inline_input)
799
790
  when :submit, :cancel
800
- # InlineInput is done, will be cleaned up by request_confirmation
791
+ # InlineInput is done, will be cleaned up by request_confirmation after collect returns
801
792
  nil
802
793
  when :toggle_mode
803
794
  # Update mode and session bar info, but don't render yet
@@ -30,20 +30,18 @@ module Clacky
30
30
  /\.ini$/,
31
31
  /\.conf$/,
32
32
  /\.config$/,
33
- /config\//,
34
- /\.config\//
35
33
  ].freeze
36
34
 
37
35
  # Find .gitignore file in the search path or parent directories
38
36
  # Only searches within the search path and up to the current working directory
39
37
  def self.find_gitignore(path)
40
38
  search_path = File.directory?(path) ? path : File.dirname(path)
41
-
39
+
42
40
  # Look for .gitignore in current and parent directories
43
41
  current = File.expand_path(search_path)
44
42
  cwd = File.expand_path(Dir.pwd)
45
43
  root = File.expand_path('/')
46
-
44
+
47
45
  # Limit search: only go up to current working directory
48
46
  # This prevents finding .gitignore files from unrelated parent directories
49
47
  # when searching in temporary directories (like /tmp in tests)
@@ -52,16 +50,16 @@ module Clacky
52
50
  else
53
51
  current
54
52
  end
55
-
53
+
56
54
  loop do
57
55
  gitignore = File.join(current, '.gitignore')
58
56
  return gitignore if File.exist?(gitignore)
59
-
57
+
60
58
  # Stop if we've reached the search limit or root
61
59
  break if current == search_limit || current == root
62
60
  current = File.dirname(current)
63
61
  end
64
-
62
+
65
63
  nil
66
64
  end
67
65
 
@@ -71,10 +69,10 @@ module Clacky
71
69
  # Expand both paths to handle symlinks and relative paths correctly
72
70
  expanded_file = File.expand_path(file)
73
71
  expanded_base = File.expand_path(base_path)
74
-
72
+
75
73
  # For files, use the directory as base
76
74
  expanded_base = File.dirname(expanded_base) if File.file?(expanded_base)
77
-
75
+
78
76
  # Calculate relative path
79
77
  if expanded_file.start_with?(expanded_base)
80
78
  relative_path = expanded_file[(expanded_base.length + 1)..-1] || File.basename(expanded_file)
@@ -82,10 +80,10 @@ module Clacky
82
80
  # File is outside base path - use just the filename
83
81
  relative_path = File.basename(expanded_file)
84
82
  end
85
-
83
+
86
84
  # Clean up relative path
87
85
  relative_path = relative_path.sub(/^\.\//, '') if relative_path
88
-
86
+
89
87
  if gitignore
90
88
  # Use .gitignore rules
91
89
  gitignore.ignored?(relative_path)
@@ -96,7 +94,7 @@ module Clacky
96
94
  File.fnmatch(pattern, relative_path, File::FNM_PATHNAME | File::FNM_DOTMATCH)
97
95
  else
98
96
  # Match pattern as a path component (not substring of absolute path)
99
- relative_path.start_with?("#{pattern}/") ||
97
+ relative_path.start_with?("#{pattern}/") ||
100
98
  relative_path.include?("/#{pattern}/") ||
101
99
  relative_path == pattern ||
102
100
  File.basename(relative_path) == pattern
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Clacky
4
- VERSION = "0.6.2"
4
+ VERSION = "0.6.3"
5
5
  end
data/lib/clacky.rb CHANGED
@@ -3,6 +3,8 @@
3
3
  require_relative "clacky/version"
4
4
  require_relative "clacky/config"
5
5
  require_relative "clacky/client"
6
+ require_relative "clacky/skill"
7
+ require_relative "clacky/skill_loader"
6
8
 
7
9
  # Agent system
8
10
  require_relative "clacky/model_pricing"
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.6.2
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - windy
@@ -167,11 +167,14 @@ files:
167
167
  - lib/clacky/cli.rb
168
168
  - lib/clacky/client.rb
169
169
  - lib/clacky/config.rb
170
+ - lib/clacky/default_skills/skill-add/SKILL.md
170
171
  - lib/clacky/gitignore_parser.rb
171
172
  - lib/clacky/hook_manager.rb
172
173
  - lib/clacky/model_pricing.rb
173
174
  - lib/clacky/progress_indicator.rb
174
175
  - lib/clacky/session_manager.rb
176
+ - lib/clacky/skill.rb
177
+ - lib/clacky/skill_loader.rb
175
178
  - lib/clacky/thinking_verbs.rb
176
179
  - lib/clacky/tool_registry.rb
177
180
  - lib/clacky/tools/base.rb
@@ -191,6 +194,7 @@ files:
191
194
  - lib/clacky/ui2.rb
192
195
  - lib/clacky/ui2/README.md
193
196
  - lib/clacky/ui2/components/base_component.rb
197
+ - lib/clacky/ui2/components/command_suggestions.rb
194
198
  - lib/clacky/ui2/components/common_component.rb
195
199
  - lib/clacky/ui2/components/inline_input.rb
196
200
  - lib/clacky/ui2/components/input_area.rb