From ad09f2455fa38cb19e5f2475470430da4211b50f Mon Sep 17 00:00:00 2001 From: Pete Cornish Date: Sat, 5 Sep 2026 23:48:45 +0100 Subject: [PATCH] fix: use a valid mtplx scheduler mode in the example preset mtplx 2.11.1 removed the old serial/parallel/concurrent scheduler modes, so the example preset's 'scheduler-mode = parallel' made 'spinloop serve' fail with an invalid choice. Use 'ar_batch' (mtplx's coding-agent scheduling mode) in the example preset and its tests, and stop pinning an exact mode list in the docs so they do not rot again when mtplx renames its modes. --- cmd/spinloop/serve_daemon_test.go | 4 ++-- cmd/spinloop/serve_test.go | 4 ++-- docs/commands/serve.md | 10 ++++++---- examples/mtplx/qwen3.8-27b/README.md | 8 +++++--- examples/mtplx/qwen3.8-27b/preset.ini | 2 +- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/cmd/spinloop/serve_daemon_test.go b/cmd/spinloop/serve_daemon_test.go index 4203f86..c597ccd 100644 --- a/cmd/spinloop/serve_daemon_test.go +++ b/cmd/spinloop/serve_daemon_test.go @@ -1002,7 +1002,7 @@ port = 8000 [qwen] model = Youssofal/Qwen3.8-27B-MTPLX-Optimized-Speed context-window = 32768 -scheduler-mode = parallel +scheduler-mode = ar_batch max-active-requests = 4 model-id = preset-alias ` @@ -1051,7 +1051,7 @@ func TestNodeDeployConfigMtplxFromPreset(t *testing.T) { } // The operator's own settings survive: the bind, and the scheduling mode, // which spinloop does not compute. - for _, want := range []string{"--host 0.0.0.0", "--port 8000", "--scheduler-mode parallel"} { + for _, want := range []string{"--host 0.0.0.0", "--port 8000", "--scheduler-mode ar_batch"} { if !strings.Contains(args, want) { t.Errorf("a node's serve args should keep %q, got: %s", want, args) } diff --git a/cmd/spinloop/serve_test.go b/cmd/spinloop/serve_test.go index 348c9ed..b4a6eeb 100644 --- a/cmd/spinloop/serve_test.go +++ b/cmd/spinloop/serve_test.go @@ -97,7 +97,7 @@ port = 8000 [qwen] model = Youssofal/Qwen3.8-27B-MTPLX-Optimized-Speed context-window = 32768 -scheduler-mode = parallel +scheduler-mode = ar_batch max-active-requests = 4 c = should-stay-literal ` @@ -810,7 +810,7 @@ func TestCmdServe_MTPPLXPresetKeysPassThrough(t *testing.T) { for _, want := range []string{ "--model Youssofal/Qwen3.8-27B-MTPLX-Optimized-Speed", "--context-window 32768", - "--scheduler-mode parallel", + "--scheduler-mode ar_batch", "--max-active-requests 4", "-c should-stay-literal", "--download", diff --git a/docs/commands/serve.md b/docs/commands/serve.md index 7b75c66..a54d826 100644 --- a/docs/commands/serve.md +++ b/docs/commands/serve.md @@ -230,10 +230,12 @@ BASEURL http://127.0.0.1:8000/v1 # mtplx serve --host/--p - `BASEURL` sets the bind address. With none, no bind flag is emitted and MTPLX's own defaults stand. -The scheduling mode (`--scheduler-mode`: `serial`, `parallel`, `concurrent`) is -per-deployment tuning, not a Spinloop field — set it in a `PRESET`, written in -MTPLX's own long-form flags. `serve` passes every other preset key through -unchanged, so a preset is portable only to MTPLX, as with every engine. +The scheduling mode (`--scheduler-mode`) is per-deployment tuning, not a +Spinloop field — set it in a `PRESET`, written in MTPLX's own long-form flags. +`serve` passes the value through without checking it, so it must be valid for +the installed `mtplx` (`mtplx serve --help` lists the current modes). Every +preset key is passed through unchanged, so a preset is portable only to MTPLX, +as with every engine. `serve` never passes `--api-key`, for the same reason as [oMLX](#omlx): it prints the command it runs, and a key on the line would be in your screen and diff --git a/examples/mtplx/qwen3.8-27b/README.md b/examples/mtplx/qwen3.8-27b/README.md index f629f08..340f1be 100644 --- a/examples/mtplx/qwen3.8-27b/README.md +++ b/examples/mtplx/qwen3.8-27b/README.md @@ -30,7 +30,7 @@ mtplx serve \ --model-id qwen3.8-27b \ --context-window 32768 \ --max-active-requests 4 \ - --scheduler-mode parallel \ + --scheduler-mode ar_batch \ --download \ --host 127.0.0.1 --port 8000 ``` @@ -44,8 +44,10 @@ What the flags do: - `--context-window` — the context a single request gets. Never scaled by `PARALLEL`. - `--max-active-requests` — an admission cap on how many requests run at once. -- `--scheduler-mode` — `serial`, `parallel`, or `concurrent`. This is - per-deployment tuning, not a Spinloop field, so it lives in the +- `--scheduler-mode` — how admitted requests execute. `spinloop` passes the + value through without checking it, so it must be valid for your `mtplx` + build (`mtplx serve --help` lists the current modes). This is per-deployment + tuning, not a Spinloop field, so it lives in the [`preset.ini`](preset.ini). - `--host`/`--port` — the OpenAI-compatible API is served at `http://127.0.0.1:8000/v1`. diff --git a/examples/mtplx/qwen3.8-27b/preset.ini b/examples/mtplx/qwen3.8-27b/preset.ini index b5b5ab9..56b7d61 100644 --- a/examples/mtplx/qwen3.8-27b/preset.ini +++ b/examples/mtplx/qwen3.8-27b/preset.ini @@ -15,4 +15,4 @@ port = 8000 model = Youssofal/Qwen3.8-27B-MTPLX-Optimized-Speed context-window = 32768 # keep in step with the Spinloop's CONTEXT max-active-requests = 4 # the Spinloop's PARALLEL, when it states one -scheduler-mode = parallel # serial | parallel | concurrent — per-deployment +scheduler-mode = ar_batch # per-deployment; 'mtplx serve --help' lists the current modes