Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
1f3c8f1
fix(tasks): #185 #187 - stop advertising device on non-consuming task…
dkackman Sep 17, 2026
09875d9
Merge fix/185-187-task-device-and-gain-audio
dkackman Sep 17, 2026
993fe44
fix(plan): #186 - surface gate status in downloads_required pre-flight
dkackman Sep 17, 2026
da1c239
Merge fix/186-gated-repo-preflight
dkackman Sep 17, 2026
ea272ce
feat(tasks): #188 - add transcribe_audio ASR task
dkackman Sep 17, 2026
3586fd3
Merge fix/188-transcribe-audio
dkackman Sep 17, 2026
3ae67b7
fix(tasks): #188 - drop unused imports left in audio_utils.py
dkackman Sep 17, 2026
f78226e
fix(plan): #186 - actually probe file access to detect a blocked gate
dkackman Sep 17, 2026
cecbc4c
Merge fix/186-gate-probe
dkackman Sep 17, 2026
a5cef23
fix(templates): #196 - resample the score at its own rate in dissolve…
dkackman Sep 17, 2026
b070e15
Merge fix/196-dissolve-slice-audio-rate
dkackman Sep 17, 2026
f19f839
docs(audio): correct loop_audio crossfade claim, document gain_audio …
dkackman Sep 17, 2026
7372e31
Merge docs/audio-loop-gain-clarifications
dkackman Sep 17, 2026
fcd87bd
fix(audio): #197 - fit in-memory-generated audio to frame count befor…
dkackman Sep 17, 2026
a0cd11a
fix(audio): #198/#199 - warn on tonal bleed material, add gain_db to …
dkackman Sep 17, 2026
3541cde
Merge fix/197-198-199-bleed-audio-seam
dkackman Sep 17, 2026
392fc0b
docs(mcp): #201 - name workspace isolation explicitly in the path-ref…
dkackman Sep 17, 2026
e9c7106
Merge branch 'docs/workspace-isolation-error-message' into develop
dkackman Sep 17, 2026
aebda18
fix(video): #197 - make _fit_audio_to_frames tensor-aware for in-memo…
dkackman Sep 17, 2026
28ee9ff
Merge fix/197-tensor-audio-pad into develop
dkackman Sep 17, 2026
15e9921
fix(audio): #198 - detect speech/tonal bleed tails at native rate
dkackman Sep 17, 2026
c42acea
Merge fix/198-bleed-join-tonal-detection into develop
dkackman Sep 17, 2026
1786a92
fix(audio): #200/#207 - add compress_audio, filter_audio, analyze_aud…
dkackman Sep 17, 2026
f4ec030
Merge fix/200-audio-dynamics-filter-analyze into develop
dkackman Sep 17, 2026
f5f0229
fix(mcp): #202 - add JSON merge patch support to save_workflow
dkackman Sep 17, 2026
c0e58e7
Merge fix/202-save-workflow-patch into develop
dkackman Sep 17, 2026
9b9b799
fix(mcp): #203/#204 - inline-bytes upload_asset content path + get_ou…
dkackman Sep 17, 2026
1abd2a6
feat: #119 - select reducer, judge scorer, selected manifest field
dkackman Sep 18, 2026
c29e2f1
Merge fix/119-score-and-select into develop
dkackman Sep 18, 2026
c15114b
docs(mcp): #203/#204 - document inline upload content= and get_output…
dkackman Sep 18, 2026
2382a72
Merge fix/203-204-inline-media into develop
dkackman Sep 18, 2026
14e118f
fix: #205 - audio sample_rate relabel silent at the engine save path
dkackman Sep 18, 2026
e762dae
Merge fix/205-audio-sample-rate-relabel into develop
dkackman Sep 18, 2026
c8460f1
docs(mcp): #206 - clarify get_health worker_alive means resident, not…
dkackman Sep 18, 2026
cb44420
Merge fix/206-worker-alive-description into develop
dkackman Sep 18, 2026
f661b8c
fix: #211 - analyze_audio spectral bands now share rms_dbfs's scale
dkackman Sep 18, 2026
2a9691a
Merge fix/211-spectral-balance-scale into develop
dkackman Sep 18, 2026
6b63b78
fix(server): #184 - echo workspace/output_dir the plan was probed aga…
dkackman Sep 18, 2026
1996f8a
Merge fix/184-plan-workspace-echo into develop
dkackman Sep 18, 2026
da32153
fix: #212 - validate_workflow refuses result on scalar-returning steps
dkackman Sep 18, 2026
36d5293
Merge fix/212-scalar-result-validation into develop
dkackman Sep 18, 2026
f6eba42
fix: #213 - select_errors catches gather: candidates/scores size mism…
dkackman Sep 18, 2026
bf6cc58
Merge fix/213-select-gather-size-mismatch into develop
dkackman Sep 18, 2026
baba4c9
fix(mcp): #214, #215 - surface match_levels clip-hold and gain as eve…
dkackman Sep 18, 2026
5b6e3d9
Merge fix/214-215-match-levels-warning-and-dbfs into develop
dkackman Sep 18, 2026
5bf862f
fix(mcp): #197 - write fitted in-memory audio back onto the AudioVide…
dkackman Sep 18, 2026
e215637
Merge fix/197-write-back-fitted-audio-onto-artifact into develop
dkackman Sep 18, 2026
4b4979a
fix(server): #216 - name the wrapper in PUT /api/workflows error, cro…
dkackman Sep 18, 2026
25fdc68
fix(mcp): #197 - memoize get_artifact_list per Result so the audio-fi…
dkackman Sep 18, 2026
5b02141
fix(mcp): #209 - drop a variable:-sourced null from arguments before …
dkackman Sep 18, 2026
506dcc6
Merge fix/209-null-variable-argument-drop into develop
dkackman Sep 18, 2026
a02bc17
docs(tasks): #220 - name the clip-hold ceiling in match_levels_dbfs docs
dkackman Sep 18, 2026
0a6154d
Merge fix/220-match-levels-dbfs-doc-ceiling into develop
dkackman Sep 18, 2026
2c661be
feat(plugin): #217 - add series-episodes skill for fixed-cast, five-b…
dkackman Sep 18, 2026
98d1b38
Merge feature/217-series-episodes-skill into develop
dkackman Sep 18, 2026
3b9a7a8
feat(server,mcp): #221 clear-memory endpoint/tool, #222 runtime env info
dkackman Sep 18, 2026
a516b12
Merge fix/221-222-memory-clear-runtime-info into develop
dkackman Sep 18, 2026
24a871f
feat(speech): #223 - add speaker_embedding arg to generate_speech
dkackman Sep 18, 2026
0d34a1b
Merge fix/223-speaker-embedding into develop
dkackman Sep 18, 2026
01b54c6
fix(tasks): #220 dissolve_videos docstring hold ceiling, #223 speaker…
dkackman Sep 18, 2026
c9b4d89
Merge fix/220-223-dissolve-doc-speaker-shape into develop
dkackman Sep 18, 2026
fda3084
fix(tests): #224 - stop pinning diffusers' private cache-context inte…
dkackman Sep 18, 2026
fe8f7ea
fix(docs): clarify workflow listing instructions in SKILL.md
dkackman Sep 18, 2026
7001b90
ruff format
dkackman Sep 18, 2026
c07f866
Bump transformers floor to 5.17.0
dkackman Sep 18, 2026
b574318
fix(speech): #225 - accept chat-templated messages input, relax text/…
dkackman Sep 18, 2026
4eae1a8
Merge fix/225-226-messages-vibevoice into develop
dkackman Sep 18, 2026
018eed4
fix(mcp): #227 - wire audio_bleed_gain_db into the three concat_video…
dkackman Sep 18, 2026
5c03105
Merge fix/227-audio-bleed-gain-db-templates into develop
dkackman Sep 18, 2026
cd2f6e2
fix(deps): #232 - revert transformers floor to >=5.16.1,!=5.17.0
dkackman Sep 19, 2026
7f588c2
Merge fix/232-revert-transformers-floor into develop
dkackman Sep 19, 2026
87c45fd
fix(mcp): #226/#233 - VITS default for generate-speech template, mess…
dkackman Sep 19, 2026
2d57b39
Merge fix/226-233-vits-default-messages-guard into develop
dkackman Sep 19, 2026
6dd35da
fix(mcp): #223/#235 - speaker_embedding dtype fix, final subfolder ma…
dkackman Sep 19, 2026
1acace7
Merge fix/223-235-speaker-dtype-template-subfolder into develop
dkackman Sep 19, 2026
e5eed6d
format
dkackman Sep 19, 2026
1ec68b4
feat: add proposal for `script-to-video` skill to enhance workflow co…
dkackman Sep 19, 2026
6fe3595
feat(proposal): add Framewright comparison proposal document
dkackman Sep 19, 2026
9637d2b
Merge branch 'develop' of https://github.com/dkackman/diffusers-workf…
dkackman Sep 19, 2026
882e0cc
Merge branch 'master' into develop
dkackman Sep 19, 2026
127a0f9
fix: PR #241 review - waveform layouts, harmonicity rate, null media …
dkackman Sep 19, 2026
d01686e
format
dkackman Sep 19, 2026
ec1df29
docs(plan): agent discoverability - the prompt library, traits, and s…
dkackman Sep 19, 2026
11d312d
feat(server): narrow the prompt listing, and let a caller drop the text
dkackman Sep 19, 2026
ccb27c8
fix(mcp): list_prompts is callable again
dkackman Sep 19, 2026
0f8838c
fix(prompts): one spelling per family in intended_model
dkackman Sep 19, 2026
7b42e12
fix(catalog): has-audio covers a workflow whose output is the track
dkackman Sep 19, 2026
0ca0abe
docs: name the prompt library where an agent will read it
dkackman Sep 19, 2026
d43dbad
docs(plugin): give the H3 skill a reason to read the exemplar, not on…
dkackman Sep 19, 2026
59f07e6
docs(plugin): list series-episodes where the plugin describes itself
dkackman Sep 19, 2026
f942916
docs: pin the stated tool count to the registered tools
dkackman Sep 19, 2026
8a99ab2
feat(guides): say how a repo path in a guide becomes a catalog name
dkackman Sep 19, 2026
81a1c18
test(mcp): put a ceiling on the resident tool surface
dkackman Sep 19, 2026
7d4fe74
test(mcp): log both surface measurements in the budget comment
dkackman Sep 19, 2026
22fa16c
fix: close the final-review findings on the discoverability branch
dkackman Sep 19, 2026
67c7f22
format (#250)
dkackman Sep 19, 2026
e34752f
fix(mcp): #247 - gallery reference contract, path leak, no-seed false…
dkackman Sep 19, 2026
8a7954e
Merge branch 'fix/247-mcp-polish' into develop
dkackman Sep 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "diffusers-workflow",
"description": "Skills for driving a diffusers-workflow server from Claude Code: one composition skill per model family.",
"description": "Skills for driving a diffusers-workflow server from Claude Code: a composition skill per model family, and one for cutting a series from them.",
"owner": {
"name": "Don Kackman"
},
"plugins": [
{
"name": "dw",
"source": "./plugins/dw",
"description": "Compose MiniMax H3 video, MiniMax Music 3 and LTX-2.5 workflows over a dw MCP server: which template fits which shape, the hard rules, cost, and how to judge the output. Prompt format comes from the vendors' own guides."
"description": "Compose MiniMax H3 video, MiniMax Music 3 and LTX-2.5 workflows over a dw MCP server, and cut a multi-episode series from them: which template fits which shape, the hard rules, cost, and how to judge the output. Prompt format comes from the vendors' own guides."
}
]
}
5 changes: 4 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ The stdio MCP server lives in `dw_mcp/` — see `dw_mcp/CLAUDE.md` and docs/MCP.

`.claude-plugin/marketplace.json` publishes the `dw` plugin in `plugins/dw/`: one
composition skill per model family (`minimax-h3`, `minimax-music3`, `ltx-2.5`) that
chooses a template for a request's shape and states the family's hard rules. Model
chooses a template for a request's shape and states the family's hard rules, plus
`series-episodes`, which is a shape above them - several episodes over one cast,
each cut and scored from those templates' runs. Every skill the directory holds is
named in `plugins/dw/README.md` and here, pinned by the same test. Model
knowledge lives there and in the catalog, never in engine code; every number a skill
states is pinned to a diffusers symbol by `tests/test_plugin_skills.py`. `plugin.json`'s
version is the engine's, bumped by `scripts/release.sh`. Adding or re-auditing a family
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ once; without it the run fails partway through with a 401/403 from the Hub.

## Drive it from an agent

Then just ask. The agent has 55 tools covering the whole surface — the
Then just ask. The agent has 57 tools covering the whole surface — the
workflow catalog, the real diffusers pipeline signatures, the job queue, the
gallery, the model cache:

Expand Down
44 changes: 27 additions & 17 deletions docs/MCP.md

Large diffs are not rendered by default.

41 changes: 34 additions & 7 deletions docs/SERVER.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ from another machine:
| `POST /api/jobs` | Queue a run: `{"workflow_path": ...}` or an inline `{"workflow": {...}, "base_dir": ...}`, plus `arguments` for variable overrides. `workflow_path` accepts a stored workflow name as listed by `/api/workflows` (with or without `.json`, nested names included), or a relative/absolute path that still resolves under `--workflow-dir` - confined the same way the `/api/workflows` CRUD routes are; a path that names a real file outside that directory is rejected with 400, not opened. Answers with argument warnings from signature checking. Takes an optional `acknowledged_cost`: `true` is recorded as `acknowledged: boolean`; the object `{fingerprint, minutes, downloads}` from a validate answer's `plan` is `bound` - the server re-plans the run for the arguments given and answers **409** when the fingerprint differs or a repo in `downloads_required` is not in `downloads` (a download that has since vanished is not a refusal); the body is `{"detail": {message, reason: "fingerprint" \| "downloads" \| "unplannable", acknowledged, plan}}` with the current plan, so the caller re-quotes from it. `minutes` is recorded, never compared. Nothing is required: the web UI and every caller that sends nothing are `acknowledged: none`, and every job answer and history row carries `acknowledged` (and `acknowledged_cost` when bound). `POST /api/jobs/{id}/rerun` takes the same field and checks against the stored spec; a fresh seed does not change a fingerprint. |
| `GET /api/jobs?workspace=&status=&limit=` | Queue + history summaries, oldest first, with `total` beside them. `status` narrows to one state or a comma-separated set (`queued`, `running`, `succeeded`, `failed`, `cancelled`; anything else is a 400); `limit` keeps the newest N, and `total` still reports how many matched, so a bounded answer cannot be mistaken for a complete one. No parameters means every job, which is what the web UI polls |
| `GET /api/jobs/{id}` | Full detail: spec, events, manifest, error. A manifest entry for a step served from the step cache carries `reused: true`. Every entry carries `subfolder` - the in-run subfolder the step's `result.subfolder` chose, `''` for none. A `for_each` step appears in the manifest as its members (`shot@wide_open`, `shot@closeup`), because the manifest records what ran; the run's `workflow.json` keeps the `for_each` form, because it records what was asked |
| `GET /api/jobs/{id}/workflow` | The workflow the job ran: `{id, definition, realized, seed_variable}`. `seed_variable` names the variable a `new_seed` rerun would draw into (null when the workflow has none), read from the workflow as written rather than the realized copy, whose seed is pinned. `realized: true` is the copy the run itself wrote (`workflow.json` in its run directory), with arguments, seed, prompts and `output:latest` pinned; `false` falls back to the submitted definition, which is what a job from before run tracking has. 404 means neither is readable - the job itself still is |
| `GET /api/jobs/{id}/workflow` | The workflow the job ran: `{id, definition, realized, seed_variable}`. `seed_variable` names the variable a `new_seed` rerun would draw into (null when the workflow has none), read from the workflow as written rather than the realized copy, whose seed is pinned. `realized: true` is the copy the run itself wrote (`workflow.json` in its run directory), with arguments, seed, prompts and `output:latest` pinned; `false` falls back to the submitted definition, which is what a job from before run tracking has. 404 means neither is readable - the job itself still is. The equivalent MCP tool is `get_job_workflow` (see [MCP.md](MCP.md#diagnose)) |
| `POST /api/jobs/{id}/export?workspace=&overwrite=` | Gather one finished job into `<workspace>/exports/<job id>/`: `workflow.json`, `manifest.json`, `job.json`, `README.md`, `assets/`, `inputs/`, `outputs/`. 201 with the file list, total bytes, anything it could not find, a `zip_url`, and the three JSON files inline. 404 unknown job, 409 for a job still running or an existing export without `overwrite` |
| `GET /exports/{id}.zip?workspace=` | The same tree as one archive, built on request rather than kept as a second copy. Entries are named `<job id>/<relative path>`. Ungated exactly as `/outputs` is |
| `GET /api/jobs/{id}/events` | Server-sent events stream; `?after=N` / `Last-Event-ID` replay missed events, so reconnects are lossless. Every event carries `seq` and `at` - seconds since the job started (since it was queued, for the events before that) - so a step's cost is a subtraction: `step_start` to `generating` is what a reused pipeline still pays before it runs, `generating` to the first `pipeline_step` is the prompt and reference encoding |
Expand Down Expand Up @@ -303,9 +303,26 @@ The editor's forms come from these; they are just as usable from scripts:
also gets a warning saying so, since `0` alone does not distinguish a
disabled cache from an empty one);
`downloads_required`, each `model_name` the hub cache does not hold as
`{repo, gb}` (`gb` from the hub, `null` when it could not be asked -
`?sizes=false` skips the hub) and each `from_single_file` URL as
`{repo: null, url, gb: null}`; and `estimate`, `{minutes, basis,
`{repo, gb, gated, access_blocked}` (`gb` from the hub, `null` when it
could not be asked - `?sizes=false` skips the hub, and then `gated` and
`access_blocked` are `null` too); `gated` is the hub's own field for the
repo (`false`, `"auto"` or `"manual"`) or `null` when the lookup itself
failed for a reason other than the gate; `access_blocked` is `true`
when this box's Hugging Face token specifically has not been granted
access to a gated repo, `false` when the repo isn't gated or the token is
accepted, and `null` when it could not be determined either way. A gated
repo's own metadata is served by the hub regardless of this token's
access, so `model_info` succeeding proves nothing about the gate; a
gated entry gets a second, real check - a HEAD request against one of the
repo's own files - and it is *that* request's `GatedRepoError` that sets
`access_blocked: true` (the pre-flight signal for what would otherwise be
a 403 partway into a run, #186). `access_blocked` is `null` when there is
no file to probe or the probe itself fails for an unrelated reason (e.g.
offline) - "unknown" is not "not blocked". `validate_workflow`'s
`warnings` carries one line per entry with `access_blocked: true`. Each
`from_single_file` URL is `{repo: null, url, gb: null, gated: null,
access_blocked: null}`, since a direct file URL is never gated; and
`estimate`, `{minutes, basis,
device, measured_on, partial, runs}` from this box's own history when it
has one and otherwise from the workflow's `cost` block -
`basis` is `observed` (the cold median of this server's own finished runs
Expand Down Expand Up @@ -517,12 +534,22 @@ The editor's forms come from these; they are just as usable from scripts:
measured because nothing is resident. health also reports `hostname`,
`device` and whether `mcp` is mounted, so a remote client can tell which
machine answered
- `POST /api/memory/clear` (#221) — drops every loaded pipeline and the step
cache, the same mechanism as the REPL's `memory clear`, and returns the
memory reading taken right after. Refused with 409 while a job is running
or queued - the queue is FIFO, so the caller retries once it finishes
rather than this call blocking until it does
- `GET /api/server` — connection details for the Server page: `hostname`,
`version`, `device`, the `bind_host`/`port`/`wildcard_bind` the server was
started with, `auth_required` (whether a token is configured - never the
token itself), `mcp` (`mounted` plus its `path`), the machine's
non-loopback `addresses`, and the `directories` in use; a client composes
its URLs from an address, the port and the MCP path
token itself), `mcp` (`mounted` plus its `path`), the `directories` in use,
and `runtime` (#222) - Python version, torch version and the CUDA version
torch was built against, the NVIDIA driver version (via `nvidia-smi`, when
it's on PATH), and the installed versions of diffusers, transformers,
accelerate, bitsandbytes, peft, safetensors and sentencepiece (`null` for
one not installed) - for diagnosing an environment mismatch between boxes
without shelling in; the machine's non-loopback `addresses`; a client
composes its URLs from an address, the port and the MCP path

## Security model

Expand Down
Loading
Loading