Class: Clacky::JsonUIController
- Inherits:
-
Object
- Object
- Clacky::JsonUIController
- Includes:
- UIInterface
- Defined in:
- lib/clacky/json_ui_controller.rb
Overview
JsonUIController implements UIInterface for JSON (NDJSON) output mode. All output is written as one-JSON-per-line to stdout. Confirmation requests read responses from stdin.
Instance Method Summary collapse
-
#append_output(content) ⇒ Object
append_output is a no-op in JSON mode (content is already emitted via semantic methods).
-
#clear_input ⇒ Object
Input control (no-ops in JSON mode) ===.
- #clear_progress ⇒ Object
-
#emit(type, **data) ⇒ Object
Emit a raw NDJSON event.
-
#initialize(output: $stdout, input: $stdin) ⇒ JsonUIController
constructor
A new instance of JsonUIController.
- #log(message, level: :info) ⇒ Object
-
#request_confirmation(message, default: true) ⇒ Object
Blocking interaction ===.
- #set_idle_status ⇒ Object
- #set_input_tips(message, type: :info) ⇒ Object
- #set_working_status ⇒ Object
-
#show_assistant_message(content, files:) ⇒ Object
Output display ===.
- #show_complete(iterations:, cost:, duration: nil, cache_stats: nil, awaiting_user_feedback: false) ⇒ Object
- #show_diff(old_content, new_content, max_lines: 50) ⇒ Object
- #show_error(message) ⇒ Object
- #show_file_edit_preview(path) ⇒ Object
- #show_file_error(error_message) ⇒ Object
- #show_file_write_preview(path, is_new_file:) ⇒ Object
- #show_idle_status(phase:, message:) ⇒ Object
-
#show_info(message, prefix_newline: true) ⇒ Object
Status messages ===.
-
#show_progress(message = nil, prefix_newline: true, output_buffer: nil) ⇒ Object
Progress ===.
- #show_shell_preview(command) ⇒ Object
- #show_success(message) ⇒ Object
- #show_token_usage(token_data) ⇒ Object
- #show_tool_args(formatted_args) ⇒ Object
- #show_tool_call(name, args) ⇒ Object
- #show_tool_error(error) ⇒ Object
- #show_tool_result(result) ⇒ Object
- #show_warning(message) ⇒ Object
-
#stop ⇒ Object
Lifecycle ===.
-
#update_sessionbar(tasks: nil, cost: nil, status: nil) ⇒ Object
State updates ===.
- #update_todos(todos) ⇒ Object
Methods included from UIInterface
Constructor Details
#initialize(output: $stdout, input: $stdin) ⇒ JsonUIController
Returns a new instance of JsonUIController.
14 15 16 17 18 |
# File 'lib/clacky/json_ui_controller.rb', line 14 def initialize(output: $stdout, input: $stdin) @output = output @input = input @mutex = Mutex.new end |
Instance Method Details
#append_output(content) ⇒ Object
append_output is a no-op in JSON mode (content is already emitted via semantic methods)
90 91 92 |
# File 'lib/clacky/json_ui_controller.rb', line 90 def append_output(content) # no-op end |
#clear_input ⇒ Object
Input control (no-ops in JSON mode) ===
183 184 185 |
# File 'lib/clacky/json_ui_controller.rb', line 183 def clear_input # no-op end |
#clear_progress ⇒ Object
127 128 129 130 131 |
# File 'lib/clacky/json_ui_controller.rb', line 127 def clear_progress elapsed = @progress_start_time ? (Time.now - @progress_start_time).round(1) : 0 @progress_start_time = nil emit("progress", status: "stop", elapsed: elapsed) end |
#emit(type, **data) ⇒ Object
Emit a raw NDJSON event
21 22 23 24 25 26 27 |
# File 'lib/clacky/json_ui_controller.rb', line 21 def emit(type, **data) event = { type: type }.merge(data) @mutex.synchronize do @output.puts(JSON.generate(event)) @output.flush end end |
#log(message, level: :info) ⇒ Object
116 117 118 |
# File 'lib/clacky/json_ui_controller.rb', line 116 def log(, level: :info) emit("log", level: level.to_s, message: ) end |
#request_confirmation(message, default: true) ⇒ Object
Blocking interaction ===
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/clacky/json_ui_controller.rb', line 157 def request_confirmation(, default: true) conf_id = "conf_#{SecureRandom.hex(4)}" emit("request_confirmation", id: conf_id, message: , default: default) # Read response from stdin (blocking) line = @input.gets return default if line.nil? begin response = JSON.parse(line.strip) result = response["result"] || response[:result] case result.to_s.downcase when "yes", "y" then true when "no", "n" then false else # Return as feedback text result.to_s end rescue JSON::ParserError default end end |
#set_idle_status ⇒ Object
151 152 153 |
# File 'lib/clacky/json_ui_controller.rb', line 151 def set_idle_status emit("session_update", status: "idle") end |
#set_input_tips(message, type: :info) ⇒ Object
187 188 189 |
# File 'lib/clacky/json_ui_controller.rb', line 187 def set_input_tips(, type: :info) # no-op end |
#set_working_status ⇒ Object
147 148 149 |
# File 'lib/clacky/json_ui_controller.rb', line 147 def set_working_status emit("session_update", status: "working") end |
#show_assistant_message(content, files:) ⇒ Object
Output display ===
31 32 33 34 35 36 37 |
# File 'lib/clacky/json_ui_controller.rb', line 31 def (content, files:) return if (content.nil? || content.strip.empty?) && files.empty? data = { content: content.to_s } data[:files] = files if files.any? emit("assistant_message", **data) end |
#show_complete(iterations:, cost:, duration: nil, cache_stats: nil, awaiting_user_feedback: false) ⇒ Object
81 82 83 84 85 86 87 |
# File 'lib/clacky/json_ui_controller.rb', line 81 def show_complete(iterations:, cost:, duration: nil, cache_stats: nil, awaiting_user_feedback: false) data = { iterations: iterations, cost: cost } data[:duration] = duration if duration data[:cache_stats] = cache_stats if cache_stats data[:awaiting_user_feedback] = awaiting_user_feedback if awaiting_user_feedback emit("complete", **data) end |
#show_diff(old_content, new_content, max_lines: 50) ⇒ Object
73 74 75 |
# File 'lib/clacky/json_ui_controller.rb', line 73 def show_diff(old_content, new_content, max_lines: 50) emit("diff", old_size: old_content.bytesize, new_size: new_content.bytesize) end |
#show_error(message) ⇒ Object
108 109 110 |
# File 'lib/clacky/json_ui_controller.rb', line 108 def show_error() emit("error", message: ) end |
#show_file_edit_preview(path) ⇒ Object
61 62 63 |
# File 'lib/clacky/json_ui_controller.rb', line 61 def show_file_edit_preview(path) emit("file_preview", path: path, operation: "edit") end |
#show_file_error(error_message) ⇒ Object
65 66 67 |
# File 'lib/clacky/json_ui_controller.rb', line 65 def show_file_error() emit("file_error", error: ) end |
#show_file_write_preview(path, is_new_file:) ⇒ Object
57 58 59 |
# File 'lib/clacky/json_ui_controller.rb', line 57 def show_file_write_preview(path, is_new_file:) emit("file_preview", path: path, operation: "write", is_new_file: is_new_file) end |
#show_idle_status(phase:, message:) ⇒ Object
100 101 102 |
# File 'lib/clacky/json_ui_controller.rb', line 100 def show_idle_status(phase:, message:) emit("idle_status", phase: phase.to_s, message: ) end |
#show_info(message, prefix_newline: true) ⇒ Object
Status messages ===
96 97 98 |
# File 'lib/clacky/json_ui_controller.rb', line 96 def show_info(, prefix_newline: true) emit("info", message: ) end |
#show_progress(message = nil, prefix_newline: true, output_buffer: nil) ⇒ Object
Progress ===
122 123 124 125 |
# File 'lib/clacky/json_ui_controller.rb', line 122 def show_progress( = nil, prefix_newline: true, output_buffer: nil) @progress_start_time = Time.now emit("progress", message: , status: "start") end |
#show_shell_preview(command) ⇒ Object
69 70 71 |
# File 'lib/clacky/json_ui_controller.rb', line 69 def show_shell_preview(command) emit("shell_preview", command: command) end |
#show_success(message) ⇒ Object
112 113 114 |
# File 'lib/clacky/json_ui_controller.rb', line 112 def show_success() emit("success", message: ) end |
#show_token_usage(token_data) ⇒ Object
77 78 79 |
# File 'lib/clacky/json_ui_controller.rb', line 77 def show_token_usage(token_data) emit("token_usage", **token_data) end |
#show_tool_args(formatted_args) ⇒ Object
53 54 55 |
# File 'lib/clacky/json_ui_controller.rb', line 53 def show_tool_args(formatted_args) emit("tool_args", args: formatted_args) end |
#show_tool_call(name, args) ⇒ Object
39 40 41 42 |
# File 'lib/clacky/json_ui_controller.rb', line 39 def show_tool_call(name, args) args_data = args.is_a?(String) ? (JSON.parse(args) rescue args) : args emit("tool_call", name: name, args: args_data) end |
#show_tool_error(error) ⇒ Object
48 49 50 51 |
# File 'lib/clacky/json_ui_controller.rb', line 48 def show_tool_error(error) error_msg = error.is_a?(Exception) ? error. : error.to_s emit("tool_error", error: error_msg) end |
#show_tool_result(result) ⇒ Object
44 45 46 |
# File 'lib/clacky/json_ui_controller.rb', line 44 def show_tool_result(result) emit("tool_result", result: result) end |
#show_warning(message) ⇒ Object
104 105 106 |
# File 'lib/clacky/json_ui_controller.rb', line 104 def show_warning() emit("warning", message: ) end |
#stop ⇒ Object
Lifecycle ===
193 194 195 |
# File 'lib/clacky/json_ui_controller.rb', line 193 def stop # no-op end |
#update_sessionbar(tasks: nil, cost: nil, status: nil) ⇒ Object
State updates ===
135 136 137 138 139 140 141 |
# File 'lib/clacky/json_ui_controller.rb', line 135 def (tasks: nil, cost: nil, status: nil) data = {} data[:tasks] = tasks if tasks data[:cost] = cost if cost data[:status] = status if status emit("session_update", **data) unless data.empty? end |
#update_todos(todos) ⇒ Object
143 144 145 |
# File 'lib/clacky/json_ui_controller.rb', line 143 def update_todos(todos) emit("todo_update", todos: todos) end |