Skip to content
Kward Search API index

Class: Kward::PluginRegistry

Inherits:
Object
  • Object
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

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.

Returns:

  • (String, nil) —

    most recent plugin file to register legacy footer output



568
569
570
# File 'lib/kward/plugins/registry.rb', line 568

def footer_path
  @footer_path
end

#paths ⇒ Array<String> (readonly)

Returns plugin files successfully loaded by this registry.

Returns:

  • (Array<String>) —

    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 footer_renderer
  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

#plugins ⇒ Array<PluginHost>

Returns identified plugins loaded by this registry.

Returns:

  • (Array<PluginHost>) —

    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

Raises:

  • (ArgumentError)


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 register_footer(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

Raises:

  • (ArgumentError)


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

Raises:

  • (ArgumentError)


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

#register_tool(name, description:, schema:, path: nil, &handler) ⇒ Object



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.



717
718
719
# File 'lib/kward/plugins/registry.rb', line 717

def reload!(timeout: PluginResources::DEFAULT_SHUTDOWN_TIMEOUT)
  stop_lifecycle!(:reload, timeout: timeout)
end

#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.



722
723
724
# File 'lib/kward/plugins/registry.rb', line 722

def shutdown!(timeout: PluginResources::DEFAULT_SHUTDOWN_TIMEOUT)
  stop_lifecycle!(:shutdown, timeout: timeout)
end

#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

Returns:

  • (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

#tool_for(name) ⇒ Object



602
603
604
# File 'lib/kward/plugins/registry.rb', line 602

def tool_for(name)
  @tools[name.to_s]
end

#tools ⇒ Object



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