Class: RosettAi::Desktop::DbusClient
- Inherits:
-
Object
- Object
- RosettAi::Desktop::DbusClient
- Defined in:
- lib/rosett_ai/desktop/dbus_client.rb
Overview
D-Bus client for communicating with be.neatnerds.rosettai service.
SAFETY: This client is designed to NEVER raise exceptions to callers. All methods return safe default values on failure. This is critical for GUI stability - a D-Bus failure should never crash the app.
All GTK4/Qt6 desktop apps use this client instead of calling Ruby Rosett-AI modules directly. This ensures the D-Bus service is the single source of truth.
Constant Summary collapse
- BUS_NAME =
Returns D-Bus well-known bus name.
'be.neatnerds.rosettai'- OBJECT_PATH =
Returns D-Bus object path.
'/be/neatnerds/rosett-ai'- MANAGER_IFACE =
Returns Manager iface constant.
'be.neatnerds.rosettai.Manager'- FOCUS_IFACE =
Returns Focus iface constant.
'be.neatnerds.rosettai.FocusMonitor'- SAFE_STATUS =
Default safe return values
{ 'error' => 'Service not available', 'version' => 'unknown' }.freeze
- SAFE_FOCUS =
Returns Safe focus constant.
['', ''].freeze
- SAFE_COMPILE_RESULT =
Returns Safe compile result constant.
'Error: D-Bus service not available'
Instance Attribute Summary collapse
-
#bus ⇒ Object
readonly
Returns the value of attribute bus.
-
#last_error ⇒ Object
readonly
Returns the value of attribute last_error.
Instance Method Summary collapse
-
#compile ⇒ String
Run compilation via D-Bus.
-
#connect ⇒ Boolean
Connect to the D-Bus session bus and get service proxy.
-
#connected? ⇒ Boolean
Check if connected to D-Bus service.
-
#current_focus ⇒ Array<String>
Get current focus from FocusMonitor interface.
-
#disconnect ⇒ Object
Disconnect from D-Bus.
-
#initialize ⇒ DbusClient
constructor
A new instance of DbusClient.
-
#list_engines ⇒ Array<Hash>
List available engines from D-Bus service.
-
#on_context_changed {|context_name| ... } ⇒ Boolean
Subscribe to ContextChanged signal.
-
#on_focus_changed {|app_id, title| ... } ⇒ Boolean
Subscribe to FocusChanged signal.
-
#service_available? ⇒ Boolean
Check if the D-Bus service is available.
-
#set_config(key, value) ⇒ Boolean
Update a configuration key via D-Bus.
-
#status ⇒ Hash
Get service status from Manager interface.
-
#switch_context(context_name) ⇒ Boolean
Switch AI context.
Constructor Details
#initialize ⇒ DbusClient
Returns a new instance of DbusClient.
39 40 41 42 43 44 |
# File 'lib/rosett_ai/desktop/dbus_client.rb', line 39 def initialize @bus = nil @object = nil @connected = false @last_error = nil end |
Instance Attribute Details
#bus ⇒ Object (readonly)
Returns the value of attribute bus.
37 38 39 |
# File 'lib/rosett_ai/desktop/dbus_client.rb', line 37 def bus @bus end |
#last_error ⇒ Object (readonly)
Returns the value of attribute last_error.
37 38 39 |
# File 'lib/rosett_ai/desktop/dbus_client.rb', line 37 def last_error @last_error end |
Instance Method Details
#compile ⇒ String
Run compilation via D-Bus. SAFETY: Never raises, returns error string on failure.
112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/rosett_ai/desktop/dbus_client.rb', line 112 def compile GuiLogger.dbus_call(:compile, interface: MANAGER_IFACE) return SAFE_COMPILE_RESULT unless safe_connect @object.default_iface = MANAGER_IFACE result = @object.Compile output = result.is_a?(Array) ? result.first : result.to_s GuiLogger.dbus_call(:compile, status: :success, result_length: output.length) output rescue StandardError => e log_error('Compile failed', e) "Error: #{e.}" end |
#connect ⇒ Boolean
Connect to the D-Bus session bus and get service proxy.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/rosett_ai/desktop/dbus_client.rb', line 49 def connect return true if @connected GuiLogger.dbus_call(:connect, bus_name: BUS_NAME) @last_error = nil @bus = ::DBus::SessionBus.instance service = @bus.service(BUS_NAME) @object = service.object(OBJECT_PATH) @object.introspect @connected = true GuiLogger.dbus_call(:connect, status: :success) true rescue ::DBus::Error => e @last_error = e. log_error('D-Bus connection failed', e) @connected = false false rescue StandardError => e @last_error = e. log_error('Unexpected error during D-Bus connection', e) @connected = false false end |
#connected? ⇒ Boolean
Check if connected to D-Bus service.
76 77 78 |
# File 'lib/rosett_ai/desktop/dbus_client.rb', line 76 def connected? @connected end |
#current_focus ⇒ Array<String>
Get current focus from FocusMonitor interface. SAFETY: Never raises, returns empty array on failure.
146 147 148 149 150 151 152 153 154 155 |
# File 'lib/rosett_ai/desktop/dbus_client.rb', line 146 def current_focus return SAFE_FOCUS.dup unless safe_connect @object.default_iface = FOCUS_IFACE result = @object.GetCurrentFocus result.is_a?(Array) && result.size >= 2 ? result : SAFE_FOCUS.dup rescue StandardError => e log_error('GetCurrentFocus failed', e) SAFE_FOCUS.dup end |
#disconnect ⇒ Object
Disconnect from D-Bus. SAFETY: Never raises.
227 228 229 230 231 232 233 234 |
# File 'lib/rosett_ai/desktop/dbus_client.rb', line 227 def disconnect @connected = false @object = nil @bus = nil @last_error = nil rescue StandardError => e log_error('Disconnect failed', e) end |
#list_engines ⇒ Array<Hash>
List available engines from D-Bus service. SAFETY: Never raises, returns empty array on failure.
195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/rosett_ai/desktop/dbus_client.rb', line 195 def list_engines return [] unless safe_connect @object.default_iface = MANAGER_IFACE result = @object.ListEngines tuples = result.is_a?(Array) ? result.first : [] (tuples || []).map { |name, display| { name: name, display_name: display } } rescue StandardError => e log_error('ListEngines failed', e) [] end |
#on_context_changed {|context_name| ... } ⇒ Boolean
Subscribe to ContextChanged signal. SAFETY: Never raises, silently fails if service unavailable.
179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/rosett_ai/desktop/dbus_client.rb', line 179 def on_context_changed(&block) return false unless safe_connect return false unless block @object.default_iface = MANAGER_IFACE @object.on_signal('ContextChanged', &block) true rescue StandardError => e log_error('ContextChanged subscription failed', e) false end |
#on_focus_changed {|app_id, title| ... } ⇒ Boolean
Subscribe to FocusChanged signal. SAFETY: Never raises, silently fails if service unavailable.
162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/rosett_ai/desktop/dbus_client.rb', line 162 def on_focus_changed(&block) return false unless safe_connect return false unless block @object.default_iface = FOCUS_IFACE @object.on_signal('FocusChanged', &block) true rescue StandardError => e log_error('FocusChanged subscription failed', e) false end |
#service_available? ⇒ Boolean
Check if the D-Bus service is available. SAFETY: Never raises, returns false on any error.
84 85 86 87 88 89 90 91 |
# File 'lib/rosett_ai/desktop/dbus_client.rb', line 84 def service_available? return false unless connect @bus.service(BUS_NAME).exists? rescue StandardError => e log_error('Service availability check failed', e) false end |
#set_config(key, value) ⇒ Boolean
Update a configuration key via D-Bus. SAFETY: Never raises, returns false on failure.
213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/rosett_ai/desktop/dbus_client.rb', line 213 def set_config(key, value) return false unless safe_connect @object.default_iface = MANAGER_IFACE result = @object.SetConfig(key, value.to_s) output = result.is_a?(Array) ? result.first : result.to_s !output.start_with?('Error:') rescue StandardError => e log_error('SetConfig failed', e) false end |
#status ⇒ Hash
Get service status from Manager interface. SAFETY: Never raises, returns safe default hash on error.
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/rosett_ai/desktop/dbus_client.rb', line 97 def status return SAFE_STATUS.dup unless safe_connect @object.default_iface = MANAGER_IFACE result = @object.GetStatus result.is_a?(Array) ? result.first : SAFE_STATUS.dup rescue StandardError => e log_error('GetStatus failed', e) SAFE_STATUS.merge('error' => e.) end |
#switch_context(context_name) ⇒ Boolean
Switch AI context. SAFETY: Never raises, returns false on failure.
131 132 133 134 135 136 137 138 139 140 |
# File 'lib/rosett_ai/desktop/dbus_client.rb', line 131 def switch_context(context_name) return false unless safe_connect @object.default_iface = MANAGER_IFACE @object.SwitchContext(context_name) true rescue StandardError => e log_error('SwitchContext failed', e) false end |