Class: Rubino::Tools::Registry

Inherits:
Object
  • Object
show all
Defined in:
lib/rubino/tools/registry.rb

Overview

Singleton registry for all available tools. Tools register themselves and can be looked up by name.

Class Method Summary collapse

Class Method Details

.allObject

Returns all registered tools



34
35
36
# File 'lib/rubino/tools/registry.rb', line 34

def all
  @tools.values
end

.enabled_toolsObject

Returns only enabled tools based on configuration AND the active mode (Modes.current). Plan mode pares the registry down to its read-only whitelist so the model literally has no ‘edit`/`shell`/ `git` definition in the request — it can’t even propose a mutating tool call. Yolo and default leave everything through; their difference is on the approval path, not the registry.



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/rubino/tools/registry.rb', line 44

def enabled_tools
  config = Rubino.configuration
  disabled = config.agent_disabled_toolsets

  @tools.values.reject do |tool|
    disabled.include?(tool.name) ||
      !tool_enabled_in_config?(tool, config) ||
      !Rubino::Modes.allows_tool?(tool.name) ||
      !aux_dependency_satisfied?(tool, config)
  end
end

.find(name) ⇒ Object

Finds a tool by name



22
23
24
# File 'lib/rubino/tools/registry.rb', line 22

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

.instanceObject

Returns the singleton instance



12
13
14
# File 'lib/rubino/tools/registry.rb', line 12

def instance
  self
end

.register(tool) ⇒ Object

Registers a tool instance



17
18
19
# File 'lib/rubino/tools/registry.rb', line 17

def register(tool)
  @tools[tool.name] = tool
end

.register_defaults!Object

Registers all default tools



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/rubino/tools/registry.rb', line 67

def register_defaults!
  register(Rubino::Tools::ReadTool.new)
  register(Rubino::Tools::SummarizeFileTool.new)
  register(Rubino::Tools::WriteTool.new)
  register(Rubino::Tools::EditTool.new)
  register(Rubino::Tools::MultiEditTool.new)
  register(Rubino::Tools::GrepTool.new)
  register(Rubino::Tools::GlobTool.new)
  register(Rubino::Tools::GitTool.new)
  register(Rubino::Tools::GitHubTool.new)
  register(Rubino::Tools::ShellTool.new)
  register(Rubino::Tools::ShellOutputTool.new)
  register(Rubino::Tools::ShellTailTool.new)
  register(Rubino::Tools::ShellInputTool.new)
  register(Rubino::Tools::ShellKillTool.new)
  register(Rubino::Tools::RubyTool.new)
  # Structured test-runner (issue #101): auto-detects rspec/minitest/
  # rake, prefers `bundle exec` (falls back when the bundle is broken),
  # and returns pass/fail counts + parsed failing examples instead of
  # the raw toolchain firehose the `shell` tool would dump.
  register(Rubino::Tools::TestTool.new)
  register(Rubino::Tools::PatchTool.new)
  register(Rubino::Tools::WebFetchTool.new)
  register(Rubino::Tools::WebSearchTool.new)
  register(Rubino::Tools::QuestionTool.new)
  register(Rubino::Tools::TodoTool.new)
  register(Rubino::Tools::MemoryTool.new)
  register(Rubino::Tools::SessionSearchTool.new)
  register(Rubino::Tools::AttachFileTool.new)
  # Gated, on-demand attachment reader (#6): converts a document to
  # Markdown IN-PROCESS (Rubino::Documents) and frames it as untrusted
  # data, so attachment bytes enter context only when the model asks.
  register(Rubino::Tools::ReadAttachmentTool.new)
  register(Rubino::Tools::VisionTool.new)
  # Skills tool: loads a skill body (Level 2) and bundled files
  # (Level 3) on demand. Gated like any tool via `tools.skill`.
  register(Rubino::Skills::SkillTool.new)
  # Delegation tool: lets the model spawn an isolated subagent run.
  # Gated like any other tool (tools.task in config). Subagents now KEEP
  # it (scoped nesting, S1) — a subagent can spawn its own subagents,
  # bounded by the depth / fan-out / global caps in BackgroundTasks#reserve.
  register(Rubino::Tools::TaskTool.new)
  # Companion poll/stop tools for background subagents (the default
  # path of `task`). Mirror the shell_output/shell_kill trio. Gated by
  # the same tools.task key — disabling delegation disables these too.
  register(Rubino::Tools::TaskResultTool.new)
  register(Rubino::Tools::TaskStopTool.new)
  # ask_parent: the child->parent escalation tool. Registered globally
  # (gated by the same tools.task key), but Definition#resolved_tools
  # exposes it ONLY to subagents — a top-level agent has no parent to ask.
  register(Rubino::Tools::AskParentTool.new)
  # steer / probe (S2/S3): the MODEL-callable parent->child channels,
  # registered for ALL agents and AUTHORIZED by ownership at call time
  # (a node with no children just gets a "not your child" error). NOT on
  # any strip list — scoping happens inside the tool, not in the registry.
  register(Rubino::Tools::SteerTool.new)
  register(Rubino::Tools::ProbeTool.new)
  # answer_child (S4): the MODEL-callable answer to a child's ask_parent,
  # the agent-parent twin of the human /reply. Registered for ALL agents
  # and AUTHORIZED by ownership at call time (like steer/probe). NOT on
  # any strip list — a node with no waiting child just gets a not-waiting
  # / not-yours error.
  register(Rubino::Tools::AnswerChildTool.new)
end

.reset!Object

Clears all registered tools (useful for testing)



62
63
64
# File 'lib/rubino/tools/registry.rb', line 62

def reset!
  @tools = {}
end

.tool_definitionsObject

Returns tool definitions for LLM registration



57
58
59
# File 'lib/rubino/tools/registry.rb', line 57

def tool_definitions
  enabled_tools.map(&:to_tool_definition)
end

.unregister(name) ⇒ Object

Removes a tool by name (#182): stopping an MCP server must also drop its MCPToolWrapper instances, or the model keeps seeing tools whose client is gone and every call fails.



29
30
31
# File 'lib/rubino/tools/registry.rb', line 29

def unregister(name)
  @tools.delete(name.to_s)
end