Class: Kward::PluginRegistry
- Inherits:
-
Object
- Object
- Kward::PluginRegistry
show all
- Defined in:
- lib/kward/plugins/registry.rb
Overview
Loads trusted user plugin files and provides the plugin DSL.
Plugins live in the user plugin directory, run as local Ruby code, and can
register slash commands, namespaced actions, model-callable tools, lifecycle
callbacks, composable status renderers, prompt context, and live
transcript-event observers for CLI and RPC frontends.
This registry is intentionally trust-based, not a sandbox. Keep plugin loading
restricted to ConfigFiles.plugin_paths, keep workspace-local code out of the
load path, and expose immutable transcript views so plugins can observe state
without corrupting active conversations.
Defined Under Namespace
Classes: Context, DSL, HookHandler, InteractiveCommand, LifecycleHandler, Status, StatusSegment, TabType, Tool, Transcript, TranscriptEvent, TransportType
Constant Summary
collapse
- PLUGIN_API_VERSION =
"1"
- COMMAND_NAME_PATTERN =
/\A[A-Za-z0-9][A-Za-z0-9_-]*\z/.freeze
- Command =
Public registration types retained under the registry namespace.
PluginCommand
- Action =
PluginAction
- STATUS_PRIORITIES =
{ low: 0, normal: 1, high: 2 }.freeze
- STATUS_SEPARATOR =
" · "
Class Attribute Summary collapse
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
-
#action_for(id) ⇒ Object
-
#actions ⇒ Object
-
#command_for(name) ⇒ Object
-
#commands ⇒ Object
-
#compose_status(segments, max_width: nil, &measure) ⇒ Object
Composes already-rendered segments.
-
#emit_warning(message) ⇒ Object
-
#evaluate(path: nil, id: nil, version: nil, api: nil, &block) ⇒ Object
-
#footer_renderer ⇒ Object
Backward-compatible aggregate footer renderer.
-
#hook_handlers ⇒ Object
-
#hook_manager ⇒ Object
-
#initialize(reserved_commands: [], warning_sink: nil) ⇒ PluginRegistry
constructor
Creates an object for trusted plugin loading and dispatch.
-
#interactive_command_for(name) ⇒ Object
-
#interactive_commands ⇒ Object
-
#load_file(path) ⇒ Object
-
#notify_transcript_event(event, context) ⇒ Object
-
#plugin_for(id) ⇒ Object
-
#plugins ⇒ Array<PluginHost>
Identified plugins loaded by this registry.
-
#prompt_context(context) ⇒ Object
-
#prompt_context_renderers ⇒ Object
-
#register_action(name, plugin_id:, description:, schema:, path: nil, &handler) ⇒ Object
-
#register_command(name, description: "", argument_hint: "", schema: nil, positionals: [], plugin_id: nil, path: nil, &handler) ⇒ Object
-
#register_footer(plugin_id: nil, path: nil, &renderer) ⇒ Object
-
#register_hook(event, id: nil, description: "", order: 100, match: nil, failure_policy: nil, path: nil, &handler) ⇒ Object
-
#register_interactive_command(name, rows:, fps: 30, description: "", argument_hint: "", path: nil, &handler) ⇒ Object
-
#register_lifecycle(event, host:, path: nil, &handler) ⇒ Object
-
#register_plugin_identity(id:, version:, api:, path: nil) ⇒ Object
-
#register_prompt_context(path: nil, &renderer) ⇒ Object
-
#register_status(name, plugin_id:, order: 100, priority: :normal, path: nil, &renderer) ⇒ Object
-
#register_tab_type(name, id:, title: nil, singleton: nil, rpc: false, transport: false, local: true, transcript_events: false, api: nil, capabilities: nil, plugin_id: nil, path: nil, &handler) ⇒ Object
-
#register_tool(name, description:, schema:, path: nil, &handler) ⇒ Object
-
#register_transcript_event(path: nil, &handler) ⇒ Object
-
#register_transport(name, id:, capabilities: nil, execution_profile: nil, path: nil, &handler) ⇒ Object
-
#reload!(timeout: PluginResources::DEFAULT_SHUTDOWN_TIMEOUT) ⇒ Object
Invokes reload callbacks on the old registry and cleans up all resources.
-
#shutdown!(timeout: PluginResources::DEFAULT_SHUTDOWN_TIMEOUT) ⇒ Object
Invokes shutdown callbacks and cleans up all resources.
-
#start! ⇒ Object
Activates identified plugins and invokes their start callbacks once.
-
#status? ⇒ Boolean
-
#status_segments(context) ⇒ Object
Evaluates every status renderer independently and returns display-ordered frontend-neutral segments.
-
#tab_type_for(name) ⇒ Object
-
#tab_type_for_id(id) ⇒ Object
-
#tab_types ⇒ Object
-
#tool_for(name) ⇒ Object
-
#tools ⇒ Object
-
#transcript_event_handlers ⇒ Object
-
#transport_for(name) ⇒ Object
-
#transport_for_id(id) ⇒ Object
-
#transport_tab_types ⇒ Object
-
#transports ⇒ Object
Constructor Details
#initialize(reserved_commands: [], warning_sink: nil) ⇒ PluginRegistry
Creates an object for trusted plugin loading and dispatch.
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
|
# File 'lib/kward/plugins/registry.rb', line 531
def initialize(reserved_commands: [], warning_sink: nil)
@reserved_commands = reserved_commands.map(&:to_s)
@warning_sink = warning_sink
@plugins = {}
@commands = {}
@actions = {}
@tools = {}
@interactive_commands = {}
@tab_types = {}
@tab_types_by_id = {}
@transports = {}
@transports_by_id = {}
@statuses = {}
@status_sequence = 0
@footer_path = nil
@transcript_event_handlers = []
@prompt_context_renderers = []
@hook_handlers = []
@lifecycle_handlers = { start: [], reload: [], shutdown: [] }
@lifecycle_state = :loaded
@lifecycle_mutex = Mutex.new
@paths = []
end
|
Class Attribute Details
.loading_path ⇒ Object
Returns the value of attribute loading_path.
519
520
521
|
# File 'lib/kward/plugins/registry.rb', line 519
def loading_path
@loading_path
end
|
.loading_registry ⇒ Object
Returns the value of attribute loading_registry.
519
520
521
|
# File 'lib/kward/plugins/registry.rb', line 519
def loading_registry
@loading_registry
end
|
Instance Attribute Details
Returns most recent plugin file to register legacy footer output.
556
557
558
|
# File 'lib/kward/plugins/registry.rb', line 556
def
@footer_path
end
|
#paths ⇒ Array<String>
Returns plugin files successfully loaded by this registry.
559
560
561
|
# File 'lib/kward/plugins/registry.rb', line 559
def paths
@paths
end
|
Class Method Details
.load(paths: nil, reserved_commands: [], warning_sink: nil) ⇒ Object
521
522
523
524
525
526
527
|
# File 'lib/kward/plugins/registry.rb', line 521
def load(paths: nil, reserved_commands: [], warning_sink: nil)
warning_sink ||= ConfigFiles.warning_sink
paths ||= ConfigFiles.plugin_paths(warning_sink: warning_sink)
registry = new(reserved_commands: reserved_commands, warning_sink: warning_sink)
paths.each { |path| registry.load_file(path) }
registry
end
|
Instance Method Details
#action_for(id) ⇒ Object
582
583
584
|
# File 'lib/kward/plugins/registry.rb', line 582
def action_for(id)
@actions[id.to_s]
end
|
#actions ⇒ Object
578
579
580
|
# File 'lib/kward/plugins/registry.rb', line 578
def actions
@actions.values
end
|
#command_for(name) ⇒ Object
574
575
576
|
# File 'lib/kward/plugins/registry.rb', line 574
def command_for(name)
@commands[name.to_s]
end
|
#commands ⇒ Object
570
571
572
|
# File 'lib/kward/plugins/registry.rb', line 570
def commands
@commands.values
end
|
#compose_status(segments, max_width: nil, &measure) ⇒ Object
Composes already-rendered segments. When max_width is supplied, complete
low-priority segments are removed first; the caller remains responsible
for truncating a final oversized segment according to frontend rules.
657
658
659
660
661
662
663
664
665
666
667
|
# File 'lib/kward/plugins/registry.rb', line 657
def compose_status(segments, max_width: nil, &measure)
visible = Array(segments).dup
return "" if visible.empty? || (!max_width.nil? && max_width.to_i <= 0)
measure ||= ->(text) { text.to_s.length }
width = max_width&.to_i
while width && visible.length > 1 && measure.call(status_text(visible)) > width
remove_lowest_priority_segment!(visible)
end
status_text(visible)
end
|
#emit_warning(message) ⇒ Object
960
961
962
|
# File 'lib/kward/plugins/registry.rb', line 960
def emit_warning(message)
@warning_sink ? @warning_sink.call(message) : warn(message)
end
|
#evaluate(path: nil, id: nil, version: nil, api: nil, &block) ⇒ Object
747
748
749
750
751
752
|
# File 'lib/kward/plugins/registry.rb', line 747
def evaluate(path: nil, id: nil, version: nil, api: nil, &block)
host = register_plugin_identity(id: id, version: version, api: api, path: path)
dsl = DSL.new(self, path, host: host)
block.arity == 1 ? block.call(dsl) : dsl.instance_eval(&block)
self
end
|
Backward-compatible aggregate footer renderer.
635
636
637
638
639
640
641
|
# File 'lib/kward/plugins/registry.rb', line 635
def
return nil unless status?
lambda do |context|
compose_status(status_segments(context))
end
end
|
#hook_handlers ⇒ Object
677
678
679
|
# File 'lib/kward/plugins/registry.rb', line 677
def hook_handlers
@hook_handlers.dup
end
|
#hook_manager ⇒ Object
700
701
702
703
704
705
706
707
708
|
# File 'lib/kward/plugins/registry.rb', line 700
def hook_manager
manager = Hooks::Manager.new
@hook_handlers.each do |hook|
manager.register(hook.event, id: hook.id, source: hook.path, order: hook.order, match: hook.match, failure_policy: hook.failure_policy) do |event, context|
hook.handler.call(event, context)
end
end
manager
end
|
#interactive_command_for(name) ⇒ Object
598
599
600
|
# File 'lib/kward/plugins/registry.rb', line 598
def interactive_command_for(name)
@interactive_commands[name.to_s]
end
|
#interactive_commands ⇒ Object
594
595
596
|
# File 'lib/kward/plugins/registry.rb', line 594
def interactive_commands
@interactive_commands.values
end
|
#load_file(path) ⇒ Object
733
734
735
736
737
738
739
740
741
742
743
744
745
|
# File 'lib/kward/plugins/registry.rb', line 733
def load_file(path)
previous_registry = self.class.loading_registry
previous_path = self.class.loading_path
self.class.loading_registry = self
self.class.loading_path = path
Kernel.load(path, true)
@paths << path
rescue StandardError => e
emit_warning "Warning: skipping Kward plugin #{path}: #{e.message}"
ensure
self.class.loading_registry = previous_registry
self.class.loading_path = previous_path
end
|
#notify_transcript_event(event, context) ⇒ Object
721
722
723
724
725
726
727
728
729
730
731
|
# File 'lib/kward/plugins/registry.rb', line 721
def notify_transcript_event(event, context)
transcript_event = transcript_event_for(event)
return unless transcript_event
@transcript_event_handlers.each do |entry|
entry[:handler].call(transcript_event, context)
rescue StandardError => e
emit_warning "Warning: Kward plugin transcript event error in #{entry[:path]}: #{e.message}"
end
nil
end
|
#plugin_for(id) ⇒ Object
566
567
568
|
# File 'lib/kward/plugins/registry.rb', line 566
def plugin_for(id)
@plugins[id.to_s]
end
|
Returns identified plugins loaded by this registry.
562
563
564
|
# File 'lib/kward/plugins/registry.rb', line 562
def plugins
@plugins.values
end
|
#prompt_context(context) ⇒ Object
710
711
712
713
714
715
716
717
718
719
|
# File 'lib/kward/plugins/registry.rb', line 710
def prompt_context(context)
parts = []
@prompt_context_renderers.each do |entry|
rendered = entry[:renderer].call(context)
parts << rendered.to_s unless rendered.to_s.empty?
rescue StandardError => e
emit_warning "Warning: Kward plugin prompt context error in #{entry[:path]}: #{e.message}"
end
parts.empty? ? nil : parts.join("\n\n")
end
|
#prompt_context_renderers ⇒ Object
673
674
675
|
# File 'lib/kward/plugins/registry.rb', line 673
def prompt_context_renderers
@prompt_context_renderers.map { |entry| entry[:renderer] }
end
|
#register_action(name, plugin_id:, description:, schema:, path: nil, &handler) ⇒ Object
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
|
# File 'lib/kward/plugins/registry.rb', line 800
def register_action(name, plugin_id:, description:, schema:, path: nil, &handler)
name = name.to_s
raise "Plugin action name is invalid: #{name}" unless name.match?(COMMAND_NAME_PATTERN)
raise "Plugin action #{plugin_id}/#{name} requires a description" if description.to_s.strip.empty?
raise "Plugin action #{plugin_id}/#{name} requires a handler" unless handler
id = "#{plugin_id}/#{name}"
if @actions.key?(id)
emit_warning "Warning: skipping duplicate Kward plugin action #{id}: #{path}"
return nil
end
@actions[id] = Action.new(
name: name,
plugin_id: plugin_id,
description: description.to_s,
schema: schema,
path: path,
handler: handler
)
end
|
#register_command(name, description: "", argument_hint: "", schema: nil, positionals: [], plugin_id: nil, path: nil, &handler) ⇒ Object
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
|
# File 'lib/kward/plugins/registry.rb', line 773
def register_command(name, description: "", argument_hint: "", schema: nil, positionals: [], plugin_id: nil, path: nil, &handler)
name = name.to_s
raise "Plugin command name is invalid: #{name}" unless name.match?(COMMAND_NAME_PATTERN)
raise "Plugin command /#{name} requires a handler" unless handler
raise ArgumentError, "Plugin command /#{name} positionals require a schema" if schema.nil? && !Array(positionals).empty?
if @reserved_commands.include?(name)
emit_warning "Warning: skipping Kward plugin command /#{name}: reserved command"
return nil
end
if @commands.key?(name)
emit_warning "Warning: skipping duplicate Kward plugin command /#{name}: #{path}"
return nil
end
@commands[name] = Command.new(
name: name,
description: description.to_s,
argument_hint: argument_hint.to_s,
schema: schema,
positionals: positionals,
plugin_id: plugin_id,
path: path,
handler: handler
)
end
|
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
|
# File 'lib/kward/plugins/registry.rb', line 916
def (plugin_id: nil, path: nil, &renderer)
raise "Plugin footer requires a renderer" unless renderer
id = if plugin_id
"#{plugin_id}/footer"
else
available_legacy_status_id("legacy/#{legacy_status_source(path)}")
end
@status_sequence += 1 unless @statuses.key?(id)
@statuses[id] = Status.new(
id: id,
order: 100,
priority: :normal,
path: path,
renderer: renderer,
sequence: @statuses[id]&.sequence || @status_sequence
)
@footer_path = path
end
|
#register_hook(event, id: nil, description: "", order: 100, match: nil, failure_policy: nil, path: nil, &handler) ⇒ Object
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
|
# File 'lib/kward/plugins/registry.rb', line 984
def register_hook(event, id: nil, description: "", order: 100, match: nil, failure_policy: nil, path: nil, &handler)
event = event.to_s
raise "Plugin hook event is required" if event.empty?
raise "Plugin hook #{event} requires a handler" unless handler
@hook_handlers << HookHandler.new(
event: event,
id: id&.to_s || "#{File.basename(path.to_s.empty? ? "plugin" : path)}:#{event}:#{@hook_handlers.length + 1}",
description: description.to_s,
path: path,
order: order.to_i,
match: match,
failure_policy: failure_policy,
handler: handler
)
end
|
#register_interactive_command(name, rows:, fps: 30, description: "", argument_hint: "", path: nil, &handler) ⇒ Object
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
|
# File 'lib/kward/plugins/registry.rb', line 842
def register_interactive_command(name, rows:, fps: 30, description: "", argument_hint: "", path: nil, &handler)
name = name.to_s
raise "Interactive command name is invalid: #{name}" unless name.match?(COMMAND_NAME_PATTERN)
raise "Interactive command /#{name} requires a handler" unless handler
if @reserved_commands.include?(name) || @commands.key?(name)
emit_warning "Warning: skipping Kward interactive command /#{name}: reserved command"
return nil
end
if @interactive_commands.key?(name)
emit_warning "Warning: skipping duplicate Kward interactive command /#{name}: #{path}"
return nil
end
@interactive_commands[name] = InteractiveCommand.new(
name: name,
description: description.to_s,
argument_hint: argument_hint.to_s,
rows: [[rows.to_i, 1].max, 1].max,
fps: [[fps.to_f, 1].max, 120].min,
path: path,
handler: handler
)
end
|
#register_lifecycle(event, host:, path: nil, &handler) ⇒ Object
976
977
978
979
980
981
982
|
# File 'lib/kward/plugins/registry.rb', line 976
def register_lifecycle(event, host:, path: nil, &handler)
event = event.to_sym
raise ArgumentError, "Unknown plugin lifecycle event: #{event}" unless @lifecycle_handlers.key?(event)
raise ArgumentError, "Plugin lifecycle #{event} requires a handler" unless handler
@lifecycle_handlers[event] << LifecycleHandler.new(event: event, host: host, path: path, handler: handler)
end
|
#register_plugin_identity(id:, version:, api:, path: nil) ⇒ Object
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
|
# File 'lib/kward/plugins/registry.rb', line 754
def register_plugin_identity(id:, version:, api:, path: nil)
values = [id, version, api]
return nil if values.all?(&:nil?)
raise ArgumentError, "Plugin id, version, and api are required together" if values.any?(&:nil?)
id = id.to_s
api = api.to_s
raise ArgumentError, "Unsupported Kward plugin API #{api.inspect} for #{id}; supported API: #{PLUGIN_API_VERSION}" unless api == PLUGIN_API_VERSION
raise ArgumentError, "Duplicate Kward plugin id: #{id}" if @plugins.key?(id)
@plugins[id] = PluginHost.new(
id: id,
version: version,
api_version: api,
source_path: path,
warning_sink: method(:emit_warning)
)
end
|
#register_prompt_context(path: nil, &renderer) ⇒ Object
970
971
972
973
974
|
# File 'lib/kward/plugins/registry.rb', line 970
def register_prompt_context(path: nil, &renderer)
raise "Plugin prompt context requires a renderer" unless renderer
@prompt_context_renderers << { path: path, renderer: renderer }
end
|
#register_status(name, plugin_id:, order: 100, priority: :normal, path: nil, &renderer) ⇒ Object
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
|
# File 'lib/kward/plugins/registry.rb', line 936
def register_status(name, plugin_id:, order: 100, priority: :normal, path: nil, &renderer)
name = name.to_s
raise "Plugin status name is invalid: #{name}" unless name.match?(COMMAND_NAME_PATTERN)
raise "Plugin status #{plugin_id}/#{name} requires a renderer" unless renderer
id = "#{plugin_id}/#{name}"
if @statuses.key?(id)
emit_warning "Warning: skipping duplicate Kward plugin status #{id}: #{path}"
return nil
end
order = Integer(order)
priority = normalize_status_priority(priority)
@status_sequence += 1
@statuses[id] = Status.new(
id: id,
order: order,
priority: priority,
path: path,
renderer: renderer,
sequence: @status_sequence
)
end
|
#register_tab_type(name, id:, title: nil, singleton: nil, rpc: false, transport: false, local: true, transcript_events: false, api: nil, capabilities: nil, plugin_id: nil, path: nil, &handler) ⇒ Object
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
|
# File 'lib/kward/plugins/registry.rb', line 867
def register_tab_type(name, id:, title: nil, singleton: nil, rpc: false, transport: false, local: true, transcript_events: false, api: nil, capabilities: nil, plugin_id: nil, path: nil, &handler)
name = name.to_s
id = id.to_s
raise "Plugin tab type name is invalid: #{name}" unless name.match?(COMMAND_NAME_PATTERN)
raise "Plugin tab type id is required" if id.empty?
raise "Plugin tab type #{name} requires a handler" unless handler
if @tab_types.key?(name) || @tab_types_by_id.key?(id)
emit_warning "Warning: skipping duplicate Kward plugin tab type #{id}: #{path}"
return nil
end
tab_type = TabType.new(
id: id,
name: name,
title: title.to_s.empty? ? name.capitalize : title.to_s,
singleton: singleton&.to_sym,
rpc: rpc == true,
transport: transport == true,
local: local == true,
transcript_events: transcript_events == true,
capabilities: PluginChatCapabilities.build(api: api, capabilities: capabilities),
plugin_id: plugin_id,
path: path,
handler: handler
)
@tab_types[name] = tab_type
@tab_types_by_id[id] = tab_type
end
|
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
|
# File 'lib/kward/plugins/registry.rb', line 822
def register_tool(name, description:, schema:, path: nil, &handler)
name = name.to_s
raise "Plugin tool name is invalid: #{name}" unless name.match?(COMMAND_NAME_PATTERN)
raise "Plugin tool #{name} requires a description" if description.to_s.strip.empty?
raise "Plugin tool #{name} requires a handler" unless handler
if @tools.key?(name)
emit_warning "Warning: skipping duplicate Kward plugin tool #{name}: #{path}"
return nil
end
@tools[name] = Tool.new(
name: name,
description: description.to_s,
schema: normalize_tool_schema(name, schema),
path: path,
handler: handler
)
end
|
#register_transcript_event(path: nil, &handler) ⇒ Object
964
965
966
967
968
|
# File 'lib/kward/plugins/registry.rb', line 964
def register_transcript_event(path: nil, &handler)
raise "Plugin transcript event requires a handler" unless handler
@transcript_event_handlers << { path: path, handler: handler }
end
|
#register_transport(name, id:, capabilities: nil, execution_profile: nil, path: nil, &handler) ⇒ Object
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
|
# File 'lib/kward/plugins/registry.rb', line 897
def register_transport(name, id:, capabilities: nil, execution_profile: nil, path: nil, &handler)
name = name.to_s
id = id.to_s
raise "Plugin transport name is invalid: #{name}" unless name.match?(COMMAND_NAME_PATTERN)
raise "Plugin transport id is required" if id.empty?
raise "Plugin transport #{name} requires a handler" unless handler
if @transports.key?(name) || @transports_by_id.key?(id)
emit_warning "Warning: skipping duplicate Kward plugin transport #{id}: #{path}"
return nil
end
capabilities = normalize_transport_capabilities(capabilities)
execution_profile = normalize_execution_profile(execution_profile)
transport = TransportType.new(id: id, name: name, capabilities: capabilities, execution_profile: execution_profile, path: path, handler: handler)
@transports[name] = transport
@transports_by_id[id] = transport
end
|
#reload!(timeout: PluginResources::DEFAULT_SHUTDOWN_TIMEOUT) ⇒ Object
Invokes reload callbacks on the old registry and cleans up all resources.
#shutdown!(timeout: PluginResources::DEFAULT_SHUTDOWN_TIMEOUT) ⇒ Object
Invokes shutdown callbacks and cleans up all resources.
#start! ⇒ Object
Activates identified plugins and invokes their start callbacks once.
682
683
684
685
686
687
688
|
# File 'lib/kward/plugins/registry.rb', line 682
def start!
transition_lifecycle!(:loaded, :active) do
@plugins.each_value(&:activate!)
run_lifecycle_callbacks(:start)
end
self
end
|
#status? ⇒ Boolean
630
631
632
|
# File 'lib/kward/plugins/registry.rb', line 630
def status?
!@statuses.empty?
end
|
#status_segments(context) ⇒ Object
Evaluates every status renderer independently and returns display-ordered
frontend-neutral segments. A broken renderer cannot hide healthy segments.
645
646
647
648
649
650
651
652
|
# File 'lib/kward/plugins/registry.rb', line 645
def status_segments(context)
@statuses.values.sort_by { |status| [status.order, status.sequence] }.filter_map do |status|
normalize_status_segment(status, status.renderer.call(context))
rescue StandardError => e
emit_warning "Warning: Kward plugin status #{status.id} error in #{status.path}: #{e.message}"
nil
end
end
|
#tab_type_for(name) ⇒ Object
606
607
608
|
# File 'lib/kward/plugins/registry.rb', line 606
def tab_type_for(name)
@tab_types[name.to_s]
end
|
#tab_type_for_id(id) ⇒ Object
610
611
612
|
# File 'lib/kward/plugins/registry.rb', line 610
def tab_type_for_id(id)
@tab_types_by_id[id.to_s]
end
|
#tab_types ⇒ Object
602
603
604
|
# File 'lib/kward/plugins/registry.rb', line 602
def tab_types
@tab_types.values
end
|
590
591
592
|
# File 'lib/kward/plugins/registry.rb', line 590
def tool_for(name)
@tools[name.to_s]
end
|
586
587
588
|
# File 'lib/kward/plugins/registry.rb', line 586
def tools
@tools.values
end
|
#transcript_event_handlers ⇒ Object
669
670
671
|
# File 'lib/kward/plugins/registry.rb', line 669
def transcript_event_handlers
@transcript_event_handlers.map { |entry| entry[:handler] }
end
|
#transport_for(name) ⇒ Object
622
623
624
|
# File 'lib/kward/plugins/registry.rb', line 622
def transport_for(name)
@transports[name.to_s]
end
|
#transport_for_id(id) ⇒ Object
626
627
628
|
# File 'lib/kward/plugins/registry.rb', line 626
def transport_for_id(id)
@transports_by_id[id.to_s]
end
|
#transport_tab_types ⇒ Object
614
615
616
|
# File 'lib/kward/plugins/registry.rb', line 614
def transport_tab_types
@tab_types.values.select(&:transport)
end
|
#transports ⇒ Object
618
619
620
|
# File 'lib/kward/plugins/registry.rb', line 618
def transports
@transports.values
end
|