Skip to content

Commit c701dc3

Browse files
authored
Merge branch 'main' into add/startup-wizard
2 parents 57cfa0e + c655a23 commit c701dc3

159 files changed

Lines changed: 17747 additions & 1067 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/transformerlab-cli/SKILL.md

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ lab task list
8787
# 3. Queue a task on a compute provider
8888
# NOTE: --no-interactive silently picks the DEFAULT provider (Local).
8989
# To pick a specific provider, run interactively (see "Selecting a provider" below).
90-
lab task queue TASK_ID --no-interactive
90+
# ALWAYS pass --description/-m with a markdown note describing the iteration
91+
# (see "Always write a run description" below).
92+
lab task queue TASK_ID --no-interactive -m "Testing lr=3e-5 after loss plateaued at 2.1"
9193

9294
# 4. Monitor the job (three log streams — see "Job logs: three real commands" below)
9395
lab job list --running
@@ -226,6 +228,37 @@ lab task add ./hello-world-task --no-interactive
226228
10. **Never use the deprecated `lab job logs`** — see the "Job logs: three real commands" section below.
227229
11. **After queuing a task, ASK the user if they'd like you to watch the logs.** Don't start streaming or polling automatically — jobs can take minutes to hours, and `--follow` blocks. Report the Job ID and ask: "Want me to watch the logs and report back?"
228230
12. **Never create API keys programmatically** — if auth fails, ask the user to provide an API key from the web UI
231+
13. **Always pass `--description/-m` when queuing a task. Generate it yourself — never ask the user.** See "Always write a run description" below.
232+
233+
### Always write a run description
234+
235+
Every `lab task queue` call MUST include `--description/-m "..."`. The description is markdown stored on the job and shown in `lab job info`. Its audience is a future researcher reading `lab job list` weeks later — they have git and the task code, but NOT this chat. The description is the only bridge.
236+
237+
**Treat it like a short PR description for this run.** Draft 1–5 lines (bullets for multi-point notes) covering:
238+
239+
1. **What changed vs the prior run / baseline** — the concrete diff (hyperparameters, code, model, data, infra). If nothing changed, say so and link the prior job.
240+
2. **What hypothesis you're testing** — why this run is worth doing.
241+
3. **What a future reader should remember** — gotchas, prior surprises, things to check in the output.
242+
243+
Pull these from the conversation and recent git diff / edited files. If the note has newlines or shell-awkward characters, pipe it: `printf '%s' "$DESC" | lab task queue abc123 -m -`.
244+
245+
```bash
246+
# Good: diff + hypothesis + watch
247+
printf '%s' "- Bumped lr 1e-5 → 3e-5, warmup 100 → 500 steps.
248+
- Testing whether higher lr clears the eval/loss=2.1 plateau seen in job 7f21 around step 2k.
249+
- Watch: earlier runs with lr≥5e-5 diverged by step 500." | lab task queue abc123 --no-interactive -m -
250+
251+
# Good: small change — one line is enough
252+
lab task queue abc123 --no-interactive -m "Rerun on H100 (was A100) to confirm throughput regression from #1850."
253+
254+
# Good: nothing changed
255+
lab task queue abc123 --no-interactive -m "Rerun of job 7f21, no code or config changes (network flake on first attempt)."
256+
257+
# Bad: generic filler that tells the reader nothing
258+
lab task queue abc123 -m "train model"
259+
```
260+
261+
Don't restate the task name, full hyperparameter dict, or file paths — those are already on the job record. Don't copy the user's last message verbatim — synthesize. If the conversation is truly empty of signal, fall back to `"Rerun of <id>, no changes"`.
229262

230263
### Selecting a provider when queuing a task
231264

@@ -308,7 +341,7 @@ This applies to launching jobs, fetching logs, checking cluster status, and ever
308341
| `lab task init` | Scaffold `task.yaml` + `main.py` in the current directory (`--interactive` to prompt) | No |
309342
| `lab task add [dir]` | Add task from directory or `--from-git` URL (`--no-interactive`, `--dry-run`) | Yes |
310343
| `lab task delete <id>` | Delete a task (`--no-interactive` to skip confirmation) | Yes |
311-
| `lab task queue <id>` | Queue task on compute provider | Yes |
344+
| `lab task queue <id>` | Queue task on compute provider (`-m/--description` for a markdown run note; required for agents, see "Always write a run description") | Yes |
312345
| `lab task gallery` | Browse/import from task gallery | Yes |
313346
| `lab job list` | List jobs (`--running` for active only) | Yes |
314347
| `lab job info <id>` | Get detailed job information | Yes |

.agents/skills/transformerlab-cli/references/commands.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ Queue a task on a compute provider.
131131
| Option | Description |
132132
|---|---|
133133
| `--no-interactive` | Skip prompts. Uses the task's configured provider or first available. Parameters use defaults. **Always use this in automated workflows.** |
134+
| `-m`, `--description <text>` | Markdown note describing what this run is trying to accomplish (stored on the job, shown in `lab job info`). Pass `-` to read from stdin. **Agents: required per SKILL.md rule 13.** |
134135

135136
**JSON output:** Returns the created job object with `id` and `status`.
136137

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,4 @@ test-results/
227227
**/.secrets
228228

229229
docs/superpowers/*
230+
.superpowers/

api/api.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@
5555

5656

5757
from transformerlab.routers.experiment import experiment # noqa: E402
58-
from transformerlab.routers.experiment import jobs # noqa: E402
5958
from transformerlab.shared import shared # noqa: E402
6059
from transformerlab.shared import dirs # noqa: E402
6160
from lab.dirs import set_organization_id as lab_set_org_id # noqa: E402
@@ -306,7 +305,6 @@ async def validation_exception_handler(request, exc):
306305
app.include_router(serverinfo.router, dependencies=[Depends(get_user_and_team)])
307306
app.include_router(data.router, dependencies=[Depends(get_user_and_team)])
308307
app.include_router(experiment.router, dependencies=[Depends(get_user_and_team)])
309-
app.include_router(jobs.router, dependencies=[Depends(get_user_and_team)])
310308
app.include_router(config.router, dependencies=[Depends(get_user_and_team)])
311309
app.include_router(teams.router, dependencies=[Depends(get_user_and_team)])
312310
app.include_router(compute_provider.router)

api/localprovider_pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ dependencies = [
3232
"soundfile==0.13.1",
3333
"tensorboardX==2.6.2.2",
3434
"timm==1.0.15",
35-
"transformerlab==0.1.22",
35+
"transformerlab==0.1.24",
3636
"transformerlab-inference==0.2.52",
3737
"transformers==4.57.1",
3838
"wandb==0.23.1",

api/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ dependencies = [
2424
"python-dotenv==1.1.0",
2525
"python-multipart==0.0.20",
2626
"sqlalchemy[asyncio]==2.0.40",
27-
"transformerlab==0.1.23",
27+
"transformerlab==0.1.24",
2828
"transformerlab-inference==0.2.52",
2929
"uvicorn==0.35.0",
3030
"watchfiles==1.0.5",
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import pytest
2+
from unittest.mock import AsyncMock, MagicMock, patch
3+
4+
5+
@pytest.mark.asyncio
6+
async def test_check_storage_probe_found():
7+
"""check_storage_probe returns found=True when sentinel file exists."""
8+
with patch("transformerlab.services.compute_provider.storage_probe_service.set_organization_id") as mock_set_org:
9+
with patch(
10+
"transformerlab.services.compute_provider.storage_probe_service.get_workspace_dir",
11+
new=AsyncMock(return_value="/mnt/nfs/orgs/team1/workspace"),
12+
):
13+
with patch("transformerlab.services.compute_provider.storage_probe_service.storage") as mock_storage:
14+
mock_storage.join = lambda *parts: "/".join(parts)
15+
mock_storage.exists = AsyncMock(return_value=True)
16+
17+
from transformerlab.services.compute_provider.storage_probe_service import check_storage_probe
18+
19+
result = await check_storage_probe(job_id="job-123", team_id="team1")
20+
21+
assert result["found"] is True
22+
assert "storage-probe-job-123.txt" in result["path"]
23+
mock_set_org.assert_any_call("team1")
24+
mock_set_org.assert_any_call(None)
25+
26+
27+
@pytest.mark.asyncio
28+
async def test_check_storage_probe_not_found():
29+
"""check_storage_probe returns found=False when sentinel file is missing."""
30+
with patch("transformerlab.services.compute_provider.storage_probe_service.set_organization_id"):
31+
with patch(
32+
"transformerlab.services.compute_provider.storage_probe_service.get_workspace_dir",
33+
new=AsyncMock(return_value="/mnt/nfs/orgs/team1/workspace"),
34+
):
35+
with patch("transformerlab.services.compute_provider.storage_probe_service.storage") as mock_storage:
36+
mock_storage.join = lambda *parts: "/".join(parts)
37+
mock_storage.exists = AsyncMock(return_value=False)
38+
39+
from transformerlab.services.compute_provider.storage_probe_service import check_storage_probe
40+
41+
result = await check_storage_probe(job_id="job-999", team_id="team1")
42+
43+
assert result["found"] is False
44+
45+
46+
@pytest.mark.asyncio
47+
async def test_launch_storage_probe_returns_job_id():
48+
"""launch_storage_probe calls launch_template_on_provider and returns job_id."""
49+
mock_launch = AsyncMock(return_value={"job_id": 42, "status": "success"})
50+
51+
with patch(
52+
"transformerlab.services.compute_provider.storage_probe_service.launch_template_on_provider",
53+
new=mock_launch,
54+
):
55+
from transformerlab.services.compute_provider.storage_probe_service import launch_storage_probe
56+
57+
user_and_team = {"team_id": "team1", "user": MagicMock(id="user1", first_name="", last_name="", email="")}
58+
result = await launch_storage_probe(
59+
provider_id="prov-1",
60+
user_and_team=user_and_team,
61+
session=MagicMock(),
62+
)
63+
64+
assert result["job_id"] == 42
65+
assert result["experiment_id"] == "__storage_probe__"
66+
call_args = mock_launch.call_args
67+
request = call_args.kwargs["request"]
68+
assert request.run == "python -m lab.probe"
69+
assert request.experiment_id == "__storage_probe__"
70+
assert request.cpus == "1"
71+
assert request.accelerators is None

api/transformerlab/galleries/channels/stable/latest/interactive-gallery.json

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
"interactive_type": "vscode",
55
"name": "VS Code",
66
"description": "Remote VS Code development environment via tunnel",
7-
"github_repo_url": "https://github.com/transformerlab/transformerlab-examples",
8-
"github_repo_dir": "interactive-vscode",
7+
"github_repo_url": "https://github.com/transformerlab/transformerlab-app",
8+
"github_repo_dir": "api/transformerlab/galleries/examples/interactive-vscode",
99
"env_parameters": [],
1010
"icon": "https://lab.cloud/img/icons/vscode.png",
1111
"supported_accelerators": [
@@ -46,8 +46,8 @@
4646
"interactive_type": "jupyter",
4747
"name": "Jupyter Notebook",
4848
"description": "Jupyter Lab notebook environment via ngrok tunnel",
49-
"github_repo_url": "https://github.com/transformerlab/transformerlab-examples",
50-
"github_repo_dir": "interactive-jupyter",
49+
"github_repo_url": "https://github.com/transformerlab/transformerlab-app",
50+
"github_repo_dir": "api/transformerlab/galleries/examples/interactive-jupyter",
5151
"env_parameters": [
5252
{
5353
"field_name": "ngrok Auth Token",
@@ -98,8 +98,8 @@
9898
"interactive_type": "vllm",
9999
"name": "vLLM Server",
100100
"description": "vLLM OpenAI-compatible API server via ngrok tunnel (plus Open WebUI)",
101-
"github_repo_url": "https://github.com/transformerlab/transformerlab-examples",
102-
"github_repo_dir": "interactive-vllm",
101+
"github_repo_url": "https://github.com/transformerlab/transformerlab-app",
102+
"github_repo_dir": "api/transformerlab/galleries/examples/interactive-vllm",
103103
"env_parameters": [
104104
{
105105
"field_name": "Model Name",
@@ -191,8 +191,8 @@
191191
"interactive_type": "ollama",
192192
"name": "Ollama + Open WebUI",
193193
"description": "Ollama model server with Open WebUI chat interface via ngrok tunnel",
194-
"github_repo_url": "https://github.com/transformerlab/transformerlab-examples",
195-
"github_repo_dir": "interactive-ollama-openwebui",
194+
"github_repo_url": "https://github.com/transformerlab/transformerlab-app",
195+
"github_repo_dir": "api/transformerlab/galleries/examples/interactive-ollama-openwebui",
196196
"env_parameters": [
197197
{
198198
"field_name": "Model Name",
@@ -268,8 +268,8 @@
268268
"id": "ollama_gradio",
269269
"name": "Ollama + Gradio",
270270
"description": "Ollama model server with Gradio chat UI via ngrok tunnel",
271-
"github_repo_url": "https://github.com/transformerlab/transformerlab-examples",
272-
"github_repo_dir": "inference-ollama-gradio-chat",
271+
"github_repo_url": "https://github.com/transformerlab/transformerlab-app",
272+
"github_repo_dir": "api/transformerlab/galleries/examples/inference-ollama-gradio-chat",
273273
"env_parameters": [
274274
{
275275
"field_name": "Model Name",
@@ -323,8 +323,8 @@
323323
"id": "comfy_ui",
324324
"name": "ComfyUI",
325325
"description": "ComfyUI server via ngrok tunnel",
326-
"github_repo_url": "https://github.com/transformerlab/transformerlab-examples",
327-
"github_repo_dir": "interactive-comfyui",
326+
"github_repo_url": "https://github.com/transformerlab/transformerlab-app",
327+
"github_repo_dir": "api/transformerlab/galleries/examples/interactive-comfyui",
328328
"env_parameters": [
329329
{
330330
"field_name": "ngrok Auth Token",
@@ -374,8 +374,8 @@
374374
"interactive_type": "ssh",
375375
"name": "SSH",
376376
"description": "SSH access via ngrok TCP tunnel",
377-
"github_repo_url": "https://github.com/transformerlab/transformerlab-examples",
378-
"github_repo_dir": "interactive-ssh",
377+
"github_repo_url": "https://github.com/transformerlab/transformerlab-app",
378+
"github_repo_dir": "api/transformerlab/galleries/examples/interactive-ssh",
379379
"env_parameters": [
380380
{
381381
"field_name": "ngrok Auth Token",
@@ -442,8 +442,8 @@
442442
"id": "mlx_gradio",
443443
"name": "MLX LM + Gradio",
444444
"description": "MLX LM inference server with Gradio chat UI for Apple Silicon",
445-
"github_repo_url": "https://github.com/transformerlab/transformerlab-examples",
446-
"github_repo_dir": "inference-mlx-gradio-chat",
445+
"github_repo_url": "https://github.com/transformerlab/transformerlab-app",
446+
"github_repo_dir": "api/transformerlab/galleries/examples/inference-mlx-gradio-chat",
447447
"env_parameters": [
448448
{
449449
"field_name": "Model Name",
@@ -494,8 +494,8 @@
494494
"id": "mlx_audio_tts",
495495
"name": "MLX Audio TTS + Gradio",
496496
"description": "Text-to-Speech using MLX Audio with Gradio UI for Apple Silicon",
497-
"github_repo_url": "https://github.com/transformerlab/transformerlab-examples",
498-
"github_repo_dir": "inference-mlx-audio-tts",
497+
"github_repo_url": "https://github.com/transformerlab/transformerlab-app",
498+
"github_repo_dir": "api/transformerlab/galleries/examples/inference-mlx-audio-tts",
499499
"env_parameters": [
500500
{
501501
"field_name": "Model Name",
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
{
2-
"bundle_version": "20260415184435",
2+
"bundle_version": "20260421193056",
33
"channel": "stable",
4-
"released_at": "2026-04-15T18:44:35.364579+00:00",
4+
"released_at": "2026-04-21T19:30:56.442725+00:00",
55
"files": {
66
"task-gallery.json": 25,
77
"interactive-gallery.json": 9,
88
"announcement-gallery.json": 2
9-
},
10-
"min_supported_app_version": "0.0.0"
9+
}
1110
}

0 commit comments

Comments
 (0)