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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eeb4172f8395dae1cecfd4019377e8ec5435746c39e785d8a74e60f0ffdfd202
4
- data.tar.gz: 60b3ee0ca0796fbbd96014487689313c1c360558df80b22404c4a8457c9f27df
3
+ metadata.gz: 5df865d45987ecd333e79480c0329acc64ef04ffec6c8810a0e43fd94b5b9236
4
+ data.tar.gz: '08b02ed42782161769e3ec9bc81e7d747b97d735cbcbb3031af01df6a94b3f5a'
5
5
  SHA512:
6
- metadata.gz: 3f4e93eed39bb3b8dc88c21f65e64504689c6c53192994dbe4d8e6b6798aef1912d620a1d3cbd1b01602b9b27715b820a4f49e812f20756e06a61a8ca7ca44d9
7
- data.tar.gz: 5e881d0b36e7d7d746c2eddf4d353c091fe51265369841ae8e58a35f1322265a64672afb857c9010e487b60b1f1b97d080608d281898be5b972a836763fdded6
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 "tty-command"
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
- cmd_obj = TTY::Command.new(printer: :null)
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 TTY::Command::TimeoutExceeded
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Aidp
4
- VERSION = "0.39.7"
4
+ VERSION = "0.39.8"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aidp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.39.7
4
+ version: 0.39.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bart Agapinan