Skip to content

Commit 439bfb4

Browse files
authored
Merge pull request #1310 from transformerlab/fix/editing-task-yaml
Fix editing of task.yaml for deleting fields
2 parents b4cda04 + cdb2cb2 commit 439bfb4

2 files changed

Lines changed: 33 additions & 1 deletion

File tree

api/transformerlab/routers/experiment/tasks2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ async def update_task_yaml(experimentId: str, task_id: str, request: Request):
213213
raise
214214
# Don't overwrite task id
215215
task_data.pop("id", None)
216-
success = await task_service.update_task(task_id, task_data)
216+
success = await task_service.update_task_from_yaml(task_id, task_data)
217217
if not success:
218218
raise HTTPException(status_code=404, detail="Task not found")
219219
return {"message": "OK"}

api/transformerlab/services/task_service.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,15 @@
44
"""
55

66
import uuid
7+
from datetime import datetime
78
from typing import List, Dict, Any, Optional
89
from lab.task_template import TaskTemplate as TaskTemplateService
910

11+
# Keys that are never removed when syncing from task.yaml (system-owned).
12+
# Any other key in stored metadata that is not in the parsed task_data is
13+
# removed, so we don't need to maintain a list of YAML field names.
14+
_PROTECTED_METADATA_KEYS = frozenset({"id", "experiment_id", "type", "plugin", "created_at"})
15+
1016

1117
class TaskService:
1218
"""Service for managing tasks using filesystem storage"""
@@ -85,6 +91,32 @@ async def update_task(self, task_id: str, new_task_data: Dict[str, Any]) -> bool
8591
except FileNotFoundError:
8692
return False
8793

94+
async def update_task_from_yaml(self, task_id: str, task_data: Dict[str, Any]) -> bool:
95+
"""Update task metadata from parsed task.yaml so it matches the YAML exactly.
96+
Keeps only protected (system) keys from existing metadata, then applies
97+
task_data; any other key not in task_data is removed (so removing a
98+
field in the editor actually removes it).
99+
"""
100+
try:
101+
task = await self.task_service.get(str(task_id))
102+
data = await task.get_json_data()
103+
104+
# Start from existing protected keys only; then apply parsed YAML
105+
out = {k: data[k] for k in _PROTECTED_METADATA_KEYS if k in data}
106+
out.update(task_data)
107+
108+
# Preserve file_mounts when YAML omits it and existing has a value
109+
if "file_mounts" not in task_data:
110+
existing_mounts = data.get("file_mounts")
111+
if existing_mounts is True or (isinstance(existing_mounts, dict) and len(existing_mounts) > 0):
112+
out["file_mounts"] = existing_mounts
113+
114+
out["updated_at"] = datetime.utcnow().isoformat()
115+
await task._set_json_data(out)
116+
return True
117+
except FileNotFoundError:
118+
return False
119+
88120
async def delete_task(self, task_id: str) -> bool:
89121
"""Delete a task"""
90122
try:

0 commit comments

Comments
 (0)