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, StartupOption, 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_startup_option(name, description:, plugin_id:, path: nil, &handler) ⇒ 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.
-
#run_startup_option(name) ⇒ Object
-
#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.
-
#startup_option_for(name) ⇒ Object
-
#startup_options ⇒ Object
-
#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.
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
|
# File 'lib/kward/plugins/registry.rb', line 542
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 = {}
@startup_options = {}
@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.
530
531
532
|
# File 'lib/kward/plugins/registry.rb', line 530
def loading_path
@loading_path
end
|
.loading_registry ⇒ Object
Returns the value of attribute loading_registry.
530
531
532
|
# File 'lib/kward/plugins/registry.rb', line 530
def loading_registry
@loading_registry
end
|
Instance Attribute Details
Returns most recent plugin file to register legacy footer output.
568
569
570
|
# File 'lib/kward/plugins/registry.rb', line 568
def
@footer_path
end
|
#paths ⇒ Array<String>
Returns plugin files successfully loaded by this registry.
571
572
573
|
# File 'lib/kward/plugins/registry.rb', line 571
def paths
@paths
end
|
Class Method Details
.load(paths: nil, reserved_commands: [], warning_sink: nil) ⇒ Object
532
533
534
535
536
537
538
|
# File 'lib/kward/plugins/registry.rb', line 532
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
594
595
596
|
# File 'lib/kward/plugins/registry.rb', line 594
def action_for(id)
@actions[id.to_s]
end
|
#actions ⇒ Object
590
591
592
|
# File 'lib/kward/plugins/registry.rb', line 590
def actions
@actions.values
end
|
#command_for(name) ⇒ Object
586
587
588
|
# File 'lib/kward/plugins/registry.rb', line 586
def command_for(name)
@commands[name.to_s]
end
|
#commands ⇒ Object
582
583
584
|
# File 'lib/kward/plugins/registry.rb', line 582
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.
683
684
685
686
687
688
689
690
691
692
693
|
# File 'lib/kward/plugins/registry.rb', line 683
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
999
1000
1001
|
# File 'lib/kward/plugins/registry.rb', line 999
def emit_warning(message)
@warning_sink ? @warning_sink.call(message) : warn(message)
end
|
#evaluate(path: nil, id: nil, version: nil, api: nil, &block) ⇒ Object
773
774
775
776
777
778
|
# File 'lib/kward/plugins/registry.rb', line 773
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.
661
662
663
664
665
666
667
|
# File 'lib/kward/plugins/registry.rb', line 661
def
return nil unless status?
lambda do |context|
compose_status(status_segments(context))
end
end
|
#hook_handlers ⇒ Object
703
704
705
|
# File 'lib/kward/plugins/registry.rb', line 703
def hook_handlers
@hook_handlers.dup
end
|
#hook_manager ⇒ Object
726
727
728
729
730
731
732
733
734
|
# File 'lib/kward/plugins/registry.rb', line 726
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
610
611
612
|
# File 'lib/kward/plugins/registry.rb', line 610
def interactive_command_for(name)
@interactive_commands[name.to_s]
end
|
#interactive_commands ⇒ Object
606
607
608
|
# File 'lib/kward/plugins/registry.rb', line 606
def interactive_commands
@interactive_commands.values
end
|
#load_file(path) ⇒ Object
759
760
761
762
763
764
765
766
767
768
769
770
771
|
# File 'lib/kward/plugins/registry.rb', line 759
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
747
748
749
750
751
752
753
754
755
756
757
|
# File 'lib/kward/plugins/registry.rb', line 747
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
578
579
580
|
# File 'lib/kward/plugins/registry.rb', line 578
def plugin_for(id)
@plugins[id.to_s]
end
|
Returns identified plugins loaded by this registry.
574
575
576
|
# File 'lib/kward/plugins/registry.rb', line 574
def plugins
@plugins.values
end
|
#prompt_context(context) ⇒ Object
736
737
738
739
740
741
742
743
744
745
|
# File 'lib/kward/plugins/registry.rb', line 736
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
699
700
701
|
# File 'lib/kward/plugins/registry.rb', line 699
def prompt_context_renderers
@prompt_context_renderers.map { |entry| entry[:renderer] }
end
|
#register_action(name, plugin_id:, description:, schema:, path: nil, &handler) ⇒ Object
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
|
# File 'lib/kward/plugins/registry.rb', line 826
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
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
|
# File 'lib/kward/plugins/registry.rb', line 799
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
|
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
|
# File 'lib/kward/plugins/registry.rb', line 955
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
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
|
# File 'lib/kward/plugins/registry.rb', line 1023
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
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
|
# File 'lib/kward/plugins/registry.rb', line 868
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
1015
1016
1017
1018
1019
1020
1021
|
# File 'lib/kward/plugins/registry.rb', line 1015
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
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
|
# File 'lib/kward/plugins/registry.rb', line 780
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
1009
1010
1011
1012
1013
|
# File 'lib/kward/plugins/registry.rb', line 1009
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_startup_option(name, description:, plugin_id:, path: nil, &handler) ⇒ Object
923
924
925
926
927
928
929
930
931
932
933
934
|
# File 'lib/kward/plugins/registry.rb', line 923
def register_startup_option(name, description:, plugin_id:, path: nil, &handler)
name = name.to_s
raise "Plugin startup option must look like --name: #{name}" unless name.match?(/\A--[a-z][a-z0-9-]*\z/)
raise "Plugin startup option requires a handler: #{name}" unless handler
if @startup_options.key?(name)
emit_warning "Warning: skipping duplicate Kward plugin startup option #{name}: #{path}"
return nil
end
@startup_options[name] = StartupOption.new(name: name, description: description.to_s, plugin_id: plugin_id, path: path, handler: handler)
end
|
#register_status(name, plugin_id:, order: 100, priority: :normal, path: nil, &renderer) ⇒ Object
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
|
# File 'lib/kward/plugins/registry.rb', line 975
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
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
|
# File 'lib/kward/plugins/registry.rb', line 893
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
|
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
|
# File 'lib/kward/plugins/registry.rb', line 848
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
1003
1004
1005
1006
1007
|
# File 'lib/kward/plugins/registry.rb', line 1003
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
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
|
# File 'lib/kward/plugins/registry.rb', line 936
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.
#run_startup_option(name) ⇒ Object
650
651
652
653
654
|
# File 'lib/kward/plugins/registry.rb', line 650
def run_startup_option(name)
option = startup_option_for(name) || raise(ArgumentError, "Unknown plugin startup option: #{name}")
start!
option.handler.call(plugin_for(option.plugin_id))
end
|
#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.
708
709
710
711
712
713
714
|
# File 'lib/kward/plugins/registry.rb', line 708
def start!
transition_lifecycle!(:loaded, :active) do
@plugins.each_value(&:activate!)
run_lifecycle_callbacks(:start)
end
self
end
|
#startup_option_for(name) ⇒ Object
646
647
648
|
# File 'lib/kward/plugins/registry.rb', line 646
def startup_option_for(name)
@startup_options[name.to_s]
end
|
#startup_options ⇒ Object
642
643
644
|
# File 'lib/kward/plugins/registry.rb', line 642
def startup_options
@startup_options.values.dup
end
|
#status? ⇒ Boolean
656
657
658
|
# File 'lib/kward/plugins/registry.rb', line 656
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.
671
672
673
674
675
676
677
678
|
# File 'lib/kward/plugins/registry.rb', line 671
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
618
619
620
|
# File 'lib/kward/plugins/registry.rb', line 618
def tab_type_for(name)
@tab_types[name.to_s]
end
|
#tab_type_for_id(id) ⇒ Object
622
623
624
|
# File 'lib/kward/plugins/registry.rb', line 622
def tab_type_for_id(id)
@tab_types_by_id[id.to_s]
end
|
#tab_types ⇒ Object
614
615
616
|
# File 'lib/kward/plugins/registry.rb', line 614
def tab_types
@tab_types.values
end
|
602
603
604
|
# File 'lib/kward/plugins/registry.rb', line 602
def tool_for(name)
@tools[name.to_s]
end
|
598
599
600
|
# File 'lib/kward/plugins/registry.rb', line 598
def tools
@tools.values
end
|
#transcript_event_handlers ⇒ Object
695
696
697
|
# File 'lib/kward/plugins/registry.rb', line 695
def transcript_event_handlers
@transcript_event_handlers.map { |entry| entry[:handler] }
end
|
#transport_for(name) ⇒ Object
634
635
636
|
# File 'lib/kward/plugins/registry.rb', line 634
def transport_for(name)
@transports[name.to_s]
end
|
#transport_for_id(id) ⇒ Object
638
639
640
|
# File 'lib/kward/plugins/registry.rb', line 638
def transport_for_id(id)
@transports_by_id[id.to_s]
end
|
#transport_tab_types ⇒ Object
626
627
628
|
# File 'lib/kward/plugins/registry.rb', line 626
def transport_tab_types
@tab_types.values.select(&:transport)
end
|
#transports ⇒ Object
630
631
632
|
# File 'lib/kward/plugins/registry.rb', line 630
def transports
@transports.values
end
|