daytona 0.163.0 → 0.164.0.alpha.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: c80d82abdea9151dd32d9e78672eeed2599929431f1eed2492eefd74a7ae69da
4
- data.tar.gz: 1a07f8be5ea538e100e7dbcf246eca724cc086bc5a60588e650b31412b234c89
3
+ metadata.gz: 064c93ac0f9ef2c0bebd53497d5f86584f8a75b684cad9029575d1a7efa37f48
4
+ data.tar.gz: c61d029c96aca2d15f62d3dec3de189d3741902bc5f818d1e07aa535f591bbe6
5
5
  SHA512:
6
- metadata.gz: d987d6679b98e3d5e259fe65b91e898d83e7ed75d4d16e82f1e7147c9b0a3c0ea7fbbf97b5d66d300ad87951fe6487ab75a61f2b69c45bf72f1c2b615e9a9603
7
- data.tar.gz: '07967504fa22e9bb43baaf68685b0ddbac35184d753155bc589c58fb6bfe12e1c76201bcb862d13c1f606845d02a738e896021e8407fe372524bf0e1bb5f7821'
6
+ metadata.gz: e26f87d3f2a68b701a07ea391adcf0c3a3316f0ac19d06ee8d4381629f223b640410950b5a8454592cf2a2634b3204bdcb5b39852414fab46ef5e0a0701bdf1b
7
+ data.tar.gz: dbb7d8482d32949673de9fb43a68544d0219c46de4905a21f187e37eb482a5dc44312cec6ccc94f6075e28ed946ed947d608a7774029a3ed41fb715a48b63e4d
@@ -1,298 +1,121 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Daytona
4
- module Charts
5
- # @param data [Hash<Symbol, Object>]
6
- # @return [Daytona::Charts::Chart]
7
- def self.parse(data)
8
- case data.fetch(:type, ChartType::UNKNOWN)
9
- when ChartType::LINE then LineChart.new(data)
10
- when ChartType::SCATTER then ScatterChart.new(data)
11
- when ChartType::BAR then BarChart.new(data)
12
- when ChartType::PIE then PieChart.new(data)
13
- when ChartType::BOX_AND_WHISKER then BoxAndWhiskerChart.new(data)
14
- when ChartType::COMPOSITE_CHART then CompositeChart.new(data)
15
- else
16
- Chart.new(data)
17
- end
18
- end
19
-
20
- class Chart
21
- # @return [String, Nil] The type of chart
22
- attr_reader :type
23
-
24
- # @return [String, Nil] The title of the chart
25
- attr_reader :title
26
-
27
- # @return [Array<Object>] The elements of the chart
28
- attr_reader :elements
29
-
30
- # @return [String, Nil] The PNG representation of the chart encoded in base64
31
- attr_reader :png
32
-
33
- # @param data [Hash<Symbol, Object>]
34
- def initialize(data)
35
- @type = data.fetch(:type, nil)
36
- @title = data.fetch(:title, nil)
37
- @elements = data.fetch(:elements, [])
38
- @png = data.fetch(:png, nil)
39
- end
40
-
41
- # @return [Hash<Symbol, Object>] original metadata
42
- def to_h = { type:, title:, elements:, png: }
43
- end
44
-
45
- class Chart2D < Chart
46
- # @return [String, Nil] The label of the x-axis
47
- attr_reader :x_label
48
-
49
- # @return [String, Nil] The label of the y-axis
50
- attr_reader :y_label
51
-
52
- # @param data [Hash<Symbol, Object>]
53
- def initialize(data)
54
- super
55
- @x_label = data.fetch(:x_label, nil)
56
- @y_label = data.fetch(:y_label, nil)
57
- end
58
-
59
- # @return [Hash<Symbol, Object>] original metadata
60
- def to_h = super.merge(x_label:, y_label:)
61
- end
62
-
63
- class PointData
64
- # @return [String] The label of the point series
65
- attr_reader :label
66
-
67
- # @return [Array<Array<Object>>] Array of [x, y] points
68
- attr_reader :points
69
-
70
- # @param data [Hash<Symbol, Object>]
71
- def initialize(data)
72
- @label = data.fetch(:label)
73
- @points = data.fetch(:points)
74
- end
75
-
76
- # @return [Hash<Symbol, Object>] original data representation
77
- def to_h = { label:, points: }
78
- end
79
-
80
- class PointChart < Chart2D
81
- # @return [Array<Object>] The ticks of the x-axis
82
- attr_reader :x_ticks
83
-
84
- # @return [Array<String>] The labels of the x-axis
85
- attr_reader :x_tick_labels
86
-
87
- # @return [String, Nil] The scale of the x-axis
88
- attr_reader :x_scale
89
-
90
- # @return [Array<Object>] The ticks of the y-axis
91
- attr_reader :y_ticks
92
-
93
- # @return [Array<String>] The labels of the y-axis
94
- attr_reader :y_tick_labels
95
-
96
- # @return [String, Nil] The scale of the y-axis
97
- attr_reader :y_scale
98
-
99
- # @return [Array<Daytona::Charts::PointData>] The points of the chart
100
- attr_reader :elements
101
-
102
- # @param data [Hash<Symbol, Object>]
103
- def initialize(data)
104
- super
105
- @x_scale = data.fetch(:x_scale, nil)
106
- @x_ticks = data.fetch(:x_ticks, nil)
107
- @x_tick_labels = data.fetch(:x_tick_labels, nil)
108
-
109
- @y_scale = data.fetch(:y_scale, nil)
110
- @y_ticks = data.fetch(:y_ticks, nil)
111
- @y_tick_labels = data.fetch(:y_tick_labels, nil)
112
-
113
- @elements = data.fetch(:elements, []).map { |e| PointData.new(e) }
114
- end
115
-
116
- # @return [Hash<Symbol, Object>] original metadata
117
- def to_h
118
- super.merge(
119
- x_scale:,
120
- x_ticks:,
121
- x_tick_labels:,
122
- y_scale:,
123
- y_ticks:,
124
- y_tick_labels:,
125
- elements: elements.map(&:to_h)
126
- )
127
- end
128
- end
129
-
130
- class LineChart < PointChart
131
- def initialize(data)
132
- super
133
- @type = ChartType::LINE
134
- end
135
- end
136
-
137
- class ScatterChart < PointChart
138
- def initialize(data)
139
- super
140
- @type = ChartType::SCATTER
141
- end
142
- end
143
-
144
- class BarData
145
- # @return [String] The label of the bar
146
- attr_reader :label
147
-
148
- # @return [String] The value of the bar
149
- attr_reader :value
150
-
151
- # @return [String] The group of the bar
152
- attr_reader :group
153
-
154
- # @param data [Hash<Symbol, Object>]
155
- def initialize(data)
156
- @label = data.fetch(:label)
157
- @value = data.fetch(:value)
158
- @group = data.fetch(:group)
159
- end
160
-
161
- # @return [Hash<Symbol, Object>]
162
- def to_h = { label:, value:, group: }
163
- end
164
-
165
- class BarChart < Chart2D
166
- # @return [Array<Daytona::Charts::BarData>] The bars of the chart
167
- attr_reader :elements
4
+ ChartElement = DaytonaToolboxApiClient::ChartElement
5
+
6
+ module ChartType
7
+ LINE = 'line'
8
+ SCATTER = 'scatter'
9
+ BAR = 'bar'
10
+ PIE = 'pie'
11
+ BOX_AND_WHISKER = 'box_and_whisker'
12
+ COMPOSITE_CHART = 'composite_chart'
13
+ UNKNOWN = 'unknown'
14
+ end
168
15
 
169
- # @param data [Hash<Symbol, Object>]
170
- def initialize(data)
171
- super
172
- @type = ChartType::BAR
173
- @elements = data.fetch(:elements, []).map { |e| BarData.new(e) }
174
- end
16
+ PointData = Struct.new(:label, :points, keyword_init: true)
17
+ BarData = Struct.new(:label, :value, :group, keyword_init: true)
18
+ PieData = Struct.new(:label, :angle, :radius, keyword_init: true)
19
+ BoxAndWhiskerData = Struct.new(:label, :min, :first_quartile, :median, :third_quartile, :max, :outliers,
20
+ keyword_init: true)
175
21
 
176
- # @return [Hash<Symbol, Object>]
177
- def to_h = super.merge(elements: elements.map(&:to_h))
22
+ Chart = Struct.new(:type, :title, :png, :elements, keyword_init: true) do
23
+ def initialize(type: nil, title: nil, png: nil, elements: [])
24
+ super
178
25
  end
26
+ end
179
27
 
180
- class PieData
181
- # @return [String] The label of the pie slice
182
- attr_reader :label
183
-
184
- # @return [Float] The angle of the pie slice
185
- attr_reader :angle
186
-
187
- # @return [Float] The radius of the pie slice
188
- attr_reader :radius
189
-
190
- # @return [Float] The autopct value of the pie slice
191
- attr_reader :autopct
192
-
193
- # @param data [Hash<Symbol, Object>]
194
- def initialize(data)
195
- @label = data.fetch(:label)
196
- @angle = data.fetch(:angle)
197
- @radius = data.fetch(:radius)
198
- @autopct = data.fetch(:autopct)
199
- end
200
-
201
- # @return [Hash<Symbol, Object>]
202
- def to_h = { label:, angle:, radius:, autopct: }
28
+ Chart2D = Struct.new(:type, :title, :png, :elements, :x_label, :y_label, keyword_init: true) do
29
+ def initialize(type: nil, title: nil, png: nil, elements: [], x_label: nil, y_label: nil)
30
+ super
203
31
  end
32
+ end
204
33
 
205
- class PieChart < Chart
206
- # @return [Array<Daytona::Charts::PieData>] The pie slices of the chart
207
- attr_reader :elements
208
-
209
- # @param data [Hash<Symbol, Object>]
210
- def initialize(data)
211
- super
212
- @type = ChartType::PIE
213
- @elements = data.fetch(:elements, []).map { |e| PieData.new(e) }
214
- end
215
-
216
- # @return [Hash<Symbol, Object>]
217
- def to_h = super.merge(elements: elements.map(&:to_h))
34
+ PointChart = Struct.new(:type, :title, :png, :elements, :x_label, :y_label,
35
+ :x_ticks, :y_ticks, :x_tick_labels, :y_tick_labels,
36
+ :x_scale, :y_scale, keyword_init: true) do
37
+ def initialize(type: nil, title: nil, png: nil, elements: [], x_label: nil, y_label: nil,
38
+ x_ticks: nil, y_ticks: nil, x_tick_labels: nil, y_tick_labels: nil,
39
+ x_scale: nil, y_scale: nil)
40
+ super
218
41
  end
42
+ end
219
43
 
220
- class BoxAndWhiskerData
221
- # @return [String] The label of the box and whisker
222
- attr_reader :label
223
-
224
- # @return [Float] The minimum value of the box and whisker
225
- attr_reader :min
226
-
227
- # @return [Float] The first quartile of the box and whisker
228
- attr_reader :first_quartile
229
-
230
- # @return [Float] The median of the box and whisker
231
- attr_reader :median
232
-
233
- # @return [Float] The third quartile of the box and whisker
234
- attr_reader :third_quartile
44
+ class LineChart < PointChart
45
+ end
235
46
 
236
- # @return [Float] The maximum value of the box and whisker
237
- attr_reader :max
47
+ class ScatterChart < PointChart
48
+ end
238
49
 
239
- # @return [Array<Float>] The outliers of the box and whisker
240
- attr_reader :outliers
50
+ class BarChart < Chart2D
51
+ end
241
52
 
242
- # @param data [Hash<Symbol, Object>]
243
- def initialize(data)
244
- @label = data.fetch(:label)
245
- @min = data.fetch(:min)
246
- @first_quartile = data.fetch(:first_quartile)
247
- @median = data.fetch(:median)
248
- @third_quartile = data.fetch(:third_quartile)
249
- @max = data.fetch(:max)
250
- @outliers = data.fetch(:outliers, [])
251
- end
53
+ class PieChart < Chart
54
+ end
252
55
 
253
- # @return [Hash<Symbol, Object>]
254
- def to_h = { label:, min:, first_quartile:, median:, third_quartile:, max:, outliers: }
255
- end
56
+ class BoxAndWhiskerChart < Chart2D
57
+ end
256
58
 
257
- class BoxAndWhiskerChart < Chart2D
258
- # @return [Array<Daytona::Charts::BoxAndWhiskerData>] The box and whiskers of the chart
259
- attr_reader :elements
59
+ class CompositeChart < Chart
60
+ end
260
61
 
261
- # @param data [Hash<Symbol, Object>]
262
- def initialize(data)
263
- super
264
- @type = ChartType::BOX_AND_WHISKER
265
- @elements = data.fetch(:elements, []).map { |e| BoxAndWhiskerData.new(e) }
62
+ module Charts
63
+ Chart = Daytona::Chart
64
+ ChartElement = Daytona::ChartElement
65
+ ChartType = Daytona::ChartType
66
+ LineChart = Daytona::LineChart
67
+ ScatterChart = Daytona::ScatterChart
68
+ BarChart = Daytona::BarChart
69
+ PieChart = Daytona::PieChart
70
+ BoxAndWhiskerChart = Daytona::BoxAndWhiskerChart
71
+ CompositeChart = Daytona::CompositeChart
72
+ PointData = Daytona::PointData
73
+ BarData = Daytona::BarData
74
+ PieData = Daytona::PieData
75
+ BoxAndWhiskerData = Daytona::BoxAndWhiskerData
76
+
77
+ def self.parse_chart(chart)
78
+ type = chart.type || ChartType::UNKNOWN
79
+ elements = (chart.elements || []).map { |el| map_element(el, type) }
80
+ common = { type: chart.type, title: chart.title, png: chart.png, elements: elements }
81
+
82
+ case type
83
+ when ChartType::LINE
84
+ LineChart.new(x_label: chart.x_label, y_label: chart.y_label, x_ticks: chart.x_ticks, y_ticks: chart.y_ticks,
85
+ x_tick_labels: chart.x_tick_labels, y_tick_labels: chart.y_tick_labels,
86
+ x_scale: chart.x_scale, y_scale: chart.y_scale, **common)
87
+ when ChartType::SCATTER
88
+ ScatterChart.new(x_label: chart.x_label, y_label: chart.y_label, x_ticks: chart.x_ticks, y_ticks: chart.y_ticks,
89
+ x_tick_labels: chart.x_tick_labels, y_tick_labels: chart.y_tick_labels,
90
+ x_scale: chart.x_scale, y_scale: chart.y_scale, **common)
91
+ when ChartType::BAR
92
+ BarChart.new(x_label: chart.x_label, y_label: chart.y_label, **common)
93
+ when ChartType::PIE
94
+ PieChart.new(**common)
95
+ when ChartType::BOX_AND_WHISKER
96
+ BoxAndWhiskerChart.new(x_label: chart.x_label, y_label: chart.y_label, **common)
97
+ when ChartType::COMPOSITE_CHART
98
+ CompositeChart.new(**common)
99
+ else
100
+ Chart.new(**common)
266
101
  end
267
-
268
- # @return [Hash<Symbol, Object>]
269
- def to_h = super.merge(elements: elements.map(&:to_h))
270
102
  end
271
103
 
272
- class CompositeChart < Chart
273
- # @return [Array<Daytona::Charts::Chart>] The charts of the composite chart
274
- attr_reader :elements
275
-
276
- # @param data [Hash<Symbol, Object>]
277
- def initialize(data)
278
- super
279
- @type = ChartType::COMPOSITE_CHART
280
- @elements = data.fetch(:elements, []).map { |e| Charts.parse(e) }
104
+ def self.map_element(el, chart_type)
105
+ case chart_type
106
+ when ChartType::LINE, ChartType::SCATTER
107
+ PointData.new(label: el.label, points: el.points)
108
+ when ChartType::BAR
109
+ BarData.new(label: el.label, value: el.value, group: el.group)
110
+ when ChartType::PIE
111
+ PieData.new(label: el.label, angle: el.angle, radius: el.radius)
112
+ when ChartType::BOX_AND_WHISKER
113
+ BoxAndWhiskerData.new(label: el.label, min: el.min, first_quartile: el.first_quartile,
114
+ median: el.median, third_quartile: el.third_quartile,
115
+ max: el.max, outliers: el.outliers)
116
+ else
117
+ el
281
118
  end
282
-
283
- def to_h = super.merge(elements: elements.map(&:to_h))
284
- end
285
-
286
- module ChartType
287
- ALL = [
288
- LINE = 'line',
289
- SCATTER = 'scatter',
290
- BAR = 'bar',
291
- PIE = 'pie',
292
- BOX_AND_WHISKER = 'box_and_whisker',
293
- COMPOSITE_CHART = 'composite_chart',
294
- UNKNOWN = 'unknown'
295
- ].freeze
296
119
  end
297
120
  end
298
121
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Daytona
4
+ CODE_TOOLBOX_LANGUAGE_LABEL = 'code-toolbox-language'
5
+
4
6
  class CreateSandboxBaseParams
5
7
  # @return [Symbol, nil] Programming language for the Sandbox
6
8
  attr_accessor :language
@@ -66,6 +66,11 @@ module Daytona
66
66
  params.language = CodeLanguage::PYTHON
67
67
  end
68
68
 
69
+ unless CodeLanguage::ALL.include?(params.language.to_s.to_sym)
70
+ raise ArgumentError,
71
+ "Invalid #{CODE_TOOLBOX_LANGUAGE_LABEL}: #{params.language}. Supported languages: #{CodeLanguage::ALL.join(', ')}"
72
+ end
73
+
69
74
  _create(params, on_snapshot_create_logs:)
70
75
  end
71
76
 
@@ -81,7 +86,7 @@ module Daytona
81
86
  # @return [Daytona::Sandbox]
82
87
  def get(id)
83
88
  sandbox_dto = sandbox_api.get_sandbox(id)
84
- to_sandbox(sandbox_dto:, code_toolbox: code_toolbox_from_labels(sandbox_dto.labels))
89
+ to_sandbox(sandbox_dto:)
85
90
  end
86
91
 
87
92
  # Lists Sandboxes filtered by labels.
@@ -102,10 +107,8 @@ module Daytona
102
107
  total: response.total,
103
108
  page: response.page,
104
109
  total_pages: response.total_pages,
105
- items: response
106
- .items
107
- .map do |sandbox_dto|
108
- to_sandbox(sandbox_dto:, code_toolbox: code_toolbox_from_labels(sandbox_dto.labels))
110
+ items: response.items.map do |sandbox_dto|
111
+ to_sandbox(sandbox_dto:)
109
112
  end
110
113
  )
111
114
  end
@@ -150,7 +153,7 @@ module Daytona
150
153
  end
151
154
 
152
155
  labels = params.labels&.dup || {}
153
- labels[LABEL_CODE_TOOLBOX_LANGUAGE] = params.language.to_s if params.language
156
+ labels[CODE_TOOLBOX_LANGUAGE_LABEL] = params.language.to_s if params.language
154
157
 
155
158
  create_sandbox = DaytonaApiClient::CreateSandbox.new(
156
159
  user: params.os_user,
@@ -204,7 +207,7 @@ module Daytona
204
207
  Util.stream_async(uri:, headers:, on_chunk: on_snapshot_create_logs)
205
208
  end
206
209
 
207
- sandbox = to_sandbox(sandbox_dto: response, code_toolbox: code_toolbox_from_labels(response.labels))
210
+ sandbox = to_sandbox(sandbox_dto: response)
208
211
 
209
212
  if sandbox.state != DaytonaApiClient::SandboxState::STARTED
210
213
  sandbox.wait_for_sandbox_start([0.001, timeout - (Time.now - start_time)].max)
@@ -246,42 +249,16 @@ module Daytona
246
249
  end
247
250
 
248
251
  # @param sandbox_dto [DaytonaApiClient::Sandbox]
249
- # @param code_toolbox [Daytona::SandboxPythonCodeToolbox, Daytona::SandboxTsCodeToolbox]
250
252
  # @return [Daytona::Sandbox]
251
- def to_sandbox(sandbox_dto:, code_toolbox:)
253
+ def to_sandbox(sandbox_dto:)
252
254
  Sandbox.new(
253
255
  sandbox_dto:,
254
256
  config:,
255
257
  sandbox_api:,
256
- code_toolbox:,
257
258
  otel_state: @otel_state
258
259
  )
259
260
  end
260
261
 
261
- # Converts a language to a code toolbox
262
- #
263
- # @param language [Symbol]
264
- # @return [Daytona::CodeToolbox]
265
- # @raise [Daytona::Sdk::Error] If the language is not supported
266
- def code_toolbox_from_language(language)
267
- case language
268
- when CodeLanguage::PYTHON, nil
269
- SandboxPythonCodeToolbox.new
270
- when SandboxTsCodeToolbox, CodeLanguage::TYPESCRIPT
271
- SandboxTsCodeToolbox.new
272
- when CodeLanguage::JAVASCRIPT
273
- SandboxJsCodeToolbox.new
274
- else
275
- raise Sdk::Error, "Unsupported language: #{language}"
276
- end
277
- end
278
-
279
- # Get code toolbox from Sandbox labels
280
- #
281
- # @param labels [Hash<String, String>]
282
- # @return [Daytona::CodeToolbox]
283
- def code_toolbox_from_labels(labels) = code_toolbox_from_language(labels[LABEL_CODE_TOOLBOX_LANGUAGE]&.to_sym)
284
-
285
262
  SOURCE_RUBY = 'sdk-ruby'
286
263
  private_constant :SOURCE_RUBY
287
264
 
@@ -293,8 +270,5 @@ module Daytona
293
270
 
294
271
  HEADER_ORGANIZATION_ID = 'X-Daytona-Organization-ID'
295
272
  private_constant :HEADER_ORGANIZATION_ID
296
-
297
- LABEL_CODE_TOOLBOX_LANGUAGE = 'code-toolbox-language'
298
- private_constant :LABEL_CODE_TOOLBOX_LANGUAGE
299
273
  end
300
274
  end
@@ -1,16 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'base64'
4
- require 'json'
5
3
  require 'uri'
6
4
 
7
5
  module Daytona
8
6
  class Process # rubocop:disable Metrics/ClassLength
9
7
  include Instrumentation
10
8
 
11
- # @return [Daytona::SandboxPythonCodeToolbox,
12
- attr_reader :code_toolbox
13
-
14
9
  # @return [String] The ID of the Sandbox
15
10
  attr_reader :sandbox_id
16
11
 
@@ -20,18 +15,21 @@ module Daytona
20
15
  # @return [Proc] Function to get preview link for a port
21
16
  attr_reader :get_preview_link
22
17
 
18
+ # @return [String] The language for code execution (e.g. 'python', 'typescript', 'javascript')
19
+ attr_reader :language
20
+
23
21
  # Initialize a new Process instance
24
22
  #
25
- # @param code_toolbox [Daytona::SandboxPythonCodeToolbox, Daytona::SandboxTsCodeToolbox]
26
23
  # @param sandbox_id [String] The ID of the Sandbox
27
24
  # @param toolbox_api [DaytonaToolboxApiClient::ProcessApi] API client for Sandbox operations
28
25
  # @param get_preview_link [Proc] Function to get preview link for a port
26
+ # @param language [String] The language for code execution
29
27
  # @param otel_state [Daytona::OtelState, nil]
30
- def initialize(code_toolbox:, sandbox_id:, toolbox_api:, get_preview_link:, otel_state: nil)
31
- @code_toolbox = code_toolbox
28
+ def initialize(sandbox_id:, toolbox_api:, get_preview_link:, language: 'python', otel_state: nil)
32
29
  @sandbox_id = sandbox_id
33
30
  @toolbox_api = toolbox_api
34
31
  @get_preview_link = get_preview_link
32
+ @language = language
35
33
  @otel_state = otel_state
36
34
  end
37
35
 
@@ -54,7 +52,8 @@ module Daytona
54
52
  #
55
53
  # # Command with timeout
56
54
  # result = sandbox.process.exec("sleep 10", timeout: 5)
57
- def exec(command:, cwd: nil, env: nil, timeout: nil) # rubocop:disable Metrics/MethodLength
55
+ def exec(command:, cwd: nil, env: nil, timeout: nil)
56
+ envs = nil
58
57
  if env && !env.empty?
59
58
  env.each_key do |key|
60
59
  unless key.match?(/\A[A-Za-z_][A-Za-z0-9_]*\z/)
@@ -62,21 +61,16 @@ module Daytona
62
61
  "Invalid environment variable name: '#{key}'"
63
62
  end
64
63
  end
65
- safe_env_exports = env.map do |key, value|
66
- "export #{key}=\"$(printf '%s' '#{Base64.strict_encode64(value)}' | base64 -d)\""
67
- end.join('; ')
68
- command = "#{safe_env_exports}; #{command}"
64
+ envs = env
69
65
  end
70
66
 
71
- response = toolbox_api.execute_command(DaytonaToolboxApiClient::ExecuteRequest.new(command:, cwd:, timeout:))
72
- # Post-process the output to extract ExecutionArtifacts
73
- artifacts = parse_output(response.result.split("\n", -1))
74
-
75
- # Create new response with processed output and charts
67
+ response = toolbox_api.execute_command(DaytonaToolboxApiClient::ExecuteRequest.new(command:, cwd:, envs:,
68
+ timeout:))
69
+ result = response.result || ''
76
70
  ExecuteResponse.new(
77
71
  exit_code: response.exit_code,
78
- result: artifacts.stdout,
79
- artifacts: artifacts
72
+ result:,
73
+ artifacts: ExecutionArtifacts.new(result, [])
80
74
  )
81
75
  end
82
76
 
@@ -96,7 +90,19 @@ module Daytona
96
90
  # CODE
97
91
  # puts response.artifacts.stdout # Prints: Sum: 30
98
92
  def code_run(code:, params: nil, timeout: nil)
99
- exec(command: code_toolbox.get_run_command(code, params), env: params&.env, timeout:)
93
+ response = toolbox_api.code_run(
94
+ DaytonaToolboxApiClient::CodeRunRequest.new(
95
+ code:, language:, argv: params&.argv, envs: params&.env, timeout:
96
+ )
97
+ )
98
+
99
+ ExecuteResponse.new(
100
+ exit_code: response.exit_code,
101
+ result: response.result,
102
+ artifacts: ExecutionArtifacts.new(response.result, (response.artifacts&.charts || []).map do |c|
103
+ Charts.parse_chart(c)
104
+ end)
105
+ )
100
106
  end
101
107
 
102
108
  # Creates a new long-running background session in the Sandbox
@@ -186,15 +192,12 @@ module Daytona
186
192
  suppress_input_echo: req.suppress_input_echo)
187
193
  )
188
194
 
189
- stdout, stderr = Util.demux(response.output || '')
190
-
191
195
  SessionExecuteResponse.new(
192
196
  cmd_id: response.cmd_id,
193
197
  output: response.output,
194
- stdout:,
195
- stderr:,
198
+ stdout: response.stdout || '',
199
+ stderr: response.stderr || '',
196
200
  exit_code: response.exit_code,
197
- # TODO: DaytonaApiClient::SessionExecuteResponse doesn't have additional_properties attribute
198
201
  additional_properties: {}
199
202
  )
200
203
  end
@@ -210,12 +213,8 @@ module Daytona
210
213
  # puts "Command stdout: #{logs.stdout}"
211
214
  # puts "Command stderr: #{logs.stderr}"
212
215
  def get_session_command_logs(session_id:, command_id:)
213
- parse_session_command_logs(
214
- toolbox_api.get_session_command_logs(
215
- session_id,
216
- command_id
217
- )
218
- )
216
+ response = toolbox_api.get_session_command_logs(session_id, command_id)
217
+ SessionCommandLogsResponse.new(output: response.output, stdout: response.stdout, stderr: response.stderr)
219
218
  end
220
219
 
221
220
  # Asynchronously retrieves and processes the logs for a command executed in a session as they become available
@@ -284,7 +283,10 @@ module Daytona
284
283
  # logs = sandbox.process.get_entrypoint_logs()
285
284
  # puts "Command stdout: #{logs.stdout}"
286
285
  # puts "Command stderr: #{logs.stderr}"
287
- def get_entrypoint_logs = parse_session_command_logs(toolbox_api.get_entrypoint_logs)
286
+ def get_entrypoint_logs
287
+ response = toolbox_api.get_entrypoint_logs
288
+ SessionCommandLogsResponse.new(output: response.output, stdout: response.stdout, stderr: response.stderr)
289
+ end
288
290
 
289
291
  # Asynchronously retrieves and processes the sandbox entrypoint logs as they become available
290
292
  #
@@ -542,64 +544,7 @@ module Daytona
542
544
  # @return [Daytona::OtelState, nil]
543
545
  attr_reader :otel_state
544
546
 
545
- # Parse the output of a command to extract ExecutionArtifacts
546
- #
547
- # @param lines [Array<String>] A list of lines of output from a command
548
- # @return [Daytona::ExecutionArtifacts] The artifacts from the command execution
549
- def parse_output(lines)
550
- artifacts = ExecutionArtifacts.new('', [])
551
- stdout_lines = []
552
-
553
- lines.each do |line|
554
- if line.start_with?(ARTIFACT_PREFIX)
555
- parse_json_line(line:, artifacts:)
556
- else
557
- stdout_lines << line
558
- end
559
- end
560
-
561
- artifacts.stdout = stdout_lines.join("\n")
562
- artifacts
563
- end
564
-
565
- # Parse a JSON line to extract artifacts
566
- #
567
- # @param line [String] The line to parse
568
- # @param artifacts [Daytona::ExecutionArtifacts] The artifacts to add to
569
- # @return [void]
570
- def parse_json_line(line:, artifacts:)
571
- data = JSON.parse(line.sub(ARTIFACT_PREFIX, '').strip, symbolize_names: true)
572
-
573
- case data.fetch(:type, nil)
574
- when ArtifactType::CHART
575
- artifacts.charts.append(Charts.parse(data.fetch(:value, {})))
576
- end
577
- end
578
-
579
- # Parse combined stdout/stderr output into separate streams
580
- #
581
- # @param data [String] Combined log string with STDOUT_PREFIX and STDERR_PREFIX markers
582
- # @return [SessionCommandLogsResponse] Response with separated stdout and stderr
583
- def parse_session_command_logs(data)
584
- stdout, stderr = Util.demux(data)
585
-
586
- SessionCommandLogsResponse.new(
587
- output: data,
588
- stdout:,
589
- stderr:
590
- )
591
- end
592
-
593
- ARTIFACT_PREFIX = 'dtn_artifact_k39fd2:'
594
- private_constant :ARTIFACT_PREFIX
595
-
596
547
  WS_PORT = 2280
597
548
  private_constant :WS_PORT
598
-
599
- module ArtifactType
600
- ALL = [
601
- CHART = 'chart'
602
- ].freeze
603
- end
604
549
  end
605
550
  end
@@ -90,9 +90,6 @@ module Daytona
90
90
  # @return [String] The version of the daemon running in the sandbox
91
91
  attr_reader :daemon_version
92
92
 
93
- # @return [Daytona::SandboxPythonCodeToolbox, Daytona::SandboxTsCodeToolbox]
94
- attr_reader :code_toolbox
95
-
96
93
  # @return [Daytona::Config]
97
94
  attr_reader :config
98
95
 
@@ -114,14 +111,12 @@ module Daytona
114
111
  # @return [Daytona::CodeInterpreter]
115
112
  attr_reader :code_interpreter
116
113
 
117
- # @params code_toolbox [Daytona::SandboxPythonCodeToolbox, Daytona::SandboxTsCodeToolbox]
118
114
  # @params config [Daytona::Config]
119
115
  # @params sandbox_api [DaytonaApiClient::SandboxApi]
120
116
  # @params sandbox_dto [DaytonaApiClient::Sandbox]
121
117
  # @params otel_state [Daytona::OtelState, nil]
122
- def initialize(code_toolbox:, sandbox_dto:, config:, sandbox_api:, otel_state: nil) # rubocop:disable Metrics/MethodLength
118
+ def initialize(sandbox_dto:, config:, sandbox_api:, otel_state: nil) # rubocop:disable Metrics/MethodLength
123
119
  process_response(sandbox_dto)
124
- @code_toolbox = code_toolbox
125
120
  @config = config
126
121
  @sandbox_api = sandbox_api
127
122
  @otel_state = otel_state
@@ -150,9 +145,9 @@ module Daytona
150
145
 
151
146
  @process = Process.new(
152
147
  sandbox_id: id,
153
- code_toolbox:,
154
148
  toolbox_api: process_api,
155
149
  get_preview_link: proc { |port| preview_url(port) },
150
+ language: (labels || {}).fetch(CODE_TOOLBOX_LANGUAGE_LABEL, 'python'),
156
151
  otel_state:
157
152
  )
158
153
  @fs = FileSystem.new(sandbox_id: id, toolbox_api: fs_api, otel_state:)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Daytona
4
4
  module Sdk
5
- VERSION = '0.163.0'
5
+ VERSION = '0.164.0.alpha.1'
6
6
  end
7
7
  end
data/lib/daytona/sdk.rb CHANGED
@@ -24,9 +24,6 @@ require_relative 'common/response'
24
24
  require_relative 'common/snapshot'
25
25
  require_relative 'code_interpreter'
26
26
  require_relative 'computer_use'
27
- require_relative 'code_toolbox/sandbox_python_code_toolbox'
28
- require_relative 'code_toolbox/sandbox_ts_code_toolbox'
29
- require_relative 'code_toolbox/sandbox_js_code_toolbox'
30
27
  require_relative 'daytona'
31
28
  require_relative 'file_system'
32
29
  require_relative 'git'
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.163.0
4
+ version: 0.164.0.alpha.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.163.0
88
+ version: 0.164.0.alpha.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.163.0
95
+ version: 0.164.0.alpha.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.163.0
102
+ version: 0.164.0.alpha.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.163.0
109
+ version: 0.164.0.alpha.1
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: dotenv
112
112
  requirement: !ruby/object:Gem::Requirement
@@ -179,9 +179,6 @@ files:
179
179
  - Rakefile
180
180
  - lib/daytona.rb
181
181
  - lib/daytona/code_interpreter.rb
182
- - lib/daytona/code_toolbox/sandbox_js_code_toolbox.rb
183
- - lib/daytona/code_toolbox/sandbox_python_code_toolbox.rb
184
- - lib/daytona/code_toolbox/sandbox_ts_code_toolbox.rb
185
182
  - lib/daytona/common/charts.rb
186
183
  - lib/daytona/common/code_interpreter.rb
187
184
  - lib/daytona/common/code_language.rb
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'base64'
4
-
5
- module Daytona
6
- class SandboxJsCodeToolbox
7
- def get_run_command(code, params = nil)
8
- # Prepend argv fix: node - places '-' at argv[1]; splice it out to match legacy node -e behaviour
9
- # Encode the provided code in base64
10
- base64_code = Base64.strict_encode64("process.argv.splice(1, 1);\n" + code)
11
-
12
- # Build command-line arguments string
13
- argv = ''
14
- argv = params.argv.join(' ') if params&.argv && !params.argv.empty?
15
-
16
- # Pipe the base64-encoded code via stdin to avoid OS ARG_MAX limits on large payloads
17
- # Use node - to read from stdin (node /dev/stdin does not work when stdin is a pipe)
18
- "printf '%s' '#{base64_code}' | base64 -d | node - #{argv}"
19
- end
20
- end
21
- end
@@ -1,438 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'base64'
4
-
5
- module Daytona
6
- class SandboxPythonCodeToolbox # rubocop:disable Metrics/ClassLength
7
- # Get the run command for executing Python code
8
- #
9
- # @param code [String] The Python code to execute
10
- # @param params [Daytona::CodeRunParams, nil] Optional parameters for code execution
11
- # @return [String] The command to run the Python code
12
- def get_run_command(code, params = nil)
13
- encoded_code = Base64.strict_encode64(code)
14
-
15
- # Override plt.show() method if matplotlib is imported
16
- if matplotlib_imported?(code)
17
- encoded_code = Base64.strict_encode64(
18
- Base64.decode64(PYTHON_CODE_WRAPPER).gsub('{encoded_code}', encoded_code)
19
- )
20
- end
21
-
22
- argv = params&.argv&.join(' ') || ''
23
-
24
- # Pipe the base64-encoded code via stdin to avoid OS ARG_MAX limits on large payloads
25
- # printf is a shell builtin that does not invoke execve(), so the base64 string bypasses the kernel ARG_MAX limit
26
- # Use -u flag to ensure unbuffered output for real-time error reporting
27
- "printf '%s' '#{encoded_code}' | base64 -d | python3 -u - #{argv}"
28
- end
29
-
30
- private
31
-
32
- # Check if matplotlib is imported in the code
33
- #
34
- # @param code [String] The Python code to check
35
- # @return [Boolean] True if matplotlib is imported, false otherwise
36
- def matplotlib_imported?(code) = PATTERNS.any? { |pattern| code.match?(pattern) }
37
-
38
- PATTERNS = [
39
- # Standard imports
40
- /^[^#]*import\s+matplotlib/m,
41
- /^[^#]*from\s+matplotlib/m,
42
- # Dynamic imports
43
- /^[^#]*__import__\s*\(\s*['"]matplotlib['"]/m,
44
- /^[^#]*importlib\.import_module\s*\(\s*['"]matplotlib['"]/m,
45
- # Other dynamic loading patterns
46
- /^[^#]*loader\.load_module\s*\(\s*['"]matplotlib['"]/m,
47
- /^[^#]*sys\.modules\[['"]matplotlib['"]\]/m
48
- ].freeze
49
- private_constant :PATTERNS
50
-
51
- PYTHON_CODE_WRAPPER = <<~BASE64.strip
52
- aW1wb3J0IGJhc2U2NAppbXBvcnQgZGF0ZXRpbWUKaW1wb3J0IGhhc2hsaWIK
53
- aW1wb3J0IGlvCmltcG9ydCBqc29uCmltcG9ydCBsaW5lY2FjaGUKaW1wb3J0
54
- IHN5cwppbXBvcnQgdHJhY2ViYWNrCmltcG9ydCB0eXBlcwpmcm9tIGltcG9y
55
- dGxpYi5hYmMgaW1wb3J0IExvYWRlciwgTWV0YVBhdGhGaW5kZXIKZnJvbSBp
56
- bXBvcnRsaWIudXRpbCBpbXBvcnQgZmluZF9zcGVjLCBzcGVjX2Zyb21fbG9h
57
- ZGVyCgojIEdsb2JhbCB2YXJpYWJsZXMgdG8gaG9sZCBpbXBvcnRlZCBsaWJy
58
- YXJpZXMgaWYgbmVlZGVkCm5wID0gTm9uZQptcGwgPSBOb25lCnBpbF9pbWcg
59
- PSBOb25lCgoKcGx0X3BhdGNoZWQgPSBGYWxzZQpwcm9jZXNzZWRfZmlndXJl
60
- cyA9IHNldCgpCgoKZGVmIF9wYXJzZV9wb2ludChwb2ludCk6CiAgICBpZiBp
61
- c2luc3RhbmNlKHBvaW50LCBkYXRldGltZS5kYXRlKToKICAgICAgICByZXR1
62
- cm4gcG9pbnQuaXNvZm9ybWF0KCkKICAgIGlmIGlzaW5zdGFuY2UocG9pbnQs
63
- IG5wLmRhdGV0aW1lNjQpOgogICAgICAgIHJldHVybiBwb2ludC5hc3R5cGUo
64
- ImRhdGV0aW1lNjRbc10iKS5hc3R5cGUoc3RyKQogICAgcmV0dXJuIHBvaW50
65
- CgoKZGVmIF9pc19ncmlkX2xpbmUobGluZTogYW55KSAtPiBib29sOgogICAg
66
- eF9kYXRhID0gbGluZS5nZXRfeGRhdGEoKQogICAgaWYgbGVuKHhfZGF0YSkg
67
- IT0gMjoKICAgICAgICByZXR1cm4gRmFsc2UKCiAgICB5X2RhdGEgPSBsaW5l
68
- LmdldF95ZGF0YSgpCiAgICBpZiBsZW4oeV9kYXRhKSAhPSAyOgogICAgICAg
69
- IHJldHVybiBGYWxzZQoKICAgIGlmIHhfZGF0YVswXSA9PSB4X2RhdGFbMV0g
70
- b3IgeV9kYXRhWzBdID09IHlfZGF0YVsxXToKICAgICAgICByZXR1cm4gVHJ1
71
- ZQoKICAgIHJldHVybiBGYWxzZQoKCmRlZiBfZXh0cmFjdF9saW5lX2NoYXJ0
72
- X2VsZW1lbnRzKGF4KToKICAgIGVsZW1lbnRzID0gW10KCiAgICBmb3IgbGlu
73
- ZSBpbiBheC5nZXRfbGluZXMoKToKICAgICAgICBpZiBfaXNfZ3JpZF9saW5l
74
- KGxpbmUpOgogICAgICAgICAgICBjb250aW51ZQogICAgICAgIGxhYmVsID0g
75
- bGluZS5nZXRfbGFiZWwoKQogICAgICAgIHBvaW50cyA9IFtfcGFyc2VfcG9p
76
- bnQoKHgsIHkpKSBmb3IgeCwgeSBpbiB6aXAobGluZS5nZXRfeGRhdGEoKSwg
77
- bGluZS5nZXRfeWRhdGEoKSldCgogICAgICAgIGVsZW1lbnQgPSB7ImxhYmVs
78
- IjogbGFiZWwsICJwb2ludHMiOiBwb2ludHN9CiAgICAgICAgZWxlbWVudHMu
79
- YXBwZW5kKGVsZW1lbnQpCgogICAgcmV0dXJuIGVsZW1lbnRzCgoKZGVmIF9l
80
- eHRyYWN0X3NjYXR0ZXJfY2hhcnRfZWxlbWVudHMoYXgpOgogICAgZWxlbWVu
81
- dHMgPSBbXQoKICAgIGZvciBjb2xsZWN0aW9uIGluIGF4LmNvbGxlY3Rpb25z
82
- OgogICAgICAgIHBvaW50cyA9IFtfcGFyc2VfcG9pbnQoKHgsIHkpKSBmb3Ig
83
- eCwgeSBpbiBjb2xsZWN0aW9uLmdldF9vZmZzZXRzKCldCiAgICAgICAgZWxl
84
- bWVudCA9IHsibGFiZWwiOiBjb2xsZWN0aW9uLmdldF9sYWJlbCgpLCAicG9p
85
- bnRzIjogcG9pbnRzfQogICAgICAgIGVsZW1lbnRzLmFwcGVuZChlbGVtZW50
86
- KQoKICAgIHJldHVybiBlbGVtZW50cwoKCmRlZiBfZXh0cmFjdF9iYXJfY2hh
87
- cnRfZWxlbWVudHMoYXgpOgogICAgZWxlbWVudHMgPSBbXQogICAgY2hhbmdl
88
- X29yaWVudGF0aW9uID0gRmFsc2UKCiAgICBmb3IgY29udGFpbmVyIGluIGF4
89
- LmNvbnRhaW5lcnM6CiAgICAgICAgaGVpZ2h0cyA9IFtyZWN0LmdldF9oZWln
90
- aHQoKSBmb3IgcmVjdCBpbiBjb250YWluZXJdCiAgICAgICAgaWYgYWxsKGhl
91
- aWdodCA9PSBoZWlnaHRzWzBdIGZvciBoZWlnaHQgaW4gaGVpZ2h0cyk6CiAg
92
- ICAgICAgICAgICMgdmVydGljYWwgYmFycwogICAgICAgICAgICBjaGFuZ2Vf
93
- b3JpZW50YXRpb24gPSBUcnVlCiAgICAgICAgICAgIGxhYmVscyA9IFtsYWJl
94
- bC5nZXRfdGV4dCgpIGZvciBsYWJlbCBpbiBheC5nZXRfeXRpY2tsYWJlbHMo
95
- KV0KICAgICAgICAgICAgdmFsdWVzID0gW3JlY3QuZ2V0X3dpZHRoKCkgZm9y
96
- IHJlY3QgaW4gY29udGFpbmVyXQogICAgICAgIGVsc2U6CiAgICAgICAgICAg
97
- ICMgaG9yaXpvbnRhbCBiYXJzCiAgICAgICAgICAgIGxhYmVscyA9IFtsYWJl
98
- bC5nZXRfdGV4dCgpIGZvciBsYWJlbCBpbiBheC5nZXRfeHRpY2tsYWJlbHMo
99
- KV0KICAgICAgICAgICAgdmFsdWVzID0gaGVpZ2h0cwogICAgICAgIGZvciBs
100
- YWJlbCwgdmFsdWUgaW4gemlwKGxhYmVscywgdmFsdWVzKToKICAgICAgICAg
101
- ICAgZWxlbWVudCA9IHsibGFiZWwiOiBsYWJlbCwgImdyb3VwIjogY29udGFp
102
- bmVyLmdldF9sYWJlbCgpLCAidmFsdWUiOiB2YWx1ZX0KICAgICAgICAgICAg
103
- ZWxlbWVudHMuYXBwZW5kKGVsZW1lbnQpCgogICAgcmV0dXJuIGVsZW1lbnRz
104
- LCBjaGFuZ2Vfb3JpZW50YXRpb24KCgpkZWYgX2V4dHJhY3RfcGllX2NoYXJ0
105
- X2VsZW1lbnRzKGF4KToKICAgIGVsZW1lbnRzID0gW10KCiAgICB3ZWRnZXMg
106
- PSBbcGF0Y2ggZm9yIHBhdGNoIGluIGF4LnBhdGNoZXMgaWYgaXNpbnN0YW5j
107
- ZShwYXRjaCwgbXBsLnBhdGNoZXMuV2VkZ2UpXQogICAgaWYgbGVuKHdlZGdl
108
- cykgPT0gMDoKICAgICAgICByZXR1cm4gZWxlbWVudHMKCiAgICB0ZXh0cyA9
109
- IFt0ZXh0X29iai5nZXRfdGV4dCgpIGZvciB0ZXh0X29iaiBpbiBheC50ZXh0
110
- c10KCiAgICBsYWJlbHMgPSBbXQogICAgYXV0b3BjdHMgPSBbXQoKICAgIGlm
111
- IGxlbih0ZXh0cykgPT0gMiAqIGxlbih3ZWRnZXMpOgogICAgICAgIGxhYmVs
112
- cyA9IFt0ZXh0c1tpXSBmb3IgaSBpbiByYW5nZSgwLCAyICogbGVuKHdlZGdl
113
- cyksIDIpXQogICAgICAgIGF1dG9wY3RzID0gW3RleHRzW2ldIGZvciBpIGlu
114
- IHJhbmdlKDEsIDIgKiBsZW4od2VkZ2VzKSwgMildCiAgICBlbHNlOgogICAg
115
- ICAgIGxhYmVscyA9IHRleHRzWzogbGVuKHdlZGdlcyldCgogICAgZm9yIGlk
116
- eCwgd2VkZ2UgaW4gZW51bWVyYXRlKHdlZGdlcyk6CiAgICAgICAgZWxlbWVu
117
- dCA9IHsKICAgICAgICAgICAgImxhYmVsIjogbGFiZWxzW2lkeF0sCiAgICAg
118
- ICAgICAgICJhbmdsZSI6IGFicyh3ZWRnZS50aGV0YTIgLSB3ZWRnZS50aGV0
119
- YTEpLAogICAgICAgICAgICAicmFkaXVzIjogd2VkZ2UuciwKICAgICAgICAg
120
- ICAgImF1dG9wY3QiOiBhdXRvcGN0c1tpZHhdIGlmIGF1dG9wY3RzIGFuZCBs
121
- ZW4oYXV0b3BjdHMpID4gaWR4IGVsc2UgTm9uZSwKICAgICAgICB9CiAgICAg
122
- ICAgZWxlbWVudHMuYXBwZW5kKGVsZW1lbnQpCgogICAgcmV0dXJuIGVsZW1l
123
- bnRzCgoKIyBweWxpbnQ6IGRpc2FibGU9dG9vLW1hbnktYnJhbmNoZXMKZGVm
124
- IF9leHRyYWN0X2JveF9jaGFydF9lbGVtZW50cyhheCk6CiAgICBjaGFuZ2Vf
125
- b3JpZW50YXRpb24gPSBGYWxzZQoKICAgIHh0aWNrbGFiZWxzID0gW2xhYmVs
126
- LmdldF90ZXh0KCkgZm9yIGxhYmVsIGluIGF4LmdldF94dGlja2xhYmVscygp
127
- XQogICAgYm94ZXMgPSBbXQogICAgZm9yIGxhYmVsLCBib3ggaW4gemlwKHh0
128
- aWNrbGFiZWxzLCBheC5wYXRjaGVzKToKICAgICAgICB2ZXJ0aWNlcyA9IGJv
129
- eC5nZXRfcGF0aCgpLnZlcnRpY2VzCiAgICAgICAgeF92ZXJ0aWNlcyA9IGxp
130
- c3QodmVydGljZXNbOiwgMF0pCiAgICAgICAgeV92ZXJ0aWNlcyA9IGxpc3Qo
131
- dmVydGljZXNbOiwgMV0pCiAgICAgICAgeCA9IG1pbih4X3ZlcnRpY2VzKQog
132
- ICAgICAgIHkgPSBtaW4oeV92ZXJ0aWNlcykKCiAgICAgICAgYm94ZXMuYXBw
133
- ZW5kKAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAieCI6IHgsCiAg
134
- ICAgICAgICAgICAgICAieSI6IHksCiAgICAgICAgICAgICAgICAibGFiZWwi
135
- OiBsYWJlbCwKICAgICAgICAgICAgICAgICJ3aWR0aCI6IG1heCh4X3ZlcnRp
136
- Y2VzKSAtIHgsCiAgICAgICAgICAgICAgICAiaGVpZ2h0IjogbWF4KHlfdmVy
137
- dGljZXMpIC0geSwKICAgICAgICAgICAgICAgICJvdXRsaWVycyI6IFtdLAog
138
- ICAgICAgICAgICB9CiAgICAgICAgKQoKICAgIG9yaWVudGF0aW9uID0gImhv
139
- cml6b250YWwiCiAgICBpZiBhbGwoYm94WyJoZWlnaHQiXSA9PSBib3hlc1sw
140
- XVsiaGVpZ2h0Il0gZm9yIGJveCBpbiBib3hlcyk6CiAgICAgICAgb3JpZW50
141
- YXRpb24gPSAidmVydGljYWwiCgogICAgaWYgb3JpZW50YXRpb24gPT0gInZl
142
- cnRpY2FsIjoKICAgICAgICBjaGFuZ2Vfb3JpZW50YXRpb24gPSBUcnVlCiAg
143
- ICAgICAgZm9yIGJveCBpbiBib3hlczoKICAgICAgICAgICAgYm94WyJ4Il0s
144
- IGJveFsieSJdID0gYm94WyJ5Il0sIGJveFsieCJdCiAgICAgICAgICAgIGJv
145
- eFsid2lkdGgiXSwgYm94WyJoZWlnaHQiXSA9IGJveFsiaGVpZ2h0Il0sIGJv
146
- eFsid2lkdGgiXQoKICAgIGZvciBsaW5lIGluIGF4LmxpbmVzOgogICAgICAg
147
- IHhkYXRhID0gbGluZS5nZXRfeGRhdGEoKQogICAgICAgIHlkYXRhID0gbGlu
148
- ZS5nZXRfeWRhdGEoKQoKICAgICAgICBpZiBvcmllbnRhdGlvbiA9PSAidmVy
149
- dGljYWwiOgogICAgICAgICAgICB4ZGF0YSwgeWRhdGEgPSB5ZGF0YSwgeGRh
150
- dGEKCiAgICAgICAgaWYgbGVuKHhkYXRhKSA8PSAxIG9yIGxlbih5ZGF0YSkg
151
- IT0gMjoKICAgICAgICAgICAgY29udGludWUKCiAgICAgICAgZm9yIGJveCBp
152
- biBib3hlczoKICAgICAgICAgICAgaWYgYm94WyJ4Il0gPD0geGRhdGFbMF0g
153
- PD0geGRhdGFbMV0gPD0gYm94WyJ4Il0gKyBib3hbIndpZHRoIl06CiAgICAg
154
- ICAgICAgICAgICAjIEhvcml6b250YWwgbGluZSAobWVkaWFuIG9yIGNhcCkK
155
- ICAgICAgICAgICAgICAgIGlmIGFicyh5ZGF0YVswXSAtIHlkYXRhWzFdKSA8
156
- IDAuMDAxIGFuZCBib3hbInkiXSA8PSB5ZGF0YVswXSA8PSBib3hbInkiXSAr
157
- IGJveFsiaGVpZ2h0Il06CiAgICAgICAgICAgICAgICAgICAgYm94WyJtZWRp
158
- YW4iXSA9IHlkYXRhWzBdCiAgICAgICAgICAgICAgICAjIFZlcnRpY2FsIGxp
159
- bmUgKHdoaXNrZXJzKQogICAgICAgICAgICAgICAgZWxpZiBhYnMoeGRhdGFb
160
- MF0gLSB4ZGF0YVsxXSkgPCAwLjAwMToKICAgICAgICAgICAgICAgICAgICB5
161
- X21pbiA9IG1pbih5ZGF0YSkKICAgICAgICAgICAgICAgICAgICB5X21heCA9
162
- IG1heCh5ZGF0YSkKCiAgICAgICAgICAgICAgICAgICAgIyBJZiBhdHRhY2hl
163
- ZCB0byBib3R0b20gb2YgYm94CiAgICAgICAgICAgICAgICAgICAgaWYgYWJz
164
- KHlfbWF4IC0gYm94WyJ5Il0pIDwgMC4wMDE6CiAgICAgICAgICAgICAgICAg
165
- ICAgICAgIGJveFsid2hpc2tlcl9sb3dlciJdID0geV9taW4KCiAgICAgICAg
166
- ICAgICAgICAgICAgIyBJZiBhdHRhY2hlZCB0byB0b3Agb2YgYm94CiAgICAg
167
- ICAgICAgICAgICAgICAgZWxpZiBhYnMoeV9taW4gLSAoYm94WyJ5Il0gKyBi
168
- b3hbImhlaWdodCJdKSkgPCAwLjAwMToKICAgICAgICAgICAgICAgICAgICAg
169
- ICAgYm94WyJ3aGlza2VyX3VwcGVyIl0gPSB5X21heAogICAgICAgICAgICAg
170
- ICAgYnJlYWsKCiAgICBvdXRsaWVyX2NhbmRpZGF0ZXMgPSBbXQoKICAgICMg
171
- Q2hlY2sgZm9yIGFueSBtYXJrZXJzIGluIGFsbCBhcnRpc3RzCiAgICBmb3Ig
172
- YXJ0aXN0IGluIGF4LmdldF9jaGlsZHJlbigpOgogICAgICAgIGlmIGhhc2F0
173
- dHIoYXJ0aXN0LCAiZ2V0X3hkYXRhIikgYW5kIGhhc2F0dHIoYXJ0aXN0LCAi
174
- Z2V0X3lkYXRhIik6CiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAg
175
- IHhkYXRhID0gYXJ0aXN0LmdldF94ZGF0YSgpCiAgICAgICAgICAgICAgICB5
176
- ZGF0YSA9IGFydGlzdC5nZXRfeWRhdGEoKQoKICAgICAgICAgICAgICAgIGlm
177
- IG9yaWVudGF0aW9uID09ICJ2ZXJ0aWNhbCI6CiAgICAgICAgICAgICAgICAg
178
- ICAgeGRhdGEsIHlkYXRhID0geWRhdGEsIHhkYXRhCgogICAgICAgICAgICAg
179
- ICAgaWYgaXNpbnN0YW5jZSh4ZGF0YSwgKGxpc3QsIG5wLm5kYXJyYXkpKSBh
180
- bmQgaXNpbnN0YW5jZSh5ZGF0YSwgKGxpc3QsIG5wLm5kYXJyYXkpKToKICAg
181
- ICAgICAgICAgICAgICAgICBmb3IgaSBpbiByYW5nZShtaW4obGVuKHhkYXRh
182
- KSwgbGVuKHlkYXRhKSkpOgogICAgICAgICAgICAgICAgICAgICAgICBvdXRs
183
- aWVyX2NhbmRpZGF0ZXMuYXBwZW5kKChmbG9hdCh4ZGF0YVtpXSksIGZsb2F0
184
- KHlkYXRhW2ldKSkpCiAgICAgICAgICAgIGV4Y2VwdDoKICAgICAgICAgICAg
185
- ICAgIHBhc3MKCiAgICAjIEFzc2lnbiBwb2ludHMgdG8gYm94ZXMgYW5kIGRl
186
- dGVybWluZSBpZiB0aGV5J3JlIG91dGxpZXJzCiAgICBmb3IgeCwgeSBpbiBv
187
- dXRsaWVyX2NhbmRpZGF0ZXM6CiAgICAgICAgZm9yIGJveCBpbiBib3hlczoK
188
- ICAgICAgICAgICAgaWYgYm94WyJ4Il0gPD0geCA8PSBib3hbIngiXSArIGJv
189
- eFsid2lkdGgiXToKICAgICAgICAgICAgICAgIGJveF9jZW50ZXIgPSBib3hb
190
- IngiXSArIGJveFsid2lkdGgiXSAvIDIKICAgICAgICAgICAgICAgIGlmIGFi
191
- cyh4IC0gYm94X2NlbnRlcikgPCAwLjAwMToKICAgICAgICAgICAgICAgICAg
192
- ICB5X21pbiA9IGJveFsieSJdCiAgICAgICAgICAgICAgICAgICAgeV9tYXgg
193
- PSBib3hbInkiXSArIGJveFsiaGVpZ2h0Il0KICAgICAgICAgICAgICAgICAg
194
- ICBpZiBib3guZ2V0KCJ3aGlza2VyX2xvd2VyIiwgTm9uZSk6CiAgICAgICAg
195
- ICAgICAgICAgICAgICAgIHlfbWluID0gYm94WyJ3aGlza2VyX2xvd2VyIl0K
196
- ICAgICAgICAgICAgICAgICAgICBpZiBib3guZ2V0KCJ3aGlza2VyX3VwcGVy
197
- IiwgTm9uZSk6CiAgICAgICAgICAgICAgICAgICAgICAgIHlfbWF4ID0gYm94
198
- WyJ3aGlza2VyX3VwcGVyIl0KICAgICAgICAgICAgICAgICAgICBpZiB5IDwg
199
- eV9taW4gb3IgeSA+IHlfbWF4OgogICAgICAgICAgICAgICAgICAgICAgICBi
200
- b3hbIm91dGxpZXJzIl0uYXBwZW5kKHkpCiAgICAgICAgICAgICAgICBicmVh
201
- awoKICAgIHJldHVybiBbCiAgICAgICAgewogICAgICAgICAgICAibGFiZWwi
202
- OiBib3hbImxhYmVsIl0sCiAgICAgICAgICAgICJtaW4iOiBib3guZ2V0KCJ3
203
- aGlza2VyX2xvd2VyIiwgTm9uZSksCiAgICAgICAgICAgICJmaXJzdF9xdWFy
204
- dGlsZSI6IGJveFsieSJdLAogICAgICAgICAgICAibWVkaWFuIjogYm94Lmdl
205
- dCgibWVkaWFuIiwgTm9uZSksCiAgICAgICAgICAgICJ0aGlyZF9xdWFydGls
206
- ZSI6IGJveFsieSJdICsgYm94WyJoZWlnaHQiXSwKICAgICAgICAgICAgIm1h
207
- eCI6IGJveC5nZXQoIndoaXNrZXJfdXBwZXIiLCBOb25lKSwKICAgICAgICAg
208
- ICAgIm91dGxpZXJzIjogYm94WyJvdXRsaWVycyJdLAogICAgICAgIH0KICAg
209
- ICAgICBmb3IgYm94IGluIGJveGVzCiAgICBdLCBjaGFuZ2Vfb3JpZW50YXRp
210
- b24KCgpkZWYgX3NhdmVfZmlndXJlX2FzX2Jhc2U2NChmaWcsIGJib3hfaW5j
211
- aGVzPSJ0aWdodCIsIGRwaT0xMDApOgogICAgIyBGaXJzdCBzYXZlIHdpdGgg
212
- bWF0cGxvdGxpYgogICAgcG5nX2J1ZmZlciA9IGlvLkJ5dGVzSU8oKQogICAg
213
- ZmlnLnNhdmVmaWcocG5nX2J1ZmZlciwgZm9ybWF0PSJwbmciLCBiYm94X2lu
214
- Y2hlcz1iYm94X2luY2hlcywgZHBpPWRwaSkKICAgIHBuZ19idWZmZXIuc2Vl
215
- aygwKQoKICAgICMgT3BlbiB3aXRoIFBJTCBhbmQgYXBwbHkgbWF4aW11bSBj
216
- b21wcmVzc2lvbgogICAgd2l0aCBwaWxfaW1nLm9wZW4ocG5nX2J1ZmZlcikg
217
- YXMgaW1nOgogICAgICAgIG9wdGltaXplZF9idWZmZXIgPSBpby5CeXRlc0lP
218
- KCkKICAgICAgICBpbWcuc2F2ZShvcHRpbWl6ZWRfYnVmZmVyLCBmb3JtYXQ9
219
- InBuZyIsIG9wdGltaXplPVRydWUsIHF1YWxpdHk9MTAwLCBjb21wcmVzc19s
220
- ZXZlbD05KQogICAgICAgIG9wdGltaXplZF9idWZmZXIuc2VlaygwKQogICAg
221
- ICAgIHJldHVybiBiYXNlNjQuYjY0ZW5jb2RlKG9wdGltaXplZF9idWZmZXIu
222
- Z2V0dmFsdWUoKSkuZGVjb2RlKCJ1dGYtOCIpCgoKZGVmIF9nZXRfZmlndXJl
223
- X2hhc2goZmlnKToKICAgIHBuZ19idWZmZXIgPSBpby5CeXRlc0lPKCkKICAg
224
- IGZpZy5zYXZlZmlnKHBuZ19idWZmZXIsIGZvcm1hdD0icG5nIiwgZHBpPTUw
225
- KQogICAgcmV0dXJuIGhhc2hsaWIubWQ1KHBuZ19idWZmZXIuZ2V0dmFsdWUo
226
- KSkuaGV4ZGlnZXN0KCkKCgpkZWYgX2dldF9jaGFydF90eXBlKGF4KToKICAg
227
- IG9iamVjdHMgPSBsaXN0KAogICAgICAgIGZpbHRlcigKICAgICAgICAgICAg
228
- bGFtYmRhIG9iajogbm90IGlzaW5zdGFuY2Uob2JqLCBtcGwudGV4dC5UZXh0
229
- KSBhbmQgbm90IGlzaW5zdGFuY2Uob2JqLCBtcGwucGF0Y2hlcy5TaGFkb3cp
230
- LAogICAgICAgICAgICBheC5fY2hpbGRyZW4sICAjIHB5bGludDogZGlzYWJs
231
- ZT1wcm90ZWN0ZWQtYWNjZXNzCiAgICAgICAgKQogICAgKQoKICAgICMgQ2hl
232
- Y2sgZm9yIExpbmUgcGxvdHMKICAgIGlmIGFsbChpc2luc3RhbmNlKGxpbmUs
233
- IG1wbC5saW5lcy5MaW5lMkQpIGZvciBsaW5lIGluIG9iamVjdHMpOgogICAg
234
- ICAgIHJldHVybiAibGluZSIKCiAgICBpZiBhbGwoaXNpbnN0YW5jZShib3hf
235
- b3JfcGF0aCwgKG1wbC5wYXRjaGVzLlBhdGhQYXRjaCwgbXBsLmxpbmVzLkxp
236
- bmUyRCkpIGZvciBib3hfb3JfcGF0aCBpbiBvYmplY3RzKToKICAgICAgICBy
237
- ZXR1cm4gImJveF9hbmRfd2hpc2tlciIKCiAgICBmaWx0ZXJlZCA9IFtdCiAg
238
- ICBmb3Igb2JqIGluIG9iamVjdHM6CiAgICAgICAgaWYgaXNpbnN0YW5jZShv
239
- YmosIG1wbC5saW5lcy5MaW5lMkQpIGFuZCBfaXNfZ3JpZF9saW5lKG9iaik6
240
- CiAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgZmlsdGVyZWQuYXBwZW5k
241
- KG9iaikKCiAgICBvYmplY3RzID0gZmlsdGVyZWQKCiAgICAjIENoZWNrIGZv
242
- ciBTY2F0dGVyIHBsb3RzCiAgICBpZiBhbGwoaXNpbnN0YW5jZShwYXRoLCBt
243
- cGwuY29sbGVjdGlvbnMuUGF0aENvbGxlY3Rpb24pIGZvciBwYXRoIGluIG9i
244
- amVjdHMpOgogICAgICAgIHJldHVybiAic2NhdHRlciIKCiAgICAjIENoZWNr
245
- IGZvciBCYXIgcGxvdHMKICAgIGlmIGFsbChpc2luc3RhbmNlKHJlY3QsIG1w
246
- bC5wYXRjaGVzLlJlY3RhbmdsZSkgZm9yIHJlY3QgaW4gb2JqZWN0cyk6CiAg
247
- ICAgICAgcmV0dXJuICJiYXIiCgogICAgIyBDaGVjayBmb3IgUGllIHBsb3Rz
248
- CiAgICBpZiBhbGwoaXNpbnN0YW5jZShhcnRpc3QsIG1wbC5wYXRjaGVzLldl
249
- ZGdlKSBmb3IgYXJ0aXN0IGluIG9iamVjdHMpOgogICAgICAgIHJldHVybiAi
250
- cGllIgoKICAgIHJldHVybiAidW5rbm93biIKCgpkZWYgX2lzX2F1dG9fZW1w
251
- dHlfYXhpcyhheCk6CiAgICByZXR1cm4gYXguZ2V0X3N1YnBsb3RzcGVjKCkg
252
- aXMgbm90IE5vbmUgYW5kIG5vdCBheC5oYXNfZGF0YSgpCgoKZGVmIF9pc19j
253
- b2xvcmJhcl9heGlzKGF4KToKICAgIHJldHVybiBhbnkoCiAgICAgICAgIyBw
254
- eWxpbnQ6IGRpc2FibGU9cHJvdGVjdGVkLWFjY2VzcwogICAgICAgIGlzaW5z
255
- dGFuY2UoY2hpbGQsIG1wbC5jb2xvcmJhci5fQ29sb3JiYXJTcGluZSkKICAg
256
- ICAgICBmb3IgY2hpbGQgaW4gYXguZ2V0X2NoaWxkcmVuKCkKICAgICkKCgpk
257
- ZWYgX2ZpbHRlcl9vdXRfdW53YW50ZWRfYXhlcyhheGVzKToKICAgIHJldHVy
258
- biBbYXggZm9yIGF4IGluIGF4ZXMgaWYgbm90IF9pc19hdXRvX2VtcHR5X2F4
259
- aXMoYXgpIGFuZCBub3QgX2lzX2NvbG9yYmFyX2F4aXMoYXgpXQoKCmRlZiBf
260
- ZXh0cmFjdF90aWNrc19kYXRhKGNvbnZlcnRlcjogYW55LCB0aWNrczogYW55
261
- KSAtPiBsaXN0OgogICAgaWYgaXNpbnN0YW5jZShjb252ZXJ0ZXIsIG1wbC5k
262
- YXRlcy5fU3dpdGNoYWJsZURhdGVDb252ZXJ0ZXIpOiAgIyBweWxpbnQ6IGRp
263
- c2FibGU9cHJvdGVjdGVkLWFjY2VzcwogICAgICAgIHJldHVybiBbbXBsLmRh
264
- dGVzLm51bTJkYXRlKHRpY2spLmlzb2Zvcm1hdCgpIGZvciB0aWNrIGluIHRp
265
- Y2tzXQogICAgdHJ5OgogICAgICAgIHJldHVybiBbZmxvYXQodGljaykgZm9y
266
- IHRpY2sgaW4gdGlja3NdCiAgICBleGNlcHQgRXhjZXB0aW9uOgogICAgICAg
267
- IHJldHVybiBsaXN0KHRpY2tzKQoKCmRlZiBfZXh0cmFjdF9zY2FsZShjb252
268
- ZXJ0ZXIsIHNjYWxlOiBzdHIsIHRpY2tzLCBsYWJlbHMpIC0+IHN0cjoKICAg
269
- IGlmIGlzaW5zdGFuY2UoY29udmVydGVyLCBtcGwuZGF0ZXMuX1N3aXRjaGFi
270
- bGVEYXRlQ29udmVydGVyKTogICMgcHlsaW50OiBkaXNhYmxlPXByb3RlY3Rl
271
- ZC1hY2Nlc3MKICAgICAgICByZXR1cm4gImRhdGV0aW1lIgoKICAgICMgSWYg
272
- dGhlIHNjYWxlIGlzIG5vdCBsaW5lYXIsIGl0IGNhbid0IGJlIGNhdGVnb3Jp
273
- Y2FsCiAgICBpZiBzY2FsZSAhPSAibGluZWFyIjoKICAgICAgICByZXR1cm4g
274
- c2NhbGUKCiAgICAjIElmIGFsbCB0aGUgdGlja3MgYXJlIGludGVnZXJzIGFu
275
- ZCBhcmUgaW4gb3JkZXIgZnJvbSAwIHRvIG4tMQogICAgIyBhbmQgdGhlIGxh
276
- YmVscyBhcmVuJ3QgY29ycmVzcG9uZGluZyB0byB0aGUgdGlja3MsIGl0J3Mg
277
- Y2F0ZWdvcmljYWwKICAgIGZvciBpLCB0aWNrX2FuZF9sYWJlbCBpbiBlbnVt
278
- ZXJhdGUoemlwKHRpY2tzLCBsYWJlbHMpKToKICAgICAgICB0aWNrLCBsYWJl
279
- bCA9IHRpY2tfYW5kX2xhYmVsCiAgICAgICAgaWYgaXNpbnN0YW5jZSh0aWNr
280
- LCAoaW50LCBmbG9hdCkpIGFuZCB0aWNrID09IGkgYW5kIHN0cihpKSAhPSBs
281
- YWJlbDoKICAgICAgICAgICAgY29udGludWUKICAgICAgICAjIEZvdW5kIGEg
282
- dGljaywgd2hpY2ggd291bGRuJ3QgYmUgaW4gYSBjYXRlZ29yaWNhbCBzY2Fs
283
- ZQogICAgICAgIHJldHVybiAibGluZWFyIgoKICAgIHJldHVybiAiY2F0ZWdv
284
- cmljYWwiCgoKZGVmIF9leHRyYWN0X2NoYXJ0X2RhdGEoYXgpOgogICAgZGF0
285
- YSA9IHt9CgogICAgZGF0YVsidGl0bGUiXSA9IGF4LmdldF90aXRsZSgpCgog
286
- ICAgZGF0YVsieF9sYWJlbCJdID0gYXguZ2V0X3hsYWJlbCgpCiAgICBkYXRh
287
- WyJ5X2xhYmVsIl0gPSBheC5nZXRfeWxhYmVsKCkKCiAgICB4X3RpY2tfbGFi
288
- ZWxzID0gW2xhYmVsLmdldF90ZXh0KCkgZm9yIGxhYmVsIGluIGF4LmdldF94
289
- dGlja2xhYmVscygpXQogICAgZGF0YVsieF90aWNrcyJdID0gX2V4dHJhY3Rf
290
- dGlja3NfZGF0YShheC54YXhpcy5nZXRfY29udmVydGVyKCksIGF4LmdldF94
291
- dGlja3MoKSkKICAgIGRhdGFbInhfdGlja19sYWJlbHMiXSA9IHhfdGlja19s
292
- YWJlbHMKICAgIGRhdGFbInhfc2NhbGUiXSA9IF9leHRyYWN0X3NjYWxlKGF4
293
- LnhheGlzLmdldF9jb252ZXJ0ZXIoKSwgYXguZ2V0X3hzY2FsZSgpLCBheC5n
294
- ZXRfeHRpY2tzKCksIHhfdGlja19sYWJlbHMpCgogICAgeV90aWNrX2xhYmVs
295
- cyA9IFtsYWJlbC5nZXRfdGV4dCgpIGZvciBsYWJlbCBpbiBheC5nZXRfeXRp
296
- Y2tsYWJlbHMoKV0KICAgIGRhdGFbInlfdGlja3MiXSA9IF9leHRyYWN0X3Rp
297
- Y2tzX2RhdGEoYXgueWF4aXMuZ2V0X2NvbnZlcnRlcigpLCBheC5nZXRfeXRp
298
- Y2tzKCkpCiAgICBkYXRhWyJ5X3RpY2tfbGFiZWxzIl0gPSB5X3RpY2tfbGFi
299
- ZWxzCiAgICBkYXRhWyJ5X3NjYWxlIl0gPSBfZXh0cmFjdF9zY2FsZShheC55
300
- YXhpcy5nZXRfY29udmVydGVyKCksIGF4LmdldF95c2NhbGUoKSwgYXguZ2V0
301
- X3l0aWNrcygpLCB5X3RpY2tfbGFiZWxzKQoKICAgIGNoYXJ0X3R5cGUgPSBf
302
- Z2V0X2NoYXJ0X3R5cGUoYXgpCiAgICBlbGVtZW50cyA9IFtdCiAgICBjaGFu
303
- Z2Vfb3JpZW50YXRpb24gPSBGYWxzZQoKICAgIGlmIGNoYXJ0X3R5cGUgPT0g
304
- ImxpbmUiOgogICAgICAgIGVsZW1lbnRzID0gX2V4dHJhY3RfbGluZV9jaGFy
305
- dF9lbGVtZW50cyhheCkKICAgIGVsaWYgY2hhcnRfdHlwZSA9PSAic2NhdHRl
306
- ciI6CiAgICAgICAgZWxlbWVudHMgPSBfZXh0cmFjdF9zY2F0dGVyX2NoYXJ0
307
- X2VsZW1lbnRzKGF4KQogICAgZWxpZiBjaGFydF90eXBlID09ICJiYXIiOgog
308
- ICAgICAgIGVsZW1lbnRzLCBjaGFuZ2Vfb3JpZW50YXRpb24gPSBfZXh0cmFj
309
- dF9iYXJfY2hhcnRfZWxlbWVudHMoYXgpCiAgICBlbGlmIGNoYXJ0X3R5cGUg
310
- PT0gImJveF9hbmRfd2hpc2tlciI6CiAgICAgICAgZWxlbWVudHMsIGNoYW5n
311
- ZV9vcmllbnRhdGlvbiA9IF9leHRyYWN0X2JveF9jaGFydF9lbGVtZW50cyhh
312
- eCkKICAgIGVsaWYgY2hhcnRfdHlwZSA9PSAicGllIjoKICAgICAgICBlbGVt
313
- ZW50cyA9IF9leHRyYWN0X3BpZV9jaGFydF9lbGVtZW50cyhheCkKCiAgICBp
314
- ZiBjaGFuZ2Vfb3JpZW50YXRpb246CiAgICAgICAgZGF0YVsieF9sYWJlbCJd
315
- LCBkYXRhWyJ5X2xhYmVsIl0gPSBkYXRhWyJ5X2xhYmVsIl0sIGRhdGFbInhf
316
- bGFiZWwiXQoKICAgIGRhdGFbInR5cGUiXSA9IGNoYXJ0X3R5cGUKICAgIGRh
317
- dGFbImVsZW1lbnRzIl0gPSBlbGVtZW50cwoKICAgIHJldHVybiBkYXRhCgoK
318
- ZGVmIF9jdXN0b21fanNvbl9zZXJpYWxpemVyKG9iaik6CiAgICBpZiBpc2lu
319
- c3RhbmNlKG9iaiwgbnAuaW50ZWdlcik6CiAgICAgICAgcmV0dXJuIGludChv
320
- YmopCiAgICBpZiBpc2luc3RhbmNlKG9iaiwgbnAuZmxvYXRpbmcpOgogICAg
321
- ICAgIHJldHVybiBmbG9hdChvYmopCiAgICBpZiBpc2luc3RhbmNlKG9iaiwg
322
- bnAubmRhcnJheSk6CiAgICAgICAgcmV0dXJuIG9iai50b2xpc3QoKQogICAg
323
- aWYgaXNpbnN0YW5jZShvYmosIHNldCk6CiAgICAgICAgcmV0dXJuIGxpc3Qo
324
- b2JqKQogICAgcmFpc2UgVHlwZUVycm9yKGYiVHlwZSB7dHlwZShvYmopfSBu
325
- b3Qgc2VyaWFsaXphYmxlIikKCgpkZWYgZXh0cmFjdF9hbmRfcHJpbnRfZmln
326
- dXJlX21ldGFkYXRhKGZpZyk6CiAgICAiIiJFeHRyYWN0IG1ldGFkYXRhIGZy
327
- b20gYSBtYXRwbG90bGliIGZpZ3VyZSBhbmQgcHJpbnQgYXMgSlNPTiIiIgog
328
- ICAgbWV0YWRhdGEgPSB7fQogICAgc3VicGxvdHMgPSBbXQoKICAgIGF4ZXMg
329
- PSBfZmlsdGVyX291dF91bndhbnRlZF9heGVzKGZpZy5heGVzKQoKICAgIGZv
330
- ciBheCBpbiBheGVzOgogICAgICAgIGRhdGEgPSBfZXh0cmFjdF9jaGFydF9k
331
- YXRhKGF4KQogICAgICAgIHN1YnBsb3RzLmFwcGVuZChkYXRhKQoKICAgIGlm
332
- IGxlbihzdWJwbG90cykgPiAxOgogICAgICAgIG1ldGFkYXRhID0gewogICAg
333
- ICAgICAgICAidGl0bGUiOiBmaWcudGV4dHNbMF0uZ2V0X3RleHQoKSBpZiBm
334
- aWcudGV4dHMgYW5kIGxlbihmaWcudGV4dHMpID4gMCBlbHNlIE5vbmUsCiAg
335
- ICAgICAgICAgICJ0eXBlIjogImNvbXBvc2l0ZV9jaGFydCIsCiAgICAgICAg
336
- ICAgICJlbGVtZW50cyI6IHN1YnBsb3RzLAogICAgICAgIH0KICAgIGVsc2U6
337
- CiAgICAgICAgbWV0YWRhdGEgPSBzdWJwbG90c1swXSBpZiBzdWJwbG90cyBh
338
- bmQgbGVuKHN1YnBsb3RzKSA+IDAgZWxzZSB7InR5cGUiOiAidW5rbm93biJ9
339
- CgogICAgbWV0YWRhdGFbInBuZyJdID0gX3NhdmVfZmlndXJlX2FzX2Jhc2U2
340
- NChmaWcpCiAgICBqc29uX291dHB1dCA9IHsidHlwZSI6ICJjaGFydCIsICJ2
341
- YWx1ZSI6IG1ldGFkYXRhfQoKICAgIHByaW50KGYiZHRuX2FydGlmYWN0X2sz
342
- OWZkMjp7anNvbi5kdW1wcyhqc29uX291dHB1dCwgZGVmYXVsdD1fY3VzdG9t
343
- X2pzb25fc2VyaWFsaXplcil9IikKCgpjbGFzcyBNYXRwbG90bGliRmluZGVy
344
- KE1ldGFQYXRoRmluZGVyKToKICAgICIiIkN1c3RvbSBmaW5kZXIgdG8gaW50
345
- ZXJjZXB0IG1hdHBsb3RsaWIucHlwbG90IGltcG9ydHMiIiIKCiAgICBkZWYg
346
- ZmluZF9zcGVjKHNlbGYsIGZ1bGxuYW1lLCBwYXRoLCB0YXJnZXQ9Tm9uZSk6
347
- ICAjIHB5bGludDogZGlzYWJsZT11bnVzZWQtYXJndW1lbnQKICAgICAgICBn
348
- bG9iYWwgcGx0X3BhdGNoZWQsIG5wLCBtcGwsIHBpbF9pbWcgICMgcHlsaW50
349
- OiBkaXNhYmxlPWdsb2JhbC1zdGF0ZW1lbnQKICAgICAgICBpZiBmdWxsbmFt
350
- ZSA9PSAibWF0cGxvdGxpYi5weXBsb3QiIGFuZCBub3QgcGx0X3BhdGNoZWQ6
351
- CiAgICAgICAgICAgIHBsdF9wYXRjaGVkID0gVHJ1ZQoKICAgICAgICAgICAg
352
- IyBJbXBvcnQgbnVtcHkgYW5kIG1hdHBsb3RsaWIgb25jZSB3ZSBhcmUgc3Vy
353
- ZSB3ZSBuZWVkIHRoZW0KICAgICAgICAgICAgIyBweWxpbnQ6IGRpc2FibGU9
354
- aW1wb3J0LW91dHNpZGUtdG9wbGV2ZWwKICAgICAgICAgICAgaW1wb3J0IG1h
355
- dHBsb3RsaWIKICAgICAgICAgICAgaW1wb3J0IG51bXB5CiAgICAgICAgICAg
356
- IGZyb20gUElMIGltcG9ydCBJbWFnZQoKICAgICAgICAgICAgIyBTdG9yZSB0
357
- aGVtIGluIGdsb2JhbCB2YXJpYWJsZXMgZm9yIHVzZSB0aHJvdWdob3V0IHRo
358
- ZSBtb2R1bGUKICAgICAgICAgICAgbnAgPSBudW1weQogICAgICAgICAgICBt
359
- cGwgPSBtYXRwbG90bGliCiAgICAgICAgICAgIHBpbF9pbWcgPSBJbWFnZQoK
360
- ICAgICAgICAgICAgb3JpZ2luYWxfc3BlYyA9IGZpbmRfc3BlYyhmdWxsbmFt
361
- ZSkKICAgICAgICAgICAgaWYgb3JpZ2luYWxfc3BlYyBpcyBOb25lOgogICAg
362
- ICAgICAgICAgICAgcmV0dXJuIE5vbmUKICAgICAgICAgICAgcmV0dXJuIHNw
363
- ZWNfZnJvbV9sb2FkZXIoCiAgICAgICAgICAgICAgICBmdWxsbmFtZSwKICAg
364
- ICAgICAgICAgICAgIE1hdHBsb3RsaWJMb2FkZXIob3JpZ2luYWxfc3BlYy5s
365
- b2FkZXIpLAogICAgICAgICAgICAgICAgb3JpZ2luPW9yaWdpbmFsX3NwZWMu
366
- b3JpZ2luLAogICAgICAgICAgICAgICAgaXNfcGFja2FnZT1vcmlnaW5hbF9z
367
- cGVjLnN1Ym1vZHVsZV9zZWFyY2hfbG9jYXRpb25zIGlzIG5vdCBOb25lLAog
368
- ICAgICAgICAgICApCiAgICAgICAgcmV0dXJuIE5vbmUKCgpjbGFzcyBNYXRw
369
- bG90bGliTG9hZGVyKExvYWRlcik6CiAgICAiIiJDdXN0b20gbG9hZGVyIHRv
370
- IHBhdGNoIHRoZSBtYXRwbG90bGliLnB5cGxvdCBtb2R1bGUiIiIKCiAgICBk
371
- ZWYgX19pbml0X18oc2VsZiwgb3JpZ2luYWxfbG9hZGVyKToKICAgICAgICBz
372
- ZWxmLm9yaWdpbmFsX2xvYWRlciA9IG9yaWdpbmFsX2xvYWRlcgoKICAgIGRl
373
- ZiBjcmVhdGVfbW9kdWxlKHNlbGYsIHNwZWMpOgogICAgICAgIHJldHVybiBz
374
- ZWxmLm9yaWdpbmFsX2xvYWRlci5jcmVhdGVfbW9kdWxlKHNwZWMpCgogICAg
375
- ZGVmIGV4ZWNfbW9kdWxlKHNlbGYsIG1vZHVsZSk6CiAgICAgICAgc2VsZi5v
376
- cmlnaW5hbF9sb2FkZXIuZXhlY19tb2R1bGUobW9kdWxlKQogICAgICAgIGlm
377
- IGhhc2F0dHIobW9kdWxlLCAic2hvdyIpOgogICAgICAgICAgICBvcmlnaW5h
378
- bF9zaG93ID0gbW9kdWxlLnNob3cKCiAgICAgICAgICAgIGRlZiBjdXN0b21f
379
- c2hvdygqYXJncywgKiprd2FyZ3MpOgogICAgICAgICAgICAgICAgZ2xvYmFs
380
- IHByb2Nlc3NlZF9maWd1cmVzICAjIHB5bGludDogZGlzYWJsZT1nbG9iYWwt
381
- dmFyaWFibGUtbm90LWFzc2lnbmVkCiAgICAgICAgICAgICAgICBmaWdfbnVt
382
- cyA9IG1vZHVsZS5nZXRfZmlnbnVtcygpCiAgICAgICAgICAgICAgICBmb3Ig
383
- ZmlnX251bSBpbiBmaWdfbnVtczoKICAgICAgICAgICAgICAgICAgICBmaWcg
384
- PSBtb2R1bGUuZmlndXJlKGZpZ19udW0pCiAgICAgICAgICAgICAgICAgICAg
385
- ZmlnX2hhc2ggPSBfZ2V0X2ZpZ3VyZV9oYXNoKGZpZykKICAgICAgICAgICAg
386
- ICAgICAgICBpZiBmaWdfaGFzaCBub3QgaW4gcHJvY2Vzc2VkX2ZpZ3VyZXM6
387
- CiAgICAgICAgICAgICAgICAgICAgICAgIGV4dHJhY3RfYW5kX3ByaW50X2Zp
388
- Z3VyZV9tZXRhZGF0YShmaWcpCiAgICAgICAgICAgICAgICAgICAgICAgIHBy
389
- b2Nlc3NlZF9maWd1cmVzLmFkZChmaWdfaGFzaCkKICAgICAgICAgICAgICAg
390
- IHJlc3VsdCA9IG9yaWdpbmFsX3Nob3coKmFyZ3MsICoqa3dhcmdzKQogICAg
391
- ICAgICAgICAgICAgbW9kdWxlLmNsb3NlKCJhbGwiKQogICAgICAgICAgICAg
392
- ICAgcmV0dXJuIHJlc3VsdAoKICAgICAgICAgICAgbW9kdWxlLnNob3cgPSBj
393
- dXN0b21fc2hvdwoKCmRlZiBzZXR1cF91c2VyX2NvZGVfZW52aXJvbm1lbnQo
394
- Y29kZSk6CiAgICAiIiJTZXQgdXAgdGhlIG1vZHVsZSB0byBydW4gdXNlciBj
395
- b2RlIGluIiIiCiAgICBtb2R1bGUgPSB0eXBlcy5Nb2R1bGVUeXBlKCJfX21h
396
- aW5fXyIpCiAgICBtb2R1bGUuX19maWxlX18gPSAiPHRhcmdldF9jb2RlPiIK
397
- ICAgIHN5cy5tb2R1bGVzWyJfX21haW5fXyJdID0gbW9kdWxlCiAgICBjb2Rl
398
- X2xpbmVzID0gY29kZS5zcGxpdGxpbmVzKCkKICAgIGxpbmVjYWNoZS5jYWNo
399
- ZVsiPHRhcmdldF9jb2RlPiJdID0gKGxlbihjb2RlKSwgTm9uZSwgY29kZV9s
400
- aW5lcywgIjx0YXJnZXRfY29kZT4iKQogICAgcmV0dXJuIG1vZHVsZQoKCmRl
401
- ZiBydW5fdXNlcl9jb2RlKGNvZGUpOgogICAgIiIiUnVuIHRoZSB1c2VyIGNv
402
- ZGUgd2l0aCB0aGUgbWF0cGxvdGxpYiBpbnRlcmNlcHRvciBpbnN0YWxsZWQi
403
- IiIKICAgICMgSW5zdGFsbCBtYXRwbG90bGliIGludGVyY2VwdG9yCiAgICBz
404
- eXMubWV0YV9wYXRoLmluc2VydCgwLCBNYXRwbG90bGliRmluZGVyKCkpCgog
405
- ICAgIyBTZXQgdXAgY2xlYW4gZW52aXJvbm1lbnQgZm9yIHVzZXIgY29kZQog
406
- ICAgbW9kdWxlID0gc2V0dXBfdXNlcl9jb2RlX2Vudmlyb25tZW50KGNvZGUp
407
- CgogICAgIyBDb21waWxlIGFuZCBydW4gdGhlIGNvZGUKICAgIGNvbXBpbGVk
408
- ID0gY29tcGlsZShjb2RlLCAiPHRhcmdldF9jb2RlPiIsICJleGVjIikKCiAg
409
- ICAjIEV4ZWN1dGUgaW4gdGhlIG1vZHVsZSdzIG5hbWVzcGFjZQogICAgZXhl
410
- Yyhjb21waWxlZCwgbW9kdWxlLl9fZGljdF9fKSAgIyBweWxpbnQ6IGRpc2Fi
411
- bGU9ZXhlYy11c2VkCgoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAg
412
- IHRyeToKICAgICAgICAjIEdldCB0aGUgZW5jb2RlZCB1c2VyIGNvZGUKICAg
413
- ICAgICB1c2VyX2NvZGUgPSBiYXNlNjQuYjY0ZGVjb2RlKCIiIntlbmNvZGVk
414
- X2NvZGV9IiIiKS5kZWNvZGUoKQoKICAgICAgICAjIFJ1biB0aGUgY29kZQog
415
- ICAgICAgIHJ1bl91c2VyX2NvZGUodXNlcl9jb2RlKQogICAgZXhjZXB0IEV4
416
- Y2VwdGlvbjoKICAgICAgICAjIFByaW50IG9ubHkgdGhlIHJlbGV2YW50IHBh
417
- cnRzIG9mIHRoZSB0cmFjZWJhY2sKICAgICAgICBleGNfdHlwZSwgZXhjX3Zh
418
- bHVlLCBleGNfdGIgPSBzeXMuZXhjX2luZm8oKQoKICAgICAgICAjIEZpbHRl
419
- ciB0cmFjZWJhY2sgdG8gb25seSBzaG93IHVzZXIgY29kZSBmcmFtZXMKICAg
420
- ICAgICBmaWx0ZXJlZF90YiA9IFtdCiAgICAgICAgdGIgPSBleGNfdGIKICAg
421
- ICAgICB3aGlsZSB0YiBpcyBub3QgTm9uZToKICAgICAgICAgICAgaWYgdGIu
422
- dGJfZnJhbWUuZl9jb2RlLmNvX2ZpbGVuYW1lID09ICI8dGFyZ2V0X2NvZGU+
423
- IjoKICAgICAgICAgICAgICAgIGZpbHRlcmVkX3RiLmFwcGVuZCh0YikKICAg
424
- ICAgICAgICAgdGIgPSB0Yi50Yl9uZXh0CgogICAgICAgIGlmIGZpbHRlcmVk
425
- X3RiOgogICAgICAgICAgICAjIENyZWF0ZSBhIG5ldyB0cmFjZWJhY2sgZnJv
426
- bSB0aGUgZmlsdGVyZWQgZnJhbWVzCiAgICAgICAgICAgIGV4Y192YWx1ZS5f
427
- X3RyYWNlYmFja19fID0gZmlsdGVyZWRfdGJbLTFdCiAgICAgICAgICAgIHRy
428
- YWNlYmFjay5wcmludF9leGNlcHRpb24oZXhjX3R5cGUsIGV4Y192YWx1ZSwg
429
- ZXhjX3ZhbHVlLl9fdHJhY2ViYWNrX18pCiAgICAgICAgZWxzZToKICAgICAg
430
- ICAgICAgIyBGYWxsYmFjayBpZiBubyB1c2VyIGNvZGUgZnJhbWVzIGZvdW5k
431
- IC0gcmFpc2UgdGhlIG9yaWdpbmFsIGV4Y2VwdGlvbiB0eXBlCiAgICAgICAg
432
- ICAgICMgd2l0aCB0aGUgb3JpZ2luYWwgbWVzc2FnZSBidXQgY3JlYXRlIGEg
433
- ZnJlc2ggdHJhY2ViYWNrCiAgICAgICAgICAgIHJhaXNlIGV4Y190eXBlKHN0
434
- cihleGNfdmFsdWUpKSBmcm9tIE5vbmUKCiAgICAgICAgc3lzLmV4aXQoMSkK
435
- BASE64
436
- private_constant :PYTHON_CODE_WRAPPER
437
- end
438
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'base64'
4
-
5
- module Daytona
6
- class SandboxTsCodeToolbox
7
- # Get the run command for executing TypeScript code
8
- #
9
- # @param code [String] The TypeScript code to execute
10
- # @param params [Daytona::CodeRunParams, nil] Optional parameters for code execution
11
- # @return [String] The command to run the TypeScript code
12
- def get_run_command(code, params = nil)
13
- # Prepend argv fix: ts-node places the script path at argv[1]; splice it out to match legacy node -e behaviour
14
- encoded_code = Base64.strict_encode64("process.argv.splice(1, 1);\n" + code)
15
-
16
- argv = params&.argv&.join(' ') || ''
17
-
18
- # Pipe the base64-encoded code via stdin to avoid OS ARG_MAX limits on large payloads
19
- # ts-node does not support - for stdin; use shell PID ($$) for the temp file — each code_run spawns its own
20
- # shell process so $$ is unique across concurrent calls; cleaned up before exit
21
- # npm_config_loglevel=error suppresses npm notice/warn output at source, preserving streaming and real errors
22
- '_f=/tmp/dtn_$$.ts; ' \
23
- "printf '%s' '#{encoded_code}' | base64 -d > \"$_f\"; " \
24
- "npm_config_loglevel=error npx ts-node -T --ignore-diagnostics 5107 -O '{\"module\":\"CommonJS\"}' \"$_f\" #{argv}; " \
25
- '_dtn_ec=$?; ' \
26
- 'rm -f "$_f"; ' \
27
- 'exit $_dtn_ec'
28
- end
29
- end
30
- end