@@ -52,6 +52,7 @@ def test_compat_env_to_config(monkeypatch, setup_env):
52
52
monkeypatch .setenv ('AGENT_MEMORY_ENABLED' , 'True' )
53
53
monkeypatch .setenv ('AGENT' , 'CodeActAgent' )
54
54
monkeypatch .setenv ('SANDBOX_TYPE' , 'local' )
55
+ monkeypatch .setenv ('SANDBOX_TIMEOUT' , '10' )
55
56
56
57
config = AppConfig ()
57
58
load_from_env (config , os .environ )
@@ -66,6 +67,7 @@ def test_compat_env_to_config(monkeypatch, setup_env):
66
67
assert config .agent .memory_enabled is True
67
68
assert config .agent .name == 'CodeActAgent'
68
69
assert config .sandbox .box_type == 'local'
70
+ assert config .sandbox .timeout == 10
69
71
70
72
71
73
def test_load_from_old_style_env (monkeypatch , default_config ):
@@ -74,6 +76,7 @@ def test_load_from_old_style_env(monkeypatch, default_config):
74
76
monkeypatch .setenv ('AGENT_MEMORY_ENABLED' , 'True' )
75
77
monkeypatch .setenv ('AGENT_NAME' , 'PlannerAgent' )
76
78
monkeypatch .setenv ('WORKSPACE_BASE' , '/opt/files/workspace' )
79
+ monkeypatch .setenv ('SANDBOX_CONTAINER_IMAGE' , 'custom_image' )
77
80
78
81
load_from_env (default_config , os .environ )
79
82
@@ -87,6 +90,7 @@ def test_load_from_old_style_env(monkeypatch, default_config):
87
90
assert (
88
91
default_config .workspace_mount_path_in_sandbox is not UndefinedString .UNDEFINED
89
92
)
93
+ assert default_config .sandbox .container_image == 'custom_image'
90
94
91
95
92
96
def test_load_from_new_style_toml (default_config , temp_toml_file ):
@@ -135,8 +139,50 @@ def test_load_from_new_style_toml(default_config, temp_toml_file):
135
139
assert default_config .workspace_mount_path == '/opt/files2/workspace'
136
140
137
141
138
- def test_env_overrides_toml (monkeypatch , default_config , temp_toml_file ):
139
- # Test that environment variables override TOML values using monkeypatch
142
+ def test_compat_load_sandbox_from_toml (default_config , temp_toml_file ):
143
+ # test loading configuration from a new-style TOML file
144
+ # uses a toml file with sandbox_vars instead of a sandbox section
145
+ with open (temp_toml_file , 'w' , encoding = 'utf-8' ) as toml_file :
146
+ toml_file .write (
147
+ """
148
+ [llm]
149
+ model = "test-model"
150
+
151
+ [agent]
152
+ name = "TestAgent"
153
+ memory_enabled = true
154
+
155
+ [core]
156
+ workspace_base = "/opt/files2/workspace"
157
+ sandbox_type = "local"
158
+ sandbox_timeout = 500
159
+ sandbox_container_image = "node:14"
160
+ sandbox_user_id = 1001
161
+ """
162
+ )
163
+
164
+ load_from_toml (default_config , temp_toml_file )
165
+
166
+ assert default_config .llm .model == 'test-model'
167
+ assert default_config .agent .name == 'TestAgent'
168
+ assert default_config .agent .memory_enabled is True
169
+ assert default_config .workspace_base == '/opt/files2/workspace'
170
+ assert default_config .sandbox .box_type == 'local'
171
+ assert default_config .sandbox .timeout == 500
172
+ assert default_config .sandbox .container_image == 'node:14'
173
+ assert default_config .sandbox .user_id == 1001
174
+ assert default_config .workspace_mount_path_in_sandbox == '/workspace'
175
+
176
+ finalize_config (default_config )
177
+
178
+ # after finalize_config, workspace_mount_path is set to the absolute path of workspace_base
179
+ # if it was undefined
180
+ assert default_config .workspace_mount_path == '/opt/files2/workspace'
181
+
182
+
183
+ def test_env_overrides_compat_toml (monkeypatch , default_config , temp_toml_file ):
184
+ # test that environment variables override TOML values using monkeypatch
185
+ # uses a toml file with sandbox_vars instead of a sandbox section
140
186
with open (temp_toml_file , 'w' , encoding = 'utf-8' ) as toml_file :
141
187
toml_file .write ("""
142
188
[llm]
@@ -147,11 +193,15 @@ def test_env_overrides_toml(monkeypatch, default_config, temp_toml_file):
147
193
workspace_base = "/opt/files3/workspace"
148
194
sandbox_type = "local"
149
195
disable_color = true
196
+ sandbox_timeout = 500
197
+ sandbox_user_id = 1001
150
198
""" )
151
199
152
200
monkeypatch .setenv ('LLM_API_KEY' , 'env-api-key' )
153
201
monkeypatch .setenv ('WORKSPACE_BASE' , 'UNDEFINED' )
154
202
monkeypatch .setenv ('SANDBOX_TYPE' , 'exec' )
203
+ monkeypatch .setenv ('SANDBOX_TIMEOUT' , '1000' )
204
+ monkeypatch .setenv ('SANDBOX_USER_ID' , '1002' )
155
205
156
206
load_from_toml (default_config , temp_toml_file )
157
207
@@ -174,6 +224,59 @@ def test_env_overrides_toml(monkeypatch, default_config, temp_toml_file):
174
224
175
225
assert default_config .sandbox .box_type == 'exec'
176
226
assert default_config .disable_color is True
227
+ assert default_config .sandbox .timeout == 1000
228
+ assert default_config .sandbox .user_id == 1002
229
+
230
+ finalize_config (default_config )
231
+ # after finalize_config, workspace_mount_path is set to absolute path of workspace_base if it was undefined
232
+ assert default_config .workspace_mount_path == os .getcwd () + '/UNDEFINED'
233
+
234
+
235
+ def test_env_overrides_sandbox_toml (monkeypatch , default_config , temp_toml_file ):
236
+ # test that environment variables override TOML values using monkeypatch
237
+ # uses a toml file with a sandbox section
238
+ with open (temp_toml_file , 'w' , encoding = 'utf-8' ) as toml_file :
239
+ toml_file .write ("""
240
+ [llm]
241
+ model = "test-model"
242
+ api_key = "toml-api-key"
243
+
244
+ [core]
245
+ workspace_base = "/opt/files3/workspace"
246
+
247
+ [sandbox]
248
+ sandbox_type = "e2b"
249
+ sandbox_timeout = 500
250
+ sandbox_user_id = 1001
251
+ """ )
252
+
253
+ monkeypatch .setenv ('LLM_API_KEY' , 'env-api-key' )
254
+ monkeypatch .setenv ('WORKSPACE_BASE' , 'UNDEFINED' )
255
+ monkeypatch .setenv ('SANDBOX_TYPE' , 'local' )
256
+ monkeypatch .setenv ('SANDBOX_TIMEOUT' , '1000' )
257
+ monkeypatch .setenv ('SANDBOX_USER_ID' , '1002' )
258
+
259
+ load_from_toml (default_config , temp_toml_file )
260
+
261
+ # before finalize_config, workspace_mount_path is UndefinedString.UNDEFINED if it was not set
262
+ assert default_config .workspace_mount_path is UndefinedString .UNDEFINED
263
+
264
+ # before load_from_env, values are set to the values from the toml file
265
+ assert default_config .llm .api_key == 'toml-api-key'
266
+ assert default_config .sandbox .box_type == 'e2b'
267
+ assert default_config .sandbox .timeout == 500
268
+ assert default_config .sandbox .user_id == 1001
269
+
270
+ load_from_env (default_config , os .environ )
271
+
272
+ # values from env override values from toml
273
+ assert os .environ .get ('LLM_MODEL' ) is None
274
+ assert default_config .llm .model == 'test-model'
275
+ assert default_config .llm .api_key == 'env-api-key'
276
+
277
+ assert default_config .sandbox .box_type == 'local'
278
+ assert default_config .sandbox .timeout == 1000
279
+ assert default_config .sandbox .user_id == 1002
177
280
178
281
finalize_config (default_config )
179
282
# after finalize_config, workspace_mount_path is set to absolute path of workspace_base if it was undefined
@@ -186,6 +289,9 @@ def test_defaults_dict_after_updates(default_config):
186
289
assert (
187
290
initial_defaults ['workspace_mount_path' ]['default' ] is UndefinedString .UNDEFINED
188
291
)
292
+ assert initial_defaults ['llm' ]['api_key' ]['default' ] is None
293
+ assert initial_defaults ['agent' ]['name' ]['default' ] == 'CodeActAgent'
294
+
189
295
updated_config = AppConfig ()
190
296
updated_config .llm .api_key = 'updated-api-key'
191
297
updated_config .agent .name = 'MonologueAgent'
@@ -197,6 +303,12 @@ def test_defaults_dict_after_updates(default_config):
197
303
defaults_after_updates ['workspace_mount_path' ]['default' ]
198
304
is UndefinedString .UNDEFINED
199
305
)
306
+ assert defaults_after_updates ['sandbox' ]['box_type' ]['default' ] == 'ssh'
307
+ assert defaults_after_updates ['sandbox' ]['timeout' ]['default' ] == 120
308
+ assert (
309
+ defaults_after_updates ['sandbox' ]['container_image' ]['default' ]
310
+ == 'ghcr.io/opendevin/sandbox:main'
311
+ )
200
312
assert defaults_after_updates == initial_defaults
201
313
202
314
0 commit comments