feat(#3996): name generated media with private markers and prompt fallback - #4027
Open
aheritier wants to merge 2 commits into
Open
feat(#3996): name generated media with private markers and prompt fallback#4027aheritier wants to merge 2 commits into
aheritier wants to merge 2 commits into
Conversation
aheritier
force-pushed
the
workspace-media-naming
branch
from
August 24, 2026 15:13
25c9d9a to
c4127a5
Compare
aheritier
force-pushed
the
workspace-media-naming
branch
from
August 25, 2026 08:00
c4127a5 to
9594ce2
Compare
Collaborator
Author
|
👋 This PR has merge conflicts with the base branch. Please rebase or merge the latest base branch and resolve them. I've moved it to draft and added |
aheritier
force-pushed
the
workspace-media-naming
branch
from
August 25, 2026 08:16
9594ce2 to
56fad2f
Compare
aheritier
force-pushed
the
workspace-media-naming
branch
from
August 25, 2026 08:32
56fad2f to
0272095
Compare
aheritier
force-pushed
the
workspace-media-naming
branch
from
August 25, 2026 20:24
0272095 to
ddcbca4
Compare
aheritier
force-pushed
the
workspace-media-naming
branch
from
August 26, 2026 11:10
ddcbca4 to
9e83563
Compare
aheritier
force-pushed
the
workspace-media-naming
branch
2 times, most recently
from
September 1, 2026 16:09
4968274 to
9e83563
Compare
aheritier
force-pushed
the
workspace-media-naming
branch
from
September 1, 2026 16:30
9e83563 to
c7783d3
Compare
aheritier
force-pushed
the
workspace-media-naming
branch
from
September 1, 2026 19:58
c7783d3 to
b18b517
Compare
aheritier
force-pushed
the
workspace-media-naming
branch
from
September 8, 2026 06:17
beea6b8 to
e9fd7c8
Compare
aheritier
force-pushed
the
workspace-media-naming
branch
from
September 8, 2026 07:57
e9fd7c8 to
9db704a
Compare
aheritier
force-pushed
the
workspace-media-naming
branch
from
September 8, 2026 17:31
9db704a to
b189b04
Compare
aheritier
force-pushed
the
workspace-media-naming
branch
from
September 8, 2026 20:36
b189b04 to
da8faa2
Compare
aheritier
marked this pull request as ready for review
September 8, 2026 20:39
dgageot
force-pushed
the
workspace-media-naming
branch
from
September 9, 2026 07:41
da8faa2 to
c40f2d7
Compare
dgageot
previously approved these changes
Sep 9, 2026
aheritier
force-pushed
the
workspace-media-naming
branch
from
September 9, 2026 11:56
c40f2d7 to
0f4ecd5
Compare
dgageot
force-pushed
the
workspace-media-naming
branch
from
September 9, 2026 12:15
0f4ecd5 to
31c417f
Compare
aheritier
force-pushed
the
workspace-media-naming
branch
from
September 9, 2026 12:56
31c417f to
19d3fc1
Compare
aheritier
force-pushed
the
workspace-media-naming
branch
from
September 9, 2026 13:32
19d3fc1 to
a26a733
Compare
aheritier
force-pushed
the
workspace-media-naming
branch
from
September 9, 2026 14:07
a26a733 to
9cddd6e
Compare
Add a naming instruction to ordinary Gemini requests whose resolved image-output capability enables TEXT+IMAGE, including gateway, direct API, and Vertex routes. Ask for one exact "[media-file: relative/path]" line per image, honoring a requested filename or choosing a meaningful name, and request one image unless multiple images or variations are requested. Filter marker lines from live and persisted assistant text with a bounded, chunk-split-safe parser. Pair paths positionally with media through MediaDelta.RequestedPath, then use provider names or generated-N for unnamed blobs; strip and ignore extra markers without dropping images. Marker paths remain untrusted and pass through workspace containment, extension correction, workspace redirection, and collision-safe publishing so model-selected names cannot bypass the existing write policy.
…named image A live image-output model can ignore the [media-file:] marker instruction entirely, leaving a prompt like "Generate an image as sunshine.jpg" to land as generated-1.png. Add a deterministic fallback: when a turn returns exactly ONE media blob that marker pairing left unnamed, parse a single unambiguous explicit output filename from the triggering user message. The cue grammar is strict, deliberately not NLP: save (it) as / save to / write to / output to / name it / call it / filename:=, plus bare "as" only inside a narrow imperative output context (generation verb + optionally-articled media noun, e.g. "Generate an image as sunshine.jpg"), and a companion of-phrase form (generation verb + media noun + "of <subject>" + "as <filename>") so "Generate an image of a red panda as assets/red-panda.jpg" extracts the intended name. The of-phrase subject cannot cross quotes, clause punctuation, or CR/LF, and any subject containing "as", "with", or "in" is refused because those prepositions introduce open-ended attribute phrases whose trailing "as" compares — a false reject only costs the generic generated-N name, while a false capture could engage the workspace-redirection policy for a merely referenced file. Bare "called" and unanchored "as" are NOT cues, so comparative references to existing files never extract a name. Candidates are keyed by the filename capture's position: one occurrence matched by both grammars counts once; distinct occurrences stay ambiguous and extract nothing. Names may be quoted, backticked, or unquoted with a known image extension; zero or multiple candidates extract nothing. Precedence stays marker -> user-prompt filename -> provider display name -> generic generated-N, and the extracted path only fills MediaDelta.RequestedPath, so the existing untrusted-path pipeline (MIME/extension correction, collision suffixing, workspace containment and workspace redirection) applies unchanged.
aheritier
force-pushed
the
workspace-media-naming
branch
from
September 9, 2026 15:55
9cddd6e to
a5e63ba
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
Request private
[media-file: ...]markers, remove them from visible and persisted text, and apply naming precedence: marker, exact one-image user-prompt filename, provider name, thengenerated-N. Prompt fallback applies only when exactly one image was returned. Requested paths remain untrusted and pass through workspace-only containment, MIME correction, and collision-safe publication.Part of #3996. Review this PR against its immediate parent, #4026, rather than the aggregate stack against
main.Commit inventory
Head:
da8faa29eace36625b546c4d7103b4d08543d57e; parent SHA:1409e8b414370be9a472cad3d889d0cc8a2316c9.69155f939bcc878aa22b53188602aeea8fbdaeb3— feat(Epic: Gemini image output with workspace deliverables and portable session copies #3996): name generated media via [media-file:] response markersda8faa29eace36625b546c4d7103b4d08543d57e— feat(Epic: Gemini image output with workspace deliverables and portable session copies #3996): fall back to an explicit user-prompt filename for one unnamed imageValidation
Build, test compilation, owning-package tests and the named fixture passed at this PR head.
Exact deterministic fixture command:
Matched top-level tests:
pkg/model/provider/gemini: 2;pkg/runtime: 8.Deterministic scope: the named local fixture exercises this PR boundary with disposable configuration/stores and fake or loopback providers as applicable. Every listed package ran nonzero matching top-level tests.
Deferred/live scope: Live provider, remote CI, and platform execution are not claimed by this deterministic receipt. The final stack head passed build, lint, full tests, an uncached full suite, focused race tests and documentation checks in disposable environments. Remote CI is tracked by the checks below; no new paid-provider or active-database validation was run.