console_agent 0.8.0 → 0.9.0
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 +58 -0
- data/app/controllers/console_agent/application_controller.rb +4 -1
- data/lib/console_agent/executor.rb +55 -21
- data/lib/console_agent/repl.rb +129 -45
- data/lib/console_agent/version.rb +1 -1
- data/lib/generators/console_agent/templates/initializer.rb +1 -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: 5f82de0e3bdd6d1e3189c3b1bd0c88c386a6b31b4dff317656365352490f06c9
|
|
4
|
+
data.tar.gz: 1347a93e946c254809cdf6bfa90e3dea0378b7aef9a5e04950bdf0151569cd79
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cec5e56aaddea19c5d1b9046fcbd7fd4707d16efa3fab65f9977703e24d28d177c12331c9cba7590048b1ad2f412d67bcb9ffe78c5cef288d6da40916cb53a86
|
|
7
|
+
data.tar.gz: 9e67f0c30bbd38561c400523ca19240f931ff5c08b353fa545037472b6b2195f931b5987b21d3c643a35e2cb3377647447cc676aa7544ba5a2ccec2a505f7e16
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [0.8.0]
|
|
6
|
+
|
|
7
|
+
- Add authentication function support so host apps can avoid using basic auth
|
|
8
|
+
- Add `/think` and `/cost` commands with Sonnet vs Opus support
|
|
9
|
+
- Gracefully handle token limit exceeded errors
|
|
10
|
+
|
|
11
|
+
## [0.7.0]
|
|
12
|
+
|
|
13
|
+
- Include binding variables and their classes in the Rails console context
|
|
14
|
+
- Add `ai_setup` command
|
|
15
|
+
- Add `/compact` mechanism for conversation management
|
|
16
|
+
- Catch errors and attempt to auto-fix them
|
|
17
|
+
|
|
18
|
+
## [0.6.0]
|
|
19
|
+
|
|
20
|
+
- Add core memory (`console_agent.md`) that persists across sessions in the system prompt
|
|
21
|
+
- Add `ai_init` command to seed core memory
|
|
22
|
+
- Allow reading partial files
|
|
23
|
+
- Fix rspec hanging issues
|
|
24
|
+
|
|
25
|
+
## [0.5.0]
|
|
26
|
+
|
|
27
|
+
- Auto-accept single-step plans
|
|
28
|
+
- Support `>` shorthand to run code directly
|
|
29
|
+
- Add `script/release` for releases
|
|
30
|
+
|
|
31
|
+
## [0.4.0]
|
|
32
|
+
|
|
33
|
+
- Fix resuming sessions repeatedly
|
|
34
|
+
- Fix terminal flashing/loading in production (kubectl)
|
|
35
|
+
- Better escaping during thinking output
|
|
36
|
+
|
|
37
|
+
## [0.3.0]
|
|
38
|
+
|
|
39
|
+
- Add plan mechanism with "auto" execution mode
|
|
40
|
+
- Add session logging to DB with `/console_agent` admin UI
|
|
41
|
+
- List and resume past sessions with pagination
|
|
42
|
+
- Add shift-tab for auto-execute mode
|
|
43
|
+
- Add usage display and debug toggle
|
|
44
|
+
- Store sessions incrementally; improved code segment display
|
|
45
|
+
|
|
46
|
+
## [0.2.0]
|
|
47
|
+
|
|
48
|
+
- Add memory system with individual file storage
|
|
49
|
+
- Add `ask_user` tool
|
|
50
|
+
- Add registry cache
|
|
51
|
+
- Fix REPL up-key and ctrl-a navigation
|
|
52
|
+
- Show tool usage and model processing info
|
|
53
|
+
- Add token count information and debug ability
|
|
54
|
+
- Use tools-based approach instead of sending everything at once
|
|
55
|
+
|
|
56
|
+
## [0.1.0]
|
|
57
|
+
|
|
58
|
+
- Initial implementation
|
|
@@ -13,7 +13,10 @@ module ConsoleAgent
|
|
|
13
13
|
username = ConsoleAgent.configuration.admin_username
|
|
14
14
|
password = ConsoleAgent.configuration.admin_password
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
unless username && password
|
|
17
|
+
head :unauthorized
|
|
18
|
+
return
|
|
19
|
+
end
|
|
17
20
|
|
|
18
21
|
authenticate_or_request_with_http_basic('ConsoleAgent Admin') do |u, p|
|
|
19
22
|
ActiveSupport::SecurityUtils.secure_compare(u, username) &
|
|
@@ -84,7 +84,7 @@ module ConsoleAgent
|
|
|
84
84
|
result = binding_context.eval(code, "(console_agent)", 1)
|
|
85
85
|
|
|
86
86
|
$stdout = old_stdout
|
|
87
|
-
|
|
87
|
+
display_result(result)
|
|
88
88
|
|
|
89
89
|
@last_output = captured_output.string
|
|
90
90
|
result
|
|
@@ -126,35 +126,69 @@ module ConsoleAgent
|
|
|
126
126
|
@last_answer = answer
|
|
127
127
|
echo_stdin(answer)
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
129
|
+
loop do
|
|
130
|
+
case answer
|
|
131
|
+
when 'y', 'yes', 'a'
|
|
132
|
+
return execute(code)
|
|
133
|
+
when 'e', 'edit'
|
|
134
|
+
edited = open_in_editor(code)
|
|
135
|
+
if edited && edited != code
|
|
136
|
+
$stdout.puts colorize("# Edited code:", :yellow)
|
|
137
|
+
$stdout.puts highlight_code(edited)
|
|
138
|
+
$stdout.print colorize("Execute edited code? [y/N] ", :yellow)
|
|
139
|
+
edit_answer = $stdin.gets.to_s.strip.downcase
|
|
140
|
+
echo_stdin(edit_answer)
|
|
141
|
+
if edit_answer == 'y'
|
|
142
|
+
return execute(edited)
|
|
143
|
+
else
|
|
144
|
+
$stdout.puts colorize("Cancelled.", :yellow)
|
|
145
|
+
return nil
|
|
146
|
+
end
|
|
142
147
|
else
|
|
143
|
-
|
|
144
|
-
nil
|
|
148
|
+
return execute(code)
|
|
145
149
|
end
|
|
150
|
+
when 'n', 'no', ''
|
|
151
|
+
$stdout.puts colorize("Cancelled.", :yellow)
|
|
152
|
+
@last_cancelled = true
|
|
153
|
+
return nil
|
|
146
154
|
else
|
|
147
|
-
|
|
155
|
+
$stdout.print colorize("Execute? [y/N/edit] ", :yellow)
|
|
156
|
+
@on_prompt&.call
|
|
157
|
+
answer = $stdin.gets.to_s.strip.downcase
|
|
158
|
+
@last_answer = answer
|
|
159
|
+
echo_stdin(answer)
|
|
148
160
|
end
|
|
149
|
-
else
|
|
150
|
-
$stdout.puts colorize("Cancelled.", :yellow)
|
|
151
|
-
@last_cancelled = true
|
|
152
|
-
nil
|
|
153
161
|
end
|
|
154
162
|
end
|
|
155
163
|
|
|
156
164
|
private
|
|
157
165
|
|
|
166
|
+
MAX_DISPLAY_LINES = 10
|
|
167
|
+
MAX_DISPLAY_CHARS = 2000
|
|
168
|
+
|
|
169
|
+
def display_result(result)
|
|
170
|
+
full = "=> #{result.inspect}"
|
|
171
|
+
lines = full.lines
|
|
172
|
+
total_lines = lines.length
|
|
173
|
+
total_chars = full.length
|
|
174
|
+
|
|
175
|
+
if total_lines <= MAX_DISPLAY_LINES && total_chars <= MAX_DISPLAY_CHARS
|
|
176
|
+
$stdout.puts colorize(full, :green)
|
|
177
|
+
else
|
|
178
|
+
# Truncate by lines first, then by chars
|
|
179
|
+
truncated = lines.first(MAX_DISPLAY_LINES).join
|
|
180
|
+
truncated = truncated[0, MAX_DISPLAY_CHARS] if truncated.length > MAX_DISPLAY_CHARS
|
|
181
|
+
$stdout.puts colorize(truncated, :green)
|
|
182
|
+
|
|
183
|
+
omitted_lines = [total_lines - MAX_DISPLAY_LINES, 0].max
|
|
184
|
+
omitted_chars = [total_chars - truncated.length, 0].max
|
|
185
|
+
parts = []
|
|
186
|
+
parts << "#{omitted_lines} lines" if omitted_lines > 0
|
|
187
|
+
parts << "#{omitted_chars} chars" if omitted_chars > 0
|
|
188
|
+
$stdout.puts colorize(" (omitting #{parts.join(', ')})", :yellow)
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
158
192
|
# Write stdin input to the capture IO only (avoids double-echo on terminal)
|
|
159
193
|
def echo_stdin(text)
|
|
160
194
|
$stdout.secondary.write("#{text}\n") if $stdout.respond_to?(:secondary)
|
data/lib/console_agent/repl.rb
CHANGED
|
@@ -241,6 +241,11 @@ module ConsoleAgent
|
|
|
241
241
|
break if input.downcase == 'exit' || input.downcase == 'quit'
|
|
242
242
|
next if input.empty?
|
|
243
243
|
|
|
244
|
+
if input == '?' || input == '/'
|
|
245
|
+
display_help
|
|
246
|
+
next
|
|
247
|
+
end
|
|
248
|
+
|
|
244
249
|
if input == '/auto'
|
|
245
250
|
ConsoleAgent.configuration.auto_execute = !ConsoleAgent.configuration.auto_execute
|
|
246
251
|
mode = ConsoleAgent.configuration.auto_execute ? 'ON' : 'OFF'
|
|
@@ -265,6 +270,16 @@ module ConsoleAgent
|
|
|
265
270
|
next
|
|
266
271
|
end
|
|
267
272
|
|
|
273
|
+
if input == '/system'
|
|
274
|
+
@interactive_old_stdout.puts "\e[2m#{context}\e[0m"
|
|
275
|
+
next
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
if input == '/context'
|
|
279
|
+
display_conversation
|
|
280
|
+
next
|
|
281
|
+
end
|
|
282
|
+
|
|
268
283
|
if input == '/cost'
|
|
269
284
|
display_cost_summary
|
|
270
285
|
next
|
|
@@ -384,18 +399,11 @@ module ConsoleAgent
|
|
|
384
399
|
result, tool_messages = send_query(nil, conversation: @history)
|
|
385
400
|
rescue Providers::ProviderError => e
|
|
386
401
|
if e.message.include?("prompt is too long") && @history.length >= 6
|
|
387
|
-
$stdout.puts "\e[33m Context limit reached.
|
|
388
|
-
compact_history
|
|
389
|
-
begin
|
|
390
|
-
result, tool_messages = send_query(nil, conversation: @history)
|
|
391
|
-
rescue Providers::ProviderError => e2
|
|
392
|
-
$stderr.puts "\e[31m Still too large after compaction: #{e2.message}\e[0m"
|
|
393
|
-
return :error
|
|
394
|
-
end
|
|
402
|
+
$stdout.puts "\e[33m Context limit reached. Run /compact to reduce context size, then try again.\e[0m"
|
|
395
403
|
else
|
|
396
404
|
$stderr.puts "\e[31mConsoleAgent Error: #{e.class}: #{e.message}\e[0m"
|
|
397
|
-
return :error
|
|
398
405
|
end
|
|
406
|
+
return :error
|
|
399
407
|
rescue Interrupt
|
|
400
408
|
$stdout.puts "\n\e[33m Aborted.\e[0m"
|
|
401
409
|
return :interrupted
|
|
@@ -564,18 +572,8 @@ module ConsoleAgent
|
|
|
564
572
|
last_tool_names = []
|
|
565
573
|
|
|
566
574
|
exhausted = false
|
|
567
|
-
thinking_suggested = false
|
|
568
575
|
|
|
569
576
|
max_rounds.times do |round|
|
|
570
|
-
if round == 5 && !thinking_suggested && !on_thinking_model?
|
|
571
|
-
thinking_suggested = true
|
|
572
|
-
thinking_name = ConsoleAgent.configuration.resolved_thinking_model
|
|
573
|
-
$stdout.puts "\e[33m This query is using many tool rounds. Switch to thinking model (#{thinking_name})? [y/N]\e[0m"
|
|
574
|
-
answer = Readline.readline(" ", false).to_s.strip.downcase
|
|
575
|
-
if answer == 'y'
|
|
576
|
-
upgrade_to_thinking_model
|
|
577
|
-
end
|
|
578
|
-
end
|
|
579
577
|
if round == 0
|
|
580
578
|
$stdout.puts "\e[2m Thinking...\e[0m"
|
|
581
579
|
else
|
|
@@ -593,17 +591,7 @@ module ConsoleAgent
|
|
|
593
591
|
provider.chat_with_tools(messages, tools: tools, system_prompt: active_system_prompt)
|
|
594
592
|
end
|
|
595
593
|
rescue Providers::ProviderError => e
|
|
596
|
-
if e.message.include?("prompt is too long") && messages.length >= 6
|
|
597
|
-
$stdout.puts "\e[33m Context limit hit mid-session. Compacting messages...\e[0m"
|
|
598
|
-
messages = compact_messages(messages)
|
|
599
|
-
unless @_retried_compact
|
|
600
|
-
@_retried_compact = true
|
|
601
|
-
retry
|
|
602
|
-
end
|
|
603
|
-
end
|
|
604
594
|
raise
|
|
605
|
-
ensure
|
|
606
|
-
@_retried_compact = nil
|
|
607
595
|
end
|
|
608
596
|
total_input += result.input_tokens || 0
|
|
609
597
|
total_output += result.output_tokens || 0
|
|
@@ -990,10 +978,7 @@ module ConsoleAgent
|
|
|
990
978
|
def warn_if_history_large
|
|
991
979
|
chars = @history.sum { |m| m[:content].to_s.length }
|
|
992
980
|
|
|
993
|
-
if chars >
|
|
994
|
-
$stdout.puts "\e[33m Context growing large (~#{format_tokens(chars)} chars). Auto-compacting...\e[0m"
|
|
995
|
-
compact_history
|
|
996
|
-
elsif chars > 50_000 && !@compact_warned
|
|
981
|
+
if chars > 50_000 && !@compact_warned
|
|
997
982
|
@compact_warned = true
|
|
998
983
|
$stdout.puts "\e[33m Conversation is getting large (~#{format_tokens(chars)} chars). Consider running /compact to reduce context size.\e[0m"
|
|
999
984
|
end
|
|
@@ -1008,6 +993,9 @@ module ConsoleAgent
|
|
|
1008
993
|
before_chars = @history.sum { |m| m[:content].to_s.length }
|
|
1009
994
|
before_count = @history.length
|
|
1010
995
|
|
|
996
|
+
# Extract successfully executed code before summarizing
|
|
997
|
+
executed_code = extract_executed_code(@history)
|
|
998
|
+
|
|
1011
999
|
$stdout.puts "\e[2m Compacting #{before_count} messages (~#{format_tokens(before_chars)} chars)...\e[0m"
|
|
1012
1000
|
|
|
1013
1001
|
system_prompt = <<~PROMPT
|
|
@@ -1018,8 +1006,8 @@ module ConsoleAgent
|
|
|
1018
1006
|
- Key findings and data discovered (include specific values, IDs, record counts)
|
|
1019
1007
|
- Current state: what worked, what failed, where things stand
|
|
1020
1008
|
- Important variable names, model names, or table names referenced
|
|
1021
|
-
- Any code that was executed and its results
|
|
1022
1009
|
|
|
1010
|
+
Do NOT include code that was executed — that will be preserved separately.
|
|
1023
1011
|
Be concise but preserve all information that would be needed to continue the conversation naturally.
|
|
1024
1012
|
Do NOT include any preamble — just output the summary directly.
|
|
1025
1013
|
PROMPT
|
|
@@ -1037,32 +1025,128 @@ module ConsoleAgent
|
|
|
1037
1025
|
return
|
|
1038
1026
|
end
|
|
1039
1027
|
|
|
1040
|
-
|
|
1028
|
+
content = "CONVERSATION SUMMARY (compacted):\n#{summary}"
|
|
1029
|
+
unless executed_code.empty?
|
|
1030
|
+
content += "\n\nCODE EXECUTED THIS SESSION (preserved for continuation):\n#{executed_code}"
|
|
1031
|
+
end
|
|
1032
|
+
|
|
1033
|
+
@history = [{ role: :user, content: content }]
|
|
1041
1034
|
@compact_warned = false
|
|
1042
1035
|
|
|
1043
1036
|
after_chars = @history.first[:content].length
|
|
1044
1037
|
$stdout.puts "\e[36m Compacted: #{before_count} messages -> 1 summary (~#{format_tokens(before_chars)} -> ~#{format_tokens(after_chars)} chars)\e[0m"
|
|
1045
1038
|
summary.each_line { |line| $stdout.puts "\e[2m #{line.rstrip}\e[0m" }
|
|
1039
|
+
if !executed_code.empty?
|
|
1040
|
+
$stdout.puts "\e[2m (preserved #{executed_code.scan(/```ruby/).length} executed code block(s))\e[0m"
|
|
1041
|
+
end
|
|
1046
1042
|
display_usage(result)
|
|
1047
1043
|
rescue => e
|
|
1048
1044
|
$stdout.puts "\e[31m Compaction failed: #{e.message}\e[0m"
|
|
1049
1045
|
end
|
|
1050
1046
|
end
|
|
1051
1047
|
|
|
1052
|
-
|
|
1053
|
-
|
|
1048
|
+
# Extracts code blocks that were successfully executed from conversation history.
|
|
1049
|
+
# Looks for:
|
|
1050
|
+
# 1. Assistant messages with ```ruby blocks followed by "Code was executed." user messages
|
|
1051
|
+
# 2. execute_plan tool calls followed by results without ERROR
|
|
1052
|
+
# Skips code that failed or was declined.
|
|
1053
|
+
def extract_executed_code(history)
|
|
1054
|
+
code_blocks = []
|
|
1055
|
+
history.each_cons(2) do |msg, next_msg|
|
|
1056
|
+
# Pattern 1: Assistant ```ruby blocks with successful execution
|
|
1057
|
+
if msg[:role].to_s == 'assistant' && next_msg[:role].to_s == 'user'
|
|
1058
|
+
content = msg[:content].to_s
|
|
1059
|
+
next_content = next_msg[:content].to_s
|
|
1060
|
+
|
|
1061
|
+
if next_content.start_with?('Code was executed.')
|
|
1062
|
+
content.scan(/```ruby\s*\n(.*?)```/m).each do |match|
|
|
1063
|
+
code = match[0].strip
|
|
1064
|
+
next if code.empty?
|
|
1065
|
+
result_summary = next_content[0..200].gsub("\n", "\n# ")
|
|
1066
|
+
code_blocks << "```ruby\n#{code}\n```\n# #{result_summary}"
|
|
1067
|
+
end
|
|
1068
|
+
end
|
|
1069
|
+
end
|
|
1054
1070
|
|
|
1055
|
-
|
|
1056
|
-
|
|
1071
|
+
# Pattern 2: execute_plan tool calls in provider-formatted messages
|
|
1072
|
+
if msg[:role].to_s == 'assistant' && msg[:content].is_a?(Array)
|
|
1073
|
+
msg[:content].each do |block|
|
|
1074
|
+
next unless block.is_a?(Hash) && block['type'] == 'tool_use' && block['name'] == 'execute_plan'
|
|
1075
|
+
input = block['input'] || {}
|
|
1076
|
+
steps = input['steps'] || []
|
|
1077
|
+
|
|
1078
|
+
# Find the matching tool_result in subsequent messages
|
|
1079
|
+
tool_id = block['id']
|
|
1080
|
+
result_msg = find_tool_result(history, tool_id)
|
|
1081
|
+
next unless result_msg
|
|
1082
|
+
|
|
1083
|
+
result_text = result_msg.to_s
|
|
1084
|
+
# Extract only steps that succeeded (no ERROR in their result)
|
|
1085
|
+
steps.each_with_index do |step, i|
|
|
1086
|
+
step_num = i + 1
|
|
1087
|
+
# Check if this specific step had an error
|
|
1088
|
+
step_section = result_text[/Step #{step_num}\b.*?(?=Step #{step_num + 1}\b|\z)/m] || ''
|
|
1089
|
+
next if step_section.include?('ERROR:')
|
|
1090
|
+
next if step_section.include?('User declined')
|
|
1091
|
+
|
|
1092
|
+
code = step['code'].to_s.strip
|
|
1093
|
+
next if code.empty?
|
|
1094
|
+
desc = step['description'] || "Step #{step_num}"
|
|
1095
|
+
code_blocks << "```ruby\n# #{desc}\n#{code}\n```"
|
|
1096
|
+
end
|
|
1097
|
+
end
|
|
1098
|
+
end
|
|
1099
|
+
end
|
|
1100
|
+
code_blocks.join("\n\n")
|
|
1101
|
+
end
|
|
1057
1102
|
|
|
1058
|
-
|
|
1103
|
+
def find_tool_result(history, tool_id)
|
|
1104
|
+
history.each do |msg|
|
|
1105
|
+
next unless msg[:content].is_a?(Array)
|
|
1106
|
+
msg[:content].each do |block|
|
|
1107
|
+
next unless block.is_a?(Hash)
|
|
1108
|
+
if block['type'] == 'tool_result' && block['tool_use_id'] == tool_id
|
|
1109
|
+
return block['content']
|
|
1110
|
+
end
|
|
1111
|
+
# OpenAI format
|
|
1112
|
+
if msg[:role].to_s == 'tool' && msg[:tool_call_id] == tool_id
|
|
1113
|
+
return msg[:content]
|
|
1114
|
+
end
|
|
1115
|
+
end
|
|
1116
|
+
end
|
|
1117
|
+
nil
|
|
1118
|
+
end
|
|
1059
1119
|
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1120
|
+
def display_conversation
|
|
1121
|
+
if @history.empty?
|
|
1122
|
+
@interactive_old_stdout.puts "\e[2m (no conversation history yet)\e[0m"
|
|
1123
|
+
return
|
|
1124
|
+
end
|
|
1125
|
+
|
|
1126
|
+
@interactive_old_stdout.puts "\e[36m Conversation (#{@history.length} messages):\e[0m"
|
|
1127
|
+
@history.each_with_index do |msg, i|
|
|
1128
|
+
role = msg[:role].to_s
|
|
1129
|
+
content = msg[:content].to_s
|
|
1130
|
+
label = role == 'user' ? "\e[33m[user]\e[0m" : "\e[36m[assistant]\e[0m"
|
|
1131
|
+
@interactive_old_stdout.puts "#{label} #{content}"
|
|
1132
|
+
@interactive_old_stdout.puts if i < @history.length - 1
|
|
1133
|
+
end
|
|
1134
|
+
end
|
|
1064
1135
|
|
|
1065
|
-
|
|
1136
|
+
def display_help
|
|
1137
|
+
auto = ConsoleAgent.configuration.auto_execute ? 'ON' : 'OFF'
|
|
1138
|
+
@interactive_old_stdout.puts "\e[36m Commands:\e[0m"
|
|
1139
|
+
@interactive_old_stdout.puts "\e[2m /auto Toggle auto-execute (currently #{auto}) (Shift-Tab)\e[0m"
|
|
1140
|
+
@interactive_old_stdout.puts "\e[2m /think Switch to thinking model\e[0m"
|
|
1141
|
+
@interactive_old_stdout.puts "\e[2m /compact Summarize conversation to reduce context\e[0m"
|
|
1142
|
+
@interactive_old_stdout.puts "\e[2m /usage Show session token totals\e[0m"
|
|
1143
|
+
@interactive_old_stdout.puts "\e[2m /cost Show cost estimate by model\e[0m"
|
|
1144
|
+
@interactive_old_stdout.puts "\e[2m /name <lbl> Name this session for easy resume\e[0m"
|
|
1145
|
+
@interactive_old_stdout.puts "\e[2m /context Show conversation history sent to the LLM\e[0m"
|
|
1146
|
+
@interactive_old_stdout.puts "\e[2m /system Show the system prompt\e[0m"
|
|
1147
|
+
@interactive_old_stdout.puts "\e[2m /debug Toggle debug mode\e[0m"
|
|
1148
|
+
@interactive_old_stdout.puts "\e[2m > code Execute Ruby directly (skip LLM)\e[0m"
|
|
1149
|
+
@interactive_old_stdout.puts "\e[2m exit/quit Leave interactive mode\e[0m"
|
|
1066
1150
|
end
|
|
1067
1151
|
|
|
1068
1152
|
def display_exit_info
|
|
@@ -35,7 +35,7 @@ ConsoleAgent.configure do |config|
|
|
|
35
35
|
# config.connection_class = Sharding::CentralizedModel
|
|
36
36
|
|
|
37
37
|
# Admin UI credentials (mount ConsoleAgent::Engine => '/console_agent' in routes.rb)
|
|
38
|
-
# When nil,
|
|
38
|
+
# When nil, all requests are denied. Set credentials or use config.authenticate.
|
|
39
39
|
# config.admin_username = 'admin'
|
|
40
40
|
# config.admin_password = 'changeme'
|
|
41
41
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: console_agent
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Cortfr
|
|
@@ -86,6 +86,7 @@ executables: []
|
|
|
86
86
|
extensions: []
|
|
87
87
|
extra_rdoc_files: []
|
|
88
88
|
files:
|
|
89
|
+
- CHANGELOG.md
|
|
89
90
|
- LICENSE
|
|
90
91
|
- README.md
|
|
91
92
|
- app/controllers/console_agent/application_controller.rb
|