rubik 0.3.2 → 0.3.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 +77 -0
- data/lib/rubik/buffer/manager.rb +21 -3
- data/lib/rubik/config/defaults.rb +19 -26
- data/lib/rubik/config/store.rb +1 -1
- data/lib/rubik/config.rb +0 -6
- data/lib/rubik/llm/client.rb +102 -72
- data/lib/rubik/orchestrator/goal_ledger/patch.rb +48 -30
- data/lib/rubik/orchestrator/subagent/budget.rb +17 -10
- data/lib/rubik/orchestrator/subagent/instance.rb +14 -2
- data/lib/rubik/orchestrator/subagent/journal.rb +56 -13
- data/lib/rubik/orchestrator/subagent/reuse.rb +3 -3
- data/lib/rubik/orchestrator/subagent/run_cycle.rb +8 -5
- data/lib/rubik/orchestrator/subagent/supervisor.rb +7 -1
- data/lib/rubik/platform/process.rb +7 -7
- data/lib/rubik/platform/sanitize.rb +41 -20
- data/lib/rubik/platform.rb +2 -2
- data/lib/rubik/prompt/doctrine.rb +4 -0
- data/lib/rubik/repl/commands/agent_execution.rb +100 -87
- data/lib/rubik/repl/commands/agent_providers.rb +190 -156
- data/lib/rubik/repl/commands/lsp.rb +212 -179
- data/lib/rubik/repl/commands/subagents.rb +12 -11
- data/lib/rubik/repl/commands/workspace.rb +156 -152
- data/lib/rubik/repl/interrupt_handler.rb +10 -10
- data/lib/rubik/runtime/overlay_storage.rb +59 -2
- data/lib/rubik/sandbox/driver/docker.rb +2 -2
- data/lib/rubik/session/replayer.rb +1 -2
- data/lib/rubik/storage/store.rb +3 -2
- data/lib/rubik/tools/builtins/subagent.rb +7 -2
- data/lib/rubik/tools/fuzzy_matcher.rb +27 -11
- data/lib/rubik/version.rb +1 -1
- metadata +1 -1
|
@@ -19,36 +19,7 @@ module Rubik
|
|
|
19
19
|
|
|
20
20
|
def self.register(shell)
|
|
21
21
|
diag_handler = lambda do |args, ctx|
|
|
22
|
-
|
|
23
|
-
if target_file
|
|
24
|
-
diags = ctx.lsp_manager.diagnostics_for(target_file)
|
|
25
|
-
if diags.empty?
|
|
26
|
-
ctx.out.puts "No LSP diagnostics or errors for '#{target_file}'."
|
|
27
|
-
else
|
|
28
|
-
ctx.out.puts "=== LSP Diagnostics for #{target_file} (#{diags.size} issue(s)) ==="
|
|
29
|
-
diags.each do |d|
|
|
30
|
-
sev = d["severity"] == 1 ? "ERROR" : "WARN"
|
|
31
|
-
line = (d.dig("range", "start", "line") || 0) + 1
|
|
32
|
-
ctx.out.puts " • [#{sev}] Line #{line}: #{d['message']}"
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
else
|
|
36
|
-
all = ctx.lsp_manager.all_diagnostics
|
|
37
|
-
if all.empty? || all.values.flatten.empty?
|
|
38
|
-
ctx.out.puts "No active LSP diagnostics across workspace."
|
|
39
|
-
else
|
|
40
|
-
all.each do |fpath, diags|
|
|
41
|
-
next if diags.empty?
|
|
42
|
-
|
|
43
|
-
ctx.out.puts "\nFile: #{fpath} (#{diags.size} issue(s)):"
|
|
44
|
-
diags.each do |d|
|
|
45
|
-
sev = d["severity"] == 1 ? "ERROR" : "WARN"
|
|
46
|
-
line = (d.dig("range", "start", "line") || 0) + 1
|
|
47
|
-
ctx.out.puts " • [#{sev}] Line #{line}: #{d['message']}"
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
22
|
+
handle_diagnostics_command(args, ctx)
|
|
52
23
|
end
|
|
53
24
|
|
|
54
25
|
shell.register_command("diagnostics", description: "Display live LSP diagnostics across workspace or for a specific file", &diag_handler)
|
|
@@ -57,176 +28,238 @@ module Rubik
|
|
|
57
28
|
audience: :both,
|
|
58
29
|
description: "Manage Language Server Protocol (LSP) integration (status|on|off|diag|start|stop|restart|servers)",
|
|
59
30
|
usage: USAGE_LSP) do |args, ctx|
|
|
60
|
-
|
|
61
|
-
sub = clean_args.first&.downcase || "status"
|
|
62
|
-
|
|
63
|
-
case sub
|
|
64
|
-
when "status"
|
|
65
|
-
summary = ctx.lsp_manager.status_summary
|
|
66
|
-
ctx.out.puts "=== LSP Integration Status ==="
|
|
67
|
-
ctx.out.puts " • Enabled : #{summary[:enabled]}"
|
|
68
|
-
ctx.out.puts " • Auto Diagnostics : #{summary[:auto_diagnostics]}"
|
|
69
|
-
ctx.out.puts "\nConfigured Language Servers:"
|
|
70
|
-
summary[:servers].each do |lang, info|
|
|
71
|
-
status_mark = if info[:running]
|
|
72
|
-
"🟢 RUNNING"
|
|
73
|
-
else
|
|
74
|
-
(info[:available] ? "⚪ AVAILABLE" : "🔴 NOT FOUND")
|
|
75
|
-
end
|
|
76
|
-
diags_str = info[:running] ? " (#{info[:diagnostics_count]} diagnostics)" : ""
|
|
77
|
-
ctx.out.puts " • #{lang.ljust(8)} : #{info[:server_cmd].ljust(16)} -> #{status_mark}#{diags_str}"
|
|
78
|
-
end
|
|
79
|
-
when "servers"
|
|
80
|
-
summary = ctx.lsp_manager.status_summary
|
|
81
|
-
ctx.out.puts "=== Supported & Configured Language Servers ==="
|
|
82
|
-
summary[:servers].each do |lang, info|
|
|
83
|
-
status_mark = if info[:running]
|
|
84
|
-
"🟢 RUNNING"
|
|
85
|
-
else
|
|
86
|
-
(info[:available] ? "⚪ AVAILABLE" : "🔴 NOT INSTALLED")
|
|
87
|
-
end
|
|
88
|
-
ctx.out.puts " • #{lang.ljust(12)} : #{info[:server_cmd].ljust(35)} -> #{status_mark}"
|
|
89
|
-
end
|
|
90
|
-
when "on", "enable"
|
|
91
|
-
res = ctx.config.set("lsp.enabled", true, persist: scope)
|
|
92
|
-
next if Base.report_persist_failure(ctx, res, scope)
|
|
93
|
-
|
|
94
|
-
ctx.out.puts "LSP integration enabled [#{Base.scope_label(scope)}]."
|
|
95
|
-
when "off", "disable"
|
|
96
|
-
res = ctx.config.set("lsp.enabled", false, persist: scope)
|
|
97
|
-
ctx.lsp_manager.stop_all
|
|
98
|
-
next if Base.report_persist_failure(ctx, res, scope)
|
|
99
|
-
|
|
100
|
-
ctx.out.puts "LSP integration disabled and running servers stopped [#{Base.scope_label(scope)}]."
|
|
101
|
-
when "diag", "diagnostics"
|
|
102
|
-
diag_handler.call(clean_args[1..], ctx)
|
|
103
|
-
when "start"
|
|
104
|
-
lang = clean_args[1]
|
|
105
|
-
if lang.nil? || lang.empty?
|
|
106
|
-
supported = (Rubik::LSP::Client::SERVERS.keys + (ctx.config.fetch("lsp.servers", {})&.keys || [])).map(&:to_s).uniq.sort
|
|
107
|
-
ctx.out.puts "Usage: !lsp start <#{supported.join('|')}>"
|
|
108
|
-
else
|
|
109
|
-
res = ctx.lsp_manager.start_client(lang)
|
|
110
|
-
if res[:ok]
|
|
111
|
-
ctx.out.puts res[:message]
|
|
112
|
-
else
|
|
113
|
-
ctx.out.puts "Error: #{res[:error]}"
|
|
114
|
-
ctx.out.puts "\n💡 Suggestion: #{res[:suggestion]}" if res[:suggestion]
|
|
115
|
-
candidates = Rubik::Runtime::Discovery.lsp_candidates(lang)
|
|
116
|
-
ctx.out.puts "Probed candidates for #{lang}: #{candidates.join(', ')}" unless candidates.empty?
|
|
117
|
-
ctx.out.puts "Tip: Use `repair_runtime_service` (or `fix_service`) to probe or configure an alternative server."
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
when "stop"
|
|
121
|
-
lang = clean_args[1]
|
|
122
|
-
if lang.nil? || lang.empty?
|
|
123
|
-
ctx.lsp_manager.stop_all
|
|
124
|
-
ctx.out.puts "Stopped all active LSP servers."
|
|
125
|
-
else
|
|
126
|
-
res = ctx.lsp_manager.stop_client(lang)
|
|
127
|
-
ctx.out.puts res[:ok] ? res[:message] : "Error: #{res[:error]}"
|
|
128
|
-
end
|
|
129
|
-
when "restart"
|
|
130
|
-
lang = clean_args[1]
|
|
131
|
-
if lang.nil? || lang.empty?
|
|
132
|
-
running_langs = ctx.lsp_manager.status_summary[:servers].select { |_, v| v[:running] }.keys
|
|
133
|
-
if running_langs.empty?
|
|
134
|
-
ctx.out.puts "No LSP servers are currently running."
|
|
135
|
-
else
|
|
136
|
-
ctx.lsp_manager.stop_all
|
|
137
|
-
restarted = []
|
|
138
|
-
running_langs.each do |l|
|
|
139
|
-
res = ctx.lsp_manager.start_client(l)
|
|
140
|
-
restarted << l if res[:ok]
|
|
141
|
-
end
|
|
142
|
-
ctx.out.puts "Restarted LSP servers: #{restarted.join(', ')}"
|
|
143
|
-
end
|
|
144
|
-
else
|
|
145
|
-
ctx.lsp_manager.stop_client(lang)
|
|
146
|
-
res = ctx.lsp_manager.start_client(lang)
|
|
147
|
-
if res[:ok]
|
|
148
|
-
ctx.out.puts "Restarted LSP server for #{lang}."
|
|
149
|
-
else
|
|
150
|
-
ctx.out.puts "Error: #{res[:error]}"
|
|
151
|
-
ctx.out.puts "💡 Suggestion: #{res[:suggestion]}" if res[:suggestion]
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
else
|
|
155
|
-
ctx.out.puts USAGE_LSP
|
|
156
|
-
end
|
|
31
|
+
handle_lsp_command(args, ctx, diag_handler)
|
|
157
32
|
end
|
|
158
33
|
|
|
159
34
|
shell.register_command("symbols", description: "Search function, class, struct definitions in AST graph",
|
|
160
35
|
usage: USAGE_SYMBOLS) do |args, ctx|
|
|
161
|
-
|
|
162
|
-
if ctx.ast_graph.symbols.empty? && ctx.indexer_thread&.alive?
|
|
163
|
-
begin
|
|
164
|
-
ctx.indexer_thread.join(0.2)
|
|
165
|
-
rescue
|
|
166
|
-
nil
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
if query.empty?
|
|
170
|
-
total = ctx.ast_graph.symbols.size
|
|
171
|
-
ctx.out.puts "AST Symbol Graph (#{total} symbols indexed). #{USAGE_SYMBOLS}"
|
|
172
|
-
else
|
|
173
|
-
tool = Rubik::Tools::SearchSymbolsTool.new(ctx.ast_graph)
|
|
174
|
-
ctx.out.puts tool.execute(query: query)
|
|
175
|
-
end
|
|
36
|
+
handle_symbols_command(args, ctx)
|
|
176
37
|
end
|
|
177
38
|
|
|
178
39
|
shell.register_command("outline", description: "Show semantic outline (classes/methods) of a source file",
|
|
179
40
|
usage: USAGE_OUTLINE) do |args, ctx|
|
|
180
|
-
|
|
181
|
-
if target.nil? || target.empty?
|
|
182
|
-
ctx.out.puts USAGE_OUTLINE
|
|
183
|
-
else
|
|
184
|
-
full_path = File.expand_path(target, ctx.buffer_manager&.root_dir || Dir.pwd)
|
|
185
|
-
ctx.ast_graph.index_file(full_path) if File.exist?(full_path) && !ctx.ast_graph.file_symbols.key?(full_path)
|
|
186
|
-
tool = Rubik::Tools::GetOutlineTool.new(ctx.ast_graph)
|
|
187
|
-
ctx.out.puts tool.execute(file_path: target)
|
|
188
|
-
end
|
|
41
|
+
handle_outline_command(args, ctx)
|
|
189
42
|
end
|
|
190
43
|
|
|
191
44
|
shell.register_command("refs", description: "Find call sites and references of a symbol across codebase",
|
|
192
45
|
usage: USAGE_REFS) do |args, ctx|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
46
|
+
handle_refs_command(args, ctx)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
shell.register_command("ast", description: "Inspect AST outline for a file or definition for a symbol",
|
|
50
|
+
usage: USAGE_AST) do |args, ctx|
|
|
51
|
+
handle_ast_command(args, ctx)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private_class_method def self.handle_diagnostics_command(args, ctx)
|
|
56
|
+
target_file = args.first
|
|
57
|
+
if target_file
|
|
58
|
+
diags = ctx.lsp_manager.diagnostics_for(target_file)
|
|
59
|
+
if diags.empty?
|
|
60
|
+
ctx.out.puts "No LSP diagnostics or errors for '#{target_file}'."
|
|
61
|
+
else
|
|
62
|
+
ctx.out.puts "=== LSP Diagnostics for #{target_file} (#{diags.size} issue(s)) ==="
|
|
63
|
+
render_diagnostics(ctx, diags)
|
|
64
|
+
end
|
|
65
|
+
else
|
|
66
|
+
all = ctx.lsp_manager.all_diagnostics
|
|
67
|
+
if all.empty? || all.values.flatten.empty?
|
|
68
|
+
ctx.out.puts "No active LSP diagnostics across workspace."
|
|
69
|
+
else
|
|
70
|
+
all.each do |fpath, diags|
|
|
71
|
+
next if diags.empty?
|
|
72
|
+
|
|
73
|
+
ctx.out.puts "\nFile: #{fpath} (#{diags.size} issue(s)):"
|
|
74
|
+
render_diagnostics(ctx, diags)
|
|
199
75
|
end
|
|
200
76
|
end
|
|
201
|
-
|
|
202
|
-
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private_class_method def self.render_diagnostics(ctx, diags)
|
|
81
|
+
diags.each do |d|
|
|
82
|
+
sev = d["severity"] == 1 ? "ERROR" : "WARN"
|
|
83
|
+
line = (d.dig("range", "start", "line") || 0) + 1
|
|
84
|
+
ctx.out.puts " • [#{sev}] Line #{line}: #{d['message']}"
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
private_class_method def self.handle_lsp_command(args, ctx, diag_handler)
|
|
89
|
+
scope, clean_args = Base.parse_scope(args)
|
|
90
|
+
sub = clean_args.first&.downcase || "status"
|
|
91
|
+
|
|
92
|
+
case sub
|
|
93
|
+
when "status"
|
|
94
|
+
handle_lsp_status(ctx)
|
|
95
|
+
when "servers"
|
|
96
|
+
handle_lsp_servers(ctx)
|
|
97
|
+
when "on", "enable"
|
|
98
|
+
res = ctx.config.set("lsp.enabled", true, persist: scope)
|
|
99
|
+
return if Base.report_persist_failure(ctx, res, scope)
|
|
100
|
+
|
|
101
|
+
ctx.out.puts "LSP integration enabled [#{Base.scope_label(scope)}]."
|
|
102
|
+
when "off", "disable"
|
|
103
|
+
res = ctx.config.set("lsp.enabled", false, persist: scope)
|
|
104
|
+
ctx.lsp_manager.stop_all
|
|
105
|
+
return if Base.report_persist_failure(ctx, res, scope)
|
|
106
|
+
|
|
107
|
+
ctx.out.puts "LSP integration disabled and running servers stopped [#{Base.scope_label(scope)}]."
|
|
108
|
+
when "diag", "diagnostics"
|
|
109
|
+
diag_handler.call(clean_args[1..], ctx)
|
|
110
|
+
when "start"
|
|
111
|
+
handle_lsp_start(clean_args[1], ctx)
|
|
112
|
+
when "stop"
|
|
113
|
+
handle_lsp_stop(clean_args[1], ctx)
|
|
114
|
+
when "restart"
|
|
115
|
+
handle_lsp_restart(clean_args[1], ctx)
|
|
116
|
+
else
|
|
117
|
+
ctx.out.puts USAGE_LSP
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
private_class_method def self.handle_lsp_status(ctx)
|
|
122
|
+
summary = ctx.lsp_manager.status_summary
|
|
123
|
+
ctx.out.puts "=== LSP Integration Status ==="
|
|
124
|
+
ctx.out.puts " • Enabled : #{summary[:enabled]}"
|
|
125
|
+
ctx.out.puts " • Auto Diagnostics : #{summary[:auto_diagnostics]}"
|
|
126
|
+
ctx.out.puts "\nConfigured Language Servers:"
|
|
127
|
+
summary[:servers].each do |lang, info|
|
|
128
|
+
status_mark = if info[:running]
|
|
129
|
+
"🟢 RUNNING"
|
|
130
|
+
else
|
|
131
|
+
(info[:available] ? "⚪ AVAILABLE" : "🔴 NOT FOUND")
|
|
132
|
+
end
|
|
133
|
+
diags_str = info[:running] ? " (#{info[:diagnostics_count]} diagnostics)" : ""
|
|
134
|
+
ctx.out.puts " • #{lang.ljust(8)} : #{info[:server_cmd].ljust(16)} -> #{status_mark}#{diags_str}"
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
private_class_method def self.handle_lsp_servers(ctx)
|
|
139
|
+
summary = ctx.lsp_manager.status_summary
|
|
140
|
+
ctx.out.puts "=== Supported & Configured Language Servers ==="
|
|
141
|
+
summary[:servers].each do |lang, info|
|
|
142
|
+
status_mark = if info[:running]
|
|
143
|
+
"🟢 RUNNING"
|
|
144
|
+
else
|
|
145
|
+
(info[:available] ? "⚪ AVAILABLE" : "🔴 NOT INSTALLED")
|
|
146
|
+
end
|
|
147
|
+
ctx.out.puts " • #{lang.ljust(12)} : #{info[:server_cmd].ljust(35)} -> #{status_mark}"
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
private_class_method def self.handle_lsp_start(lang, ctx)
|
|
152
|
+
if lang.nil? || lang.empty?
|
|
153
|
+
supported = (Rubik::LSP::Client::SERVERS.keys + (ctx.config.fetch("lsp.servers", {})&.keys || [])).map(&:to_s).uniq.sort
|
|
154
|
+
ctx.out.puts "Usage: !lsp start <#{supported.join('|')}>"
|
|
155
|
+
else
|
|
156
|
+
res = ctx.lsp_manager.start_client(lang)
|
|
157
|
+
if res[:ok]
|
|
158
|
+
ctx.out.puts res[:message]
|
|
203
159
|
else
|
|
204
|
-
|
|
205
|
-
ctx.out.puts
|
|
160
|
+
ctx.out.puts "Error: #{res[:error]}"
|
|
161
|
+
ctx.out.puts "\n💡 Suggestion: #{res[:suggestion]}" if res[:suggestion]
|
|
162
|
+
candidates = Rubik::Runtime::Discovery.lsp_candidates(lang)
|
|
163
|
+
ctx.out.puts "Probed candidates for #{lang}: #{candidates.join(', ')}" unless candidates.empty?
|
|
164
|
+
ctx.out.puts "Tip: Use `repair_runtime_service` (or `fix_service`) to probe or configure an alternative server."
|
|
206
165
|
end
|
|
207
166
|
end
|
|
167
|
+
end
|
|
208
168
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
169
|
+
private_class_method def self.handle_lsp_stop(lang, ctx)
|
|
170
|
+
if lang.nil? || lang.empty?
|
|
171
|
+
ctx.lsp_manager.stop_all
|
|
172
|
+
ctx.out.puts "Stopped all active LSP servers."
|
|
173
|
+
else
|
|
174
|
+
res = ctx.lsp_manager.stop_client(lang)
|
|
175
|
+
ctx.out.puts res[:ok] ? res[:message] : "Error: #{res[:error]}"
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
private_class_method def self.handle_lsp_restart(lang, ctx)
|
|
180
|
+
if lang.nil? || lang.empty?
|
|
181
|
+
running_langs = ctx.lsp_manager.status_summary[:servers].select { |_, v| v[:running] }.keys
|
|
182
|
+
if running_langs.empty?
|
|
183
|
+
ctx.out.puts "No LSP servers are currently running."
|
|
219
184
|
else
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
end
|
|
185
|
+
ctx.lsp_manager.stop_all
|
|
186
|
+
restarted = []
|
|
187
|
+
running_langs.each do |l|
|
|
188
|
+
res = ctx.lsp_manager.start_client(l)
|
|
189
|
+
restarted << l if res[:ok]
|
|
226
190
|
end
|
|
227
|
-
|
|
228
|
-
ctx.out.puts tool.execute(symbol_name: target)
|
|
191
|
+
ctx.out.puts "Restarted LSP servers: #{restarted.join(', ')}"
|
|
229
192
|
end
|
|
193
|
+
else
|
|
194
|
+
ctx.lsp_manager.stop_client(lang)
|
|
195
|
+
res = ctx.lsp_manager.start_client(lang)
|
|
196
|
+
if res[:ok]
|
|
197
|
+
ctx.out.puts "Restarted LSP server for #{lang}."
|
|
198
|
+
else
|
|
199
|
+
ctx.out.puts "Error: #{res[:error]}"
|
|
200
|
+
ctx.out.puts "💡 Suggestion: #{res[:suggestion]}" if res[:suggestion]
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
private_class_method def self.wait_for_indexer(ctx)
|
|
206
|
+
return unless ctx.ast_graph.symbols.empty? && ctx.indexer_thread&.alive?
|
|
207
|
+
|
|
208
|
+
begin
|
|
209
|
+
ctx.indexer_thread.join(0.2)
|
|
210
|
+
rescue
|
|
211
|
+
nil
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
private_class_method def self.handle_symbols_command(args, ctx)
|
|
216
|
+
query = args.join(" ").strip
|
|
217
|
+
wait_for_indexer(ctx)
|
|
218
|
+
if query.empty?
|
|
219
|
+
total = ctx.ast_graph.symbols.size
|
|
220
|
+
ctx.out.puts "AST Symbol Graph (#{total} symbols indexed). #{USAGE_SYMBOLS}"
|
|
221
|
+
else
|
|
222
|
+
tool = Rubik::Tools::SearchSymbolsTool.new(ctx.ast_graph)
|
|
223
|
+
ctx.out.puts tool.execute(query: query)
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
private_class_method def self.handle_outline_command(args, ctx)
|
|
228
|
+
target = args.first
|
|
229
|
+
if target.nil? || target.empty?
|
|
230
|
+
ctx.out.puts USAGE_OUTLINE
|
|
231
|
+
else
|
|
232
|
+
full_path = File.expand_path(target, ctx.buffer_manager&.root_dir || Dir.pwd)
|
|
233
|
+
ctx.ast_graph.index_file(full_path) if File.exist?(full_path) && !ctx.ast_graph.file_symbols.key?(full_path)
|
|
234
|
+
tool = Rubik::Tools::GetOutlineTool.new(ctx.ast_graph)
|
|
235
|
+
ctx.out.puts tool.execute(file_path: target)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
private_class_method def self.handle_refs_command(args, ctx)
|
|
240
|
+
sym = args.first
|
|
241
|
+
wait_for_indexer(ctx)
|
|
242
|
+
if sym.nil? || sym.empty?
|
|
243
|
+
ctx.out.puts USAGE_REFS
|
|
244
|
+
else
|
|
245
|
+
tool = Rubik::Tools::FindReferencesTool.new(ctx.ast_graph)
|
|
246
|
+
ctx.out.puts tool.execute(symbol_name: sym)
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
private_class_method def self.handle_ast_command(args, ctx)
|
|
251
|
+
target = args.first
|
|
252
|
+
if target.nil? || target.empty?
|
|
253
|
+
ctx.out.puts USAGE_AST
|
|
254
|
+
elsif File.exist?(target)
|
|
255
|
+
full_path = File.expand_path(target, ctx.buffer_manager&.root_dir || Dir.pwd)
|
|
256
|
+
ctx.ast_graph.index_file(full_path) unless ctx.ast_graph.file_symbols.key?(full_path)
|
|
257
|
+
tool = Rubik::Tools::GetOutlineTool.new(ctx.ast_graph)
|
|
258
|
+
ctx.out.puts tool.execute(file_path: target)
|
|
259
|
+
else
|
|
260
|
+
wait_for_indexer(ctx)
|
|
261
|
+
tool = Rubik::Tools::GetSymbolTool.new(ctx.ast_graph)
|
|
262
|
+
ctx.out.puts tool.execute(symbol_name: target)
|
|
230
263
|
end
|
|
231
264
|
end
|
|
232
265
|
end
|
|
@@ -113,10 +113,7 @@ module Rubik
|
|
|
113
113
|
end
|
|
114
114
|
|
|
115
115
|
def self.handle_kill(ctx, sup, id)
|
|
116
|
-
if id.to_s.strip.empty?
|
|
117
|
-
ctx.out.puts "Usage: !subagents kill <subagent_id>"
|
|
118
|
-
return
|
|
119
|
-
end
|
|
116
|
+
return ctx.out.puts "Usage: !subagents kill <subagent_id>" if id.to_s.strip.empty?
|
|
120
117
|
|
|
121
118
|
if sup.kill(id)
|
|
122
119
|
ctx.out.puts "Subagent '#{id}' and child tree killed."
|
|
@@ -126,17 +123,21 @@ module Rubik
|
|
|
126
123
|
end
|
|
127
124
|
|
|
128
125
|
def self.handle_extend(ctx, sup, id, steps_arg)
|
|
129
|
-
if id.to_s.strip.empty?
|
|
130
|
-
ctx.out.puts "Usage: !subagents extend <subagent_id> [additional_steps]"
|
|
131
|
-
return
|
|
132
|
-
end
|
|
126
|
+
return ctx.out.puts "Usage: !subagents extend <subagent_id> [additional_steps]" if id.to_s.strip.empty?
|
|
133
127
|
|
|
134
128
|
steps = Rubik::Orchestrator::Subagent::Budget.normalize_grant(steps_arg)
|
|
129
|
+
inst = sup.get(id)
|
|
135
130
|
if sup.extend_budget(id, steps)
|
|
136
|
-
|
|
137
|
-
ctx.out.puts "Extended budget for #{id} by #{steps} steps (total: #{inst.max_steps}
|
|
131
|
+
ceiling = inst.respond_to?(:max_total_steps) ? "/#{inst.max_total_steps}" : ""
|
|
132
|
+
ctx.out.puts "Extended budget for #{id} by #{steps} steps (total: #{inst.max_steps}#{ceiling}, " \
|
|
133
|
+
"state: #{inst.state.to_s.upcase})."
|
|
138
134
|
else
|
|
139
|
-
|
|
135
|
+
msg = if inst.respond_to?(:max_total_steps) && inst.max_steps >= inst.max_total_steps
|
|
136
|
+
"Could not extend budget for #{id}: lifetime step limit of #{inst.max_total_steps} reached."
|
|
137
|
+
else
|
|
138
|
+
"Could not extend budget for #{id} (not found or inactive)."
|
|
139
|
+
end
|
|
140
|
+
ctx.out.puts msg
|
|
140
141
|
end
|
|
141
142
|
end
|
|
142
143
|
|