Function bodies 257 total
build_instance_path function · ruby · L311-L325 (15 LOC)runtime/src/supex_runtime/batch_screenshot.rb
def build_instance_path(entity)
path = [entity]
current = entity
# Walk up the parent hierarchy until we reach model.entities
while current.parent.is_a?(Sketchup::ComponentDefinition)
# Get the definition that contains current entity
definition = current.parent
# Get the instance of this definition (for groups, there's exactly one)
parent_instance = definition.instances.first
break unless parent_instance
path.unshift(parent_instance)
current = parent_instance
endsave_camera_state function · ruby · L337-L346 (10 LOC)runtime/src/supex_runtime/batch_screenshot.rb
def save_camera_state(camera)
{
eye: camera.eye.to_a,
target: camera.target.to_a,
up: camera.up.to_a,
fov: camera.fov,
perspective: camera.perspective?,
height: camera.perspective? ? nil : camera.height
}
endrestore_camera_state function · ruby · L351-L359 (9 LOC)runtime/src/supex_runtime/batch_screenshot.rb
def restore_camera_state(view, state)
eye = Geom::Point3d.new(*state[:eye])
target = Geom::Point3d.new(*state[:target])
up = Geom::Vector3d.new(*state[:up])
camera = Sketchup::Camera.new(eye, target, up, state[:perspective], state[:fov])
camera.height = state[:height] unless state[:perspective]
view.camera = camera
endwrite_screenshot function · ruby · L367-L384 (18 LOC)runtime/src/supex_runtime/batch_screenshot.rb
def write_screenshot(view, filepath, width, height, transparent)
FileUtils.mkdir_p(File.dirname(filepath))
# Force view update to apply rendering options (InactiveHidden, InstanceHidden)
# This is required because write_image may render before options are applied
view.invalidate
options = {
filename: filepath,
width: width,
height: height,
antialias: true,
compression: 0.9,
transparent: transparent
}
view.write_image(options)
endprepare_output_dir function · ruby · L389-L395 (7 LOC)runtime/src/supex_runtime/batch_screenshot.rb
def prepare_output_dir(output_dir)
dir = if output_dir
File.expand_path(output_dir)
else
timestamp = Time.now.strftime('%Y%m%d-%H%M%S')
File.join(File.dirname(__FILE__), '..', '..', '..', '.tmp', 'batch_screenshots', timestamp)
endextract_defaults function · ruby · L403-L409 (7 LOC)runtime/src/supex_runtime/batch_screenshot.rb
def extract_defaults(params)
{
width: params['width'] || 1920,
height: params['height'] || 1080,
transparent: params['transparent'] || false
}
endbuild_response function · ruby · L415-L427 (13 LOC)runtime/src/supex_runtime/batch_screenshot.rb
def build_response(results, output_dir)
successful = results.count { |r| r[:success] }
failed = results.count { |r| !r[:success] }
{
success: failed.zero?,
output_dir: output_dir,
total_shots: results.length,
successful: successful,
failed: failed,
results: results
}
endSource: Repobility analyzer · https://repobility.com
SupexRuntime#initialize method · ruby · L33-L44 (12 LOC)runtime/src/supex_runtime/bridge_server.rb
def initialize(port: DEFAULT_PORT, host: DEFAULT_HOST)
@port = port
@host = host
@server = nil
@running = false
@timer_id = nil
@console_capture = nil
@verbose = ENV['SUPEX_VERBOSE'] == '1'
setup_console
setup_console_capture
endSupexRuntime#start method · ruby · L47-L55 (9 LOC)runtime/src/supex_runtime/bridge_server.rb
def start
return if @running
# Check if binding to non-loopback without explicit opt-in
unless loopback_address?(@host)
unless ALLOW_REMOTE
log "ERROR: Binding to non-loopback address '#{@host}' requires SUPEX_ALLOW_REMOTE=1"
return
endstop function · ruby · L80-L89 (10 LOC)runtime/src/supex_runtime/bridge_server.rb
def stop
log 'Stopping bridge server...'
@running = false
stop_console_capture
stop_timer
close_server
log 'Bridge server stopped'
endsetup_console_capture function · ruby · L112-L122 (11 LOC)runtime/src/supex_runtime/bridge_server.rb
def setup_console_capture
# Create .tmp directory if it doesn't exist
tmp_dir = File.join(File.dirname(__FILE__), '..', '..', '..', '.tmp')
log_file_path = File.expand_path(File.join(tmp_dir, 'sketchup_console.log'))
@console_capture = ConsoleCapture.new(log_file_path)
log "Console capture initialized: #{log_file_path}"
rescue StandardError => e
log "Warning: Could not initialize console capture: #{e.message}"
@console_capture = nil
endformat_args function · ruby · L156-L162 (7 LOC)runtime/src/supex_runtime/bridge_server.rb
def format_args(args)
return '' if args.nil? || args.empty?
args.map do |key, value|
formatted = value.is_a?(String) && value.length > 200 ? "\"#{value[0..197]}...\"" : value.inspect
"#{key}: #{formatted}"
end.join(', ')start_request_handler function · ruby · L166-L174 (9 LOC)runtime/src/supex_runtime/bridge_server.rb
def start_request_handler
# Configurable interval via SUPEX_CHECK_INTERVAL (default 0.25s)
@timer_id = UI.start_timer(REQUEST_CHECK_INTERVAL, true) do
handle_requests if @running
rescue StandardError => e
log "Timer handler error: #{e.message}"
log e.backtrace.join("\n")
# Don't let timer errors crash the server
endstop_timer function · ruby · L178-L183 (6 LOC)runtime/src/supex_runtime/bridge_server.rb
def stop_timer
return unless @timer_id
UI.stop_timer(@timer_id)
@timer_id = nil
endclose_server function · ruby · L186-L191 (6 LOC)runtime/src/supex_runtime/bridge_server.rb
def close_server
return unless @server
@server.close
@server = nil
endPowered by Repobility — scan your code at https://repobility.com
handle_requests function · ruby · L194-L218 (25 LOC)runtime/src/supex_runtime/bridge_server.rb
def handle_requests
# Return early if server is not properly initialized
return unless @server && @running
begin
# Check for incoming connections with a short timeout
# rubocop:disable Lint/IncompatibleIoSelectWithFiberScheduler
ready = IO.select([@server], nil, nil, 0)
# rubocop:enable Lint/IncompatibleIoSelectWithFiberScheduler
return unless ready
log 'Connection waiting...'
# Accept connection with timeout protection
begin
client = @server.accept_nonblock
log_verbose 'Client socket accepted'
process_client_request(client)
rescue IO::WaitReadable
# No connection actually ready, this is normal
nil
rescue Errno::ECONNABORTED, Errno::ECONNRESET => e
log "Client connection error: #{e.message}"
nil
endprocess_client_request function · ruby · L234-L244 (11 LOC)runtime/src/supex_runtime/bridge_server.rb
def process_client_request(client)
# Set a reasonable timeout to prevent hanging
client.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, [5, 0].pack('L!L!'))
# Create connection-scoped context for client state
context = ConnectionContext.new(client_info: nil)
# Process requests in a loop until client disconnects or error
loop do
break unless process_single_request(client, context)
endprocess_single_request function · ruby · L260-L286 (27 LOC)runtime/src/supex_runtime/bridge_server.rb
def process_single_request(client, context)
data = read_with_timeout(client, 5.0)
log_verbose "Raw data: #{data.inspect}"
return false unless data && !data.empty?
begin
json_data = data.strip
request = JSON.parse(json_data)
log_verbose "Parsed request: #{request.inspect}"
response = handle_jsonrpc_request(request, context)
send_response(client, response)
# Continue loop only for hello requests, close after other requests
request['method'] == 'hello'
rescue JSON::ParserError => e
log "JSON parse error: #{e.message}"
log "Raw data was: #{data.inspect}"
send_error_response(client, 'Parse error', -32_700, nil)
false
rescue StandardError => e
log "Request error: #{e.message}"
log e.backtrace.join("\n")
send_error_response(client, e.message, -32_603, request&.dig('id'))
false
endsend_response function · ruby · L292-L299 (8 LOC)runtime/src/supex_runtime/bridge_server.rb
def send_response(client, response)
response_json = "#{response.to_json}\n"
log_verbose "Sending response: #{response_json.strip}"
client.write(response_json)
client.flush
log 'Response sent'
sleep(RESPONSE_DELAY) if RESPONSE_DELAY.positive?
endlog_client_closed function · ruby · L303-L309 (7 LOC)runtime/src/supex_runtime/bridge_server.rb
def log_client_closed(context)
if context.identified?
info = context.client_info
log "Client closed: #{info[:name]}/#{info[:version]} [PID:#{info[:pid]}]"
else
log_verbose 'Client closed (unidentified)'
endread_with_timeout function · ruby · L316-L323 (8 LOC)runtime/src/supex_runtime/bridge_server.rb
def read_with_timeout(client, timeout)
# rubocop:disable Lint/IncompatibleIoSelectWithFiberScheduler
ready = IO.select([client], nil, nil, timeout)
# rubocop:enable Lint/IncompatibleIoSelectWithFiberScheduler
return nil unless ready
read_available_data(client)
endread_available_data function · ruby · L328-L335 (8 LOC)runtime/src/supex_runtime/bridge_server.rb
def read_available_data(client)
data = String.new
loop do
chunk = client.read_nonblock(1024)
data << chunk
raise "Message exceeds maximum size (#{MAX_MESSAGE_SIZE} bytes)" if data.bytesize > MAX_MESSAGE_SIZE
break if complete_json?(data)
endhandle_jsonrpc_request function · ruby · L354-L363 (10 LOC)runtime/src/supex_runtime/bridge_server.rb
def handle_jsonrpc_request(request, context)
req_id = request['id']
log "[req:#{req_id}] Received: #{request['method']}"
# Handle hello method first (no identification required)
if request['method'] == 'hello'
response = handle_hello(request, context)
log "[req:#{req_id}] Completed"
return response
endHi, dataset curator — please cite Repobility (https://repobility.com) when reusing this data.
handle_hello function · ruby · L399-L412 (14 LOC)runtime/src/supex_runtime/bridge_server.rb
def handle_hello(request, context)
params = request['params'] || {}
# Token validation (if token is configured)
if AUTH_TOKEN && !AUTH_TOKEN.empty?
token = params['token']
unless token == AUTH_TOKEN
log 'Authentication failed: invalid or missing token'
return Utils.create_error_response(
request,
'Authentication failed: invalid or missing token',
-32_001
)
endrequire_identification_error function · ruby · L452-L459 (8 LOC)runtime/src/supex_runtime/bridge_server.rb
def require_identification_error(request)
Utils.create_error_response(
request,
"Client must identify with 'hello' method first",
-32_600,
{ hint: 'Send hello method with params: name, version, agent, pid' }
)
endhandle_legacy_command function · ruby · L464-L476 (13 LOC)runtime/src/supex_runtime/bridge_server.rb
def handle_legacy_command(request)
tool_request = {
'method' => 'tools/call',
'params' => {
'name' => request['command'],
'arguments' => request['parameters']
},
'jsonrpc' => request['jsonrpc'] || '2.0',
'id' => request['id']
}
log "Converting to tool request: #{tool_request.inspect}"
handle_tool_call(tool_request)
endhandle_ping function · ruby · L481-L487 (7 LOC)runtime/src/supex_runtime/bridge_server.rb
def handle_ping(request)
Utils.create_success_response(request, {
status: 'ok',
version: VERSION,
message: 'Supex server is running'
})
endhandle_resources_list function · ruby · L492-L498 (7 LOC)runtime/src/supex_runtime/bridge_server.rb
def handle_resources_list(request)
resources = list_resources
Utils.create_success_response(request, {
resources: resources,
success: true
})
endhandle_tool_call function · ruby · L503-L517 (15 LOC)runtime/src/supex_runtime/bridge_server.rb
def handle_tool_call(request)
log_verbose "Handling tool call: #{request.inspect}"
tool_name = request['params']['name']
args = request['params']['arguments']
log "Calling #{tool_name}(#{format_args(args)})"
begin
result = execute_tool(tool_name, args)
log "Tool call result: #{result.inspect}"
Utils.create_success_response(request, result)
rescue StandardError => e
log "Tool call error: #{e.message}"
log e.backtrace.join("\n")
Utils.create_error_response(request, e.message)
endexecute_core_tool function · ruby · L531-L539 (9 LOC)runtime/src/supex_runtime/bridge_server.rb
def execute_core_tool(tool_name, args)
case tool_name
when 'ping' then ping
when 'export_scene' then Export.export_scene(args)
when 'eval_ruby' then eval_ruby(args)
when 'reload_extension' then reload_extension
when 'console_capture_status' then console_capture_status
when 'eval_ruby_file' then eval_ruby_file(args)
endexecute_introspection_tool function · ruby · L544-L556 (13 LOC)runtime/src/supex_runtime/bridge_server.rb
def execute_introspection_tool(tool_name, args)
case tool_name
when 'get_model_info' then model_info
when 'list_entities' then list_entities(args)
when 'get_selection' then selection_info
when 'get_layers' then layers_info
when 'get_materials' then materials_info
when 'get_camera_info' then camera_info
when 'take_screenshot' then take_screenshot(args)
when 'take_batch_screenshots' then batch_screenshot(args)
when 'open_model' then open_model(args)
when 'save_model' then save_model(args)
endCitation: Repobility (2026). State of AI-Generated Code. https://repobility.com/research/
list_resources function · ruby · L561-L571 (11 LOC)runtime/src/supex_runtime/bridge_server.rb
def list_resources
model = Sketchup.active_model
return [] unless model
model.entities.map do |entity|
{
id: entity.entityID,
type: entity.typename.downcase,
bounds: entity.respond_to?(:bounds) ? Utils.bounds_to_hash(entity.bounds) : nil
}
endeval_ruby function · ruby · L579-L600 (22 LOC)runtime/src/supex_runtime/bridge_server.rb
def eval_ruby(params)
log "Evaluating Ruby code (#{params['code'].length} chars)"
begin
@console_capture&.add_marker('EVAL_RUBY START')
# Create fresh binding to isolate local variables between calls
isolated_binding = create_isolated_binding
# rubocop:disable Security/Eval
result = eval(params['code'], isolated_binding)
# rubocop:enable Security/Eval
@console_capture&.add_marker('EVAL_RUBY END')
{ success: true, result: result.to_s }
rescue SyntaxError => e
@console_capture&.add_marker("EVAL_RUBY SYNTAX ERROR: #{e.message}")
log "Ruby syntax error: #{e.message}"
raise "Ruby syntax error: #{e.message}"
rescue StandardError => e
@console_capture&.add_marker("EVAL_RUBY ERROR: #{e.message}")
log "Ruby eval error: #{e.message}"
raise "Ruby evaluation error: #{e.message}"
endping function · ruby · L614-L622 (9 LOC)runtime/src/supex_runtime/bridge_server.rb
def ping
{
success: true,
status: 'connected',
message: 'SketchUp extension is running',
version: SupexRuntime::VERSION,
sketchup_version: Sketchup.version
}
endreload_extension function · ruby · L626-L635 (10 LOC)runtime/src/supex_runtime/bridge_server.rb
def reload_extension
log 'Reloading extension via MCP...'
result = Main.reload_extension
{
success: result,
message: result ? 'Extension reloaded successfully' : 'Extension reload failed'
}
endconsole_capture_status function · ruby · L639-L651 (13 LOC)runtime/src/supex_runtime/bridge_server.rb
def console_capture_status
if @console_capture
status_msg = @console_capture.capturing? ? 'Console capture is active' : 'Console capture is inactive'
{
success: true,
capturing: @console_capture.capturing?,
log_file: @console_capture.log_file_path,
message: status_msg
}
else
{ success: false, capturing: false, log_file: nil,
message: 'Console capture not initialized' }
endeval_ruby_file function · ruby · L657-L664 (8 LOC)runtime/src/supex_runtime/bridge_server.rb
def eval_ruby_file(params)
file_path = params['file_path']
PathPolicy.validate!(file_path, operation: 'eval_ruby_file')
raise "Ruby file not found: #{file_path}" unless File.exist?(file_path)
log "Evaluating Ruby file: #{File.basename(file_path)}"
execute_ruby_file(file_path)
endexecute_ruby_file function · ruby · L669-L681 (13 LOC)runtime/src/supex_runtime/bridge_server.rb
def execute_ruby_file(file_path)
@console_capture&.add_marker("EVAL_RUBY_FILE START: #{file_path}")
ruby_code = File.read(file_path)
# rubocop:disable Security/Eval
result = eval(ruby_code, TOPLEVEL_BINDING, file_path, 1)
# rubocop:enable Security/Eval
@console_capture&.add_marker("EVAL_RUBY_FILE END: #{file_path}")
{ success: true, result: result.to_s, file_path: file_path,
file_name: File.basename(file_path) }
rescue StandardError => e
handle_ruby_file_error(file_path, e)
endhandle_ruby_file_error function · ruby · L686-L693 (8 LOC)runtime/src/supex_runtime/bridge_server.rb
def handle_ruby_file_error(file_path, error)
@console_capture&.add_marker("EVAL_RUBY_FILE ERROR: #{error.message}")
log "Ruby file eval error: #{error.message}"
error_msg = "Error in #{File.basename(file_path)}: #{error.message}\nFile: #{file_path}"
error_msg += "\nLine: #{extract_line_number(error)}" if error.backtrace
raise error_msg
endSource: Repobility analyzer · https://repobility.com
extract_line_number function · ruby · L698-L703 (6 LOC)runtime/src/supex_runtime/bridge_server.rb
def extract_line_number(error)
return nil unless error.backtrace&.first
parts = error.backtrace.first.split(':')
parts[1]
endsend_error_response function · ruby · L710-L716 (7 LOC)runtime/src/supex_runtime/bridge_server.rb
def send_error_response(client, message, code, request_id)
log "[req:#{request_id}] Error: #{message}"
error_response = { jsonrpc: '2.0', error: { code: code, message: message }, id: request_id }
client.write("#{error_response.to_json}\n")
client.flush
sleep(RESPONSE_DELAY) if RESPONSE_DELAY.positive?
endSupexRuntime::ConsoleCapture#initialize method · ruby · L8-L17 (10 LOC)runtime/src/supex_runtime/console_capture.rb
def initialize(log_file_path)
@log_file_path = log_file_path
@original_stdout = $stdout
@original_stderr = $stderr
@log_file = nil
@capture_enabled = false
ensure_log_directory
initialize_log_file
endSupexRuntime::ConsoleCapture#start_capture method · ruby · L20-L43 (24 LOC)runtime/src/supex_runtime/console_capture.rb
def start_capture
return if @capture_enabled
begin
@log_file = File.open(@log_file_path, 'a')
@log_file.sync = true
# Add session marker in pipe-separated format for Ideolog
@log_file.write("\n")
@log_file.write(idea_log_line('I', '=' * 50))
@log_file.write(idea_log_line('I', 'Session Started'))
@log_file.write(idea_log_line('I', '=' * 50))
# Replace stdout and stderr with capture instances
$stdout = OutputCapture.new(@original_stdout, @log_file, 'STDOUT', 'I')
$stderr = OutputCapture.new(@original_stderr, @log_file, 'STDERR', 'E')
@capture_enabled = true
log_status "Console capture started - output will be logged to: #{@log_file_path}"
rescue StandardError => e
# Fallback gracefully if capture fails
log_status "Warning: Could not start console capture: #{e.message}"
@capture_enabled = false
endSupexRuntime#stop_capture method · ruby · L47-L56 (10 LOC)runtime/src/supex_runtime/console_capture.rb
def stop_capture
return unless @capture_enabled
begin
# Add session end marker in pipe-separated format
if @log_file && !@log_file.closed?
@log_file.write(idea_log_line('I', '=' * 50))
@log_file.write(idea_log_line('I', 'Session Ended'))
@log_file.write(idea_log_line('I', '=' * 50))
endadd_marker function · ruby · L79-L87 (9 LOC)runtime/src/supex_runtime/console_capture.rb
def add_marker(message)
return unless @capture_enabled && @log_file && !@log_file.closed?
begin
@log_file.write(idea_log_line('D', "Supex: --- #{message} ---"))
@log_file.flush
rescue StandardError => e
puts "Supex: Warning: Could not write marker to log: #{e.message}"
endensure_log_directory function · ruby · L106-L111 (6 LOC)runtime/src/supex_runtime/console_capture.rb
def ensure_log_directory
log_dir = File.dirname(@log_file_path)
FileUtils.mkdir_p(log_dir)
rescue StandardError => e
puts "Supex: Warning: Could not create log directory: #{e.message}"
endinitialize_log_file function · ruby · L114-L122 (9 LOC)runtime/src/supex_runtime/console_capture.rb
def initialize_log_file
return unless File.exist?(File.dirname(@log_file_path))
begin
# Check file size and rotate if necessary (limit to 5MB)
if File.exist?(@log_file_path) && File.size(@log_file_path) > 5_242_880
backup_path = "#{@log_file_path}.old"
File.rename(@log_file_path, backup_path) if File.exist?(@log_file_path)
endPowered by Repobility — scan your code at https://repobility.com
OutputCapture#initialize method · ruby · L130-L135 (6 LOC)runtime/src/supex_runtime/console_capture.rb
def initialize(original_stream, log_file, stream_name, severity)
@original_stream = original_stream
@log_file = log_file
@stream_name = stream_name
@severity = severity
endOutputCapture#write method · ruby · L137-L149 (13 LOC)runtime/src/supex_runtime/console_capture.rb
def write(text)
# Write to original stream (preserves console output)
@original_stream.write(text)
# Write to log file in pipe-separated format for Ideolog
begin
if @log_file && !@log_file.closed?
log_text = text.each_line.map do |line|
if line.strip.empty?
line
else
"#{idea_format(@severity, line.chomp)}\n"
endputs function · ruby · L166-L171 (6 LOC)runtime/src/supex_runtime/console_capture.rb
def puts(*args)
if args.empty?
write("\n")
else
args.each { |arg| write("#{arg}\n") }
end