openclacky 0.7.0 → 0.7.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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.clacky/skills/commit/SKILL.md +29 -4
  3. data/.clackyrules +3 -1
  4. data/CHANGELOG.md +103 -2
  5. data/README.md +70 -161
  6. data/bin/clarky +11 -0
  7. data/docs/HOW-TO-USE-CN.md +96 -0
  8. data/docs/HOW-TO-USE.md +94 -0
  9. data/docs/config.example.yml +27 -0
  10. data/docs/deploy_subagent_design.md +540 -0
  11. data/docs/time_machine_design.md +247 -0
  12. data/docs/why-openclacky.md +0 -1
  13. data/lib/clacky/agent/cost_tracker.rb +180 -0
  14. data/lib/clacky/agent/llm_caller.rb +54 -0
  15. data/lib/clacky/{message_compressor.rb → agent/message_compressor.rb} +12 -36
  16. data/lib/clacky/agent/message_compressor_helper.rb +534 -0
  17. data/lib/clacky/agent/session_serializer.rb +152 -0
  18. data/lib/clacky/agent/skill_manager.rb +138 -0
  19. data/lib/clacky/agent/system_prompt_builder.rb +96 -0
  20. data/lib/clacky/agent/time_machine.rb +199 -0
  21. data/lib/clacky/agent/tool_executor.rb +434 -0
  22. data/lib/clacky/{tool_registry.rb → agent/tool_registry.rb} +1 -1
  23. data/lib/clacky/agent.rb +260 -1370
  24. data/lib/clacky/agent_config.rb +447 -10
  25. data/lib/clacky/cli.rb +275 -98
  26. data/lib/clacky/client.rb +12 -2
  27. data/lib/clacky/default_skills/code-explorer/SKILL.md +34 -0
  28. data/lib/clacky/default_skills/deploy/SKILL.md +13 -0
  29. data/lib/clacky/default_skills/deploy/scripts/rails_deploy.rb +383 -0
  30. data/lib/clacky/default_skills/deploy/tools/check_health.rb +116 -0
  31. data/lib/clacky/default_skills/deploy/tools/execute_deployment.rb +174 -0
  32. data/lib/clacky/default_skills/deploy/tools/fetch_runtime_logs.rb +67 -0
  33. data/lib/clacky/default_skills/deploy/tools/list_services.rb +80 -0
  34. data/lib/clacky/default_skills/deploy/tools/report_deploy_status.rb +67 -0
  35. data/lib/clacky/default_skills/deploy/tools/set_deploy_variables.rb +138 -0
  36. data/lib/clacky/default_skills/new/SKILL.md +2 -2
  37. data/lib/clacky/json_ui_controller.rb +195 -0
  38. data/lib/clacky/providers.rb +107 -0
  39. data/lib/clacky/skill.rb +48 -7
  40. data/lib/clacky/skill_loader.rb +7 -0
  41. data/lib/clacky/tools/edit.rb +105 -48
  42. data/lib/clacky/tools/file_reader.rb +44 -73
  43. data/lib/clacky/tools/invoke_skill.rb +89 -0
  44. data/lib/clacky/tools/list_tasks.rb +54 -0
  45. data/lib/clacky/tools/redo_task.rb +41 -0
  46. data/lib/clacky/tools/safe_shell.rb +1 -1
  47. data/lib/clacky/tools/shell.rb +74 -62
  48. data/lib/clacky/tools/trash_manager.rb +1 -1
  49. data/lib/clacky/tools/undo_task.rb +32 -0
  50. data/lib/clacky/tools/web_fetch.rb +2 -1
  51. data/lib/clacky/ui2/components/command_suggestions.rb +13 -3
  52. data/lib/clacky/ui2/components/inline_input.rb +23 -2
  53. data/lib/clacky/ui2/components/input_area.rb +65 -21
  54. data/lib/clacky/ui2/components/modal_component.rb +199 -62
  55. data/lib/clacky/ui2/layout_manager.rb +75 -25
  56. data/lib/clacky/ui2/line_editor.rb +23 -2
  57. data/lib/clacky/ui2/markdown_renderer.rb +31 -10
  58. data/lib/clacky/ui2/screen_buffer.rb +2 -0
  59. data/lib/clacky/ui2/ui_controller.rb +316 -37
  60. data/lib/clacky/ui2.rb +2 -0
  61. data/lib/clacky/ui_interface.rb +50 -0
  62. data/lib/clacky/utils/arguments_parser.rb +31 -3
  63. data/lib/clacky/utils/file_processor.rb +13 -18
  64. data/lib/clacky/version.rb +1 -1
  65. data/lib/clacky.rb +19 -9
  66. data/scripts/install.sh +274 -97
  67. data/scripts/uninstall.sh +12 -12
  68. metadata +40 -13
  69. data/.clacky/skills/test-skill/SKILL.md +0 -15
  70. data/lib/clacky/compression/base.rb +0 -231
  71. data/lib/clacky/compression/standard.rb +0 -339
  72. data/lib/clacky/config.rb +0 -117
  73. /data/lib/clacky/{hook_manager.rb → agent/hook_manager.rb} +0 -0
  74. /data/lib/clacky/{progress_indicator.rb → ui2/progress_indicator.rb} +0 -0
  75. /data/lib/clacky/{thinking_verbs.rb → ui2/thinking_verbs.rb} +0 -0
  76. /data/lib/clacky/{gitignore_parser.rb → utils/gitignore_parser.rb} +0 -0
  77. /data/lib/clacky/{model_pricing.rb → utils/model_pricing.rb} +0 -0
  78. /data/lib/clacky/{trash_directory.rb → utils/trash_directory.rb} +0 -0
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.7.0
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - windy
@@ -142,13 +142,13 @@ email:
142
142
  - yafei@dao42.com
143
143
  executables:
144
144
  - clacky
145
+ - clarky
145
146
  - openclacky
146
147
  extensions: []
147
148
  extra_rdoc_files: []
148
149
  files:
149
150
  - ".clacky/skills/commit/SKILL.md"
150
151
  - ".clacky/skills/gem-release/SKILL.md"
151
- - ".clacky/skills/test-skill/SKILL.md"
152
152
  - ".clackyrules"
153
153
  - ".rspec"
154
154
  - ".rubocop.yml"
@@ -158,9 +158,15 @@ files:
158
158
  - README.md
159
159
  - Rakefile
160
160
  - bin/clacky
161
+ - bin/clarky
161
162
  - bin/openclacky
162
163
  - clacky-legacy/clacky.gemspec
163
164
  - clacky-legacy/clarky.gemspec
165
+ - docs/HOW-TO-USE-CN.md
166
+ - docs/HOW-TO-USE.md
167
+ - docs/config.example.yml
168
+ - docs/deploy_subagent_design.md
169
+ - docs/time_machine_design.md
164
170
  - docs/ui2-architecture.md
165
171
  - docs/why-developer.md
166
172
  - docs/why-openclacky.md
@@ -168,39 +174,54 @@ files:
168
174
  - homebrew/openclacky.rb
169
175
  - lib/clacky.rb
170
176
  - lib/clacky/agent.rb
177
+ - lib/clacky/agent/cost_tracker.rb
178
+ - lib/clacky/agent/hook_manager.rb
179
+ - lib/clacky/agent/llm_caller.rb
180
+ - lib/clacky/agent/message_compressor.rb
181
+ - lib/clacky/agent/message_compressor_helper.rb
182
+ - lib/clacky/agent/session_serializer.rb
183
+ - lib/clacky/agent/skill_manager.rb
184
+ - lib/clacky/agent/system_prompt_builder.rb
185
+ - lib/clacky/agent/time_machine.rb
186
+ - lib/clacky/agent/tool_executor.rb
187
+ - lib/clacky/agent/tool_registry.rb
171
188
  - lib/clacky/agent_config.rb
172
189
  - lib/clacky/cli.rb
173
190
  - lib/clacky/client.rb
174
- - lib/clacky/compression/base.rb
175
- - lib/clacky/compression/standard.rb
176
- - lib/clacky/config.rb
191
+ - lib/clacky/default_skills/code-explorer/SKILL.md
192
+ - lib/clacky/default_skills/deploy/SKILL.md
193
+ - lib/clacky/default_skills/deploy/scripts/rails_deploy.rb
194
+ - lib/clacky/default_skills/deploy/tools/check_health.rb
195
+ - lib/clacky/default_skills/deploy/tools/execute_deployment.rb
196
+ - lib/clacky/default_skills/deploy/tools/fetch_runtime_logs.rb
197
+ - lib/clacky/default_skills/deploy/tools/list_services.rb
198
+ - lib/clacky/default_skills/deploy/tools/report_deploy_status.rb
199
+ - lib/clacky/default_skills/deploy/tools/set_deploy_variables.rb
177
200
  - lib/clacky/default_skills/new/SKILL.md
178
201
  - lib/clacky/default_skills/skill-add/SKILL.md
179
- - lib/clacky/gitignore_parser.rb
180
- - lib/clacky/hook_manager.rb
181
- - lib/clacky/message_compressor.rb
182
- - lib/clacky/model_pricing.rb
183
- - lib/clacky/progress_indicator.rb
202
+ - lib/clacky/json_ui_controller.rb
203
+ - lib/clacky/providers.rb
184
204
  - lib/clacky/session_manager.rb
185
205
  - lib/clacky/skill.rb
186
206
  - lib/clacky/skill_loader.rb
187
- - lib/clacky/thinking_verbs.rb
188
- - lib/clacky/tool_registry.rb
189
207
  - lib/clacky/tools/base.rb
190
208
  - lib/clacky/tools/edit.rb
191
209
  - lib/clacky/tools/file_reader.rb
192
210
  - lib/clacky/tools/glob.rb
193
211
  - lib/clacky/tools/grep.rb
212
+ - lib/clacky/tools/invoke_skill.rb
213
+ - lib/clacky/tools/list_tasks.rb
214
+ - lib/clacky/tools/redo_task.rb
194
215
  - lib/clacky/tools/request_user_feedback.rb
195
216
  - lib/clacky/tools/run_project.rb
196
217
  - lib/clacky/tools/safe_shell.rb
197
218
  - lib/clacky/tools/shell.rb
198
219
  - lib/clacky/tools/todo_manager.rb
199
220
  - lib/clacky/tools/trash_manager.rb
221
+ - lib/clacky/tools/undo_task.rb
200
222
  - lib/clacky/tools/web_fetch.rb
201
223
  - lib/clacky/tools/web_search.rb
202
224
  - lib/clacky/tools/write.rb
203
- - lib/clacky/trash_directory.rb
204
225
  - lib/clacky/ui2.rb
205
226
  - lib/clacky/ui2/README.md
206
227
  - lib/clacky/ui2/components/base_component.rb
@@ -216,18 +237,24 @@ files:
216
237
  - lib/clacky/ui2/layout_manager.rb
217
238
  - lib/clacky/ui2/line_editor.rb
218
239
  - lib/clacky/ui2/markdown_renderer.rb
240
+ - lib/clacky/ui2/progress_indicator.rb
219
241
  - lib/clacky/ui2/screen_buffer.rb
220
242
  - lib/clacky/ui2/theme_manager.rb
221
243
  - lib/clacky/ui2/themes/base_theme.rb
222
244
  - lib/clacky/ui2/themes/hacker_theme.rb
223
245
  - lib/clacky/ui2/themes/minimal_theme.rb
246
+ - lib/clacky/ui2/thinking_verbs.rb
224
247
  - lib/clacky/ui2/ui_controller.rb
225
248
  - lib/clacky/ui2/view_renderer.rb
249
+ - lib/clacky/ui_interface.rb
226
250
  - lib/clacky/utils/arguments_parser.rb
227
251
  - lib/clacky/utils/file_ignore_helper.rb
228
252
  - lib/clacky/utils/file_processor.rb
253
+ - lib/clacky/utils/gitignore_parser.rb
229
254
  - lib/clacky/utils/limit_stack.rb
255
+ - lib/clacky/utils/model_pricing.rb
230
256
  - lib/clacky/utils/path_helper.rb
257
+ - lib/clacky/utils/trash_directory.rb
231
258
  - lib/clacky/version.rb
232
259
  - scripts/install.sh
233
260
  - scripts/uninstall.sh
@@ -1,15 +0,0 @@
1
- ---
2
- name: test-skill
3
- description: A test skill for demonstrating skill loading
4
- disable-model-invocation: false
5
- user-invocable: true
6
- ---
7
-
8
- # Test Skill
9
-
10
- This is a test skill to verify that skills are being loaded into the system prompt.
11
-
12
- When you see this skill in your context, you should:
13
- 1. Acknowledge that you have access to this skill
14
- 2. Explain what this skill does
15
- 3. Demonstrate that you can use it
@@ -1,231 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "json"
4
- require "time"
5
-
6
- module Clacky
7
- module Compression
8
- # Base class for all compression strategies
9
- #
10
- # Subclasses must implement:
11
- # - #compress(messages, options) - Main compression method
12
- # - #strategy_name - Unique identifier for the strategy
13
- #
14
- # Optional overrides:
15
- # - #setup(options) - Initialize strategy with options
16
- # - #teardown - Cleanup after compression
17
- #
18
- class Base
19
- attr_reader :strategy_name, :compression_count, :options
20
-
21
- def initialize(options = {})
22
- @options = options
23
- @compression_count = 0
24
- @initialized = false
25
- end
26
-
27
- # Main compression method - must be implemented by subclasses
28
- # @param messages [Array<Hash>] Array of message objects
29
- # @param options [Hash] Additional compression options
30
- # @return [Array<Hash>] Compressed messages
31
- def compress(messages, options = {})
32
- raise NotImplementedError, "#{self.class} must implement #compress"
33
- end
34
-
35
- # Get unique strategy identifier
36
- # @return [Symbol]
37
- def strategy_name
38
- raise NotImplementedError, "#{self.class} must implement #strategy_name"
39
- end
40
-
41
- # Initialize strategy before compression
42
- # @param options [Hash] Configuration options
43
- def setup(options = {})
44
- @options = options
45
- @initialized = true
46
- end
47
-
48
- # Cleanup after compression
49
- def teardown; end
50
-
51
- # Check if strategy is initialized
52
- def initialized?
53
- @initialized
54
- end
55
-
56
- # Get compression statistics
57
- # @return [Hash]
58
- def stats
59
- {
60
- strategy: strategy_name,
61
- total_compressions: @compression_count,
62
- initialized: @initialized
63
- }
64
- end
65
-
66
- # Reset strategy state
67
- def reset
68
- @compression_count = 0
69
- @initialized = false
70
- end
71
-
72
- # Increment compression counter
73
- def increment_count
74
- @compression_count += 1
75
- end
76
-
77
- # Estimate token count for content
78
- # @param content [String, Array, Hash] Message content
79
- # @return [Integer] Estimated token count
80
- def estimate_tokens(content)
81
- return 0 if content.nil?
82
-
83
- text = case content
84
- when String
85
- content
86
- when Array
87
- content.map { |c| c[:text] if c.is_a?(Hash) }.compact.join
88
- when Hash
89
- content[:text].to_s
90
- else
91
- content.to_s
92
- end
93
-
94
- return 0 if text.empty?
95
-
96
- # Detect language mix
97
- ascii_count = text.bytes.count { |b| b < 128 }
98
- total_bytes = text.bytes.length
99
- mix_ratio = total_bytes > 0 ? ascii_count.to_f / total_bytes : 1.0
100
-
101
- # English: ~4 chars/token, Chinese: ~2 chars/token
102
- base_chars_per_token = mix_ratio * 4 + (1 - mix_ratio) * 2
103
-
104
- (text.length / base_chars_per_token).to_i + 50
105
- end
106
-
107
- # Calculate total tokens for messages
108
- # @param messages [Array<Hash>]
109
- # @return [Hash] Token breakdown by category
110
- def total_message_tokens(messages)
111
- system_tokens = 0
112
- user_tokens = 0
113
- assistant_tokens = 0
114
- tool_tokens = 0
115
-
116
- messages.each do |msg|
117
- tokens = estimate_tokens(msg[:content])
118
- case msg[:role]
119
- when "system"
120
- system_tokens += tokens
121
- when "user"
122
- user_tokens += tokens
123
- when "assistant"
124
- assistant_tokens += tokens
125
- when "tool"
126
- tool_tokens += tokens
127
- end
128
- end
129
-
130
- {
131
- total: system_tokens + user_tokens + assistant_tokens + tool_tokens,
132
- system: system_tokens,
133
- user: user_tokens,
134
- assistant: assistant_tokens,
135
- tool: tool_tokens
136
- }
137
- end
138
-
139
- # Parse file action from tool result
140
- # @param content [String] Tool result content
141
- # @param action [Symbol] :created or :modified
142
- # @return [String, nil] File path or nil
143
- def parse_file_action(content, action)
144
- return nil unless content.is_a?(String)
145
-
146
- case action
147
- when :created
148
- content[/Created:\s*(.+)/, 1]&.strip
149
- when :modified
150
- content[/Updated:\s*(.+)/, 1]&.strip || content[/modified:\s*(.+)/, 1]&.strip
151
- else
152
- nil
153
- end
154
- end
155
-
156
- # Parse completed task from todo result
157
- # @param content [String] Tool result content
158
- # @return [String, nil] Task name or nil
159
- def parse_todo_result(content)
160
- return nil unless content.is_a?(String)
161
-
162
- if content.include?("completed")
163
- content[/completed[:\s]*(.+)/i, 1]&.strip || "task"
164
- elsif content.include?("added")
165
- content[/added[:\s]*(.+)/i, 1]&.strip || "task"
166
- else
167
- nil
168
- end
169
- end
170
-
171
- # Extract decisions from assistant messages
172
- # @param messages [Array<Hash>]
173
- # @return [Array<String>] List of decisions
174
- def extract_decisions(messages)
175
- messages
176
- .select { |m| m[:role] == "assistant" && m[:content].is_a?(String) }
177
- .select { |m| m[:content].include?("decision") || m[:content].include?("chose") }
178
- .map { |m| m[:content][/.{1,150}/] }
179
- end
180
-
181
- # Extract tool names from messages
182
- # @param messages [Array<Hash>]
183
- # @return [Array<String>] List of unique tool names
184
- def extract_tool_names(messages)
185
- messages
186
- .select { |m| m[:role] == "assistant" && m[:tool_calls] }
187
- .flat_map { |m| m[:tool_calls].map { |tc| tc.dig(:function, :name) } }
188
- .compact
189
- .uniq
190
- end
191
-
192
- # Find in-progress work from tool messages
193
- # @param messages [Array<Hash>]
194
- # @return [String, nil] In-progress description
195
- def find_in_progress(messages)
196
- messages
197
- .reverse
198
- .select { |m| m[:role] == "tool" && m[:content].is_a?(String) }
199
- .find { |m| m[:content].include?("in progress") || m[:content].include?("working on") }
200
- &.yield_self { |m| m[:content][/TODO[:\s]*(.+)/, 1]&.strip || m[:content] }
201
- end
202
-
203
- # Extract errors from tool messages
204
- # @param messages [Array<Hash>]
205
- # @return [Array<String>] List of error messages
206
- def extract_errors(messages)
207
- messages
208
- .select { |m| m[:role] == "tool" && m[:content].is_a?(String) }
209
- .select { |m| m[:content].include?("error") || m[:content].include?("failed") }
210
- .map { |m| m[:content][0..100] }
211
- end
212
-
213
- # Build empty extraction data structure
214
- # @return [Hash]
215
- def empty_extraction_data
216
- {
217
- user_msgs: 0,
218
- assistant_msgs: 0,
219
- tool_msgs: 0,
220
- tools_used: [],
221
- files_created: [],
222
- files_modified: [],
223
- decisions: [],
224
- completed_tasks: [],
225
- in_progress: nil,
226
- errors: []
227
- }
228
- end
229
- end
230
- end
231
- end