13
14
15
16
17
18
19
20
21
22
23
24
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
51
52
53
54
55
56
57
58
59
|
# File 'lib/legion/extensions/exec/runners/shell.rb', line 13
def execute(command:, cwd: Dir.pwd, timeout: Helpers::Constants::DEFAULT_TIMEOUT, env: {}, **)
check = default_sandbox.allowed?(command)
return { success: false, error: :blocked, reason: check[:reason] } unless check[:allowed]
command = rewrite_python_command(command)
start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
timeout_secs = [timeout, Helpers::Constants::MAX_TIMEOUT].min / 1000.0
begin
stdout, stderr, status = Timeout.timeout(timeout_secs) do
Open3.capture3(env, command, chdir: cwd)
end
rescue Timeout::Error => _e
return { success: false, error: :timeout, timeout_ms: timeout }
rescue ArgumentError => e
return { success: false, error: e.message }
end
duration_ms = ((::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - start_time) * 1000).round
exit_code = status.exitstatus.to_i
truncated = false
if stdout.bytesize > Helpers::Constants::MAX_OUTPUT_BYTES
stdout = stdout.byteslice(0, Helpers::Constants::MAX_OUTPUT_BYTES)
truncated = true
end
stderr = stderr.byteslice(0, Helpers::Constants::MAX_OUTPUT_BYTES) if stderr.bytesize > Helpers::Constants::MAX_OUTPUT_BYTES
audit_log.record(command: command, cwd: cwd, exit_code: exit_code,
duration_ms: duration_ms, truncated: truncated)
Legion::Logging.debug("[lex-exec] exit=#{exit_code} duration=#{duration_ms}ms cmd=#{command}")
{
success: exit_code.zero?,
stdout: stdout,
stderr: stderr,
exit_code: exit_code,
duration_ms: duration_ms,
truncated: truncated
}
end
|