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 +4 -4
- data/lib/daytona/code_interpreter.rb +39 -58
- data/lib/daytona/common/daytona.rb +12 -2
- data/lib/daytona/computer_use.rb +1 -1
- data/lib/daytona/daytona.rb +2 -1
- data/lib/daytona/sdk/version.rb +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5471eba0ff200757c6372f92f80f5369c48a17cddb2dcf46f1c75f802a5e4519
|
|
4
|
+
data.tar.gz: d3ce842087c3ce1a84ee083d510650e2cd64ff3c516ab0240a967e9a59047810
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
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
|
-
|
|
150
|
-
|
|
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
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
data/lib/daytona/computer_use.rb
CHANGED
|
@@ -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 "
|
|
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)
|
data/lib/daytona/daytona.rb
CHANGED
|
@@ -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)
|
data/lib/daytona/sdk/version.rb
CHANGED
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
109
|
+
version: 0.171.0.rc.1
|
|
110
110
|
- !ruby/object:Gem::Dependency
|
|
111
111
|
name: dotenv
|
|
112
112
|
requirement: !ruby/object:Gem::Requirement
|