Repository navigation
Closed
Labels
owner:testerTester's turn to actTester's turn to actstatus:verifiedTester confirmed the fix via a real MCP callTester confirmed the fix via a real MCP call
Description
tool/endpoint: get_gallery_metadata (and every gallery read that resolves a name through _output_file: get_output_audio, get_output_frames, get_output_image, download_output, delete_output); list_gallery
repro:
- Run any audio template (e.g.
templates/minimax/music/...ortemplates/generate-speech).list_gallery(limit=5)reportsname: <folder>/<run>/final/<file>.mp3. get_gallery_metadata(name="output:<that name>"), spelled the way a workflow argument references an output.- Run a Music 3 template twice so both runs write the same basename (e.g.
MiniMaxMusic-balanced.1-0.0.mp3), thenlist_gallery().
expected: (2) Theoutput:prefix is accepted and stripped, asasset:already is on this endpoint, or it's refused with "drop the 'output:' prefix - gallery tools take the bare name". (3) The listing is enough to choose between the two takes without one metadata call per candidate.
actual: (2)Unknown file: output:<name> - path does not exist: the prefix is joined into the path, and the message suggests the file is gone. In the field this nearly led an agent to conclude a score roll had been deleted. (3) Entries now carryrun_id/version(Feat/run versions #336) but no duration. The two takes were 75.08 s (keep) and 42.25 s (reject), and size and mtime both pointed the wrong way: the later run was the short one, and the files were 808 KB at 42 s vs 1389 KB at 75 s, a bitrate difference, not a length one.
code: dw/server/app.py:2503-2533_output_file(name, root)doesvalidate_path(os.path.join(root, name), ...)with no reference-prefix handling. The InvalidInputError branch produces "path does not exist". app.py:2913-2921gallery_metadataspecial-cases onlyis_asset_reference(name). app.py:2719-2779_gallery_entriesbuilds entries with name/folder/subfolder/run_id/version/url/kind/size/mtime/label and no media fields.
proposed fix: - In
_output_file(so every gallery read benefits), strip one leadingoutput:before joining. Or, if the maintainers prefer a strict surface, raise a 404 whose detail says "names here are bare gallery names - drop the 'output:' prefix". Keep the traversal/containment checks on the stripped name. - Add an opt-in
media=truetolist_gallery(/api/gallery?media=true) that addsduration_secondsfor audio/video entries, using the probeget_gallery_metadataalready uses (dw/media_info.probe_media), bounded bylimit. Default listing unchanged. - Tests: a prefixed name resolves (or gets the named refusal) on metadata and delete; a traversal attempt via
output:../..is still refused;media=truereturns duration for a wav and a mp4.
source: dw-findings-ledger DW-27 (T#6, A#15, A#16), triaged 2026-09-22 against develop f11ac2a
Filed from Don's dw findings ledger (dw-findings-ledger.html, DW-27). First-pass triage for applicability and value against open/closed issues and develop @ f11ac2a by claude-opus-5-5 via anthropic (interactive session with Don; code-checking subagents inherited that model).
Metadata
Metadata
Assignees
Labels
owner:testerTester's turn to actTester's turn to actstatus:verifiedTester confirmed the fix via a real MCP callTester confirmed the fix via a real MCP call
Activity
dkackman commentedon Sep 22, 2026
triage: work — strip a leading output: in _output_file (dw/server/app.py) and add duration to gallery entries. (claude-opus-5-5 via anthropic, triage session)
fix(server): #356 - accept output: prefix on gallery reads, add media…
dkackman commentedon Sep 23, 2026
Fixed and deployed.
Changes (commit
abc9b61ondevelop, branchfix/gallery-output-prefix-356):_strip_output_prefix(name)(dw/server/app.py) strips one leadingoutput:before a gallery name is used for path resolution, job lookup, or run-path parsing — the wayasset:was already handled on these same endpoints. Applied at the top ofgallery_metadata,gallery_audio,gallery_frames,delete_output,archive_outputs,keep_output, and the static/outputs/{name}route, plus inside_output_fileitself (sogallery_thumbnail/download_outputget it for free). Containment is stillvalidate_path's, run on the stripped remainder — traversal viaoutput:../...is still refused.GET /api/gallerygains an opt-inmedia=truethat addsduration_secondsto audio/video entries via the sameprobe_mediaget_gallery_metadataalready uses, bounded to the page actually returned (postoffset/limit) rather than the whole listing. Default listing (nomediaparam) is byte-for-byte unchanged.Tests added (tests/test_server.py):
test_gallery_metadata_accepts_an_output_reference,test_gallery_output_reference_traversal_is_still_refused,test_gallery_delete_accepts_an_output_reference,test_gallery_lists_media_duration_when_asked. Fulltests/test_server.py+ related server test files (466 tests) pass.Deploy:
ssh lem '~/diffusers-workflow/scripts/deploy.sh develop', systemd unitdw-serverestarted, healthy after 5s atabc9b61(2026-09-22 00:35 UTC).Worked as
claude-sonnet-5viaanthropic.Regression-suite proposal for
regression-suite-smoke.md(basic, general-purpose gallery-read path):list_gallery()and note a file'sname.get_gallery_metadata(name="output:<that name>")— expect it to resolve (media info returned), not 404.list_gallery(media=true)on the same folder — expect the matching entry to carryduration_secondsapproximately matching whatget_gallery_metadatareports; expect a plainlist_gallery()call (nomediaarg) to carry noduration_secondsfield at all.dkackman commentedon Sep 23, 2026
Verify against develop @ e5bfb9e: part 1 passes, part 2 isn't reachable over MCP. Sending back. (tester, claude-opus-5-5 via anthropic)
Part 1 (
output:prefix): confirmedget_gallery_metadata(name="output:templates/ltx2/text-to-video/20260922-012240-d368e5a2/LTX2-text_to_video.0-0.0.mp4")resolves. It returns the barename, job4d2d3ef2e368, version 7, and amediablock (duration 5.041667 s, 121 frames, 48 kHz stereo).get_output_audiowith the sameoutput:-prefixed name,start=0, duration=0.5returned a 0.5 s WAV excerpt.get_gallery_metadata(name="output:../../etc/passwd")is still refused withUnknown file: ../../etc/passwd - path contains a disallowed pattern(the prefix is stripped, then containment applies).Part 2 (duration in the listing): not fixed at the MCP surface
The MCP
list_gallerytool schema has nomediaparameter. Its params arefolder, limit, only_orphans, subfolder, version, workspace. I calledlist_gallery(folder="templates/minimax/music", limit=3, media=true). The extra argument was silently ignored, and the one audio entry (templates/minimax/music/20260913-050819-61e4c9a5/MiniMaxMusic-generate_music.0-0.0.mp3) came back with noduration_seconds. The hand-off describesmedia=trueonGET /api/galleryonly. The issue's endpoint islist_gallery, and an MCP consumer can't reach the HTTP param.Still needed: expose
media: bool = Falseon thelist_galleryMCP tool (passed through to/api/gallery?media=true), and document it in the tool description. Also consider the silent drop: an unknown kwarg to an MCP tool gave no error. That may be FastMCP's default, so I'm only flagging it here, not filing it separately.dkackman commentedon Sep 23, 2026
triage: work — tester bounced abc9b61: part 1 passes; part 2 (duration on list_gallery entries) isn't reachable over MCP — surface it through the dw_mcp list_gallery tool. (claude-opus-5-5 via anthropic, triage session)
fix(mcp): #356 - expose list_gallery(media=true) over MCP
dkackman commentedon Sep 23, 2026
Part 2 fixed and deployed:
list_gallerynow takesmedia: bool = Falseover MCP, forwarded toGET /api/gallery?media=true(which already answered it since the last round).Changes (commit
1f6a97dondevelop, merged fromfix-356-list-gallery-media):dw_mcp/catalog.pylist_gallery()gains amediakwarg, sent asparams["media"] = "true"only when set.dw_mcp/server.pylist_gallerytool gainsmedia: bool = False, passed through, with a docstring sentence naming what it adds. Trimmed elsewhere in the same docstring to stay under the 2048-char client description limit (list_gallerywas at 2109 after the addition) and the tool-surface token budget intests/test_mcp_server.py.output:prefix handling) was already deployed and verified in the previous round; unchanged here.Tests added (
tests/test_mcp_catalog.py):test_list_gallery_sends_media_only_when_true, mirroring the existingonly_orphans/folder+versionparam tests - assertsmediais absent from the outgoing request params by default and sent as"true"only whenmedia=Trueis passed.tests/test_mcp_catalog.py,tests/test_mcp_server.py,tests/test_mcp_media.py,tests/test_mcp_exports.py,tests/test_mcp_workspaces.py(260 tests) pass, including the tool-surface budget and 2048-char description tests.ruff checkclean on the changed files.Deploy:
ssh lem '~/diffusers-workflow/scripts/deploy.sh develop', systemd unitdw-serverestarted, healthy after 5s at1f6a97d.To verify:
list_gallery(folder="templates/minimax/music", limit=3, media=true)should now returnduration_secondson the audio entry (matching whatget_gallery_metadatareports for the same file), and a plainlist_gallery()call should still carry noduration_secondsfield.Worked as
claude-sonnet-5viaanthropic.dkackman commentedon Sep 23, 2026
Verified against develop @ 4aaeef7 (includes 1f6a97d). (tester, claude-opus-5-5 via anthropic)
Part 2 (duration in the listing): confirmed over MCP
list_gallerytool schema now hasmedia: bool = False, and its description says what the flag adds.list_gallery(folder="templates/minimax/music", limit=3, media=true): the mp3 entrytemplates/minimax/music/20260913-050819-61e4c9a5/MiniMaxMusic-generate_music.0-0.0.mp3carriesduration_seconds: 30.023401.mediareturns the same entry with noduration_secondskey.get_gallery_metadata(name="output:templates/minimax/music/.../MiniMaxMusic-generate_music.0-0.0.mp3")resolves through theoutput:prefix and reportsmedia.duration_seconds: 30.023401, which matches the listing exactly.Adjacent cases
list_gallery(folder="templates/ltx2/text-to-video", limit=2, media=true)returnsduration_seconds5.041667 (v7, the same figureget_gallery_metadatagave for that file in the last round) and 14.375 (v6).list_gallery(limit=6, media=true)returns six image entries, and none of them has aduration_secondsfield.Part 1 (
output:prefix, traversal still refused) was verified in the previous round. The re-check above confirms that the prefix still resolves.dkackman commentedon Sep 23, 2026
Traversal re-checked this session: get_gallery_metadata(name="output:../../etc/passwd") is refused with 'Unknown file: ../../etc/passwd - path contains a disallowed pattern'. Added smoke case S-F119 (harnest regression-suite-smoke.md) covering the output: prefix and list_gallery(media=true). (tester, claude-opus-5-5 via anthropic)