aidp 0.39.7 → 0.39.8
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/aidp/interfaces/command_executor_interface.rb +56 -9
- data/lib/aidp/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5df865d45987ecd333e79480c0329acc64ef04ffec6c8810a0e43fd94b5b9236
|
|
4
|
+
data.tar.gz: '08b02ed42782161769e3ec9bc81e7d747b97d735cbcbb3031af01df6a94b3f5a'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 118d2e50c63cd1bc536d3c0acd8dd01b626f174328eed7e0614e3ba13cb29315472cdc4caa0a6dda6f8672498b0bbae404e00cb11fcef40d36643b195c8b7a72
|
|
7
|
+
data.tar.gz: a0667e973b6ed0a1eaf704a7ee5bb019870d4ad2163c00ba40c2b5cd3009add2dbf9c99172b4678e0588dfd7e2a821025a1bcbaf0311b99cf0282e33b4001600
|
|
@@ -128,6 +128,8 @@ module Aidp
|
|
|
128
128
|
class TtyCommandExecutor
|
|
129
129
|
include CommandExecutorInterface
|
|
130
130
|
|
|
131
|
+
TERMINATION_GRACE_PERIOD = 0.1
|
|
132
|
+
|
|
131
133
|
# @param logger [LoggerInterface] optional logger for debug output
|
|
132
134
|
# @param component_name [String] component name for logging
|
|
133
135
|
def initialize(logger: nil, component_name: "command_executor")
|
|
@@ -144,20 +146,14 @@ module Aidp
|
|
|
144
146
|
# @param options [Hash] additional options passed to TTY::Command#run
|
|
145
147
|
# @return [CommandResult] the result of the command execution
|
|
146
148
|
def execute(command, args: [], input: nil, timeout: nil, **options)
|
|
147
|
-
require "
|
|
149
|
+
require "open3"
|
|
148
150
|
|
|
149
151
|
log_debug("executing_command", command: command, args: args, timeout: timeout)
|
|
150
152
|
|
|
151
153
|
start_time = Time.now
|
|
152
154
|
|
|
153
155
|
begin
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
# Prepare input data
|
|
157
|
-
input_data = resolve_input(input)
|
|
158
|
-
|
|
159
|
-
# Execute command - use run! to get result even on non-zero exit
|
|
160
|
-
result = cmd_obj.run!(command, *args, input: input_data, timeout: timeout, **options)
|
|
156
|
+
result = execute_command(command, args, resolve_input(input), timeout, options)
|
|
161
157
|
|
|
162
158
|
duration = Time.now - start_time
|
|
163
159
|
log_debug("command_completed",
|
|
@@ -170,7 +166,7 @@ module Aidp
|
|
|
170
166
|
stderr: result.err,
|
|
171
167
|
exit_status: result.exit_status
|
|
172
168
|
)
|
|
173
|
-
rescue
|
|
169
|
+
rescue CommandTimeoutError
|
|
174
170
|
duration = Time.now - start_time
|
|
175
171
|
log_debug("command_timeout",
|
|
176
172
|
command: command,
|
|
@@ -197,6 +193,57 @@ module Aidp
|
|
|
197
193
|
|
|
198
194
|
private
|
|
199
195
|
|
|
196
|
+
def execute_command(command, args, input_data, timeout, options)
|
|
197
|
+
env = options.delete(:env) || {}
|
|
198
|
+
Open3.popen3(env, command.to_s, *args.map(&:to_s), **options) do |stdin, stdout, stderr, wait_thread|
|
|
199
|
+
write_input(stdin, input_data)
|
|
200
|
+
out_reader = Thread.new { read_stream(stdout) }
|
|
201
|
+
err_reader = Thread.new { read_stream(stderr) }
|
|
202
|
+
status = wait_for_process(wait_thread, command, timeout)
|
|
203
|
+
CommandResult.new(
|
|
204
|
+
stdout: out_reader.value,
|
|
205
|
+
stderr: err_reader.value,
|
|
206
|
+
exit_status: status.exitstatus
|
|
207
|
+
)
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def write_input(stdin, input_data)
|
|
212
|
+
return stdin.close unless input_data
|
|
213
|
+
|
|
214
|
+
stdin.write(input_data)
|
|
215
|
+
stdin.close
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def wait_for_process(wait_thread, command, timeout)
|
|
219
|
+
return wait_thread.value unless timeout
|
|
220
|
+
|
|
221
|
+
return wait_thread.value if wait_thread.join(timeout)
|
|
222
|
+
|
|
223
|
+
terminate_process(wait_thread)
|
|
224
|
+
raise CommandTimeoutError.new(command: command, timeout: timeout)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def terminate_process(wait_thread)
|
|
228
|
+
signal_process(wait_thread.pid, "TERM")
|
|
229
|
+
return if wait_thread.join(TERMINATION_GRACE_PERIOD)
|
|
230
|
+
|
|
231
|
+
signal_process(wait_thread.pid, "KILL")
|
|
232
|
+
wait_thread.join
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def signal_process(pid, signal)
|
|
236
|
+
Process.kill(signal, pid)
|
|
237
|
+
rescue Errno::ESRCH
|
|
238
|
+
nil
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def read_stream(stream)
|
|
242
|
+
stream.read
|
|
243
|
+
rescue IOError
|
|
244
|
+
""
|
|
245
|
+
end
|
|
246
|
+
|
|
200
247
|
def resolve_input(input)
|
|
201
248
|
return nil unless input
|
|
202
249
|
|
data/lib/aidp/version.rb
CHANGED