rhylthyme-cli-runner 0.1.0a0__py3-none-any.whl
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.
- rhylthyme_cli_runner/__init__.py +15 -0
- rhylthyme_cli_runner/cli.py +273 -0
- rhylthyme_cli_runner/environment_icons.py +258 -0
- rhylthyme_cli_runner/environment_loader.py +293 -0
- rhylthyme_cli_runner/environment_schemas.py +443 -0
- rhylthyme_cli_runner/program_planner.py +871 -0
- rhylthyme_cli_runner/program_runner.py +2257 -0
- rhylthyme_cli_runner/validate_program.py +457 -0
- rhylthyme_cli_runner-0.1.0a0.dist-info/METADATA +268 -0
- rhylthyme_cli_runner-0.1.0a0.dist-info/RECORD +13 -0
- rhylthyme_cli_runner-0.1.0a0.dist-info/WHEEL +5 -0
- rhylthyme_cli_runner-0.1.0a0.dist-info/entry_points.txt +2 -0
- rhylthyme_cli_runner-0.1.0a0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Environment Schema Validation System
|
|
4
|
+
|
|
5
|
+
This module provides schemas and validation for environment catalog files,
|
|
6
|
+
ensuring they conform to the expected structure for their environment type.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import jsonschema
|
|
11
|
+
from typing import Dict, List, Any, Optional, Set
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
# Base environment schema that all environments must conform to
|
|
15
|
+
BASE_ENVIRONMENT_SCHEMA = {
|
|
16
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
17
|
+
"title": "Base Environment Schema",
|
|
18
|
+
"description": "Base schema for environment catalog files",
|
|
19
|
+
"type": "object",
|
|
20
|
+
"required": ["environmentId", "name", "type", "resourceConstraints"],
|
|
21
|
+
"properties": {
|
|
22
|
+
"environmentId": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"description": "Unique identifier for the environment",
|
|
25
|
+
"pattern": "^[a-z0-9-]+$"
|
|
26
|
+
},
|
|
27
|
+
"name": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"description": "Human-readable name for the environment"
|
|
30
|
+
},
|
|
31
|
+
"description": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"description": "Detailed description of the environment"
|
|
34
|
+
},
|
|
35
|
+
"type": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"description": "Type of environment (e.g., kitchen, laboratory, bakery, airport)",
|
|
38
|
+
"enum": [
|
|
39
|
+
"kitchen", "laboratory", "bakery", "airport", "restaurant",
|
|
40
|
+
"home", "commercial-kitchen", "lab", "research", "biotech",
|
|
41
|
+
"pharma", "medical", "artisan", "pastry", "aviation",
|
|
42
|
+
"runway", "terminal", "manufacturing", "warehouse", "office",
|
|
43
|
+
"hospital", "school", "retail", "farm", "datacenter",
|
|
44
|
+
"factory", "workshop", "garage", "gym", "studio", "theater",
|
|
45
|
+
"library", "garden", "greenhouse", "clinic", "spa", "hotel"
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"actors": {
|
|
49
|
+
"type": "integer",
|
|
50
|
+
"minimum": 1,
|
|
51
|
+
"description": "Legacy: Total number of actors (use actorTypes for new environments)"
|
|
52
|
+
},
|
|
53
|
+
"actorTypes": {
|
|
54
|
+
"type": "object",
|
|
55
|
+
"description": "Definition of different actor types and their counts",
|
|
56
|
+
"patternProperties": {
|
|
57
|
+
"^[a-z0-9-]+$": {
|
|
58
|
+
"type": "object",
|
|
59
|
+
"required": ["name", "count"],
|
|
60
|
+
"properties": {
|
|
61
|
+
"name": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"description": "Human-readable name for the actor type"
|
|
64
|
+
},
|
|
65
|
+
"count": {
|
|
66
|
+
"type": "integer",
|
|
67
|
+
"minimum": 1,
|
|
68
|
+
"description": "Number of actors of this type"
|
|
69
|
+
},
|
|
70
|
+
"description": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"description": "Description of the actor type's role"
|
|
73
|
+
},
|
|
74
|
+
"qualifications": {
|
|
75
|
+
"type": "array",
|
|
76
|
+
"items": {"type": "string"},
|
|
77
|
+
"description": "List of qualifications this actor type possesses"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"resourceConstraints": {
|
|
84
|
+
"type": "array",
|
|
85
|
+
"description": "List of resource constraints for this environment",
|
|
86
|
+
"minItems": 1,
|
|
87
|
+
"items": {
|
|
88
|
+
"type": "object",
|
|
89
|
+
"required": ["task", "maxConcurrent", "description"],
|
|
90
|
+
"properties": {
|
|
91
|
+
"task": {
|
|
92
|
+
"type": "string",
|
|
93
|
+
"description": "Name of the task/resource type"
|
|
94
|
+
},
|
|
95
|
+
"maxConcurrent": {
|
|
96
|
+
"type": "integer",
|
|
97
|
+
"minimum": 1,
|
|
98
|
+
"description": "Maximum number of concurrent uses of this resource"
|
|
99
|
+
},
|
|
100
|
+
"actorsRequired": {
|
|
101
|
+
"type": "number",
|
|
102
|
+
"minimum": 0,
|
|
103
|
+
"description": "Number of actors required for this task"
|
|
104
|
+
},
|
|
105
|
+
"qualifiedActorTypes": {
|
|
106
|
+
"type": "array",
|
|
107
|
+
"items": {"type": "string"},
|
|
108
|
+
"description": "Actor types qualified to perform this task"
|
|
109
|
+
},
|
|
110
|
+
"description": {
|
|
111
|
+
"type": "string",
|
|
112
|
+
"description": "Description of the resource or equipment"
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"metadata": {
|
|
118
|
+
"type": "object",
|
|
119
|
+
"description": "Additional metadata about the environment"
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
"anyOf": [
|
|
123
|
+
{"required": ["actors"]},
|
|
124
|
+
{"required": ["actorTypes"]}
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# Type-specific task definitions for different environment types
|
|
129
|
+
ENVIRONMENT_TYPE_TASKS = {
|
|
130
|
+
"kitchen": {
|
|
131
|
+
"required_tasks": ["stove-burner", "prep-work", "cleanup"],
|
|
132
|
+
"common_tasks": [
|
|
133
|
+
"stove-burner", "oven", "microwave", "toaster", "prep-work",
|
|
134
|
+
"plating", "cleanup", "mixer", "refrigerator", "dishwasher",
|
|
135
|
+
"grill", "fryer", "steamer", "food-processor", "walk-in-cooler",
|
|
136
|
+
"freezer", "expediting", "service-window", "prep-station",
|
|
137
|
+
"cold-prep", "grill-station", "pastry-oven", "dishwashing"
|
|
138
|
+
],
|
|
139
|
+
"actor_types": [
|
|
140
|
+
"home-cook", "chef", "cook", "prep-cook", "head-chef",
|
|
141
|
+
"sous-chef", "line-cook", "dishwasher", "chef-de-partie",
|
|
142
|
+
"commis-chef", "kitchen-porter", "pastry-chef", "expediter"
|
|
143
|
+
]
|
|
144
|
+
},
|
|
145
|
+
"laboratory": {
|
|
146
|
+
"required_tasks": ["bench-space", "cleanup"],
|
|
147
|
+
"common_tasks": [
|
|
148
|
+
"fume-hood", "biosafety-cabinet", "incubator", "centrifuge",
|
|
149
|
+
"microscope", "spectrophotometer", "pcr-machine", "hplc",
|
|
150
|
+
"mass-spectrometer", "flow-cytometer", "bench-space",
|
|
151
|
+
"prep-work", "autoclave", "freezer-80", "liquid-nitrogen",
|
|
152
|
+
"data-analysis", "cleanup"
|
|
153
|
+
],
|
|
154
|
+
"actor_types": [
|
|
155
|
+
"principal-investigator", "lab-manager", "senior-scientist",
|
|
156
|
+
"postdoc", "grad-student", "lab-technician", "undergrad"
|
|
157
|
+
]
|
|
158
|
+
},
|
|
159
|
+
"bakery": {
|
|
160
|
+
"required_tasks": ["oven", "mixer", "work-bench"],
|
|
161
|
+
"common_tasks": [
|
|
162
|
+
"oven", "convection-oven", "proofer", "mixer", "dough-sheeter",
|
|
163
|
+
"work-bench", "prep-work", "decorating-station", "cooling-rack",
|
|
164
|
+
"packaging", "cleanup", "refrigeration", "freezer", "laminator"
|
|
165
|
+
],
|
|
166
|
+
"actor_types": ["head-baker", "pastry-chef", "baker", "assistant-baker"]
|
|
167
|
+
},
|
|
168
|
+
"airport": {
|
|
169
|
+
"required_tasks": ["runway", "gate"],
|
|
170
|
+
"common_tasks": [
|
|
171
|
+
"runway", "gate", "baggage-handling", "check-in-counter",
|
|
172
|
+
"security-checkpoint", "air-traffic-control", "ground-crew",
|
|
173
|
+
"fueling-station", "maintenance-hangar", "cargo-terminal",
|
|
174
|
+
"customs", "immigration"
|
|
175
|
+
],
|
|
176
|
+
"actor_types": [
|
|
177
|
+
"pilot", "air-traffic-controller", "ground-crew", "baggage-handler",
|
|
178
|
+
"security-officer", "check-in-agent", "maintenance-technician"
|
|
179
|
+
]
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
# Additional type aliases
|
|
184
|
+
ENVIRONMENT_TYPE_TASKS.update({
|
|
185
|
+
"home": ENVIRONMENT_TYPE_TASKS["kitchen"],
|
|
186
|
+
"restaurant": ENVIRONMENT_TYPE_TASKS["kitchen"],
|
|
187
|
+
"commercial-kitchen": ENVIRONMENT_TYPE_TASKS["kitchen"],
|
|
188
|
+
"lab": ENVIRONMENT_TYPE_TASKS["laboratory"],
|
|
189
|
+
"research": ENVIRONMENT_TYPE_TASKS["laboratory"],
|
|
190
|
+
"biotech": ENVIRONMENT_TYPE_TASKS["laboratory"],
|
|
191
|
+
"pharma": ENVIRONMENT_TYPE_TASKS["laboratory"],
|
|
192
|
+
"artisan": ENVIRONMENT_TYPE_TASKS["bakery"],
|
|
193
|
+
"pastry": ENVIRONMENT_TYPE_TASKS["bakery"],
|
|
194
|
+
"aviation": ENVIRONMENT_TYPE_TASKS["airport"],
|
|
195
|
+
"runway": ENVIRONMENT_TYPE_TASKS["airport"],
|
|
196
|
+
"terminal": ENVIRONMENT_TYPE_TASKS["airport"]
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
class EnvironmentValidator:
|
|
201
|
+
"""Validator for environment catalog files."""
|
|
202
|
+
|
|
203
|
+
def __init__(self):
|
|
204
|
+
"""Initialize the validator with schemas."""
|
|
205
|
+
self.base_schema = BASE_ENVIRONMENT_SCHEMA
|
|
206
|
+
self.type_tasks = ENVIRONMENT_TYPE_TASKS
|
|
207
|
+
|
|
208
|
+
def validate_environment(self, environment_data: Dict[str, Any]) -> List[str]:
|
|
209
|
+
"""
|
|
210
|
+
Validate an environment against both base schema and type-specific requirements.
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
environment_data: The environment data to validate
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
List of validation errors (empty if valid)
|
|
217
|
+
"""
|
|
218
|
+
errors = []
|
|
219
|
+
|
|
220
|
+
# Validate against base schema
|
|
221
|
+
try:
|
|
222
|
+
jsonschema.validate(environment_data, self.base_schema)
|
|
223
|
+
except jsonschema.ValidationError as e:
|
|
224
|
+
errors.append(f"Schema validation error: {e.message}")
|
|
225
|
+
return errors # Don't continue if basic schema is invalid
|
|
226
|
+
|
|
227
|
+
# Get environment type for type-specific validation
|
|
228
|
+
env_type = environment_data.get('type', '')
|
|
229
|
+
|
|
230
|
+
# Validate type-specific requirements
|
|
231
|
+
type_errors = self._validate_type_specific(environment_data, env_type)
|
|
232
|
+
errors.extend(type_errors)
|
|
233
|
+
|
|
234
|
+
# Validate actor types consistency
|
|
235
|
+
actor_errors = self._validate_actor_types(environment_data, env_type)
|
|
236
|
+
errors.extend(actor_errors)
|
|
237
|
+
|
|
238
|
+
# Validate resource constraints
|
|
239
|
+
resource_errors = self._validate_resource_constraints(environment_data)
|
|
240
|
+
errors.extend(resource_errors)
|
|
241
|
+
|
|
242
|
+
return errors
|
|
243
|
+
|
|
244
|
+
def _validate_type_specific(self, environment_data: Dict[str, Any], env_type: str) -> List[str]:
|
|
245
|
+
"""Validate type-specific requirements."""
|
|
246
|
+
errors = []
|
|
247
|
+
|
|
248
|
+
if env_type not in self.type_tasks:
|
|
249
|
+
# Don't error for unknown types, just warn
|
|
250
|
+
return []
|
|
251
|
+
|
|
252
|
+
type_config = self.type_tasks[env_type]
|
|
253
|
+
resource_constraints = environment_data.get('resourceConstraints', [])
|
|
254
|
+
task_names = {constraint['task'] for constraint in resource_constraints}
|
|
255
|
+
|
|
256
|
+
# Check for required tasks
|
|
257
|
+
required_tasks = set(type_config.get('required_tasks', []))
|
|
258
|
+
missing_required = required_tasks - task_names
|
|
259
|
+
if missing_required:
|
|
260
|
+
errors.append(f"Missing required tasks for {env_type}: {', '.join(missing_required)}")
|
|
261
|
+
|
|
262
|
+
# Check for unexpected tasks (warn only)
|
|
263
|
+
common_tasks = set(type_config.get('common_tasks', []))
|
|
264
|
+
unexpected_tasks = task_names - common_tasks
|
|
265
|
+
if unexpected_tasks:
|
|
266
|
+
# This is a warning, not an error
|
|
267
|
+
errors.append(f"Warning: Uncommon tasks for {env_type}: {', '.join(unexpected_tasks)}")
|
|
268
|
+
|
|
269
|
+
return errors
|
|
270
|
+
|
|
271
|
+
def _validate_actor_types(self, environment_data: Dict[str, Any], env_type: str) -> List[str]:
|
|
272
|
+
"""Validate actor types are appropriate for environment type."""
|
|
273
|
+
errors = []
|
|
274
|
+
|
|
275
|
+
if env_type not in self.type_tasks:
|
|
276
|
+
return []
|
|
277
|
+
|
|
278
|
+
type_config = self.type_tasks[env_type]
|
|
279
|
+
expected_actor_types = set(type_config.get('actor_types', []))
|
|
280
|
+
|
|
281
|
+
# Check actor types (if using new format)
|
|
282
|
+
if 'actorTypes' in environment_data:
|
|
283
|
+
actual_actor_types = set(environment_data['actorTypes'].keys())
|
|
284
|
+
|
|
285
|
+
# Validate actor type names are reasonable for this environment
|
|
286
|
+
unexpected_actors = actual_actor_types - expected_actor_types
|
|
287
|
+
if unexpected_actors:
|
|
288
|
+
errors.append(f"Warning: Uncommon actor types for {env_type}: {', '.join(unexpected_actors)}")
|
|
289
|
+
|
|
290
|
+
return errors
|
|
291
|
+
|
|
292
|
+
def _validate_resource_constraints(self, environment_data: Dict[str, Any]) -> List[str]:
|
|
293
|
+
"""Validate resource constraints for consistency."""
|
|
294
|
+
errors = []
|
|
295
|
+
|
|
296
|
+
resource_constraints = environment_data.get('resourceConstraints', [])
|
|
297
|
+
actor_types = environment_data.get('actorTypes', {})
|
|
298
|
+
|
|
299
|
+
# Check that qualified actor types exist
|
|
300
|
+
all_actor_type_ids = set(actor_types.keys())
|
|
301
|
+
if environment_data.get('actors'):
|
|
302
|
+
all_actor_type_ids.add('generic') # Legacy support
|
|
303
|
+
|
|
304
|
+
for constraint in resource_constraints:
|
|
305
|
+
qualified_types = constraint.get('qualifiedActorTypes', [])
|
|
306
|
+
for actor_type in qualified_types:
|
|
307
|
+
if actor_type not in all_actor_type_ids:
|
|
308
|
+
errors.append(f"Task '{constraint['task']}' references unknown actor type: {actor_type}")
|
|
309
|
+
|
|
310
|
+
# Validate actors vs actorsRequired totals don't exceed capacity
|
|
311
|
+
total_actors = 0
|
|
312
|
+
if 'actorTypes' in environment_data:
|
|
313
|
+
total_actors = sum(actor_info['count'] for actor_info in actor_types.values())
|
|
314
|
+
elif 'actors' in environment_data:
|
|
315
|
+
total_actors = environment_data['actors']
|
|
316
|
+
|
|
317
|
+
max_required = 0
|
|
318
|
+
for constraint in resource_constraints:
|
|
319
|
+
actors_required = constraint.get('actorsRequired', 0)
|
|
320
|
+
max_concurrent = constraint.get('maxConcurrent', 1)
|
|
321
|
+
max_required = max(max_required, actors_required * max_concurrent)
|
|
322
|
+
|
|
323
|
+
if max_required > total_actors:
|
|
324
|
+
errors.append(f"Resource constraints require up to {max_required} actors but only {total_actors} available")
|
|
325
|
+
|
|
326
|
+
return errors
|
|
327
|
+
|
|
328
|
+
def validate_environment_file(self, file_path: str) -> List[str]:
|
|
329
|
+
"""
|
|
330
|
+
Validate an environment file.
|
|
331
|
+
|
|
332
|
+
Args:
|
|
333
|
+
file_path: Path to the environment file
|
|
334
|
+
|
|
335
|
+
Returns:
|
|
336
|
+
List of validation errors
|
|
337
|
+
"""
|
|
338
|
+
try:
|
|
339
|
+
with open(file_path, 'r') as f:
|
|
340
|
+
if file_path.endswith('.json'):
|
|
341
|
+
data = json.load(f)
|
|
342
|
+
else:
|
|
343
|
+
import yaml
|
|
344
|
+
data = yaml.safe_load(f)
|
|
345
|
+
|
|
346
|
+
return self.validate_environment(data)
|
|
347
|
+
|
|
348
|
+
except FileNotFoundError:
|
|
349
|
+
return [f"File not found: {file_path}"]
|
|
350
|
+
except json.JSONDecodeError as e:
|
|
351
|
+
return [f"JSON decode error: {e}"]
|
|
352
|
+
except Exception as e:
|
|
353
|
+
return [f"Error reading file: {e}"]
|
|
354
|
+
|
|
355
|
+
def get_environment_type_info(self, env_type: str) -> Optional[Dict[str, Any]]:
|
|
356
|
+
"""Get information about a specific environment type."""
|
|
357
|
+
return self.type_tasks.get(env_type)
|
|
358
|
+
|
|
359
|
+
def list_supported_types(self) -> List[str]:
|
|
360
|
+
"""Get list of supported environment types."""
|
|
361
|
+
return list(self.type_tasks.keys())
|
|
362
|
+
|
|
363
|
+
def suggest_tasks_for_type(self, env_type: str) -> List[str]:
|
|
364
|
+
"""Suggest common tasks for an environment type."""
|
|
365
|
+
if env_type in self.type_tasks:
|
|
366
|
+
return self.type_tasks[env_type].get('common_tasks', [])
|
|
367
|
+
return []
|
|
368
|
+
|
|
369
|
+
def suggest_actor_types_for_type(self, env_type: str) -> List[str]:
|
|
370
|
+
"""Suggest actor types for an environment type."""
|
|
371
|
+
if env_type in self.type_tasks:
|
|
372
|
+
return self.type_tasks[env_type].get('actor_types', [])
|
|
373
|
+
return []
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def validate_all_environments(environments_dir: str = "environments") -> Dict[str, List[str]]:
|
|
377
|
+
"""
|
|
378
|
+
Validate all environment files in a directory.
|
|
379
|
+
|
|
380
|
+
Args:
|
|
381
|
+
environments_dir: Directory containing environment files
|
|
382
|
+
|
|
383
|
+
Returns:
|
|
384
|
+
Dictionary mapping file names to validation errors
|
|
385
|
+
"""
|
|
386
|
+
validator = EnvironmentValidator()
|
|
387
|
+
results = {}
|
|
388
|
+
|
|
389
|
+
env_path = Path(environments_dir)
|
|
390
|
+
if not env_path.exists():
|
|
391
|
+
return {"error": ["Environments directory not found"]}
|
|
392
|
+
|
|
393
|
+
for file_path in env_path.glob("*.json"):
|
|
394
|
+
errors = validator.validate_environment_file(str(file_path))
|
|
395
|
+
if errors:
|
|
396
|
+
results[file_path.name] = errors
|
|
397
|
+
|
|
398
|
+
for file_path in env_path.glob("*.yaml"):
|
|
399
|
+
errors = validator.validate_environment_file(str(file_path))
|
|
400
|
+
if errors:
|
|
401
|
+
results[file_path.name] = errors
|
|
402
|
+
|
|
403
|
+
for file_path in env_path.glob("*.yml"):
|
|
404
|
+
errors = validator.validate_environment_file(str(file_path))
|
|
405
|
+
if errors:
|
|
406
|
+
results[file_path.name] = errors
|
|
407
|
+
|
|
408
|
+
return results
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
if __name__ == "__main__":
|
|
412
|
+
# Example usage and testing
|
|
413
|
+
validator = EnvironmentValidator()
|
|
414
|
+
|
|
415
|
+
print("Environment Schema Validation System")
|
|
416
|
+
print("=" * 50)
|
|
417
|
+
|
|
418
|
+
print(f"\nSupported environment types: {len(validator.list_supported_types())}")
|
|
419
|
+
for env_type in sorted(validator.list_supported_types()):
|
|
420
|
+
info = validator.get_environment_type_info(env_type)
|
|
421
|
+
required = info.get('required_tasks', [])
|
|
422
|
+
print(f" {env_type:20} - Required: {', '.join(required) if required else 'None'}")
|
|
423
|
+
|
|
424
|
+
# Test validation on existing environment files
|
|
425
|
+
print(f"\nValidating existing environment files...")
|
|
426
|
+
validation_results = validate_all_environments()
|
|
427
|
+
|
|
428
|
+
if not validation_results:
|
|
429
|
+
print("✓ All environment files are valid!")
|
|
430
|
+
else:
|
|
431
|
+
for filename, errors in validation_results.items():
|
|
432
|
+
print(f"\n{filename}:")
|
|
433
|
+
for error in errors:
|
|
434
|
+
print(f" - {error}")
|
|
435
|
+
|
|
436
|
+
# Test the specific environment types requested
|
|
437
|
+
print(f"\nEnvironment type suggestions:")
|
|
438
|
+
for env_type in ["kitchen", "laboratory", "bakery", "airport"]:
|
|
439
|
+
tasks = validator.suggest_tasks_for_type(env_type)
|
|
440
|
+
actors = validator.suggest_actor_types_for_type(env_type)
|
|
441
|
+
print(f"\n{env_type}:")
|
|
442
|
+
print(f" Suggested tasks: {', '.join(tasks[:5])}...")
|
|
443
|
+
print(f" Suggested actors: {', '.join(actors)}")
|