Class: Chocomint::Tools::Shell

Inherits:
Base
  • Object
show all
Defined in:
lib/chocomint/tools/shell.rb

Overview

shell を明示的に介してスクリプトを実行する (bash / powershell)。

DESIGN §13 の「shell 展開禁止」原則からは外れる強力なツールなので、 cwd を base_dir に固定し、timeout と出力サイズ制限を必ず適用する。 bash / powershell の 2 種類を launcher で切り替える。

Constant Summary collapse

GIT_BASH_CANDIDATES =

Windows では PATH 上の "bash" が WSL インタロップ (system32\bash.exe) に 解決されることがあり、これは -c に渡した複数文スクリプト中の変数展開が 壊れる既知の癖を持つ。Git Bash を優先的に探し、無ければ "bash" にフォールバックする。

[
  "C:/Program Files/Git/bin/bash.exe",
  "C:/Program Files (x86)/Git/bin/bash.exe"
].freeze
LAUNCHERS =
{
  "bash" => {
    name: "bash",
    exe: resolve_bash_exe,
    argv: ->(script) { ["-c", script] }
  },
  "powershell" => {
    name: "powershell",
    exe: "pwsh",
    argv: ->(script) { ["-NoProfile", "-NonInteractive", "-Command", script] }
  }
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#to_tool_definition

Constructor Details

#initialize(spec:, timeout_sec:, max_output_bytes:, cwd: Dir.pwd, path_guard: nil) ⇒ Shell

Returns a new instance of Shell.



45
46
47
48
49
50
51
# File 'lib/chocomint/tools/shell.rb', line 45

def initialize(spec:, timeout_sec:, max_output_bytes:, cwd: Dir.pwd, path_guard: nil)
  @spec = spec
  @timeout_sec = timeout_sec
  @max_output_bytes = max_output_bytes
  @cwd = cwd
  @path_guard = path_guard
end

Class Method Details

.build(kind, **opts) ⇒ Object



40
41
42
43
# File 'lib/chocomint/tools/shell.rb', line 40

def self.build(kind, **opts)
  spec = LAUNCHERS.fetch(kind)
  new(spec: spec, **opts)
end

.resolve_bash_exeObject



23
24
25
# File 'lib/chocomint/tools/shell.rb', line 23

def self.resolve_bash_exe
  GIT_BASH_CANDIDATES.find { |path| File.exist?(path) } || "bash"
end

Instance Method Details

#call(args) ⇒ Object



71
72
73
74
75
76
77
78
79
80
# File 'lib/chocomint/tools/shell.rb', line 71

def call(args)
  measure do
    script = args["script"].to_s
    if (denied = sandbox_violation(script))
      next fail(stderr: denied)
    end

    run(script)
  end
end

#descriptionObject



55
56
57
58
# File 'lib/chocomint/tools/shell.rb', line 55

def description
  "#{@spec[:name]} スクリプトを実行する。作業ディレクトリは固定され、" \
    "timeout #{@timeout_sec}s と出力サイズ制限が適用される。"
end

#nameObject



53
# File 'lib/chocomint/tools/shell.rb', line 53

def name = @spec[:name]

#schemaObject



60
61
62
63
64
65
66
67
68
69
# File 'lib/chocomint/tools/shell.rb', line 60

def schema
  {
    "type" => "object",
    "properties" => {
      "script" => { "type" => "string" }
    },
    "required" => %w[script],
    "additionalProperties" => false
  }
end