feat(media): keep AI-enhanced prompts inside the render backend's character cap - #6354
Merged
Conversation
…racter cap reactor.inc's fast-h3 rejects a prompt over 800 characters outright rather than truncating it, so "Enhance with AI" reliably produced a richer prompt the render then refused — and the same for "Prompt from media", which writes into the same field. Both AI paths now receive the backend's budget, state it in the LLM prompt as a hard limit, and clamp the answer on a sentence or word boundary if the model overshoots anyway. The clamp is reported rather than silent, so a trimmed prompt reads as "trimmed to fit the render limit" instead of the AI losing detail on its own. The budget VideoGen sends is the cap MINUS the style-preset prefix, since that prefix is part of what PortOS submits — enhancing to exactly 800 characters would still be rejected once the preset is prepended. Adds clampToCharLimit() to server/lib/textUtils.js: unlike the existing marker-appending helpers (clampText, truncateForTelegram), it appends nothing, because a marker would count against the same renderer cap.
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.
Summary
reactor.inc's
fast-h3rejects a prompt over 800 characters outright rather than truncating it. The VideoGen form already counted characters and gated Generate on that cap — but the two AI paths that write into the prompt field did not know about it, so "Enhance with AI" reliably produced a richer prompt the renderer then refused.Both AI paths now receive the backend's budget:
POST /api/media-jobs/refine-prompt) — new optionalmaxPromptLengthPOST /api/media-jobs/prompt-from-media) — new optionalmaxVideoPromptLengthEach states the limit in the LLM prompt as a hard constraint ("AT MOST N characters … the renderer REJECTS a longer prompt outright rather than trimming it"), then clamps the answer if the model overshoots anyway. The clamp is reported (
truncated/videoPromptTruncated), not silent — the UI toasts "trimmed to fit the N character render limit" so it doesn't read as the AI losing detail on its own.The budget is the cap minus the style-preset prefix. Style presets prepend to what PortOS actually submits, so enhancing to exactly 800 characters would still be rejected once the preset is applied.
VideoGenderives the budget from the same submitted-length calculation that drives the character counter.New shared helper
clampToCharLimit(text, max)inserver/lib/textUtils.js→{ text, truncated }. It cuts at the last sentence end when one sits 60%+ into the allowance, else at the last word boundary — a mid-word cut in a render prompt can change what the final phrase asks for. Deliberately distinct from the two existing capping helpers (clampText,truncateForTelegram), which append a marker: a marker would count against the same renderer cap.Backends with no cap pass nothing and behave exactly as before (ImageGen, local video models, grok, fal).
Test plan
server/lib/textUtils.test.js— pass-through (no cap / already fits / non-string), sentence-end cut, word-boundary fallbackserver/services/mediaPromptRefiner.test.js— the cap reaches the LLM prompt; an over-length answer is clamped and reported; a within-limit answer is untouched; no cap ⇒ no length ruleserver/services/mediaPromptFromMedia.test.js— cap stated only when the caller has one; over-lengthvideoPromptclamped whileimagePromptis untouchedclient/src/components/media/PromptEnhancer.test.jsx— forwards the cap, warns on a trimmed result, shows the budget hintclient/src/pages/VideoGen.reactor.test.jsx— enhancer budget isundefinedoff the reactor lane,800on it, and785once a 15-character style prefix is appliedFull suites green: server 2004 files / 39,881 tests, client 867 files / 10,564 tests.