openclacky 0.6.3 → 0.6.4
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 +30 -0
- data/docs/why-openclacky.md +267 -0
- data/lib/clacky/agent.rb +52 -60
- data/lib/clacky/cli.rb +9 -7
- data/lib/clacky/client.rb +519 -58
- data/lib/clacky/config.rb +71 -4
- data/lib/clacky/skill.rb +6 -6
- data/lib/clacky/skill_loader.rb +3 -3
- data/lib/clacky/tools/edit.rb +111 -8
- data/lib/clacky/tools/glob.rb +9 -2
- data/lib/clacky/ui2/ui_controller.rb +4 -4
- data/lib/clacky/version.rb +1 -1
- data/lib/clacky.rb +2 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dcf90e79799d6f487ba77c084b9b3b72fc7c5252e2ffc7a3e56a0973bb9df977
|
|
4
|
+
data.tar.gz: 52a2e19427036920d29ee27c5021f731cfc924fc9c6800e22040a017f74c7fc7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 90180817198ad434c4920c855e92215fafe0495f11b93cdf156e1a1a13239219bf3d68f061900265165cf897d601f6913a8815e5c22e60d341cdb3ea6b661bde
|
|
7
|
+
data.tar.gz: e09ba63257284794970bd5929d1e310465120e98fe5330be371cd5a00935976f1e537843b7d05e7532400f757564a8be860b3621125f665fecb30eb81ff76199
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,36 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.6.3] - 2026-02-01
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Complete skill system with loader and core functionality
|
|
14
|
+
- Default skill support with auto-loading mechanism
|
|
15
|
+
- Skills CLI command for skill management (`clacky skills list/show/create`)
|
|
16
|
+
- Command suggestions UI component for better user guidance
|
|
17
|
+
- Skip safety check option for safe_shell tool
|
|
18
|
+
- UI2 component comprehensive test suite
|
|
19
|
+
- Token output control for file_reader and shell tools
|
|
20
|
+
- Grep max files limit configuration
|
|
21
|
+
- File_reader tool index support
|
|
22
|
+
- Web fetch content length limiting
|
|
23
|
+
|
|
24
|
+
### Improved
|
|
25
|
+
- File_reader line range handling logic
|
|
26
|
+
- Message compression strategy (100 message compress)
|
|
27
|
+
- Inline input wrap line handling
|
|
28
|
+
- Cursor position calculation for multi-line inline input
|
|
29
|
+
- Theme adjustments for better visual experience
|
|
30
|
+
- Skill system integration with agent
|
|
31
|
+
- Gem-release skill metadata standardization
|
|
32
|
+
- Skill documentation with user experience summaries
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
- Skill commands now properly pass through to agent
|
|
36
|
+
- Session restore data loading with -a or -c flags
|
|
37
|
+
- Inline input cursor positioning for wrapped lines
|
|
38
|
+
- Multi-line inline input cursor calculation
|
|
39
|
+
|
|
10
40
|
## [0.6.2] - 2026-01-30
|
|
11
41
|
|
|
12
42
|
### Added
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# Why OpenClacky?
|
|
2
|
+
|
|
3
|
+
## The Vision: AI-Powered Development for Everyone
|
|
4
|
+
|
|
5
|
+
**Clacky** is an open-source, CLI-first AI development assistant designed to make software creation accessible to non-technical users while remaining powerful enough for professional developers.
|
|
6
|
+
|
|
7
|
+
Our ultimate vision: **OpenClacky = Lovable + Supabase** — an open-source alternative that combines the ease-of-use of no-code platforms with the flexibility of a modern Rails application.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## The Problem
|
|
12
|
+
|
|
13
|
+
Building software today is still too hard for most people:
|
|
14
|
+
|
|
15
|
+
| Challenge | Current Solutions |
|
|
16
|
+
|-----------|-------------------|
|
|
17
|
+
| **Too technical** | Requires learning programming, DevOps, deployment |
|
|
18
|
+
| **Too expensive** | Enterprise tools cost $100+/month |
|
|
19
|
+
| **Too locked-in** | Vendor lock-in with proprietary platforms |
|
|
20
|
+
| **Too complex** | Modern tech stacks have steep learning curves |
|
|
21
|
+
|
|
22
|
+
Non-technical founders, designers, and product managers often have great ideas but can't build them. Existing AI tools either:
|
|
23
|
+
- **Are too technical** (Claude Code, GitHub Copilot)
|
|
24
|
+
- **Are too expensive** (Lovable $25+/month)
|
|
25
|
+
- **Lock you into proprietary platforms** (v0, Lovable)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## The Solution: Clacky
|
|
30
|
+
|
|
31
|
+
Clacky bridges the gap between no-code simplicity and developer-grade power.
|
|
32
|
+
|
|
33
|
+
### Our Two-Part Strategy
|
|
34
|
+
|
|
35
|
+
#### Part 1: CLI for Everyone (Current Focus)
|
|
36
|
+
|
|
37
|
+
A command-line AI assistant that's approachable for non-technical users but powerful enough to rival Claude Code.
|
|
38
|
+
|
|
39
|
+
**Key Differentiators:**
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
43
|
+
│ Clacky CLI Features │
|
|
44
|
+
├─────────────────────────────────────────────────────────────┤
|
|
45
|
+
│ ✅ confirm_safes mode │ More automation than Claude │
|
|
46
|
+
│ ✅ Real-time cost monitor │ See token usage in real-time │
|
|
47
|
+
│ ✅ Session persistence │ Pause & resume your work │
|
|
48
|
+
│ ✅ SafeShell protection │ Commands made safe automatically│
|
|
49
|
+
│ ✅ Multi-API support │ DeepSeek, OpenRouter, OpenAI │
|
|
50
|
+
│ ✅ Skills system │ Extensible command shortcuts │
|
|
51
|
+
│ ✅ Open source │ MIT License - no vendor lock-in │
|
|
52
|
+
│ ✅ $0 monthly cost │ Pay only for API usage │
|
|
53
|
+
└─────────────────────────────────────────────────────────────┘
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Why Non-Technical Users Love Clacky:**
|
|
57
|
+
|
|
58
|
+
1. **Natural Language Commands**
|
|
59
|
+
```
|
|
60
|
+
clacky agent "Create a REST API for user management"
|
|
61
|
+
clacky agent "Add authentication to my Rails app"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
2. **Safe by Default**
|
|
65
|
+
- Dangerous commands (`rm`, `curl | sh`) are automatically made safe
|
|
66
|
+
- Files moved to trash instead of deleted
|
|
67
|
+
- Project boundaries enforced
|
|
68
|
+
|
|
69
|
+
3. **Transparent Costs**
|
|
70
|
+
```
|
|
71
|
+
💰 Cost: $0.0042 (Claude 3.5 Sonnet)
|
|
72
|
+
📊 Tokens: 1,250 in / 850 out
|
|
73
|
+
🗜️ Compression saved: 60%
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
4. **Permission Modes for Every Situation**
|
|
77
|
+
|
|
78
|
+
| Mode | Behavior | Best For |
|
|
79
|
+
|------|----------|----------|
|
|
80
|
+
| `auto_approve` | Execute all tools automatically | Batch operations |
|
|
81
|
+
| `confirm_safes` | Auto-approve safe operations | Daily development |
|
|
82
|
+
| `confirm_edits` | Confirm file modifications | Careful work |
|
|
83
|
+
| `plan_only` | Generate plans only | Code review |
|
|
84
|
+
|
|
85
|
+
5. **Session Recovery**
|
|
86
|
+
```bash
|
|
87
|
+
clacky agent -c # Continue last session
|
|
88
|
+
clacky agent -l # List recent sessions
|
|
89
|
+
clacky agent -a 2 # Attach to specific session
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### Part 2: AI-Ready Rails Template (Coming Soon)
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
clacky new my_project
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
A production-ready Rails application scaffold designed specifically for AI-powered development, including:
|
|
99
|
+
|
|
100
|
+
| Feature | Description |
|
|
101
|
+
|---------|-------------|
|
|
102
|
+
| 🔐 **Authentication** | Built-in login/registration with Devise |
|
|
103
|
+
| 🤖 **LLM Integration** | Pre-configured for Claude, OpenAI, DeepSeek |
|
|
104
|
+
| ⚡ **Async Jobs** | Sidekiq for background processing |
|
|
105
|
+
| 🔄 **WebSockets** | Action Cable for real-time features |
|
|
106
|
+
| 🎨 **Beautiful UI** | Tailwind CSS + Hotwire components |
|
|
107
|
+
| 📊 **Admin Dashboard** | ActiveAdmin or Avo integration |
|
|
108
|
+
| 🚀 **One-Click Deploy** | Docker + Kamal/Cloud66 ready |
|
|
109
|
+
|
|
110
|
+
**Why Rails?**
|
|
111
|
+
|
|
112
|
+
- Mature, stable, and well-documented
|
|
113
|
+
- Great for AI apps (LLM calls, async processing, web interface)
|
|
114
|
+
- Strong conventions reduce decision fatigue
|
|
115
|
+
- ActiveJob, Action Cable, Hotwire built-in
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Clacky vs. The Competition
|
|
120
|
+
|
|
121
|
+
| Feature | **Clacky** | Claude Code | Lovable | Cursor |
|
|
122
|
+
|---------|------------|-------------|---------|--------|
|
|
123
|
+
| **Target Users** | Non-technical + Devs | Developers only | Non-technical | Developers |
|
|
124
|
+
| **Interface** | CLI | CLI + IDE + Web | Web only | IDE |
|
|
125
|
+
| **Open Source** | ✅ MIT | ❌ Closed | ❌ Closed | ❌ Closed |
|
|
126
|
+
| **Monthly Cost** | $0 (API only) | $17-200 | $25-99+ | $20+ |
|
|
127
|
+
| **Self-Hosted** | ✅ Yes | ❌ No | ❌ No | ❌ No |
|
|
128
|
+
| **Multi-API** | ✅ DeepSeek, OpenRouter | ❌ Anthropic only | ❌ Limited | ❌ OpenAI only |
|
|
129
|
+
| **SafeShell** | ✅ Auto-protection | ⚠️ Manual | N/A | ⚠️ Manual |
|
|
130
|
+
| **Sessions** | ✅ Persistent | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited |
|
|
131
|
+
| **Skills/Plugins** | ✅ Extensible | ❌ No | ❌ No | ⚠️ Limited |
|
|
132
|
+
| **Rails Template** | ✅ Coming soon | ❌ No | ⚠️ Limited | ❌ No |
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Why Now?
|
|
137
|
+
|
|
138
|
+
### The AI Development Revolution
|
|
139
|
+
|
|
140
|
+
We're at a unique moment in software history:
|
|
141
|
+
|
|
142
|
+
1. **AI models are now capable** of generating production-quality code
|
|
143
|
+
2. **APIs are affordable** - DeepSeek is 95% cheaper than OpenAI
|
|
144
|
+
3. **CLI is experiencing a renaissance** - Developers prefer terminal tools
|
|
145
|
+
4. **Open source AI is viable** - No vendor lock-in
|
|
146
|
+
|
|
147
|
+
### The Open Source Advantage
|
|
148
|
+
|
|
149
|
+
Unlike proprietary platforms, Clacky gives you:
|
|
150
|
+
|
|
151
|
+
- **Freedom**: Use any model, any API, any provider
|
|
152
|
+
- **Control**: Self-host everything, no data leaves your machine
|
|
153
|
+
- **Customization**: Modify the source code for your needs
|
|
154
|
+
- **Community**: Learn from others, contribute back
|
|
155
|
+
- **Longevity**: No risk of the platform shutting down
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Our Roadmap
|
|
160
|
+
|
|
161
|
+
### Phase 1: CLI Excellence (Current)
|
|
162
|
+
- [x] Core agent with tool execution
|
|
163
|
+
- [x] confirm_safes mode (more automation)
|
|
164
|
+
- [x] Real-time cost monitoring
|
|
165
|
+
- [x] SafeShell protection
|
|
166
|
+
- [x] Session persistence
|
|
167
|
+
- [x] Skills system
|
|
168
|
+
|
|
169
|
+
### Phase 2: Rails Template (Coming Soon)
|
|
170
|
+
- [ ] `clacky new` command
|
|
171
|
+
- [ ] Pre-configured authentication
|
|
172
|
+
- [ ] LLM integration ready
|
|
173
|
+
- [ ] Async job system
|
|
174
|
+
- [ ] WebSocket support
|
|
175
|
+
- [ ] Admin dashboard
|
|
176
|
+
- [ ] Docker + deployment configs
|
|
177
|
+
|
|
178
|
+
### Phase 3: The Lovable Alternative
|
|
179
|
+
- [ ] Web-based project manager
|
|
180
|
+
- [ ] Visual component library
|
|
181
|
+
- [ ] Database schema designer
|
|
182
|
+
- [ ] One-click deployment
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Pricing Philosophy
|
|
187
|
+
|
|
188
|
+
We believe AI development tools should be accessible to everyone.
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
┌────────────────────────────────────────────────────────────┐
|
|
192
|
+
│ Clacky Pricing │
|
|
193
|
+
├────────────────────────────────────────────────────────────┤
|
|
194
|
+
│ 📦 Clacky CLI │ $0/month (Open Source) │
|
|
195
|
+
│ • All features │ Pay only for API usage │
|
|
196
|
+
│ • No subscription │ Use DeepSeek, OpenRouter, etc. │
|
|
197
|
+
│ │ │
|
|
198
|
+
│ 🚀 Rails Template │ $0 (Open Source) │
|
|
199
|
+
│ • Full source code │ MIT License │
|
|
200
|
+
│ • Self-host │ No vendor lock-in │
|
|
201
|
+
│ │ │
|
|
202
|
+
│ 💎 Enterprise Support │ Contact us │
|
|
203
|
+
│ • Custom development│ Training & consulting │
|
|
204
|
+
└────────────────────────────────────────────────────────────┘
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Get Started
|
|
210
|
+
|
|
211
|
+
### Quick Install
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
# One-line installation (macOS/Linux)
|
|
215
|
+
curl -sSL https://raw.githubusercontent.com/clacky-ai/open-clacky/main/scripts/install.sh | bash
|
|
216
|
+
|
|
217
|
+
# Or if you have Ruby 3.1+
|
|
218
|
+
gem install openclacky
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### First Steps
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
# Configure your API key
|
|
225
|
+
clacky config set
|
|
226
|
+
|
|
227
|
+
# Start the agent
|
|
228
|
+
clacky agent
|
|
229
|
+
|
|
230
|
+
# Or give it a task
|
|
231
|
+
clacky agent "Create a TODO list app"
|
|
232
|
+
|
|
233
|
+
# See all tools
|
|
234
|
+
clacky tools
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Join Us
|
|
240
|
+
|
|
241
|
+
Clacky is an open-source project. We welcome contributions!
|
|
242
|
+
|
|
243
|
+
- **GitHub**: https://github.com/clacky-ai/open-clacky
|
|
244
|
+
- **Discord**: https://discord.gg/clacky
|
|
245
|
+
- **Twitter**: https://twitter.com/clacky_ai
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Summary
|
|
250
|
+
|
|
251
|
+
**Clacky** is for anyone who wants to build software but has been held back by technical complexity or expensive tools.
|
|
252
|
+
|
|
253
|
+
Whether you're a:
|
|
254
|
+
- 🎨 **Designer** who wants to prototype ideas
|
|
255
|
+
- 💼 **Product Manager** who wants to validate concepts
|
|
256
|
+
- 🚀 **Founder** who wants to build an MVP
|
|
257
|
+
- 👨💻 **Developer** who wants a more automated CLI
|
|
258
|
+
|
|
259
|
+
...Clacky is here to help.
|
|
260
|
+
|
|
261
|
+
**The future of software development is accessible, open, and AI-powered.**
|
|
262
|
+
|
|
263
|
+
**Welcome to Clacky.**
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
*Last updated: February 2025*
|
data/lib/clacky/agent.rb
CHANGED
|
@@ -226,6 +226,17 @@ module Clacky
|
|
|
226
226
|
# Check if done (no more tool calls needed)
|
|
227
227
|
if response[:finish_reason] == "stop" || response[:tool_calls].nil? || response[:tool_calls].empty?
|
|
228
228
|
@ui&.show_assistant_message(response[:content]) if response[:content] && !response[:content].empty?
|
|
229
|
+
|
|
230
|
+
# Debug: log why we're stopping
|
|
231
|
+
if @config.verbose && (response[:tool_calls].nil? || response[:tool_calls].empty?)
|
|
232
|
+
reason = response[:finish_reason] == "stop" ? "API returned finish_reason=stop" : "No tool calls in response"
|
|
233
|
+
@ui&.log("Stopping: #{reason}", level: :debug)
|
|
234
|
+
if response[:content] && response[:content].is_a?(String)
|
|
235
|
+
preview = response[:content].length > 200 ? response[:content][0...200] + "..." : response[:content]
|
|
236
|
+
@ui&.log("Response content: #{preview}", level: :debug)
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
229
240
|
break
|
|
230
241
|
end
|
|
231
242
|
|
|
@@ -526,7 +537,7 @@ module Clacky
|
|
|
526
537
|
@ui&.show_progress
|
|
527
538
|
|
|
528
539
|
# Compress messages if needed to reduce cost
|
|
529
|
-
compress_messages_if_needed
|
|
540
|
+
compression_message = compress_messages_if_needed
|
|
530
541
|
|
|
531
542
|
# Always send tools definitions to allow multi-step tool calling
|
|
532
543
|
tools_to_send = @tool_registry.all_definitions
|
|
@@ -552,13 +563,16 @@ module Clacky
|
|
|
552
563
|
retry
|
|
553
564
|
else
|
|
554
565
|
@ui&.show_error("Network failed after #{max_retries} retries: #{e.message}")
|
|
555
|
-
raise
|
|
566
|
+
raise AgentError, "Network connection failed after #{max_retries} retries: #{e.message}"
|
|
556
567
|
end
|
|
557
568
|
end
|
|
558
569
|
|
|
559
570
|
# Clear progress indicator (change to gray and show final time)
|
|
560
571
|
@ui&.clear_progress
|
|
561
572
|
|
|
573
|
+
# Show compression message after clearing progress (so it doesn't get deleted)
|
|
574
|
+
@ui&.show_info(compression_message) if compression_message
|
|
575
|
+
|
|
562
576
|
track_cost(response[:usage], raw_api_usage: response[:raw_api_usage])
|
|
563
577
|
|
|
564
578
|
# Handle truncated responses (when max_tokens limit is reached)
|
|
@@ -613,7 +627,10 @@ module Clacky
|
|
|
613
627
|
# Always include content field (some APIs require it even with tool_calls)
|
|
614
628
|
# Use empty string instead of null for better compatibility
|
|
615
629
|
msg[:content] = response[:content] || ""
|
|
616
|
-
|
|
630
|
+
# Only add tool_calls if they actually exist (don't add empty arrays)
|
|
631
|
+
if response[:tool_calls]&.any?
|
|
632
|
+
msg[:tool_calls] = format_tool_calls_for_api(response[:tool_calls])
|
|
633
|
+
end
|
|
617
634
|
@messages << msg
|
|
618
635
|
|
|
619
636
|
response
|
|
@@ -655,7 +672,8 @@ module Clacky
|
|
|
655
672
|
denied = true
|
|
656
673
|
user_feedback = confirmation[:feedback]
|
|
657
674
|
feedback = user_feedback if user_feedback
|
|
658
|
-
|
|
675
|
+
system_injected = confirmation[:system_injected]
|
|
676
|
+
results << build_denied_result(call, user_feedback, system_injected)
|
|
659
677
|
|
|
660
678
|
# Auto-deny all remaining tools
|
|
661
679
|
remaining_calls = tool_calls[(index + 1)..-1] || []
|
|
@@ -663,7 +681,7 @@ module Clacky
|
|
|
663
681
|
reason = user_feedback && !user_feedback.empty? ?
|
|
664
682
|
user_feedback :
|
|
665
683
|
"Auto-denied due to user rejection of previous tool"
|
|
666
|
-
results << build_denied_result(remaining_call, reason)
|
|
684
|
+
results << build_denied_result(remaining_call, reason, system_injected)
|
|
667
685
|
end
|
|
668
686
|
break
|
|
669
687
|
end
|
|
@@ -720,10 +738,11 @@ module Clacky
|
|
|
720
738
|
error_message: e.message,
|
|
721
739
|
backtrace: e.backtrace&.first(20) # Keep first 20 lines of backtrace
|
|
722
740
|
}
|
|
723
|
-
|
|
741
|
+
|
|
724
742
|
@hooks.trigger(:on_tool_error, call, e)
|
|
725
743
|
@ui&.show_tool_error(e)
|
|
726
|
-
|
|
744
|
+
# Use build_denied_result with system_injected=true so LLM knows it can retry
|
|
745
|
+
results << build_denied_result(call, e.message, true)
|
|
727
746
|
end
|
|
728
747
|
end
|
|
729
748
|
|
|
@@ -736,35 +755,11 @@ module Clacky
|
|
|
736
755
|
|
|
737
756
|
def observe(response, tool_results)
|
|
738
757
|
# Add tool results as messages
|
|
739
|
-
#
|
|
740
|
-
|
|
741
|
-
# CRITICAL: Tool results must be in the same order as tool_calls in the response
|
|
742
|
-
# Claude/Bedrock API requires this strict ordering
|
|
758
|
+
# Use Client to format results based on API type (Anthropic vs OpenAI)
|
|
743
759
|
return if tool_results.empty?
|
|
744
760
|
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
hash[result[:id]] = result
|
|
748
|
-
end
|
|
749
|
-
|
|
750
|
-
# Add results in the same order as the original tool_calls
|
|
751
|
-
response[:tool_calls].each do |tool_call|
|
|
752
|
-
result = results_map[tool_call[:id]]
|
|
753
|
-
if result
|
|
754
|
-
@messages << {
|
|
755
|
-
role: "tool",
|
|
756
|
-
tool_call_id: result[:id],
|
|
757
|
-
content: result[:content]
|
|
758
|
-
}
|
|
759
|
-
else
|
|
760
|
-
# This shouldn't happen, but add a fallback error result
|
|
761
|
-
@messages << {
|
|
762
|
-
role: "tool",
|
|
763
|
-
tool_call_id: tool_call[:id],
|
|
764
|
-
content: JSON.generate({ error: "Tool result missing" })
|
|
765
|
-
}
|
|
766
|
-
end
|
|
767
|
-
end
|
|
761
|
+
formatted_messages = @client.format_tool_results(response, tool_results, model: @config.model)
|
|
762
|
+
formatted_messages.each { |msg| @messages << msg }
|
|
768
763
|
end
|
|
769
764
|
|
|
770
765
|
# Interrupt the agent's current run
|
|
@@ -1031,9 +1026,6 @@ module Clacky
|
|
|
1031
1026
|
|
|
1032
1027
|
original_tokens = total_tokens
|
|
1033
1028
|
|
|
1034
|
-
@ui&.show_info("Compressing history (~#{original_tokens} tokens -> ~#{TARGET_COMPRESSED_TOKENS} tokens)...")
|
|
1035
|
-
@ui&.show_info("Compression level: #{@compression_level}")
|
|
1036
|
-
|
|
1037
1029
|
# Find the system message (should be first)
|
|
1038
1030
|
system_msg = @messages.find { |m| m[:role] == "system" }
|
|
1039
1031
|
|
|
@@ -1044,8 +1036,6 @@ module Clacky
|
|
|
1044
1036
|
# Get messages to compress (everything except system and recent)
|
|
1045
1037
|
messages_to_compress = @messages.reject { |m| m[:role] == "system" || recent_messages.include?(m) }
|
|
1046
1038
|
|
|
1047
|
-
@ui&.show_info(" debug: total=#{@messages.size}, recent=#{recent_messages.size}, to_compress=#{messages_to_compress.size}")
|
|
1048
|
-
|
|
1049
1039
|
return if messages_to_compress.empty?
|
|
1050
1040
|
|
|
1051
1041
|
# Create hierarchical summary based on compression level
|
|
@@ -1065,7 +1055,8 @@ module Clacky
|
|
|
1065
1055
|
|
|
1066
1056
|
final_tokens = total_message_tokens[:total]
|
|
1067
1057
|
|
|
1068
|
-
|
|
1058
|
+
# Return compression message (to be shown after clearing progress)
|
|
1059
|
+
"History compressed (~#{original_tokens} -> ~#{final_tokens} tokens, level #{@compression_level})"
|
|
1069
1060
|
end
|
|
1070
1061
|
|
|
1071
1062
|
# Calculate how many recent messages to keep based on how much we need to compress
|
|
@@ -1446,9 +1437,8 @@ module Clacky
|
|
|
1446
1437
|
|
|
1447
1438
|
# If preview detected an error, auto-deny and provide feedback
|
|
1448
1439
|
if preview_error && preview_error[:error]
|
|
1449
|
-
@ui&.show_warning("Tool call auto-denied due to preview error")
|
|
1450
1440
|
feedback = build_preview_error_feedback(call[:name], preview_error)
|
|
1451
|
-
return { approved: false, feedback: feedback }
|
|
1441
|
+
return { approved: false, feedback: feedback, system_injected: true }
|
|
1452
1442
|
end
|
|
1453
1443
|
|
|
1454
1444
|
# Request confirmation via UI
|
|
@@ -1479,7 +1469,7 @@ module Clacky
|
|
|
1479
1469
|
private def build_preview_error_feedback(tool_name, error_info)
|
|
1480
1470
|
case tool_name
|
|
1481
1471
|
when "edit"
|
|
1482
|
-
"The edit operation will fail because the old_string was not found in the file. " \
|
|
1472
|
+
"Tool edit denied: The edit operation will fail because the old_string was not found in the file. " \
|
|
1483
1473
|
"Please use file_reader to read '#{error_info[:path]}' first, " \
|
|
1484
1474
|
"find the correct string to replace, and try again with the exact string (including whitespace)."
|
|
1485
1475
|
else
|
|
@@ -1607,9 +1597,7 @@ module Clacky
|
|
|
1607
1597
|
file_size: file_content.length
|
|
1608
1598
|
}
|
|
1609
1599
|
|
|
1610
|
-
@ui&.show_file_error("
|
|
1611
|
-
@ui&.show_file_error("Looking for (first 100 chars):")
|
|
1612
|
-
@ui&.show_file_error(old_string[0..100].inspect)
|
|
1600
|
+
@ui&.show_file_error("Edit file error")
|
|
1613
1601
|
return {
|
|
1614
1602
|
error: "String to replace not found in file",
|
|
1615
1603
|
path: path,
|
|
@@ -1653,21 +1641,25 @@ module Clacky
|
|
|
1653
1641
|
}
|
|
1654
1642
|
end
|
|
1655
1643
|
|
|
1656
|
-
def build_denied_result(call, user_feedback = nil)
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1644
|
+
def build_denied_result(call, user_feedback = nil, system_injected = false)
|
|
1645
|
+
if system_injected
|
|
1646
|
+
# System-generated feedback (e.g., from preview errors)
|
|
1647
|
+
tool_content = {
|
|
1648
|
+
error: "Tool #{call[:name]} denied: #{user_feedback}",
|
|
1649
|
+
system_injected: true
|
|
1650
|
+
}
|
|
1651
|
+
else
|
|
1652
|
+
# User manually denied or provided feedback
|
|
1653
|
+
message = if user_feedback && !user_feedback.empty?
|
|
1654
|
+
"Tool use denied by user. User feedback: #{user_feedback}"
|
|
1655
|
+
else
|
|
1656
|
+
"Tool use denied by user"
|
|
1657
|
+
end
|
|
1668
1658
|
|
|
1669
|
-
|
|
1670
|
-
|
|
1659
|
+
tool_content = {
|
|
1660
|
+
error: message,
|
|
1661
|
+
user_feedback: user_feedback
|
|
1662
|
+
}
|
|
1671
1663
|
end
|
|
1672
1664
|
|
|
1673
1665
|
{
|
data/lib/clacky/cli.rb
CHANGED
|
@@ -62,6 +62,13 @@ module Clacky
|
|
|
62
62
|
end
|
|
63
63
|
config = Clacky::Config.load
|
|
64
64
|
|
|
65
|
+
# Show message when using ClaudeCode environment variables
|
|
66
|
+
if config.config_source == "claude_code"
|
|
67
|
+
say "🔑 Using API key from ClaudeCode environment variables", :cyan
|
|
68
|
+
say " (#{config.base_url})", :white
|
|
69
|
+
say ""
|
|
70
|
+
end
|
|
71
|
+
|
|
65
72
|
unless config.api_key
|
|
66
73
|
say "Error: API key not found. Please run 'clacky config set' first.", :red
|
|
67
74
|
exit 1
|
|
@@ -750,14 +757,14 @@ module Clacky
|
|
|
750
757
|
# Save final session state before exit
|
|
751
758
|
if session_manager && agent.total_tasks > 0
|
|
752
759
|
session_data = agent.to_session_data(status: :exited)
|
|
753
|
-
session_manager.save(session_data)
|
|
760
|
+
saved_path = session_manager.save(session_data)
|
|
754
761
|
|
|
755
762
|
# Show session saved message in output area (before stopping UI)
|
|
756
763
|
session_id = session_data[:session_id][0..7]
|
|
757
764
|
ui_controller.append_output("")
|
|
758
765
|
ui_controller.append_output("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
|
|
759
766
|
ui_controller.append_output("")
|
|
760
|
-
ui_controller.append_output("Session saved: #{
|
|
767
|
+
ui_controller.append_output("Session saved: #{saved_path}")
|
|
761
768
|
ui_controller.append_output("Tasks completed: #{agent.total_tasks}")
|
|
762
769
|
ui_controller.append_output("Total cost: $#{agent.total_cost.round(4)}")
|
|
763
770
|
ui_controller.append_output("")
|
|
@@ -868,11 +875,6 @@ module Clacky
|
|
|
868
875
|
if session_manager && agent.total_tasks > 0
|
|
869
876
|
session_manager.save(agent.to_session_data)
|
|
870
877
|
end
|
|
871
|
-
|
|
872
|
-
# Show goodbye message
|
|
873
|
-
say "\n👋 Goodbye! Session stats:", :green
|
|
874
|
-
say " Tasks completed: #{agent.total_tasks}", :cyan
|
|
875
|
-
say " Total cost: $#{agent.total_cost.round(4)}", :cyan
|
|
876
878
|
end
|
|
877
879
|
|
|
878
880
|
end
|