openclacky 0.6.1 ā 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 +26 -0
- data/README.md +39 -88
- data/homebrew/README.md +96 -0
- data/homebrew/openclacky.rb +24 -0
- data/lib/clacky/agent.rb +17 -70
- data/lib/clacky/cli.rb +90 -1
- data/lib/clacky/tools/file_reader.rb +135 -2
- data/lib/clacky/tools/safe_shell.rb +39 -9
- data/lib/clacky/tools/shell.rb +67 -0
- data/lib/clacky/ui2/components/input_area.rb +175 -59
- data/lib/clacky/ui2/layout_manager.rb +83 -59
- data/lib/clacky/ui2/themes/hacker_theme.rb +2 -2
- data/lib/clacky/ui2/themes/minimal_theme.rb +2 -2
- data/lib/clacky/ui2/ui_controller.rb +80 -20
- 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 +6 -2
- data/lib/clacky/ui2/components/output_area.rb +0 -112
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 84e359dab8c2113e7b9160f92eadff62872bce2a1c1713abee9a2cbf4cac80b1
|
|
4
|
+
data.tar.gz: 604a48aaa45cf5bc79667e9fbd0792626aa578b65d7d0a8b06c5548759d3de39
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8c037ed1835e6295338b3136795d8be58ad3ae3654d6174c85cc7b05e237094fa8a39c96ec26c16106c6ff2ef382f7e5c88aca8b01da7e0b891ec438c579fd17
|
|
7
|
+
data.tar.gz: ebdd5c9a65cd21fdc7fb47743f3c6b9b5ce9fd0552fabb1a0a1c02554da8c91b9464718e1fd01f5dc18593740c22377ca67e132fd5c4ab67183166a878b039b7
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.6.2] - 2026-01-30
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- `--theme` CLI option to switch UI themes (hacker, minimal)
|
|
14
|
+
- Support for reading binary files (with 5MB limit)
|
|
15
|
+
- Cost color coding for better visibility
|
|
16
|
+
- Install script for easier installation
|
|
17
|
+
- New command handling improvements
|
|
18
|
+
|
|
19
|
+
### Improved
|
|
20
|
+
- User input style enhancements
|
|
21
|
+
- Tool execution output simplification
|
|
22
|
+
- Thinking mode output improvements
|
|
23
|
+
- Diff format display with cleaner line numbers
|
|
24
|
+
- Terminal resize handling
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- BadQuotedString parsing error
|
|
28
|
+
- Token counting for every new task
|
|
29
|
+
- Shell output max characters limit
|
|
30
|
+
- Inline input cursor positioning
|
|
31
|
+
- Compress message display (now hidden)
|
|
32
|
+
|
|
33
|
+
### Removed
|
|
34
|
+
- Redundant output components for cleaner architecture
|
|
35
|
+
|
|
10
36
|
## [0.6.1] - 2026-01-29
|
|
11
37
|
|
|
12
38
|
### Added
|
data/README.md
CHANGED
|
@@ -18,19 +18,36 @@ OpenClacky = Lovable + Supabase
|
|
|
18
18
|
|
|
19
19
|
## Installation
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
### Quick Install (Recommended)
|
|
22
|
+
|
|
23
|
+
**One-line installation** (auto-detects your system):
|
|
22
24
|
|
|
23
25
|
```bash
|
|
24
|
-
|
|
26
|
+
curl -sSL https://raw.githubusercontent.com/clacky-ai/open-clacky/main/scripts/install.sh | bash
|
|
25
27
|
```
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
This script will:
|
|
30
|
+
- Check your Ruby version
|
|
31
|
+
- Install via Homebrew (macOS) if available
|
|
32
|
+
- Install via RubyGems if Ruby >= 3.1.0 is installed
|
|
33
|
+
- Guide you to install Ruby if needed
|
|
34
|
+
|
|
35
|
+
### Method 1: Homebrew (macOS/Linux)
|
|
36
|
+
|
|
37
|
+
**Best for macOS users** - Automatically handles Ruby dependencies:
|
|
28
38
|
|
|
29
39
|
```bash
|
|
30
|
-
|
|
40
|
+
brew tap clacky-ai/openclacky
|
|
41
|
+
brew install openclacky
|
|
31
42
|
```
|
|
32
43
|
|
|
33
|
-
|
|
44
|
+
### Method 2: RubyGems (If you already have Ruby >= 3.1.0)
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
gem install openclacky
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Method 3: From Source (For Development)
|
|
34
51
|
|
|
35
52
|
```bash
|
|
36
53
|
git clone https://github.com/clacky-ai/open-clacky.git
|
|
@@ -39,6 +56,22 @@ bundle install
|
|
|
39
56
|
bin/clacky
|
|
40
57
|
```
|
|
41
58
|
|
|
59
|
+
### System Requirements
|
|
60
|
+
|
|
61
|
+
- **Ruby**: >= 3.1.0 (automatically handled by Homebrew)
|
|
62
|
+
- **OS**: macOS, Linux, or Windows (WSL)
|
|
63
|
+
|
|
64
|
+
### Uninstallation
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Quick uninstall
|
|
68
|
+
curl -sSL https://raw.githubusercontent.com/clacky-ai/open-clacky/main/scripts/uninstall.sh | bash
|
|
69
|
+
|
|
70
|
+
# Or manually
|
|
71
|
+
brew uninstall openclacky # If installed via Homebrew
|
|
72
|
+
gem uninstall openclacky # If installed via gem
|
|
73
|
+
```
|
|
74
|
+
|
|
42
75
|
## Configuration
|
|
43
76
|
|
|
44
77
|
Before using Clacky, you need to configure your settings:
|
|
@@ -60,32 +93,6 @@ clacky config show
|
|
|
60
93
|
|
|
61
94
|
## Usage
|
|
62
95
|
|
|
63
|
-
### Interactive Chat Mode
|
|
64
|
-
|
|
65
|
-
Start an interactive chat session:
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
clacky chat
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Type your messages and press Enter. Type `exit` or `quit` to end the session.
|
|
72
|
-
|
|
73
|
-
### Single Message Mode
|
|
74
|
-
|
|
75
|
-
Send a single message and get a response:
|
|
76
|
-
|
|
77
|
-
```bash
|
|
78
|
-
clacky chat "What is Ruby?"
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Specify Model
|
|
82
|
-
|
|
83
|
-
You can specify which model to use (overrides config):
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
clacky chat --model=gpt-4 "Hello!"
|
|
87
|
-
```
|
|
88
|
-
|
|
89
96
|
### AI Agent Mode (Interactive)
|
|
90
97
|
|
|
91
98
|
Run an autonomous AI agent in interactive mode. The agent can use tools to complete tasks and runs in a continuous loop, allowing you to have multi-turn conversations with tool use capabilities.
|
|
@@ -103,22 +110,10 @@ clacky agent --mode=auto_approve
|
|
|
103
110
|
# Work in a specific project directory
|
|
104
111
|
clacky agent --path /path/to/project
|
|
105
112
|
|
|
106
|
-
# Limit tools available to the agent
|
|
107
|
-
clacky agent --tools file_reader glob grep
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
The agent will:
|
|
111
|
-
1. Complete each task using its React (Reason-Act-Observe) cycle
|
|
112
|
-
2. Show you the results
|
|
113
|
-
3. Wait for your next instruction
|
|
114
|
-
4. Maintain conversation context across tasks
|
|
115
|
-
5. Type 'exit' or 'quit' to end the session
|
|
116
|
-
|
|
117
113
|
#### Permission Modes
|
|
118
114
|
|
|
119
|
-
- `confirm_all` (default) - Confirm every tool use
|
|
120
|
-
- `confirm_edits` - Auto-approve read-only tools, confirm edits
|
|
121
115
|
- `auto_approve` - Automatically execute all tools (use with caution)
|
|
116
|
+
- `confirm_safes` - Auto-approve read-only tools, confirm edits
|
|
122
117
|
- `plan_only` - Generate plan without executing
|
|
123
118
|
|
|
124
119
|
#### Agent Options
|
|
@@ -126,9 +121,6 @@ The agent will:
|
|
|
126
121
|
```bash
|
|
127
122
|
--path PATH # Project directory (defaults to current directory)
|
|
128
123
|
--mode MODE # Permission mode
|
|
129
|
-
--tools TOOL1 TOOL2 # Allowed tools (or "all")
|
|
130
|
-
--max-iterations N # Maximum iterations (default: 50)
|
|
131
|
-
--max-cost N # Maximum cost in USD (default: 5.0)
|
|
132
124
|
--verbose # Show detailed output
|
|
133
125
|
```
|
|
134
126
|
|
|
@@ -138,30 +130,17 @@ The agent includes intelligent cost control features:
|
|
|
138
130
|
|
|
139
131
|
- **Automatic Message Compression**: When conversation history grows beyond 100 messages, the agent automatically compresses older messages into a summary, keeping only the system prompt and the most recent 20 messages. This dramatically reduces token costs for long-running tasks (achieves ~60% compression ratio).
|
|
140
132
|
|
|
141
|
-
- **Configurable Limits**:
|
|
142
|
-
- `max_iterations`: Maximum number of agent loops (default: 200)
|
|
143
|
-
- `max_cost_usd`: Maximum total cost in USD (default: $5.00)
|
|
144
|
-
- `timeout_seconds`: Maximum execution time (default: none)
|
|
145
|
-
|
|
146
133
|
- **Compression Settings**:
|
|
147
134
|
- `enable_compression`: Enable/disable automatic compression (default: true)
|
|
148
135
|
- `keep_recent_messages`: Number of recent messages to preserve (default: 20)
|
|
149
136
|
- Compression triggers at: ~100 messages (keep_recent_messages + 80)
|
|
150
137
|
|
|
151
|
-
Example with custom limits:
|
|
152
|
-
```bash
|
|
153
|
-
clacky agent --max-iterations=100 --max-cost=10.0 --verbose
|
|
154
|
-
```
|
|
155
|
-
|
|
156
138
|
### List Available Tools
|
|
157
139
|
|
|
158
140
|
View all built-in tools:
|
|
159
141
|
|
|
160
142
|
```bash
|
|
161
143
|
clacky tools
|
|
162
|
-
|
|
163
|
-
# Filter by category
|
|
164
|
-
clacky tools --category file_system
|
|
165
144
|
```
|
|
166
145
|
|
|
167
146
|
#### Built-in Tools
|
|
@@ -173,14 +152,12 @@ clacky tools --category file_system
|
|
|
173
152
|
- **glob** - Find files by pattern matching
|
|
174
153
|
- **grep** - Search file contents with regex
|
|
175
154
|
- **shell** - Execute shell commands
|
|
176
|
-
- **calculator** - Perform mathematical calculations
|
|
177
155
|
- **web_search** - Search the web for information
|
|
178
156
|
- **web_fetch** - Fetch and parse web page content
|
|
179
157
|
|
|
180
158
|
### Available Commands
|
|
181
159
|
|
|
182
160
|
```bash
|
|
183
|
-
clacky chat [MESSAGE] # Start a chat or send a single message
|
|
184
161
|
clacky agent [MESSAGE] # Run autonomous agent with tool use
|
|
185
162
|
clacky tools # List available tools
|
|
186
163
|
clacky config set # Set your API key
|
|
@@ -191,19 +168,6 @@ clacky help # Show help information
|
|
|
191
168
|
|
|
192
169
|
## Examples
|
|
193
170
|
|
|
194
|
-
### Chat Examples
|
|
195
|
-
|
|
196
|
-
```bash
|
|
197
|
-
# Quick question
|
|
198
|
-
clacky chat "Explain closures in Ruby"
|
|
199
|
-
|
|
200
|
-
# Start interactive session
|
|
201
|
-
clacky chat
|
|
202
|
-
|
|
203
|
-
# Check version
|
|
204
|
-
clacky version
|
|
205
|
-
```
|
|
206
|
-
|
|
207
171
|
### Agent Examples
|
|
208
172
|
|
|
209
173
|
```bash
|
|
@@ -214,25 +178,12 @@ clacky agent
|
|
|
214
178
|
# > Now add more items to the TODO list
|
|
215
179
|
# > exit
|
|
216
180
|
|
|
217
|
-
# Start with initial task, then continue
|
|
218
|
-
clacky agent "Add a .gitignore file for Ruby projects"
|
|
219
|
-
# After completing, agent waits for next task
|
|
220
|
-
# > List all Ruby files
|
|
221
|
-
# > Count lines in each file
|
|
222
|
-
# > exit
|
|
223
|
-
|
|
224
181
|
# Auto-approve mode for trusted operations
|
|
225
182
|
clacky agent --mode=auto_approve --path ~/my-project
|
|
226
183
|
# > Count all lines of code
|
|
227
184
|
# > Create a summary report
|
|
228
185
|
# > exit
|
|
229
186
|
|
|
230
|
-
# Use specific tools only in interactive mode
|
|
231
|
-
clacky agent --tools file_reader glob grep
|
|
232
|
-
# > Find all TODO comments
|
|
233
|
-
# > Search for FIXME comments
|
|
234
|
-
# > exit
|
|
235
|
-
|
|
236
187
|
# Using TODO manager for complex tasks
|
|
237
188
|
clacky agent "Implement a new feature with user authentication"
|
|
238
189
|
# Agent will:
|
data/homebrew/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Homebrew Formula for OpenClacky
|
|
2
|
+
|
|
3
|
+
This directory contains the Homebrew formula for OpenClacky.
|
|
4
|
+
|
|
5
|
+
## For Maintainers: Publishing to Homebrew Tap
|
|
6
|
+
|
|
7
|
+
### One-time Setup
|
|
8
|
+
|
|
9
|
+
1. Create a GitHub repository named `homebrew-openclacky` (must start with `homebrew-`)
|
|
10
|
+
2. Push this formula to the repository
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# In your GitHub account, create: homebrew-openclacky
|
|
14
|
+
git clone https://github.com/YOUR_USERNAME/homebrew-openclacky.git
|
|
15
|
+
cd homebrew-openclacky
|
|
16
|
+
cp /path/to/openclacky/homebrew/openclacky.rb ./Formula/openclacky.rb
|
|
17
|
+
git add Formula/openclacky.rb
|
|
18
|
+
git commit -m "Add openclacky formula"
|
|
19
|
+
git push origin main
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Update Formula for New Release
|
|
23
|
+
|
|
24
|
+
When you release a new version:
|
|
25
|
+
|
|
26
|
+
1. Download the new gem and calculate SHA256:
|
|
27
|
+
```bash
|
|
28
|
+
VERSION=0.6.1
|
|
29
|
+
wget https://rubygems.org/downloads/openclacky-${VERSION}.gem
|
|
30
|
+
shasum -a 256 openclacky-${VERSION}.gem
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
2. Update the formula in `homebrew-openclacky` repository:
|
|
34
|
+
- Update `url` with new version
|
|
35
|
+
- Update `sha256` with calculated hash
|
|
36
|
+
- Commit and push
|
|
37
|
+
|
|
38
|
+
3. Users can then upgrade:
|
|
39
|
+
```bash
|
|
40
|
+
brew update
|
|
41
|
+
brew upgrade openclacky
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## For Users: Installation
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Add the tap (one-time)
|
|
48
|
+
brew tap YOUR_USERNAME/openclacky
|
|
49
|
+
|
|
50
|
+
# Install
|
|
51
|
+
brew install openclacky
|
|
52
|
+
|
|
53
|
+
# Or in one command
|
|
54
|
+
brew install YOUR_USERNAME/openclacky/openclacky
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Testing the Formula Locally
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Install from local formula
|
|
61
|
+
brew install --build-from-source ./homebrew/openclacky.rb
|
|
62
|
+
|
|
63
|
+
# Or test without installing
|
|
64
|
+
brew test ./homebrew/openclacky.rb
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Automation Script
|
|
68
|
+
|
|
69
|
+
For easier updates, use this script:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
#!/bin/bash
|
|
73
|
+
# update_formula.sh
|
|
74
|
+
|
|
75
|
+
VERSION=$1
|
|
76
|
+
if [ -z "$VERSION" ]; then
|
|
77
|
+
echo "Usage: ./update_formula.sh VERSION"
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# Download gem
|
|
82
|
+
wget https://rubygems.org/downloads/openclacky-${VERSION}.gem -O /tmp/openclacky.gem
|
|
83
|
+
|
|
84
|
+
# Calculate SHA256
|
|
85
|
+
SHA256=$(shasum -a 256 /tmp/openclacky.gem | cut -d' ' -f1)
|
|
86
|
+
|
|
87
|
+
# Update formula
|
|
88
|
+
sed -i '' "s|url \".*\"|url \"https://rubygems.org/downloads/openclacky-${VERSION}.gem\"|" openclacky.rb
|
|
89
|
+
sed -i '' "s|sha256 \".*\"|sha256 \"${SHA256}\"|" openclacky.rb
|
|
90
|
+
|
|
91
|
+
echo "Formula updated to version ${VERSION}"
|
|
92
|
+
echo "SHA256: ${SHA256}"
|
|
93
|
+
echo "Don't forget to commit and push to homebrew-openclacky repository!"
|
|
94
|
+
|
|
95
|
+
rm /tmp/openclacky.gem
|
|
96
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Openclacky < Formula
|
|
4
|
+
desc "Command-line interface for AI models with autonomous agent capabilities"
|
|
5
|
+
homepage "https://github.com/clacky-ai/open-clacky"
|
|
6
|
+
url "https://rubygems.org/downloads/openclacky-0.6.1.gem"
|
|
7
|
+
sha256 "" # Will be updated when gem is published
|
|
8
|
+
license "MIT"
|
|
9
|
+
|
|
10
|
+
depends_on "ruby@3.3"
|
|
11
|
+
|
|
12
|
+
def install
|
|
13
|
+
ENV["GEM_HOME"] = libexec
|
|
14
|
+
system "gem", "install", cached_download, "--no-document"
|
|
15
|
+
|
|
16
|
+
# Create wrapper scripts
|
|
17
|
+
(bin/"openclacky").write_env_script libexec/"bin/openclacky", GEM_HOME: ENV["GEM_HOME"]
|
|
18
|
+
(bin/"clacky").write_env_script libexec/"bin/clacky", GEM_HOME: ENV["GEM_HOME"]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
test do
|
|
22
|
+
assert_match "openclacky version #{version}", shell_output("#{bin}/openclacky version")
|
|
23
|
+
end
|
|
24
|
+
end
|
data/lib/clacky/agent.rb
CHANGED
|
@@ -4,8 +4,8 @@ require "securerandom"
|
|
|
4
4
|
require "json"
|
|
5
5
|
require "tty-prompt"
|
|
6
6
|
require "set"
|
|
7
|
-
require "base64"
|
|
8
7
|
require_relative "utils/arguments_parser"
|
|
8
|
+
require_relative "utils/file_processor"
|
|
9
9
|
|
|
10
10
|
module Clacky
|
|
11
11
|
class Agent
|
|
@@ -137,7 +137,7 @@ module Clacky
|
|
|
137
137
|
user_messages = @messages.select do |m|
|
|
138
138
|
m[:role] == "user" && !m[:system_injected]
|
|
139
139
|
end
|
|
140
|
-
|
|
140
|
+
|
|
141
141
|
# Extract text content from the last N user messages
|
|
142
142
|
user_messages.last(limit).map do |msg|
|
|
143
143
|
extract_text_from_content(msg[:content])
|
|
@@ -163,10 +163,11 @@ module Clacky
|
|
|
163
163
|
def run(user_input, images: [])
|
|
164
164
|
@start_time = Time.now
|
|
165
165
|
@task_cost_source = :estimated # Reset for new task
|
|
166
|
-
@previous_total_tokens
|
|
166
|
+
# Note: Do NOT reset @previous_total_tokens here - it should maintain the value from the last iteration
|
|
167
|
+
# across tasks to correctly calculate delta tokens in each iteration
|
|
167
168
|
@task_start_iterations = @iterations # Track starting iterations for this task
|
|
168
169
|
@task_start_cost = @total_cost # Track starting cost for this task
|
|
169
|
-
|
|
170
|
+
|
|
170
171
|
# Track cache stats for current task
|
|
171
172
|
@task_cache_stats = {
|
|
172
173
|
cache_creation_input_tokens: 0,
|
|
@@ -538,7 +539,7 @@ module Clacky
|
|
|
538
539
|
denial_message += ": #{confirmation[:feedback]}"
|
|
539
540
|
end
|
|
540
541
|
@ui&.show_warning(denial_message)
|
|
541
|
-
|
|
542
|
+
|
|
542
543
|
denied = true
|
|
543
544
|
user_feedback = confirmation[:feedback]
|
|
544
545
|
feedback = user_feedback if user_feedback
|
|
@@ -666,7 +667,7 @@ module Clacky
|
|
|
666
667
|
# Check if the command is a slow command
|
|
667
668
|
command = args[:command] || args['command']
|
|
668
669
|
return false unless command
|
|
669
|
-
|
|
670
|
+
|
|
670
671
|
# List of slow command patterns
|
|
671
672
|
slow_patterns = [
|
|
672
673
|
/bundle\s+(install|exec\s+rspec|exec\s+rake)/,
|
|
@@ -679,7 +680,7 @@ module Clacky
|
|
|
679
680
|
/pytest/,
|
|
680
681
|
/jest/
|
|
681
682
|
]
|
|
682
|
-
|
|
683
|
+
|
|
683
684
|
slow_patterns.any? { |pattern| command.match?(pattern) }
|
|
684
685
|
when 'web_fetch', 'web_search'
|
|
685
686
|
true # Network operations can be slow
|
|
@@ -692,11 +693,7 @@ module Clacky
|
|
|
692
693
|
private def build_tool_progress_message(tool_name, args)
|
|
693
694
|
case tool_name.to_s.downcase
|
|
694
695
|
when 'shell', 'safe_shell'
|
|
695
|
-
|
|
696
|
-
# Extract the main command for display
|
|
697
|
-
cmd_parts = command.to_s.split
|
|
698
|
-
main_cmd = cmd_parts.first(2).join(' ')
|
|
699
|
-
"Running #{main_cmd}"
|
|
696
|
+
"Running command"
|
|
700
697
|
when 'web_fetch'
|
|
701
698
|
"Fetching web page"
|
|
702
699
|
when 'web_search'
|
|
@@ -755,15 +752,15 @@ module Clacky
|
|
|
755
752
|
@cache_stats[:raw_api_usage_samples] << raw_api_usage
|
|
756
753
|
@cache_stats[:raw_api_usage_samples] = @cache_stats[:raw_api_usage_samples].last(3)
|
|
757
754
|
end
|
|
758
|
-
|
|
755
|
+
|
|
759
756
|
# Track cache usage for current task
|
|
760
757
|
if @task_cache_stats
|
|
761
758
|
@task_cache_stats[:total_requests] += 1
|
|
762
|
-
|
|
759
|
+
|
|
763
760
|
if usage[:cache_creation_input_tokens]
|
|
764
761
|
@task_cache_stats[:cache_creation_input_tokens] += usage[:cache_creation_input_tokens]
|
|
765
762
|
end
|
|
766
|
-
|
|
763
|
+
|
|
767
764
|
if usage[:cache_read_input_tokens]
|
|
768
765
|
@task_cache_stats[:cache_read_input_tokens] += usage[:cache_read_input_tokens]
|
|
769
766
|
@task_cache_stats[:cache_hit_requests] += 1
|
|
@@ -957,7 +954,8 @@ module Clacky
|
|
|
957
954
|
|
|
958
955
|
{
|
|
959
956
|
role: "user",
|
|
960
|
-
content: "[SYSTEM] " + summary_text
|
|
957
|
+
content: "[SYSTEM] " + summary_text,
|
|
958
|
+
system_injected: true
|
|
961
959
|
}
|
|
962
960
|
end
|
|
963
961
|
|
|
@@ -1200,10 +1198,10 @@ module Clacky
|
|
|
1200
1198
|
def build_result(status, error: nil)
|
|
1201
1199
|
# Calculate iterations for current task only
|
|
1202
1200
|
task_iterations = @iterations - (@task_start_iterations || 0)
|
|
1203
|
-
|
|
1201
|
+
|
|
1204
1202
|
# Calculate cost for current task only
|
|
1205
1203
|
task_cost = @total_cost - (@task_start_cost || 0)
|
|
1206
|
-
|
|
1204
|
+
|
|
1207
1205
|
{
|
|
1208
1206
|
status: status,
|
|
1209
1207
|
session_id: @session_id,
|
|
@@ -1257,64 +1255,13 @@ module Clacky
|
|
|
1257
1255
|
content << { type: "text", text: text } unless text.nil? || text.empty?
|
|
1258
1256
|
|
|
1259
1257
|
images.each do |image_path|
|
|
1260
|
-
image_url = image_path_to_data_url(image_path)
|
|
1258
|
+
image_url = Utils::FileProcessor.image_path_to_data_url(image_path)
|
|
1261
1259
|
content << { type: "image_url", image_url: { url: image_url } }
|
|
1262
1260
|
end
|
|
1263
1261
|
|
|
1264
1262
|
content
|
|
1265
1263
|
end
|
|
1266
1264
|
|
|
1267
|
-
# Convert image file path to base64 data URL
|
|
1268
|
-
# @param path [String] File path to image
|
|
1269
|
-
# @return [String] base64 data URL (e.g., "data:image/png;base64,...")
|
|
1270
|
-
def image_path_to_data_url(path)
|
|
1271
|
-
unless File.exist?(path)
|
|
1272
|
-
raise ArgumentError, "Image file not found: #{path}"
|
|
1273
|
-
end
|
|
1274
|
-
|
|
1275
|
-
# Read file as binary
|
|
1276
|
-
image_data = File.binread(path)
|
|
1277
|
-
|
|
1278
|
-
# Detect MIME type from file extension or content
|
|
1279
|
-
mime_type = detect_image_mime_type(path, image_data)
|
|
1280
|
-
|
|
1281
|
-
# Encode to base64
|
|
1282
|
-
base64_data = Base64.strict_encode64(image_data)
|
|
1283
|
-
|
|
1284
|
-
"data:#{mime_type};base64,#{base64_data}"
|
|
1285
|
-
end
|
|
1286
1265
|
|
|
1287
|
-
# Detect image MIME type
|
|
1288
|
-
# @param path [String] File path
|
|
1289
|
-
# @param data [String] Binary image data
|
|
1290
|
-
# @return [String] MIME type (e.g., "image/png")
|
|
1291
|
-
def detect_image_mime_type(path, data)
|
|
1292
|
-
# Try to detect from file extension first
|
|
1293
|
-
ext = File.extname(path).downcase
|
|
1294
|
-
case ext
|
|
1295
|
-
when ".png"
|
|
1296
|
-
"image/png"
|
|
1297
|
-
when ".jpg", ".jpeg"
|
|
1298
|
-
"image/jpeg"
|
|
1299
|
-
when ".gif"
|
|
1300
|
-
"image/gif"
|
|
1301
|
-
when ".webp"
|
|
1302
|
-
"image/webp"
|
|
1303
|
-
else
|
|
1304
|
-
# Try to detect from file signature (magic bytes)
|
|
1305
|
-
if data.start_with?("\x89PNG".b)
|
|
1306
|
-
"image/png"
|
|
1307
|
-
elsif data.start_with?("\xFF\xD8\xFF".b)
|
|
1308
|
-
"image/jpeg"
|
|
1309
|
-
elsif data.start_with?("GIF87a".b) || data.start_with?("GIF89a".b)
|
|
1310
|
-
"image/gif"
|
|
1311
|
-
elsif data.start_with?("RIFF".b) && data[8..11] == "WEBP".b
|
|
1312
|
-
"image/webp"
|
|
1313
|
-
else
|
|
1314
|
-
# Default to png if unknown
|
|
1315
|
-
"image/png"
|
|
1316
|
-
end
|
|
1317
|
-
end
|
|
1318
|
-
end
|
|
1319
1266
|
end
|
|
1320
1267
|
end
|
data/lib/clacky/cli.rb
CHANGED
|
@@ -32,6 +32,10 @@ module Clacky
|
|
|
32
32
|
confirm_edits - Auto-approve read-only tools, confirm edits
|
|
33
33
|
plan_only - Generate plan without executing
|
|
34
34
|
|
|
35
|
+
UI themes:
|
|
36
|
+
hacker - Matrix/hacker-style with bracket symbols (default)
|
|
37
|
+
minimal - Clean, simple symbols
|
|
38
|
+
|
|
35
39
|
Session management:
|
|
36
40
|
-c, --continue - Continue the most recent session for this directory
|
|
37
41
|
-l, --list - List recent sessions
|
|
@@ -42,6 +46,8 @@ module Clacky
|
|
|
42
46
|
LONGDESC
|
|
43
47
|
option :mode, type: :string, default: "confirm_safes",
|
|
44
48
|
desc: "Permission mode: auto_approve, confirm_safes, confirm_edits, plan_only"
|
|
49
|
+
option :theme, type: :string, default: "hacker",
|
|
50
|
+
desc: "UI theme: hacker, minimal (default: hacker)"
|
|
45
51
|
option :verbose, type: :boolean, aliases: "-v", default: false, desc: "Show detailed output"
|
|
46
52
|
option :path, type: :string, desc: "Project directory path (defaults to current directory)"
|
|
47
53
|
option :continue, type: :boolean, aliases: "-c", desc: "Continue most recent session"
|
|
@@ -127,6 +133,80 @@ module Clacky
|
|
|
127
133
|
end
|
|
128
134
|
end
|
|
129
135
|
|
|
136
|
+
desc "new PROJECT_NAME", "Create a new Rails project from the official template"
|
|
137
|
+
long_desc <<-LONGDESC
|
|
138
|
+
Create a new Rails project from the official template.
|
|
139
|
+
|
|
140
|
+
This command will:
|
|
141
|
+
1. Clone the template from git@github.com:clacky-ai/rails-template-7x-starter.git
|
|
142
|
+
2. Change into the project directory
|
|
143
|
+
3. Run bin/setup to install dependencies and configure the project
|
|
144
|
+
|
|
145
|
+
Example:
|
|
146
|
+
$ clacky new my_rails_app
|
|
147
|
+
LONGDESC
|
|
148
|
+
def new(project_name = nil)
|
|
149
|
+
unless project_name
|
|
150
|
+
say "Error: Project name is required.", :red
|
|
151
|
+
say "Usage: clacky new <project_name>", :yellow
|
|
152
|
+
exit 1
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Validate project name
|
|
156
|
+
unless project_name.match?(/^[a-zA-Z][a-zA-Z0-9_-]*$/)
|
|
157
|
+
say "Error: Invalid project name. Use only letters, numbers, underscores, and hyphens.", :red
|
|
158
|
+
exit 1
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
template_repo = "git@github.com:clacky-ai/rails-template-7x-starter.git"
|
|
162
|
+
current_dir = Dir.pwd
|
|
163
|
+
target_dir = File.join(current_dir, project_name)
|
|
164
|
+
|
|
165
|
+
# Check if target directory already exists
|
|
166
|
+
if Dir.exist?(target_dir)
|
|
167
|
+
say "Error: Directory '#{project_name}' already exists.", :red
|
|
168
|
+
exit 1
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
say "Creating new Rails project: #{project_name}", :green
|
|
172
|
+
|
|
173
|
+
# Clone the template repository
|
|
174
|
+
say "\nš¦ Cloning template repository...", :cyan
|
|
175
|
+
clone_command = "git clone #{template_repo} #{project_name}"
|
|
176
|
+
|
|
177
|
+
clone_result = system(clone_command)
|
|
178
|
+
|
|
179
|
+
unless clone_result
|
|
180
|
+
say "\nā Failed to clone repository. Please check your git configuration and network connection.", :red
|
|
181
|
+
exit 1
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
say "ā Repository cloned successfully", :green
|
|
185
|
+
|
|
186
|
+
# Run bin/setup
|
|
187
|
+
say "\nāļø Running bin/setup...", :cyan
|
|
188
|
+
|
|
189
|
+
Dir.chdir(target_dir)
|
|
190
|
+
|
|
191
|
+
setup_command = "./bin/setup"
|
|
192
|
+
|
|
193
|
+
setup_result = system(setup_command)
|
|
194
|
+
|
|
195
|
+
Dir.chdir(current_dir)
|
|
196
|
+
|
|
197
|
+
unless setup_result
|
|
198
|
+
say "\nā Failed to run bin/setup. Please check the setup script for errors.", :red
|
|
199
|
+
say "You can try running it manually:", :yellow
|
|
200
|
+
say " cd #{project_name} && ./bin/setup", :cyan
|
|
201
|
+
exit 1
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
say "\nā
Project '#{project_name}' created successfully!", :green
|
|
205
|
+
say "\nNext steps:", :green
|
|
206
|
+
say " cd #{project_name}", :cyan
|
|
207
|
+
say " clacky agent", :cyan
|
|
208
|
+
end
|
|
209
|
+
|
|
130
210
|
desc "price", "Show pricing information for AI models"
|
|
131
211
|
def price
|
|
132
212
|
say "\nš° Model Pricing Information\n\n", :green
|
|
@@ -300,11 +380,20 @@ module Clacky
|
|
|
300
380
|
|
|
301
381
|
# Run agent with UI2 split-screen interface
|
|
302
382
|
def run_agent_with_ui2(agent, working_dir, agent_config, initial_message = nil, session_manager = nil, client = nil, is_session_load: false)
|
|
383
|
+
# Validate theme
|
|
384
|
+
theme_name = options[:theme] || "hacker"
|
|
385
|
+
available_themes = UI2::ThemeManager.available_themes.map(&:to_s)
|
|
386
|
+
unless available_themes.include?(theme_name)
|
|
387
|
+
say "Error: Unknown theme '#{theme_name}'. Available themes: #{available_themes.join(', ')}", :red
|
|
388
|
+
exit 1
|
|
389
|
+
end
|
|
390
|
+
|
|
303
391
|
# Create UI2 controller with configuration
|
|
304
392
|
ui_controller = UI2::UIController.new(
|
|
305
393
|
working_dir: working_dir,
|
|
306
394
|
mode: agent_config.permission_mode.to_s,
|
|
307
|
-
model: agent_config.model
|
|
395
|
+
model: agent_config.model,
|
|
396
|
+
theme: theme_name
|
|
308
397
|
)
|
|
309
398
|
|
|
310
399
|
# Inject UI into agent
|