Skip to content

Commit 1f86d96

Browse files
authored
Merge branch 'main' into fix/local-model-vllm
2 parents 8868026 + 4fea393 commit 1f86d96

1 file changed

Lines changed: 24 additions & 61 deletions

File tree

  • api/transformerlab/routers/experiment

api/transformerlab/routers/experiment/task.py

Lines changed: 24 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
)
3535
from transformerlab.routers.auth import get_user_and_team
3636
from transformerlab.shared.models.user_model import get_async_session
37-
from lab.task_template import TaskTemplate
3837
from transformerlab.schemas.task import (
3938
ExportTaskToTeamGalleryRequest,
4039
ImportTaskFromGalleryRequest,
@@ -245,20 +244,15 @@ async def task_list_files(experimentId: str, task_id: str) -> TaskFilesResponse:
245244
"/{task_id}/file/{file_path:path}",
246245
summary="Serve a file from a task's local workspace directory for preview",
247246
)
248-
async def task_get_file(task_id: str, file_path: str):
247+
async def task_get_file(experimentId: str, task_id: str, file_path: str):
249248
"""
250249
Serve a file from the per-task workspace directory (used for upload-from-directory tasks).
251250
252251
This mirrors the behavior of the jobs get_job_file endpoint but is scoped to
253-
workspace/task/{task_id}. It is primarily intended for lightweight previews in
254-
the UI and supports both text and binary content.
252+
the task's experiment-scoped directory. It is primarily intended for lightweight
253+
previews in the UI and supports both text and binary content.
255254
"""
256-
workspace_dir = await get_workspace_dir()
257-
if not workspace_dir:
258-
raise HTTPException(status_code=500, detail="Workspace directory is not configured")
259-
260-
# Files for upload-from-directory tasks are materialized under workspace/task/{task_id}
261-
task_dir = storage.join(workspace_dir, "task", str(task_id))
255+
task_dir = await task_service.get_task_dir(task_id, experiment_id=experimentId)
262256
safe_rel = posixpath.normpath(file_path).lstrip("/")
263257
if safe_rel.startswith("..") or "/.." in safe_rel:
264258
raise HTTPException(status_code=400, detail="Invalid file path")
@@ -365,11 +359,7 @@ async def task_update_file(experimentId: str, task_id: str, file_path: str, requ
365359
if not task:
366360
raise HTTPException(status_code=404, detail="Task not found")
367361

368-
workspace_dir = await get_workspace_dir()
369-
if not workspace_dir:
370-
raise HTTPException(status_code=500, detail="Workspace directory is not configured")
371-
372-
task_dir = storage.join(workspace_dir, "task", str(task_id))
362+
task_dir = await task_service.get_task_dir(task_id, experiment_id=experimentId)
373363
safe_rel = posixpath.normpath(file_path).lstrip("/")
374364
if safe_rel.startswith("..") or "/.." in safe_rel:
375365
raise HTTPException(status_code=400, detail="Invalid file path")
@@ -401,11 +391,7 @@ async def task_delete_file(experimentId: str, task_id: str, file_path: str):
401391
if not task:
402392
raise HTTPException(status_code=404, detail="Task not found")
403393

404-
workspace_dir = await get_workspace_dir()
405-
if not workspace_dir:
406-
raise HTTPException(status_code=500, detail="Workspace directory is not configured")
407-
408-
task_dir = storage.join(workspace_dir, "task", str(task_id))
394+
task_dir = await task_service.get_task_dir(task_id, experiment_id=experimentId)
409395
safe_rel = posixpath.normpath(file_path).lstrip("/")
410396
if safe_rel.startswith("..") or "/.." in safe_rel:
411397
raise HTTPException(status_code=400, detail="Invalid file path")
@@ -436,11 +422,7 @@ async def task_upload_file(
436422
if not task:
437423
raise HTTPException(status_code=404, detail="Task not found")
438424

439-
workspace_dir = await get_workspace_dir()
440-
if not workspace_dir:
441-
raise HTTPException(status_code=500, detail="Workspace directory is not configured")
442-
443-
task_dir = storage.join(workspace_dir, "task", str(task_id))
425+
task_dir = await task_service.get_task_dir(task_id, experiment_id=experimentId)
444426
await storage.makedirs(task_dir, exist_ok=True)
445427

446428
saved_files: list[str] = []
@@ -1151,21 +1133,17 @@ async def import_task_from_gallery(
11511133
# Invalidate cached task lists for this experiment (best-effort).
11521134
await cache.invalidate(f"tasks:{experimentId}")
11531135

1154-
# Store task.yaml in the task directory for GitHub-sourced interactive tasks
1136+
# Store task.yaml in the task directory for GitHub-sourced interactive tasks.
1137+
# Use task_service.write_task_yaml so the file lands in the experiment-scoped
1138+
# path that task_list_files reads from (workspace/experiments/{exp_id}/tasks/{id}).
11551139
if github_repo_url and source_yaml_data:
1156-
task_template = TaskTemplate(secure_filename(str(task_id)))
1157-
task_dir_path = await task_template.get_dir()
1158-
await storage.makedirs(task_dir_path, exist_ok=True)
1159-
yaml_path = storage.join(task_dir_path, "task.yaml")
1160-
async with await storage.open(yaml_path, "w", encoding="utf-8") as f:
1161-
await f.write(task_yaml_content)
1140+
await task_service.write_task_yaml(task_id, task_yaml_content, experiment_id=experimentId)
11621141

11631142
# Copy local_task_dir files into the task directory (inside a subdirectory
11641143
# matching the source directory name, mirroring what github_repo_dir does
11651144
# at clone time) and mark file_mounts so the runner copies them at launch.
11661145
if local_task_dir and os.path.isdir(local_task_dir):
1167-
task_template = TaskTemplate(secure_filename(str(task_id)))
1168-
task_dir_path = await task_template.get_dir()
1146+
task_dir_path = await task_service.get_task_dir(task_id, experiment_id=experimentId)
11691147
await storage.makedirs(task_dir_path, exist_ok=True)
11701148
dest_subdir = storage.join(task_dir_path, os.path.basename(local_task_dir.rstrip("/")))
11711149
await storage.copy_dir(local_task_dir, dest_subdir)
@@ -1267,13 +1245,8 @@ async def import_task_from_gallery(
12671245
# Create the task with all fields stored directly (flat structure)
12681246
task_id = await task_service.add_task(task_data)
12691247

1270-
# Store task.yaml in task directory
1271-
task = TaskTemplate(secure_filename(str(task_id)))
1272-
task_dir = await task.get_dir()
1273-
await storage.makedirs(task_dir, exist_ok=True)
1274-
yaml_path = storage.join(task_dir, "task.yaml")
1275-
async with await storage.open(yaml_path, "w", encoding="utf-8") as f:
1276-
await f.write(task_yaml_content)
1248+
# Store task.yaml in the experiment-scoped task directory
1249+
await task_service.write_task_yaml(task_id, task_yaml_content, experiment_id=experimentId)
12771250

12781251
# Invalidate cached task lists for this experiment (best-effort).
12791252
await cache.invalidate(f"tasks:{experimentId}")
@@ -1550,11 +1523,10 @@ async def import_task_from_team_gallery(
15501523

15511524
# Create task + copy full directory into the task workspace dir
15521525
task_id = await task_service.add_task(task_data)
1553-
task = TaskTemplate(secure_filename(str(task_id)))
1554-
task_dir = await task.get_dir()
1526+
task_dir = await task_service.get_task_dir(task_id, experiment_id=experimentId)
15551527
await storage.makedirs(task_dir, exist_ok=True)
15561528

1557-
# Copy the entire directory contents (task.yaml + attachments) into workspace/task/{task_id}
1529+
# Copy the entire directory contents (task.yaml + attachments) into the experiment-scoped task dir
15581530
try:
15591531
await storage.copy_dir(str(local_task_dir), task_dir)
15601532
except Exception as e:
@@ -1630,10 +1602,7 @@ async def import_task_from_team_gallery(
16301602
_clear_interactive_launch_provider(task_data)
16311603
task_id = await task_service.add_task(task_data)
16321604

1633-
# Write a task.yaml into the task directory so the editor works
1634-
task = TaskTemplate(secure_filename(str(task_id)))
1635-
task_dir = await task.get_dir()
1636-
await storage.makedirs(task_dir, exist_ok=True)
1605+
# Write a task.yaml into the experiment-scoped task directory so the editor works
16371606
yaml_obj = {
16381607
"name": task_data["name"],
16391608
"setup": task_data.get("setup"),
@@ -1651,9 +1620,9 @@ async def import_task_from_team_gallery(
16511620
# Remove empty values so YAML stays tidy
16521621
yaml_obj["resources"] = {k: v for k, v in (yaml_obj.get("resources") or {}).items() if v is not None}
16531622
yaml_obj = {k: v for k, v in yaml_obj.items() if v not in (None, {}, [])}
1654-
yaml_path = storage.join(task_dir, "task.yaml")
1655-
async with await storage.open(yaml_path, "w", encoding="utf-8") as f:
1656-
await f.write(yaml.safe_dump(yaml_obj, sort_keys=False))
1623+
await task_service.write_task_yaml(
1624+
task_id, yaml.safe_dump(yaml_obj, sort_keys=False), experiment_id=experimentId
1625+
)
16571626

16581627
await cache.invalidate(f"tasks:{experimentId}")
16591628
return {
@@ -1730,13 +1699,8 @@ async def import_task_from_team_gallery(
17301699
# Create the task with all fields stored directly (flat structure)
17311700
task_id = await task_service.add_task(task_data)
17321701

1733-
# Store task.yaml in task directory
1734-
task = TaskTemplate(secure_filename(str(task_id)))
1735-
task_dir = await task.get_dir()
1736-
await storage.makedirs(task_dir, exist_ok=True)
1737-
yaml_path = storage.join(task_dir, "task.yaml")
1738-
async with await storage.open(yaml_path, "w", encoding="utf-8") as f:
1739-
await f.write(task_yaml_content)
1702+
# Store task.yaml in the experiment-scoped task directory
1703+
await task_service.write_task_yaml(task_id, task_yaml_content, experiment_id=experimentId)
17401704

17411705
# Invalidate cached task lists for this experiment (best-effort).
17421706
await cache.invalidate(f"tasks:{experimentId}")
@@ -1827,9 +1791,8 @@ async def export_task_to_team_gallery(
18271791
short_id = secure_filename(str(request.task_id))[:12]
18281792
dest_dir = storage.join(export_root, f"{safe_title}-{short_id}")
18291793

1830-
# Copy from the task's workspace dir (workspace/task/{task_id})
1831-
src_task = TaskTemplate(secure_filename(str(request.task_id)))
1832-
src_dir = await src_task.get_dir()
1794+
# Copy from the task's experiment-scoped workspace directory
1795+
src_dir = await task_service.get_task_dir(request.task_id, experiment_id=experimentId)
18331796
if await storage.exists(src_dir):
18341797
# Ensure destination is clean
18351798
if await storage.exists(dest_dir):

0 commit comments

Comments
 (0)