Module: Ukiryu::Tool::CommandResolution Private

Included in:
Ukiryu::Tool
Defined in:
lib/ukiryu/tool/command_resolution.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Command resolution and routing for hierarchical tools

Provides methods to resolve command paths in tools with routing, such as git where commands are organized hierarchically (e.g., ‘remote:add’, ‘branch:delete’).

Instance Method Summary collapse

Instance Method Details

#execute(root_path, execution_timeout:, **params) ⇒ Executor::Result

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Execute a command with root-path notation (for hierarchical tools)

Root-path uses ‘:’ to separate levels, e.g., ‘remote:add’ -> [‘remote’, ‘add’] This provides a cleaner API for executing routed actions.

Examples:

Root-path notation

tool.execute('remote:add', {name: 'origin', url: 'https://...'}, execution_timeout: 90)
tool.execute('branch:delete', {branch_name: 'feature'}, execution_timeout: 90)
tool.execute('stash:save', {message: 'WIP'}, execution_timeout: 90)

Simple command (backward compatible)

tool.execute(:convert, {inputs: ['image.png'], output: 'output.jpg'}, execution_timeout: 90)

Parameters:

  • root_path (String, Symbol)

    the action path with ‘:’ separator (e.g., ‘remote:add’)

  • execution_timeout (Integer)

    timeout in seconds for command execution (required)

  • params (Hash)

    action parameters

Returns:

  • (Executor::Result)

    the execution result



117
118
119
120
121
122
123
124
125
126
# File 'lib/ukiryu/tool/command_resolution.rb', line 117

def execute(root_path, execution_timeout:, **params)
  # Check if this is a root-path (contains ':')
  if root_path.is_a?(String) && root_path.include?(':')
    path = root_path.split(':').map(&:strip)
    execute_action(path, execution_timeout: execution_timeout, **params)
  else
    # Use simple execute for regular commands
    execute_simple(root_path, execution_timeout: execution_timeout, **params)
  end
end

#execute_action(path, execution_timeout:, **params) ⇒ Executor::Result

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Execute a routed action (for tools with routing)

Examples:

tool.execute_action(['remote', 'add'], {name: 'origin', url: 'https://...'}, execution_timeout: 90)

Parameters:

  • path (Array<String, Symbol>)

    the action path (e.g., [‘remote’, ‘add’])

  • execution_timeout (Integer)

    timeout in seconds (required)

  • params (Hash)

    action parameters

Returns:

  • (Executor::Result)

    the execution result

Raises:

  • (ArgumentError)


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/ukiryu/tool/command_resolution.rb', line 78

def execute_action(path, execution_timeout:, **params)
  resolution = resolve_action_path(path)
  raise ArgumentError, "Cannot resolve action path: #{path.inspect}" unless resolution

  action = resolution[:action]
  raise ArgumentError, "Action not found: #{path.inspect}" unless action

  # Normalize params to hash with symbol keys
  params = normalize_params(params)

  # Extract stdin parameter
  stdin = params.delete(:stdin)

  # Build command arguments
  args = build_args(action, params)

  # Execute with the routed executable, passing tool_name and command_name for exit code lookups
  execute_with_config(resolution[:executable], args, action, params, execution_timeout: execution_timeout,
                                                                     stdin: stdin)
end

#find_action_with_parent(parent_name, action_name) ⇒ Models::CommandDefinition?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Find an action that belongs to a parent command

Parameters:

  • parent_name (String, Symbol)

    the parent command name

  • action_name (String, Symbol)

    the action name

Returns:



58
59
60
61
62
63
64
65
66
# File 'lib/ukiryu/tool/command_resolution.rb', line 58

def find_action_with_parent(parent_name, action_name)
  parent = parent_name.to_s
  action = action_name.to_s

  # Search for command with matching belongs_to
  commands&.find do |cmd|
    cmd.belongs_to == parent && cmd.name == action
  end
end

#find_command_profileModels::CommandProfile?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Find the best matching command profile

Strategy:

  1. If multiple profiles exist, find one matching current platform/shell

  2. If single profile exists, use it (PATH discovery is primary)

  3. If no matching profile found among multiple, raise error

Returns:

  • (Models::CommandProfile, nil)

    the compatible profile

Raises:

  • (ProfileNotFoundError)

    if no compatible profile found



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/ukiryu/tool/command_resolution.rb', line 137

def find_command_profile
  return nil unless @profile.profiles

  # Single profile: always use as fallback (PATH discovery is primary)
  return @profile.profiles.first if @profile.profiles.one?

  # Multiple profiles: find compatible one
  @profile.profiles.find do |p|
    platforms = p.platforms&.map(&:to_sym) || []
    shells = p.shells&.map(&:to_sym) || []

    # Match if profile is universal OR compatible with current platform/shell
    (platforms.empty? || platforms.include?(@platform)) &&
      (shells.empty? || shells.include?(@shell))
  end || raise(ProfileNotFoundError,
               "No compatible profile for #{@name}. " \
               "Current: #{@platform}/#{@shell}")
end

#resolve_action_path(path) ⇒ Hash?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Resolve a hierarchical action path

For tools with routing (like git), resolves paths like [‘remote’, ‘add’] to their executable targets and action definitions.

Examples:

tool.resolve_action_path(['remote', 'add'])
# => { executable: 'git-remote', action: <CommandDefinition>, path: ['remote', 'add'] }

Parameters:

  • path (Array<String, Symbol>)

    the action path to resolve

Returns:

  • (Hash, nil)

    resolution info with :executable, :action, :path keys



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/ukiryu/tool/command_resolution.rb', line 25

def resolve_action_path(path)
  return nil unless routing?
  return nil if path.empty?

  # Convert to strings
  path = path.map(&:to_s)

  # Resolve first level through routing
  first_target = routing.resolve(path.first)
  return nil unless first_target

  # Find action definition
  action = if path.size > 1
             # Multi-level: find action with belongs_to
             find_action_with_parent(path[0], path[1])
           else
             # Single level: find direct command
             command_definition(path[0])
           end

  {
    executable: first_target,
    action: action,
    path: path
  }
end