generative_ui 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +15 -0
- data/README.md +370 -0
- data/app/helpers/generative_ui/view_helper.rb +10 -0
- data/app/views/messages/tool_calls/_generate_ui.html.erb +6 -0
- data/app/views/messages/tool_results/_generate_ui.html.erb +1 -0
- data/generative_ui.gemspec +31 -0
- data/lib/generative_ui/attributes.rb +182 -0
- data/lib/generative_ui/catalog.rb +419 -0
- data/lib/generative_ui/component.rb +22 -0
- data/lib/generative_ui/component_definition.rb +73 -0
- data/lib/generative_ui/component_set.rb +37 -0
- data/lib/generative_ui/component_tree_validator.rb +176 -0
- data/lib/generative_ui/component_validator.rb +78 -0
- data/lib/generative_ui/conventions.rb +22 -0
- data/lib/generative_ui/engine.rb +27 -0
- data/lib/generative_ui/invalid_component_tree_error.rb +12 -0
- data/lib/generative_ui/renderer.rb +139 -0
- data/lib/generative_ui/renderers/json.rb +26 -0
- data/lib/generative_ui/renderers/partial.rb +24 -0
- data/lib/generative_ui/renderers/view_component.rb +27 -0
- data/lib/generative_ui/structural_ref.rb +13 -0
- data/lib/generative_ui/tool.rb +76 -0
- data/lib/generative_ui/version.rb +5 -0
- data/lib/generative_ui.rb +121 -0
- metadata +109 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support'
|
|
4
|
+
require 'active_support/concern'
|
|
5
|
+
require 'active_support/core_ext'
|
|
6
|
+
require 'ruby_llm/schema'
|
|
7
|
+
require 'json'
|
|
8
|
+
|
|
9
|
+
require_relative 'generative_ui/version'
|
|
10
|
+
require_relative 'generative_ui/structural_ref'
|
|
11
|
+
require_relative 'generative_ui/attributes'
|
|
12
|
+
require_relative 'generative_ui/component_definition'
|
|
13
|
+
require_relative 'generative_ui/component'
|
|
14
|
+
require_relative 'generative_ui/component_set'
|
|
15
|
+
require_relative 'generative_ui/component_validator'
|
|
16
|
+
require_relative 'generative_ui/component_tree_validator'
|
|
17
|
+
require_relative 'generative_ui/invalid_component_tree_error'
|
|
18
|
+
require_relative 'generative_ui/tool'
|
|
19
|
+
require_relative 'generative_ui/conventions'
|
|
20
|
+
require_relative 'generative_ui/catalog'
|
|
21
|
+
require_relative 'generative_ui/renderer'
|
|
22
|
+
require_relative 'generative_ui/renderers/partial'
|
|
23
|
+
require_relative 'generative_ui/renderers/view_component'
|
|
24
|
+
require_relative 'generative_ui/renderers/json'
|
|
25
|
+
require_relative 'generative_ui/engine' if defined?(::Rails::Engine)
|
|
26
|
+
|
|
27
|
+
module GenerativeUI
|
|
28
|
+
class Configuration
|
|
29
|
+
attr_accessor :default_renderer
|
|
30
|
+
attr_reader :renderers
|
|
31
|
+
|
|
32
|
+
def initialize
|
|
33
|
+
@renderers = {}
|
|
34
|
+
@catalogs = {}
|
|
35
|
+
@default_renderer = :partial
|
|
36
|
+
|
|
37
|
+
register_renderer(:partial) do |view_context|
|
|
38
|
+
GenerativeUI::Renderers::Partial.new(view_context: view_context)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
register_renderer(:view_component) do |view_context|
|
|
42
|
+
GenerativeUI::Renderers::ViewComponent.new(view_context: view_context)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
register_renderer(:json) do |_view_context|
|
|
46
|
+
GenerativeUI::Renderers::Json.new
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def register_renderer(name, &factory)
|
|
51
|
+
renderers[name.to_sym] = factory
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def catalog(name, catalog_class = nil)
|
|
55
|
+
if catalog_class.nil?
|
|
56
|
+
@catalogs[name.to_sym]
|
|
57
|
+
else
|
|
58
|
+
@catalogs[name.to_sym] = normalize_catalog_value(catalog_class)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def normalize_catalog_value(value)
|
|
65
|
+
value.is_a?(Class) && value.name ? value.name : value
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
class << self
|
|
70
|
+
def configure
|
|
71
|
+
yield configuration
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def configuration
|
|
75
|
+
@configuration ||= Configuration.new
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def reset_configuration!
|
|
79
|
+
@configuration = Configuration.new
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def renderer_for(view_context, renderer: nil, catalog: nil)
|
|
83
|
+
name = (renderer || configuration.default_renderer).to_sym
|
|
84
|
+
factory = configuration.renderers[name]
|
|
85
|
+
raise ArgumentError, "Unknown renderer: #{name}" unless factory
|
|
86
|
+
|
|
87
|
+
factory.call(view_context).tap do |renderer|
|
|
88
|
+
renderer.catalog = catalog if catalog && renderer.respond_to?(:catalog=)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def render(arguments, renderer:, catalog: :default, view_context: nil)
|
|
93
|
+
raise ArgumentError, 'arguments must be a Hash' unless arguments.is_a?(Hash)
|
|
94
|
+
|
|
95
|
+
unknown = arguments.keys.map(&:to_s) - %w[components]
|
|
96
|
+
raise InvalidComponentTreeError, { '_arguments' => ["unknown arguments: #{unknown.join(', ')}"] } if unknown.any?
|
|
97
|
+
|
|
98
|
+
components = arguments['components'] || arguments[:components]
|
|
99
|
+
raise InvalidComponentTreeError, { '_arguments' => ['components must be an array'] } unless components.is_a?(Array)
|
|
100
|
+
|
|
101
|
+
catalog = Catalog.coerce(catalog)
|
|
102
|
+
raise ArgumentError, 'generative UI catalog is empty' if catalog.empty?
|
|
103
|
+
|
|
104
|
+
set = ComponentSet.from_args(components)
|
|
105
|
+
validation = ComponentTreeValidator.call(set, catalog:)
|
|
106
|
+
raise InvalidComponentTreeError, validation.errors unless validation.valid?
|
|
107
|
+
|
|
108
|
+
resolve_renderer(renderer, view_context:, catalog:).call(set)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
private
|
|
112
|
+
|
|
113
|
+
def resolve_renderer(renderer, view_context:, catalog:)
|
|
114
|
+
if renderer.is_a?(Symbol)
|
|
115
|
+
renderer_for(view_context, renderer:, catalog:)
|
|
116
|
+
else
|
|
117
|
+
renderer.tap { |instance| instance.catalog = catalog if instance.respond_to?(:catalog=) }
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: generative_ui
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Andrey Samsonov
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: activesupport
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '7.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '7.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: ruby_llm
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '1.15'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.15'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: json_schemer
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '2.5'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '2.5'
|
|
54
|
+
description: Define a safe component catalog, expose it as a RubyLLM tool schema,
|
|
55
|
+
validate model-generated component trees, and render them with Rails partials, ViewComponent,
|
|
56
|
+
or JSON.
|
|
57
|
+
email:
|
|
58
|
+
- me@samsonov.io
|
|
59
|
+
executables: []
|
|
60
|
+
extensions: []
|
|
61
|
+
extra_rdoc_files: []
|
|
62
|
+
files:
|
|
63
|
+
- LICENSE.txt
|
|
64
|
+
- README.md
|
|
65
|
+
- app/helpers/generative_ui/view_helper.rb
|
|
66
|
+
- app/views/messages/tool_calls/_generate_ui.html.erb
|
|
67
|
+
- app/views/messages/tool_results/_generate_ui.html.erb
|
|
68
|
+
- generative_ui.gemspec
|
|
69
|
+
- lib/generative_ui.rb
|
|
70
|
+
- lib/generative_ui/attributes.rb
|
|
71
|
+
- lib/generative_ui/catalog.rb
|
|
72
|
+
- lib/generative_ui/component.rb
|
|
73
|
+
- lib/generative_ui/component_definition.rb
|
|
74
|
+
- lib/generative_ui/component_set.rb
|
|
75
|
+
- lib/generative_ui/component_tree_validator.rb
|
|
76
|
+
- lib/generative_ui/component_validator.rb
|
|
77
|
+
- lib/generative_ui/conventions.rb
|
|
78
|
+
- lib/generative_ui/engine.rb
|
|
79
|
+
- lib/generative_ui/invalid_component_tree_error.rb
|
|
80
|
+
- lib/generative_ui/renderer.rb
|
|
81
|
+
- lib/generative_ui/renderers/json.rb
|
|
82
|
+
- lib/generative_ui/renderers/partial.rb
|
|
83
|
+
- lib/generative_ui/renderers/view_component.rb
|
|
84
|
+
- lib/generative_ui/structural_ref.rb
|
|
85
|
+
- lib/generative_ui/tool.rb
|
|
86
|
+
- lib/generative_ui/version.rb
|
|
87
|
+
homepage: https://github.com/kryzhovnik/generative_ui
|
|
88
|
+
licenses:
|
|
89
|
+
- MIT
|
|
90
|
+
metadata:
|
|
91
|
+
source_code_uri: https://github.com/kryzhovnik/generative_ui
|
|
92
|
+
rdoc_options: []
|
|
93
|
+
require_paths:
|
|
94
|
+
- lib
|
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
96
|
+
requirements:
|
|
97
|
+
- - ">="
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: 3.2.0
|
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
|
+
requirements:
|
|
102
|
+
- - ">="
|
|
103
|
+
- !ruby/object:Gem::Version
|
|
104
|
+
version: '0'
|
|
105
|
+
requirements: []
|
|
106
|
+
rubygems_version: 3.6.9
|
|
107
|
+
specification_version: 4
|
|
108
|
+
summary: Catalog-driven generative UI for RubyLLM and Rails
|
|
109
|
+
test_files: []
|