openclacky 0.6.0 → 0.6.2
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/CHANGELOG.md +54 -0
- data/README.md +39 -88
- data/homebrew/README.md +96 -0
- data/homebrew/openclacky.rb +24 -0
- data/lib/clacky/agent.rb +139 -67
- data/lib/clacky/cli.rb +105 -6
- data/lib/clacky/tools/file_reader.rb +135 -2
- data/lib/clacky/tools/glob.rb +2 -2
- data/lib/clacky/tools/grep.rb +2 -2
- data/lib/clacky/tools/run_project.rb +5 -5
- data/lib/clacky/tools/safe_shell.rb +140 -17
- data/lib/clacky/tools/shell.rb +69 -2
- data/lib/clacky/tools/todo_manager.rb +50 -3
- data/lib/clacky/tools/trash_manager.rb +1 -1
- data/lib/clacky/tools/web_fetch.rb +2 -2
- data/lib/clacky/tools/web_search.rb +2 -2
- data/lib/clacky/ui2/components/common_component.rb +14 -5
- data/lib/clacky/ui2/components/input_area.rb +300 -89
- data/lib/clacky/ui2/components/message_component.rb +7 -3
- data/lib/clacky/ui2/components/todo_area.rb +38 -45
- data/lib/clacky/ui2/components/welcome_banner.rb +10 -0
- data/lib/clacky/ui2/layout_manager.rb +180 -50
- data/lib/clacky/ui2/markdown_renderer.rb +80 -0
- data/lib/clacky/ui2/screen_buffer.rb +26 -7
- data/lib/clacky/ui2/themes/base_theme.rb +32 -46
- data/lib/clacky/ui2/themes/hacker_theme.rb +4 -2
- data/lib/clacky/ui2/themes/minimal_theme.rb +4 -2
- data/lib/clacky/ui2/ui_controller.rb +150 -32
- data/lib/clacky/ui2/view_renderer.rb +21 -4
- data/lib/clacky/ui2.rb +0 -1
- data/lib/clacky/utils/arguments_parser.rb +7 -2
- data/lib/clacky/utils/file_processor.rb +201 -0
- data/lib/clacky/version.rb +1 -1
- data/scripts/install.sh +249 -0
- data/scripts/uninstall.sh +146 -0
- metadata +21 -2
- data/lib/clacky/ui2/components/output_area.rb +0 -112
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "base64"
|
|
4
|
+
|
|
5
|
+
module Clacky
|
|
6
|
+
module Utils
|
|
7
|
+
# File processing utilities for binary files, images, and PDFs
|
|
8
|
+
class FileProcessor
|
|
9
|
+
# Maximum file size for binary files (5MB)
|
|
10
|
+
MAX_FILE_SIZE = 5 * 1024 * 1024
|
|
11
|
+
|
|
12
|
+
# Supported image formats
|
|
13
|
+
IMAGE_FORMATS = {
|
|
14
|
+
"png" => "image/png",
|
|
15
|
+
"jpg" => "image/jpeg",
|
|
16
|
+
"jpeg" => "image/jpeg",
|
|
17
|
+
"gif" => "image/gif",
|
|
18
|
+
"webp" => "image/webp"
|
|
19
|
+
}.freeze
|
|
20
|
+
|
|
21
|
+
# Supported document formats
|
|
22
|
+
DOCUMENT_FORMATS = {
|
|
23
|
+
"pdf" => "application/pdf"
|
|
24
|
+
}.freeze
|
|
25
|
+
|
|
26
|
+
# All supported formats
|
|
27
|
+
SUPPORTED_FORMATS = IMAGE_FORMATS.merge(DOCUMENT_FORMATS).freeze
|
|
28
|
+
|
|
29
|
+
# File signatures (magic bytes) for format detection
|
|
30
|
+
FILE_SIGNATURES = {
|
|
31
|
+
"\x89PNG\r\n\x1a\n".b => "png",
|
|
32
|
+
"\xFF\xD8\xFF".b => "jpg",
|
|
33
|
+
"GIF87a".b => "gif",
|
|
34
|
+
"GIF89a".b => "gif",
|
|
35
|
+
"%PDF".b => "pdf"
|
|
36
|
+
}.freeze
|
|
37
|
+
|
|
38
|
+
class << self
|
|
39
|
+
# Convert image file path to base64 data URL
|
|
40
|
+
# @param path [String] File path to image
|
|
41
|
+
# @return [String] base64 data URL (e.g., "data:image/png;base64,...")
|
|
42
|
+
# @raise [ArgumentError] If file not found or unsupported format
|
|
43
|
+
def image_path_to_data_url(path)
|
|
44
|
+
unless File.exist?(path)
|
|
45
|
+
raise ArgumentError, "Image file not found: #{path}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Check file size
|
|
49
|
+
file_size = File.size(path)
|
|
50
|
+
if file_size > MAX_FILE_SIZE
|
|
51
|
+
raise ArgumentError, "File too large: #{file_size} bytes (max: #{MAX_FILE_SIZE} bytes)"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Read file as binary
|
|
55
|
+
image_data = File.binread(path)
|
|
56
|
+
|
|
57
|
+
# Detect MIME type from file extension or content
|
|
58
|
+
mime_type = detect_mime_type(path, image_data)
|
|
59
|
+
|
|
60
|
+
# Verify it's an image format
|
|
61
|
+
unless IMAGE_FORMATS.values.include?(mime_type)
|
|
62
|
+
raise ArgumentError, "Unsupported image format: #{mime_type}"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Encode to base64
|
|
66
|
+
base64_data = Base64.strict_encode64(image_data)
|
|
67
|
+
|
|
68
|
+
"data:#{mime_type};base64,#{base64_data}"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Convert file to base64 with format detection
|
|
72
|
+
# @param path [String] File path
|
|
73
|
+
# @return [Hash] Hash with :format, :mime_type, :base64_data, :size_bytes
|
|
74
|
+
# @raise [ArgumentError] If file not found or too large
|
|
75
|
+
def file_to_base64(path)
|
|
76
|
+
unless File.exist?(path)
|
|
77
|
+
raise ArgumentError, "File not found: #{path}"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Check file size
|
|
81
|
+
file_size = File.size(path)
|
|
82
|
+
if file_size > MAX_FILE_SIZE
|
|
83
|
+
raise ArgumentError, "File too large: #{file_size} bytes (max: #{MAX_FILE_SIZE} bytes)"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Read file as binary
|
|
87
|
+
file_data = File.binread(path)
|
|
88
|
+
|
|
89
|
+
# Detect format and MIME type
|
|
90
|
+
format = detect_format(path, file_data)
|
|
91
|
+
mime_type = detect_mime_type(path, file_data)
|
|
92
|
+
|
|
93
|
+
# Encode to base64
|
|
94
|
+
base64_data = Base64.strict_encode64(file_data)
|
|
95
|
+
|
|
96
|
+
{
|
|
97
|
+
format: format,
|
|
98
|
+
mime_type: mime_type,
|
|
99
|
+
base64_data: base64_data,
|
|
100
|
+
size_bytes: file_size
|
|
101
|
+
}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Detect file format from path and content
|
|
105
|
+
# @param path [String] File path
|
|
106
|
+
# @param data [String] Binary file data
|
|
107
|
+
# @return [String] Format (e.g., "png", "jpg", "pdf")
|
|
108
|
+
def detect_format(path, data)
|
|
109
|
+
# Try to detect from file extension first
|
|
110
|
+
ext = File.extname(path).downcase.delete_prefix(".")
|
|
111
|
+
return ext if SUPPORTED_FORMATS.key?(ext)
|
|
112
|
+
|
|
113
|
+
# Try to detect from file signature (magic bytes)
|
|
114
|
+
FILE_SIGNATURES.each do |signature, format|
|
|
115
|
+
return format if data.start_with?(signature)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Special case for WebP (RIFF format)
|
|
119
|
+
if data.start_with?("RIFF".b) && data[8..11] == "WEBP".b
|
|
120
|
+
return "webp"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
nil
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Detect MIME type from file path and content
|
|
127
|
+
# @param path [String] File path
|
|
128
|
+
# @param data [String] Binary file data
|
|
129
|
+
# @return [String] MIME type (e.g., "image/png")
|
|
130
|
+
def detect_mime_type(path, data)
|
|
131
|
+
format = detect_format(path, data)
|
|
132
|
+
return SUPPORTED_FORMATS[format] if format && SUPPORTED_FORMATS[format]
|
|
133
|
+
|
|
134
|
+
# Default to application/octet-stream for unknown formats
|
|
135
|
+
"application/octet-stream"
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Check if file is a supported binary format
|
|
139
|
+
# @param path [String] File path
|
|
140
|
+
# @return [Boolean] True if supported binary format
|
|
141
|
+
def supported_binary_file?(path)
|
|
142
|
+
return false unless File.exist?(path)
|
|
143
|
+
|
|
144
|
+
ext = File.extname(path).downcase.delete_prefix(".")
|
|
145
|
+
SUPPORTED_FORMATS.key?(ext)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Check if file is an image
|
|
149
|
+
# @param path [String] File path
|
|
150
|
+
# @return [Boolean] True if image format
|
|
151
|
+
def image_file?(path)
|
|
152
|
+
return false unless File.exist?(path)
|
|
153
|
+
|
|
154
|
+
ext = File.extname(path).downcase.delete_prefix(".")
|
|
155
|
+
IMAGE_FORMATS.key?(ext)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Check if file is a PDF
|
|
159
|
+
# @param path [String] File path
|
|
160
|
+
# @return [Boolean] True if PDF format
|
|
161
|
+
def pdf_file?(path)
|
|
162
|
+
return false unless File.exist?(path)
|
|
163
|
+
|
|
164
|
+
ext = File.extname(path).downcase.delete_prefix(".")
|
|
165
|
+
ext == "pdf"
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Check if file is binary (not text)
|
|
169
|
+
# @param data [String] File content
|
|
170
|
+
# @param sample_size [Integer] Number of bytes to check (default: 8192)
|
|
171
|
+
# @return [Boolean] True if file appears to be binary
|
|
172
|
+
def binary_file?(data, sample_size: 8192)
|
|
173
|
+
# Check first N bytes for null bytes or high ratio of non-printable characters
|
|
174
|
+
sample = data[0, sample_size] || ""
|
|
175
|
+
return false if sample.empty?
|
|
176
|
+
|
|
177
|
+
# Check for known binary signatures first
|
|
178
|
+
FILE_SIGNATURES.each do |signature, _format|
|
|
179
|
+
return true if sample.start_with?(signature)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Check for WebP (RIFF format)
|
|
183
|
+
if sample.start_with?("RIFF".b) && sample.length >= 12 && sample[8..11] == "WEBP".b
|
|
184
|
+
return true
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# If contains null bytes, it's binary
|
|
188
|
+
return true if sample.include?("\x00")
|
|
189
|
+
|
|
190
|
+
# Count non-printable characters (excluding common whitespace)
|
|
191
|
+
non_printable = sample.bytes.count do |byte|
|
|
192
|
+
byte < 32 && ![9, 10, 13].include?(byte) || byte >= 127
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# If more than 30% non-printable, consider it binary
|
|
196
|
+
(non_printable.to_f / sample.size) > 0.3
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
data/lib/clacky/version.rb
CHANGED
data/scripts/install.sh
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# OpenClacky Installation Script
|
|
3
|
+
# This script automatically detects your system and installs OpenClacky
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
# Colors for output
|
|
8
|
+
RED='\033[0;31m'
|
|
9
|
+
GREEN='\033[0;32m'
|
|
10
|
+
YELLOW='\033[1;33m'
|
|
11
|
+
BLUE='\033[0;34m'
|
|
12
|
+
NC='\033[0m' # No Color
|
|
13
|
+
|
|
14
|
+
# Print colored messages
|
|
15
|
+
print_info() {
|
|
16
|
+
echo -e "${BLUE}ℹ${NC} $1"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
print_success() {
|
|
20
|
+
echo -e "${GREEN}✓${NC} $1"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
print_warning() {
|
|
24
|
+
echo -e "${YELLOW}⚠${NC} $1"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
print_error() {
|
|
28
|
+
echo -e "${RED}✗${NC} $1"
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
print_step() {
|
|
32
|
+
echo -e "\n${BLUE}==>${NC} $1"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# Detect OS
|
|
36
|
+
detect_os() {
|
|
37
|
+
case "$(uname -s)" in
|
|
38
|
+
Linux*) OS=Linux;;
|
|
39
|
+
Darwin*) OS=macOS;;
|
|
40
|
+
CYGWIN*) OS=Windows;;
|
|
41
|
+
MINGW*) OS=Windows;;
|
|
42
|
+
*) OS=Unknown;;
|
|
43
|
+
esac
|
|
44
|
+
print_info "Detected OS: $OS"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# Check if command exists
|
|
48
|
+
command_exists() {
|
|
49
|
+
command -v "$1" >/dev/null 2>&1
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# Compare version strings
|
|
53
|
+
version_ge() {
|
|
54
|
+
# Returns 0 (true) if $1 >= $2
|
|
55
|
+
printf '%s\n%s\n' "$2" "$1" | sort -V -C
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# Check Ruby version
|
|
59
|
+
check_ruby() {
|
|
60
|
+
if command_exists ruby; then
|
|
61
|
+
RUBY_VERSION=$(ruby -e 'puts RUBY_VERSION' 2>/dev/null)
|
|
62
|
+
print_info "Found Ruby version: $RUBY_VERSION"
|
|
63
|
+
|
|
64
|
+
if version_ge "$RUBY_VERSION" "3.1.0"; then
|
|
65
|
+
print_success "Ruby version is compatible (>= 3.1.0)"
|
|
66
|
+
return 0
|
|
67
|
+
else
|
|
68
|
+
print_warning "Ruby version $RUBY_VERSION is too old (need >= 3.1.0)"
|
|
69
|
+
return 1
|
|
70
|
+
fi
|
|
71
|
+
else
|
|
72
|
+
print_warning "Ruby is not installed"
|
|
73
|
+
return 1
|
|
74
|
+
fi
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
# Install via Homebrew
|
|
78
|
+
install_via_homebrew() {
|
|
79
|
+
print_step "Installing via Homebrew..."
|
|
80
|
+
|
|
81
|
+
if ! command_exists brew; then
|
|
82
|
+
print_error "Homebrew is not installed"
|
|
83
|
+
print_info "Install Homebrew from: https://brew.sh"
|
|
84
|
+
return 1
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
print_info "Adding OpenClacky tap..."
|
|
88
|
+
brew tap clacky-ai/openclacky 2>/dev/null || {
|
|
89
|
+
print_warning "Tap not found or already added, trying direct installation..."
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
print_info "Installing OpenClacky..."
|
|
93
|
+
brew install openclacky
|
|
94
|
+
|
|
95
|
+
if [ $? -eq 0 ]; then
|
|
96
|
+
print_success "OpenClacky installed successfully via Homebrew!"
|
|
97
|
+
return 0
|
|
98
|
+
else
|
|
99
|
+
print_error "Homebrew installation failed"
|
|
100
|
+
return 1
|
|
101
|
+
fi
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
# Install via RubyGems
|
|
105
|
+
install_via_gem() {
|
|
106
|
+
print_step "Installing via RubyGems..."
|
|
107
|
+
|
|
108
|
+
if ! command_exists gem; then
|
|
109
|
+
print_error "RubyGems is not available"
|
|
110
|
+
return 1
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
print_info "Installing OpenClacky gem..."
|
|
114
|
+
gem install openclacky
|
|
115
|
+
|
|
116
|
+
if [ $? -eq 0 ]; then
|
|
117
|
+
print_success "OpenClacky installed successfully via gem!"
|
|
118
|
+
return 0
|
|
119
|
+
else
|
|
120
|
+
print_error "Gem installation failed"
|
|
121
|
+
return 1
|
|
122
|
+
fi
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
# Suggest Ruby installation
|
|
126
|
+
suggest_ruby_installation() {
|
|
127
|
+
print_step "Ruby Installation Options"
|
|
128
|
+
echo ""
|
|
129
|
+
|
|
130
|
+
if [ "$OS" = "macOS" ]; then
|
|
131
|
+
print_info "Option 1: Install Ruby via Homebrew (Recommended)"
|
|
132
|
+
echo " brew install ruby@3.3"
|
|
133
|
+
echo " export PATH=\"/usr/local/opt/ruby@3.3/bin:\$PATH\""
|
|
134
|
+
echo ""
|
|
135
|
+
print_info "Option 2: Use rbenv"
|
|
136
|
+
echo " brew install rbenv ruby-build"
|
|
137
|
+
echo " rbenv install 3.3.0"
|
|
138
|
+
echo " rbenv global 3.3.0"
|
|
139
|
+
|
|
140
|
+
elif [ "$OS" = "Linux" ]; then
|
|
141
|
+
print_info "Option 1: Use rbenv"
|
|
142
|
+
echo " curl -fsSL https://github.com/rbenv/rbenv-installer/raw/main/bin/rbenv-installer | bash"
|
|
143
|
+
echo " rbenv install 3.3.0"
|
|
144
|
+
echo " rbenv global 3.3.0"
|
|
145
|
+
echo ""
|
|
146
|
+
print_info "Option 2: Use RVM"
|
|
147
|
+
echo " curl -sSL https://get.rvm.io | bash -s stable --ruby"
|
|
148
|
+
echo ""
|
|
149
|
+
print_info "Option 3: Use system package manager"
|
|
150
|
+
echo " # Ubuntu/Debian:"
|
|
151
|
+
echo " sudo apt-get update"
|
|
152
|
+
echo " sudo apt-get install ruby-full"
|
|
153
|
+
echo ""
|
|
154
|
+
echo " # Fedora:"
|
|
155
|
+
echo " sudo dnf install ruby ruby-devel"
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
echo ""
|
|
159
|
+
print_info "After installing Ruby, run this script again or use:"
|
|
160
|
+
echo " gem install openclacky"
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
# Main installation logic
|
|
166
|
+
main() {
|
|
167
|
+
echo ""
|
|
168
|
+
echo "╔═══════════════════════════════════════════════════════════╗"
|
|
169
|
+
echo "║ ║"
|
|
170
|
+
echo "║ 🤖 OpenClacky Installation Script ║"
|
|
171
|
+
echo "║ ║"
|
|
172
|
+
echo "║ AI Agent CLI with Tool Use Capabilities ║"
|
|
173
|
+
echo "║ ║"
|
|
174
|
+
echo "╚═══════════════════════════════════════════════════════════╝"
|
|
175
|
+
echo ""
|
|
176
|
+
|
|
177
|
+
detect_os
|
|
178
|
+
|
|
179
|
+
# Strategy 1: On macOS, try Homebrew first if available
|
|
180
|
+
if [ "$OS" = "macOS" ] && command_exists brew; then
|
|
181
|
+
print_info "Homebrew detected, using it for installation (recommended)"
|
|
182
|
+
if install_via_homebrew; then
|
|
183
|
+
show_post_install_info
|
|
184
|
+
exit 0
|
|
185
|
+
fi
|
|
186
|
+
print_warning "Homebrew installation failed, trying Ruby gem installation..."
|
|
187
|
+
fi
|
|
188
|
+
|
|
189
|
+
# Strategy 2: Check Ruby and install via gem
|
|
190
|
+
if check_ruby; then
|
|
191
|
+
if install_via_gem; then
|
|
192
|
+
show_post_install_info
|
|
193
|
+
exit 0
|
|
194
|
+
fi
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
# Strategy 3: Suggest installation options
|
|
198
|
+
print_error "Could not install OpenClacky automatically"
|
|
199
|
+
echo ""
|
|
200
|
+
print_step "Available Installation Options:"
|
|
201
|
+
echo ""
|
|
202
|
+
|
|
203
|
+
if [ "$OS" = "macOS" ]; then
|
|
204
|
+
if ! command_exists brew; then
|
|
205
|
+
print_info "Option 1: Install via Homebrew (Recommended)"
|
|
206
|
+
echo " If you have Homebrew, install it from: https://brew.sh"
|
|
207
|
+
echo " Then run:"
|
|
208
|
+
echo " brew tap clacky-ai/openclacky"
|
|
209
|
+
echo " brew install openclacky"
|
|
210
|
+
echo ""
|
|
211
|
+
fi
|
|
212
|
+
fi
|
|
213
|
+
|
|
214
|
+
suggest_ruby_installation
|
|
215
|
+
echo ""
|
|
216
|
+
|
|
217
|
+
print_info "For more information, visit: https://github.com/clacky-ai/open-clacky"
|
|
218
|
+
exit 1
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
# Post-installation information
|
|
222
|
+
show_post_install_info() {
|
|
223
|
+
echo ""
|
|
224
|
+
echo "╔═══════════════════════════════════════════════════════════╗"
|
|
225
|
+
echo "║ ║"
|
|
226
|
+
echo "║ ✨ OpenClacky Installed Successfully! ║"
|
|
227
|
+
echo "║ ║"
|
|
228
|
+
echo "╚═══════════════════════════════════════════════════════════╝"
|
|
229
|
+
echo ""
|
|
230
|
+
print_step "Quick Start Guide:"
|
|
231
|
+
echo ""
|
|
232
|
+
print_info "1. Configure your API key:"
|
|
233
|
+
echo " clacky config set"
|
|
234
|
+
echo ""
|
|
235
|
+
print_info "2. Start chatting:"
|
|
236
|
+
echo " clacky chat"
|
|
237
|
+
echo ""
|
|
238
|
+
print_info "3. Use AI agent mode:"
|
|
239
|
+
echo " clacky agent"
|
|
240
|
+
echo ""
|
|
241
|
+
print_info "4. Get help:"
|
|
242
|
+
echo " clacky help"
|
|
243
|
+
echo ""
|
|
244
|
+
print_success "Happy coding! 🚀"
|
|
245
|
+
echo ""
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
# Run main installation
|
|
249
|
+
main
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# OpenClacky Uninstallation Script
|
|
3
|
+
# This script removes OpenClacky from your system
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
# Colors for output
|
|
8
|
+
RED='\033[0;31m'
|
|
9
|
+
GREEN='\033[0;32m'
|
|
10
|
+
YELLOW='\033[1;33m'
|
|
11
|
+
BLUE='\033[0;34m'
|
|
12
|
+
NC='\033[0m' # No Color
|
|
13
|
+
|
|
14
|
+
print_info() {
|
|
15
|
+
echo -e "${BLUE}ℹ${NC} $1"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
print_success() {
|
|
19
|
+
echo -e "${GREEN}✓${NC} $1"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
print_warning() {
|
|
23
|
+
echo -e "${YELLOW}⚠${NC} $1"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
print_error() {
|
|
27
|
+
echo -e "${RED}✗${NC} $1"
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
print_step() {
|
|
31
|
+
echo -e "\n${BLUE}==>${NC} $1"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
command_exists() {
|
|
35
|
+
command -v "$1" >/dev/null 2>&1
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# Check if OpenClacky is installed
|
|
39
|
+
check_installation() {
|
|
40
|
+
if command_exists clacky || command_exists openclacky; then
|
|
41
|
+
return 0
|
|
42
|
+
else
|
|
43
|
+
return 1
|
|
44
|
+
fi
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# Uninstall via Homebrew
|
|
48
|
+
uninstall_homebrew() {
|
|
49
|
+
if command_exists brew; then
|
|
50
|
+
if brew list openclacky >/dev/null 2>&1; then
|
|
51
|
+
print_step "Uninstalling via Homebrew..."
|
|
52
|
+
brew uninstall openclacky
|
|
53
|
+
|
|
54
|
+
# Optionally untap
|
|
55
|
+
if brew tap | grep -q "clacky-ai/openclacky"; then
|
|
56
|
+
read -p "$(echo -e ${YELLOW}?${NC}) Remove Homebrew tap (clacky-ai/openclacky)? [y/N] " -n 1 -r
|
|
57
|
+
echo
|
|
58
|
+
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
59
|
+
brew untap clacky-ai/openclacky
|
|
60
|
+
print_success "Tap removed"
|
|
61
|
+
fi
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
return 0
|
|
65
|
+
fi
|
|
66
|
+
fi
|
|
67
|
+
return 1
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Uninstall via gem
|
|
71
|
+
uninstall_gem() {
|
|
72
|
+
if command_exists gem; then
|
|
73
|
+
if gem list -i openclacky >/dev/null 2>&1; then
|
|
74
|
+
print_step "Uninstalling via RubyGems..."
|
|
75
|
+
gem uninstall openclacky -x
|
|
76
|
+
return 0
|
|
77
|
+
fi
|
|
78
|
+
fi
|
|
79
|
+
return 1
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Remove configuration files
|
|
83
|
+
remove_config() {
|
|
84
|
+
CONFIG_DIR="$HOME/.clacky"
|
|
85
|
+
|
|
86
|
+
if [ -d "$CONFIG_DIR" ]; then
|
|
87
|
+
print_warning "Configuration directory found: $CONFIG_DIR"
|
|
88
|
+
read -p "$(echo -e ${YELLOW}?${NC}) Remove configuration files (including API keys)? [y/N] " -n 1 -r
|
|
89
|
+
echo
|
|
90
|
+
|
|
91
|
+
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
92
|
+
rm -rf "$CONFIG_DIR"
|
|
93
|
+
print_success "Configuration removed"
|
|
94
|
+
else
|
|
95
|
+
print_info "Configuration preserved at: $CONFIG_DIR"
|
|
96
|
+
fi
|
|
97
|
+
fi
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# Main uninstallation
|
|
101
|
+
main() {
|
|
102
|
+
echo ""
|
|
103
|
+
echo "╔═══════════════════════════════════════════════════════════╗"
|
|
104
|
+
echo "║ ║"
|
|
105
|
+
echo "║ 🗑️ OpenClacky Uninstallation ║"
|
|
106
|
+
echo "║ ║"
|
|
107
|
+
echo "╚═══════════════════════════════════════════════════════════╝"
|
|
108
|
+
echo ""
|
|
109
|
+
|
|
110
|
+
if ! check_installation; then
|
|
111
|
+
print_warning "OpenClacky does not appear to be installed"
|
|
112
|
+
exit 0
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
UNINSTALLED=false
|
|
116
|
+
|
|
117
|
+
# Try Homebrew first
|
|
118
|
+
if uninstall_homebrew; then
|
|
119
|
+
UNINSTALLED=true
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# Try gem
|
|
123
|
+
if uninstall_gem; then
|
|
124
|
+
UNINSTALLED=true
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
if [ "$UNINSTALLED" = false ]; then
|
|
128
|
+
print_error "Could not automatically uninstall OpenClacky"
|
|
129
|
+
print_info "You may need to uninstall manually:"
|
|
130
|
+
echo " - Via Homebrew: brew uninstall openclacky"
|
|
131
|
+
echo " - Via RubyGems: gem uninstall openclacky"
|
|
132
|
+
exit 1
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
print_success "OpenClacky uninstalled successfully"
|
|
136
|
+
|
|
137
|
+
# Ask about config removal
|
|
138
|
+
remove_config
|
|
139
|
+
|
|
140
|
+
echo ""
|
|
141
|
+
print_success "Uninstallation complete!"
|
|
142
|
+
print_info "Thank you for using OpenClacky 👋"
|
|
143
|
+
echo ""
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
main
|
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.
|
|
4
|
+
version: 0.6.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- windy
|
|
@@ -107,6 +107,20 @@ dependencies:
|
|
|
107
107
|
- - "~>"
|
|
108
108
|
- !ruby/object:Gem::Version
|
|
109
109
|
version: '0.8'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: tty-markdown
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '0.7'
|
|
117
|
+
type: :runtime
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - "~>"
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '0.7'
|
|
110
124
|
- !ruby/object:Gem::Dependency
|
|
111
125
|
name: base64
|
|
112
126
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -145,6 +159,8 @@ files:
|
|
|
145
159
|
- clacky-legacy/clacky.gemspec
|
|
146
160
|
- clacky-legacy/clarky.gemspec
|
|
147
161
|
- docs/ui2-architecture.md
|
|
162
|
+
- homebrew/README.md
|
|
163
|
+
- homebrew/openclacky.rb
|
|
148
164
|
- lib/clacky.rb
|
|
149
165
|
- lib/clacky/agent.rb
|
|
150
166
|
- lib/clacky/agent_config.rb
|
|
@@ -179,12 +195,12 @@ files:
|
|
|
179
195
|
- lib/clacky/ui2/components/inline_input.rb
|
|
180
196
|
- lib/clacky/ui2/components/input_area.rb
|
|
181
197
|
- lib/clacky/ui2/components/message_component.rb
|
|
182
|
-
- lib/clacky/ui2/components/output_area.rb
|
|
183
198
|
- lib/clacky/ui2/components/todo_area.rb
|
|
184
199
|
- lib/clacky/ui2/components/tool_component.rb
|
|
185
200
|
- lib/clacky/ui2/components/welcome_banner.rb
|
|
186
201
|
- lib/clacky/ui2/layout_manager.rb
|
|
187
202
|
- lib/clacky/ui2/line_editor.rb
|
|
203
|
+
- lib/clacky/ui2/markdown_renderer.rb
|
|
188
204
|
- lib/clacky/ui2/screen_buffer.rb
|
|
189
205
|
- lib/clacky/ui2/theme_manager.rb
|
|
190
206
|
- lib/clacky/ui2/themes/base_theme.rb
|
|
@@ -194,9 +210,12 @@ files:
|
|
|
194
210
|
- lib/clacky/ui2/view_renderer.rb
|
|
195
211
|
- lib/clacky/utils/arguments_parser.rb
|
|
196
212
|
- lib/clacky/utils/file_ignore_helper.rb
|
|
213
|
+
- lib/clacky/utils/file_processor.rb
|
|
197
214
|
- lib/clacky/utils/limit_stack.rb
|
|
198
215
|
- lib/clacky/utils/path_helper.rb
|
|
199
216
|
- lib/clacky/version.rb
|
|
217
|
+
- scripts/install.sh
|
|
218
|
+
- scripts/uninstall.sh
|
|
200
219
|
- sig/clacky.rbs
|
|
201
220
|
homepage: https://github.com/yafeilee/clacky
|
|
202
221
|
licenses:
|