Class: Kward::RPC::SessionTreeRows
- Inherits:
-
Object
- Object
- Kward::RPC::SessionTreeRows
- Defined in:
- lib/kward/rpc/session_tree_rows.rb
Overview
Builds frontend-neutral RPC row payloads from a persisted session tree.
SessionManager owns session lifecycle and decides when a tree is needed;
this class owns only the mechanics of flattening tree nodes into the row
fields sent over JSON-RPC. Keeping row presentation here prevents the RPC
session coordinator from accumulating rendering details while preserving the
exact Tauren-compatible payload shape.
Instance Method Summary collapse
-
#initialize(roots:, current_leaf:, selectable:) ⇒ SessionTreeRows
constructor
A new instance of SessionTreeRows.
-
#rows ⇒ Array<Hash>
Returns flattened RPC row hashes in active-path-first display order.
Constructor Details
#initialize(roots:, current_leaf:, selectable:) ⇒ SessionTreeRows
Returns a new instance of SessionTreeRows.
21 22 23 24 25 |
# File 'lib/kward/rpc/session_tree_rows.rb', line 21 def initialize(roots:, current_leaf:, selectable:) @roots = roots @current_leaf = current_leaf @selectable = selectable end |
Instance Method Details
#rows ⇒ Array<Hash>
Returns flattened RPC row hashes in active-path-first display order.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/kward/rpc/session_tree_rows.rb', line 30 def rows active_path = tree_active_path(@roots, @current_leaf) tool_calls_by_id = tree_tool_calls(@roots) visible_roots = @roots.flat_map { |root| visible_tree_nodes(root) } multiple_roots = visible_roots.length > 1 result = [] walk = lambda do |node, indent, just_branched, show_connector, is_last, gutters, virtual_root_child| entry = node[:source]["entry"] || {} entry_id = entry["id"].to_s formatted = tree_entry_display(entry, tool_calls_by_id) display_indent = multiple_roots ? [indent - 1, 0].max : indent result << { entryId: entry_id, parentId: entry["parentId"], role: formatted[:role], text: formatted[:text], current: !@current_leaf.to_s.empty? && entry_id == @current_leaf.to_s, depth: display_indent, isLast: is_last, ancestorContinues: gutters.map { |gutter| gutter[:show] }, activePath: active_path.include?(entry_id), selectable: @selectable.call(entry), label: node[:source]["label"] || entry["resolvedLabel"], labelTimestamp: node[:source]["labelTimestamp"], prefix: tree_prefix(display_indent, gutters, show_connector && !virtual_root_child, is_last, !node[:children].empty?) }.compact children = node[:children].sort_by { |child| tree_contains_active_path?(child, active_path) ? 0 : 1 } multiple_children = children.length > 1 child_indent = if multiple_children indent + 1 elsif just_branched && indent.positive? indent + 1 else indent end connector_position = [display_indent - 1, 0].max child_gutters = show_connector && !virtual_root_child ? gutters + [{ position: connector_position, show: !is_last }] : gutters children.each_with_index do |child, index| walk.call(child, child_indent, multiple_children, multiple_children, index == children.length - 1, child_gutters, false) end end visible_roots.sort_by { |root| tree_contains_active_path?(root, active_path) ? 0 : 1 }.each_with_index do |root, index| walk.call(root, multiple_roots ? 1 : 0, multiple_roots, multiple_roots, index == visible_roots.length - 1, [], multiple_roots) end result end |