Module: RobotLab::Web
- Defined in:
- lib/robot_lab/web.rb,
lib/robot_lab/web/app.rb,
lib/robot_lab/web/event.rb,
lib/robot_lab/web/version.rb,
lib/robot_lab/web/registry.rb,
lib/robot_lab/web/event_sink.rb,
lib/robot_lab/web/stream_hook.rb,
lib/robot_lab/web/activity_log.rb,
lib/robot_lab/web/components/chat.rb,
lib/robot_lab/web/components/layout.rb,
lib/robot_lab/web/components/message.rb,
lib/robot_lab/web/components/dashboard.rb,
lib/robot_lab/web/components/error_page.rb,
sig/robot_lab/web.rbs
Overview
Browser front end for a robot_lab project: stream a robot's run to a web page over Server-Sent Events (an on_event -> SSE bridge, an immutable Event value object, an in-memory ActivityLog, and a hardened dev-tool security posture).
Defined Under Namespace
Modules: Components, EventSink, Registry Classes: ActivityLog, App, Error, Event, StreamHook
Constant Summary collapse
- VERSION =
"0.2.6"
Class Method Summary collapse
-
.app ⇒ Object
Boot the Sinatra app.
-
.register(robot, name: nil) ⇒ Object
Register a robot the web UI can drive.
-
.run(robot, message, sink = nil, &block) ⇒ Object
Run
robotagainstmessage, delivering each lifecycle Event tosink(a callable taking an Event) as it happens, and returning the robot's RobotResult.
Class Method Details
.app ⇒ Object
72 73 74 75 |
# File 'lib/robot_lab/web.rb', line 72 def app require_relative 'web/app' App end |
.register(robot, name: nil) ⇒ Object
35 36 37 |
# File 'lib/robot_lab/web.rb', line 35 def register(robot, name: nil) Registry.register(robot, name: name) end |
.run(robot, message, sink = nil, &block) ⇒ Object
Run robot against message, delivering each lifecycle Event to sink
(a callable taking an Event) as it happens, and returning the robot's
RobotResult. This is the one call the web routes wrap; it is also the
cleanest way to consume the stream from plain Ruby or a test.
Two layers of events arrive at the sink:
* StreamHook turns robot_lab hook moments into :user / :tool_call /
:tool_result / :robot / :error events.
* the streaming block below turns each RubyLLM content chunk into a
:delta event, so the reply can be rendered token by token. (A model or
run that doesn't stream simply produces no deltas — the final :robot
event still carries the whole reply.)
events = []
RobotLab::Web.run(robot, "hello") { |event| events << event }
54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/robot_lab/web.rb', line 54 def run(robot, , sink = nil, &block) sink ||= block name = robot.respond_to?(:name) ? robot.name : nil EventSink.capture(sink) do robot.run(, hooks: [StreamHook]) do |chunk| delta = chunk.respond_to?(:content) ? chunk.content : chunk.to_s next if delta.nil? || delta.empty? # Emit straight to the sink — deltas bypass the ActivityLog so token # spam never floods the dashboard's recent-activity feed. EventSink.emit(Event.new(role: :delta, content: delta, robot_name: name)) end end end |