daytona 0.170.0 → 0.171.0.rc.1

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: 7515dcf7e9ce6366233315925a09418cfe7714473f55ccf2062010f3d5ac692c
4
- data.tar.gz: 85148ff08b50b7a9d647ac53ae8b73622e5e3d9d01f9a211229a1ec071f49979
3
+ metadata.gz: 5471eba0ff200757c6372f92f80f5369c48a17cddb2dcf46f1c75f802a5e4519
4
+ data.tar.gz: d3ce842087c3ce1a84ee083d510650e2cd64ff3c516ab0240a967e9a59047810
5
5
  SHA512:
6
- metadata.gz: ccd9ad77b30a91e4aa4ca503d87d3d9a976978b553bf3c0a1ba6e80c912c804bfab99b520377edc71ab17abd4eb22790edac7ae683bf2f6a58bfe6419a08e390
7
- data.tar.gz: 071d6d27256509829400a640d70b386c7a627e44731b07b0a2ba04559c3837bf31ec4f037c76f9f4bdbe5073af58d9660551d14ccac9e6fff5dd653712c0b04a
6
+ metadata.gz: 15fa69f937b6c13f5ae96509ae0ab2e31be713075f7247fd3d3a71c1078771aa775f762a00ab9c6e84cd78688ac7cda9973ca0c12bced64894d758100758f5bc
7
+ data.tar.gz: b5cccda24d664d4ecc74a01fe891e12310a51d20152dfbae8be15255da5ed4244c23cd7e77250cbb8405ba98871e25e40125a0f1538615124d2e3f9a3e599710
@@ -103,15 +103,11 @@ module Daytona
103
103
  'Accept' => 'application/json'
104
104
  )
105
105
 
106
- # Use queue for synchronization
107
106
  completion_queue = Queue.new
108
- interpreter = self # Capture self for use in blocks
109
- last_message_time = Time.now
110
- message_mutex = Mutex.new
107
+ interpreter = self
111
108
 
112
109
  puts "[DEBUG] Connecting to WebSocket: #{ws_url}" if ENV['DEBUG']
113
110
 
114
- # Connect to WebSocket and execute
115
111
  ws = WebSocket::Client::Simple.connect(ws_url, headers:)
116
112
 
117
113
  ws.on :open do
@@ -120,8 +116,6 @@ module Daytona
120
116
  end
121
117
 
122
118
  ws.on :message do |msg|
123
- message_mutex.synchronize { last_message_time = Time.now }
124
-
125
119
  puts "[DEBUG] Received message (length=#{msg.data.length}): #{msg.data.inspect[0..200]}" if ENV['DEBUG']
126
120
 
127
121
  interpreter.send(:handle_message, msg.data, result, on_stdout, on_stderr, on_error, completion_queue)
@@ -146,72 +140,59 @@ module Daytona
146
140
  end
147
141
  end
148
142
 
149
- # Wait for completion signal with idle timeout
150
- # If timeout is specified, wait longer to detect actual timeout errors
151
- # Otherwise use short idle timeout for normal completion
152
- idle_timeout = timeout ? (timeout + 2.0) : 1.0
153
- max_wait = (timeout || 300) + 3 # Add buffer to configured timeout
143
+ no_timeout = timeout.is_a?(Numeric) && timeout <= 0
144
+ max_wait = no_timeout ? nil : (timeout || 600) + 3
154
145
  start_time = Time.now
155
146
  completion_reason = nil
156
147
 
157
- # Wait for completion or close event
158
148
  loop do
159
- begin
160
- completion = completion_queue.pop(true) # non-blocking
161
- puts "[DEBUG] Got completion signal: #{completion[:type]}" if ENV['DEBUG']
162
-
163
- # Control message (completed/interrupted) = normal completion
164
- if completion[:type] == :completed
165
- completion_reason = :completed
166
- break
167
- # If it's an error from close event (like timeout), raise it
168
- elsif completion[:type] == :error_from_close
169
- error_msg = completion[:error]
170
- # Raise TimeoutError for timeout cases, regular Error for others
171
- if error_msg.include?('timed out') || error_msg.include?('Execution timed out')
172
- raise Sdk::TimeoutError, error_msg
173
- end
174
-
175
- raise Sdk::Error, error_msg
176
-
177
- # Close event during execution (before control message) = likely timeout or error
178
- elsif completion[:type] == :close
179
- elapsed = Time.now - start_time
180
- # If we got close near the timeout, it's likely a timeout
181
- if timeout && elapsed >= timeout && elapsed < (timeout + 2)
182
- raise Sdk::TimeoutError,
183
- 'Execution timed out: operation exceeded the configured `timeout`. Provide a larger value if needed.'
184
- end
185
- # Otherwise normal close
186
- completion_reason = :close
187
- break
188
- # WebSocket errors
189
- elsif completion[:type] == :error && !completion[:error].message.include?('stream closed')
190
- raise Sdk::Error, "WebSocket error: #{completion[:error].message}"
149
+ if max_wait
150
+ remaining = max_wait - (Time.now - start_time)
151
+ if remaining <= 0
152
+ ws.close
153
+ raise Sdk::TimeoutError,
154
+ 'Execution timed out: operation exceeded the configured `timeout`. Provide a larger value if needed.'
191
155
  end
192
- rescue ThreadError
193
- # Queue is empty, check idle timeout
194
156
  end
195
157
 
196
- # Check idle timeout (no messages for N seconds = completion)
197
- time_since_last_message = message_mutex.synchronize { Time.now - last_message_time }
198
- if time_since_last_message > idle_timeout
199
- puts "[DEBUG] Idle timeout reached (#{idle_timeout}s), assuming completion" if ENV['DEBUG']
200
- completion_reason = :idle_complete
201
- break
202
- end
158
+ completion = completion_queue.pop(timeout: max_wait ? remaining : nil)
203
159
 
204
- # Check for absolute timeout (safety net)
205
- if Time.now - start_time > max_wait
160
+ if completion.nil?
206
161
  ws.close
207
162
  raise Sdk::TimeoutError,
208
163
  'Execution timed out: operation exceeded the configured `timeout`. Provide a larger value if needed.'
209
164
  end
210
165
 
211
- sleep 0.05 # Check every 50ms
166
+ puts "[DEBUG] Got completion signal: #{completion[:type]}" if ENV['DEBUG']
167
+
168
+ if completion[:type] == :completed
169
+ completion_reason = :completed
170
+ break
171
+ elsif completion[:type] == :error_from_close
172
+ error_msg = completion[:error]
173
+ if error_msg.include?('timed out') || error_msg.include?('Execution timed out')
174
+ raise Sdk::TimeoutError, error_msg
175
+ end
176
+
177
+ raise Sdk::Error, error_msg
178
+ elsif completion[:type] == :close
179
+ elapsed = Time.now - start_time
180
+ if timeout && timeout > 0 && elapsed >= timeout && elapsed < (timeout + 2)
181
+ raise Sdk::TimeoutError,
182
+ 'Execution timed out: operation exceeded the configured `timeout`. Provide a larger value if needed.'
183
+ end
184
+ completion_reason = :close
185
+ break
186
+ elsif completion[:type] == :error
187
+ unless completion[:error].message.include?('stream closed')
188
+ raise Sdk::Error, "WebSocket error: #{completion[:error].message}"
189
+ end
190
+
191
+ completion_reason = :close
192
+ break
193
+ end
212
194
  end
213
195
 
214
- # Close WebSocket if not already closed
215
196
  ws.close if completion_reason != :close
216
197
  sleep 0.05
217
198
 
@@ -46,6 +46,12 @@ module Daytona
46
46
  # @return [Boolean, nil] Whether the Sandbox should be ephemeral
47
47
  attr_accessor :ephemeral
48
48
 
49
+ # @return [String, nil] ID or name of an existing Sandbox to link the new Sandbox to. The new
50
+ # Sandbox will be scheduled on the same runner as the linked Sandbox so a local network can be
51
+ # established between them. Only supported for android-class snapshots. Linked Sandboxes must be
52
+ # ephemeral (auto_delete_interval=0) and cannot themselves be linked to another Sandbox.
53
+ attr_accessor :linked_sandbox
54
+
49
55
  # Initialize CreateSandboxBaseParams
50
56
  #
51
57
  # @param language [Symbol, nil] Programming language for the Sandbox
@@ -61,6 +67,7 @@ module Daytona
61
67
  # @param network_block_all [Boolean, nil] Whether to block all network access for the Sandbox
62
68
  # @param network_allow_list [String, nil] Comma-separated list of allowed CIDR network addresses for the Sandbox
63
69
  # @param ephemeral [Boolean, nil] Whether the Sandbox should be ephemeral
70
+ # @param linked_sandbox [String, nil] ID or name of an existing Sandbox to link the new Sandbox to
64
71
  def initialize( # rubocop:disable Metrics/MethodLength, Metrics/ParameterLists
65
72
  language: nil,
66
73
  os_user: nil,
@@ -74,7 +81,8 @@ module Daytona
74
81
  volumes: nil,
75
82
  network_block_all: nil,
76
83
  network_allow_list: nil,
77
- ephemeral: nil
84
+ ephemeral: nil,
85
+ linked_sandbox: nil
78
86
  )
79
87
  @language = language
80
88
  @os_user = os_user
@@ -89,6 +97,7 @@ module Daytona
89
97
  @network_block_all = network_block_all
90
98
  @network_allow_list = network_allow_list
91
99
  @ephemeral = ephemeral
100
+ @linked_sandbox = linked_sandbox
92
101
 
93
102
  # Handle ephemeral and auto_delete_interval conflict
94
103
  handle_ephemeral_auto_delete_conflict
@@ -111,7 +120,8 @@ module Daytona
111
120
  volumes:,
112
121
  network_block_all:,
113
122
  network_allow_list:,
114
- ephemeral:
123
+ ephemeral:,
124
+ linked_sandbox:
115
125
  }.compact
116
126
  end
117
127
 
@@ -91,7 +91,7 @@ module Daytona
91
91
  #
92
92
  # @example
93
93
  # result = sandbox.computer_use.mouse.drag(start_x: 50, start_y: 50, end_x: 150, end_y: 150)
94
- # puts "Dragged from #{result.from_x},#{result.from_y} to #{result.to_x},#{result.to_y}"
94
+ # puts "Drag ended at #{result.x}, #{result.y}"
95
95
  def drag(start_x:, start_y:, end_x:, end_y:, button: 'left')
96
96
  request = DaytonaToolboxApiClient::MouseDragRequest.new(start_x:, start_y:, end_x:, end_y:, button:)
97
97
  toolbox_api.drag(request)
@@ -169,7 +169,8 @@ module Daytona
169
169
  auto_delete_interval: params.auto_delete_interval,
170
170
  volumes: params.volumes,
171
171
  network_block_all: params.network_block_all,
172
- network_allow_list: params.network_allow_list
172
+ network_allow_list: params.network_allow_list,
173
+ linked_sandbox: params.linked_sandbox
173
174
  )
174
175
 
175
176
  create_sandbox.snapshot = params.snapshot if params.respond_to?(:snapshot)
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Daytona
7
7
  module Sdk
8
- VERSION = '0.170.0'
8
+ VERSION = '0.171.0.rc.1'
9
9
  end
10
10
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: daytona
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.170.0
4
+ version: 0.171.0.rc.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daytona Platforms Inc.
@@ -85,28 +85,28 @@ dependencies:
85
85
  requirements:
86
86
  - - '='
87
87
  - !ruby/object:Gem::Version
88
- version: 0.170.0
88
+ version: 0.171.0.rc.1
89
89
  type: :runtime
90
90
  prerelease: false
91
91
  version_requirements: !ruby/object:Gem::Requirement
92
92
  requirements:
93
93
  - - '='
94
94
  - !ruby/object:Gem::Version
95
- version: 0.170.0
95
+ version: 0.171.0.rc.1
96
96
  - !ruby/object:Gem::Dependency
97
97
  name: daytona_toolbox_api_client
98
98
  requirement: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - '='
101
101
  - !ruby/object:Gem::Version
102
- version: 0.170.0
102
+ version: 0.171.0.rc.1
103
103
  type: :runtime
104
104
  prerelease: false
105
105
  version_requirements: !ruby/object:Gem::Requirement
106
106
  requirements:
107
107
  - - '='
108
108
  - !ruby/object:Gem::Version
109
- version: 0.170.0
109
+ version: 0.171.0.rc.1
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: dotenv
112
112
  requirement: !ruby/object:Gem::Requirement