ask-tools-shell 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/ask/tools/shell/bash.rb +21 -57
- data/lib/ask/tools/shell/code.rb +19 -40
- data/lib/ask/tools/shell/version.rb +1 -1
- data/lib/ask/tools/shell.rb +9 -11
- data/lib/ask-tools-shell.rb +1 -10
- metadata +15 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 40e217bcf42a1f1cdf4b3bf6d256e06aa21ee4e9c946706a1728dc8bf049e6a0
|
|
4
|
+
data.tar.gz: cb157c2d84e1c162de9cab25394dec75ffdf65276e55a70537acc145424a7c1f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9b204fd0304eb672ad90c8359bafe27454441019079a64a38a73026f8fc3b0003098cb9df034827feb19324490c82f88d67b9642d521a3a7aad0769cb0cab9c7
|
|
7
|
+
data.tar.gz: 9150cd2ccab75a75dfec81125b6ab6c8308ae2853a07e4d158e3244a231777acbd2f03895deacf53c910f2229f06005c70a032253ee6c14a02c2d7381e9e1149
|
data/lib/ask/tools/shell/bash.rb
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "
|
|
4
|
-
require "tempfile"
|
|
5
|
-
require "stringio"
|
|
6
|
-
require "tmpdir"
|
|
3
|
+
require "ask-sandbox-providers"
|
|
7
4
|
|
|
8
5
|
module Ask
|
|
9
6
|
module Tools
|
|
10
7
|
# Execute shell commands in a sandboxed environment.
|
|
11
|
-
#
|
|
12
|
-
#
|
|
8
|
+
# Runs via Ask::Sandbox.provider (Local by default, configurable for
|
|
9
|
+
# stronger isolation via Docker, Daytona, or Cloudflare).
|
|
13
10
|
class Bash < Ask::Tool
|
|
14
11
|
description "Execute a bash command in a sandboxed environment. " \
|
|
15
12
|
"Returns stdout, stderr, and exit code. " \
|
|
@@ -19,59 +16,26 @@ module Ask
|
|
|
19
16
|
param :timeout, type: :integer, desc: "Timeout in seconds", required: false
|
|
20
17
|
param :workdir, type: :string, desc: "Working directory", required: false
|
|
21
18
|
|
|
22
|
-
MAX_OUTPUT_SIZE = 102_400
|
|
23
|
-
|
|
24
19
|
def execute(command:, timeout: 30, workdir: nil)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
threads = [
|
|
38
|
-
Thread.new { IO.copy_stream(out, stdout) rescue nil },
|
|
39
|
-
Thread.new { IO.copy_stream(err, stderr) rescue nil }
|
|
40
|
-
]
|
|
41
|
-
|
|
42
|
-
unless wait_thr.join(timeout)
|
|
43
|
-
Process.kill("-KILL", wait_thr.pid) rescue nil
|
|
44
|
-
timed_out = true
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
threads.each(&:join)
|
|
48
|
-
exit_code = timed_out ? -1 : wait_thr.value.exitstatus
|
|
49
|
-
end
|
|
50
|
-
rescue => e
|
|
51
|
-
return Ask::Result.error(message: "Bash execution failed: #{e.message}",
|
|
52
|
-
metadata: { stdout: stdout.string, stderr: stderr.string })
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
out_text = stdout.string
|
|
56
|
-
err_text = stderr.string
|
|
57
|
-
|
|
58
|
-
if out_text.length > MAX_OUTPUT_SIZE
|
|
59
|
-
header = "[Output truncated to #{MAX_OUTPUT_SIZE / 1024}KB]\n"
|
|
60
|
-
out_text = "#{header}#{out_text[-(MAX_OUTPUT_SIZE - header.length)..]}"
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
if err_text.length > MAX_OUTPUT_SIZE
|
|
64
|
-
header = "[Error output truncated to #{MAX_OUTPUT_SIZE / 1024}KB]\n"
|
|
65
|
-
err_text = "#{header}#{err_text[-(MAX_OUTPUT_SIZE - header.length)..]}"
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
Ask::Result.ok(data: {
|
|
69
|
-
stdout: out_text,
|
|
70
|
-
stderr: err_text,
|
|
71
|
-
exit_code: exit_code,
|
|
72
|
-
timed_out: timed_out
|
|
73
|
-
})
|
|
20
|
+
result = Ask::Sandbox.provider.call(
|
|
21
|
+
command,
|
|
22
|
+
timeout: timeout,
|
|
23
|
+
workdir: workdir
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
if result.timed_out
|
|
27
|
+
return Ask::Result.error(
|
|
28
|
+
message: "Command timed out",
|
|
29
|
+
metadata: { stdout: result.stdout, stderr: result.stderr }
|
|
30
|
+
)
|
|
74
31
|
end
|
|
32
|
+
|
|
33
|
+
Ask::Result.ok(data: {
|
|
34
|
+
stdout: result.stdout,
|
|
35
|
+
stderr: result.stderr,
|
|
36
|
+
exit_code: result.exit_code,
|
|
37
|
+
timed_out: result.timed_out
|
|
38
|
+
})
|
|
75
39
|
end
|
|
76
40
|
end
|
|
77
41
|
end
|
data/lib/ask/tools/shell/code.rb
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "
|
|
4
|
-
require "tmpdir"
|
|
3
|
+
require "ask-sandbox-providers"
|
|
5
4
|
|
|
6
5
|
module Ask
|
|
7
6
|
module Tools
|
|
8
7
|
# Write and execute Ruby code in a subprocess.
|
|
9
|
-
# Runs
|
|
8
|
+
# Runs via Ask::Sandbox.provider (Local by default, configurable for
|
|
9
|
+
# stronger isolation via Docker, Daytona, or Cloudflare).
|
|
10
10
|
class Code < Ask::Tool
|
|
11
11
|
description "Write and execute Ruby code in a subprocess. " \
|
|
12
12
|
"Returns stdout, stderr, and exit code. " \
|
|
@@ -14,45 +14,24 @@ module Ask
|
|
|
14
14
|
|
|
15
15
|
param :code, type: :string, desc: "Ruby source code to execute", required: true
|
|
16
16
|
|
|
17
|
-
MAX_OUTPUT_SIZE = 102_400
|
|
18
|
-
|
|
19
17
|
def execute(code:)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
Thread.new { IO.copy_stream(out, stdout) rescue nil },
|
|
31
|
-
Thread.new { IO.copy_stream(err, stderr) rescue nil }
|
|
32
|
-
]
|
|
33
|
-
|
|
34
|
-
threads.each(&:join)
|
|
35
|
-
exit_code = wait_thr.value.exitstatus
|
|
36
|
-
end
|
|
37
|
-
rescue => e
|
|
38
|
-
return Ask::Result.error(message: "Code execution failed: #{e.message}",
|
|
39
|
-
metadata: { stdout: stdout.string, stderr: stderr.string })
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
out_text = stdout.string
|
|
43
|
-
err_text = stderr.string
|
|
44
|
-
|
|
45
|
-
if out_text.length > MAX_OUTPUT_SIZE
|
|
46
|
-
header = "[Output truncated to #{MAX_OUTPUT_SIZE / 1024}KB]\n"
|
|
47
|
-
out_text = "#{header}#{out_text[-(MAX_OUTPUT_SIZE - header.length)..]}"
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
Ask::Result.ok(data: {
|
|
51
|
-
stdout: out_text,
|
|
52
|
-
stderr: err_text,
|
|
53
|
-
exit_code: exit_code
|
|
54
|
-
})
|
|
18
|
+
result = Ask::Sandbox.provider.call(
|
|
19
|
+
["ruby", "-e", code],
|
|
20
|
+
timeout: 30
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
if result.timed_out
|
|
24
|
+
return Ask::Result.error(
|
|
25
|
+
message: "Code execution timed out",
|
|
26
|
+
metadata: { stdout: result.stdout, stderr: result.stderr }
|
|
27
|
+
)
|
|
55
28
|
end
|
|
29
|
+
|
|
30
|
+
Ask::Result.ok(data: {
|
|
31
|
+
stdout: result.stdout,
|
|
32
|
+
stderr: result.stderr,
|
|
33
|
+
exit_code: result.exit_code
|
|
34
|
+
})
|
|
56
35
|
end
|
|
57
36
|
end
|
|
58
37
|
end
|
data/lib/ask/tools/shell.rb
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "shell/version"
|
|
4
|
+
require_relative "shell/bash"
|
|
5
|
+
require_relative "shell/read"
|
|
6
|
+
require_relative "shell/write"
|
|
7
|
+
require_relative "shell/edit"
|
|
8
|
+
require_relative "shell/glob"
|
|
9
|
+
require_relative "shell/grep"
|
|
10
|
+
require_relative "shell/code"
|
|
11
|
+
|
|
3
12
|
module Ask
|
|
4
13
|
module Tools
|
|
5
|
-
# Collection point for shell tools.
|
|
6
|
-
#
|
|
7
|
-
# Ask::Tools::Shell.all # => [Bash, Read, Write, ...] instances
|
|
8
|
-
#
|
|
9
14
|
module Shell
|
|
10
15
|
TOOLS = [Bash, Read, Write, Edit, Glob, Grep, Code].freeze
|
|
11
|
-
|
|
12
|
-
# Return an instance of every registered shell tool.
|
|
13
|
-
#
|
|
14
|
-
# @return [Array<Ask::Tool>]
|
|
15
|
-
def self.all
|
|
16
|
-
TOOLS.map(&:new)
|
|
17
|
-
end
|
|
18
16
|
end
|
|
19
17
|
end
|
|
20
18
|
end
|
data/lib/ask-tools-shell.rb
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "ask-tools"
|
|
4
|
-
|
|
5
|
-
require_relative "ask/tools/shell/version"
|
|
6
|
-
require_relative "ask/tools/shell/bash"
|
|
7
|
-
require_relative "ask/tools/shell/read"
|
|
8
|
-
require_relative "ask/tools/shell/write"
|
|
9
|
-
require_relative "ask/tools/shell/edit"
|
|
10
|
-
require_relative "ask/tools/shell/glob"
|
|
11
|
-
require_relative "ask/tools/shell/grep"
|
|
12
|
-
require_relative "ask/tools/shell/code"
|
|
13
|
-
require_relative "ask/tools/shell"
|
|
4
|
+
require "ask/tools/shell"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ask-tools-shell
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kaka Ruto
|
|
@@ -23,6 +23,20 @@ dependencies:
|
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '0.1'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: ask-sandbox-providers
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0.1'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0.1'
|
|
26
40
|
- !ruby/object:Gem::Dependency
|
|
27
41
|
name: minitest
|
|
28
42
|
requirement: !ruby/object:Gem::Requirement
|