From c6241ecad291129bd31070f9e7bdf6cfdd97c504 Mon Sep 17 00:00:00 2001 From: YOMXXX Date: Mon, 13 Jul 2026 14:23:18 +0800 Subject: [PATCH] fix(daemon): honor BYOK media defaults in dispatch hint (#5440) --- apps/daemon/src/prompts/system.ts | 29 ++++++++++++++++--- .../tests/system-prompt-template.test.ts | 5 ++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/apps/daemon/src/prompts/system.ts b/apps/daemon/src/prompts/system.ts index c96790c358..d9ec123486 100644 --- a/apps/daemon/src/prompts/system.ts +++ b/apps/daemon/src/prompts/system.ts @@ -285,16 +285,17 @@ The daemon injects these env vars into your shell (**POSIX bash — not PowerShe - \`OD_BIN\` — absolute path to the OD CLI script - \`OD_PROJECT_ID\` — the active project id -**Always use the generate→wait loop below.** \`media generate\` always exits 0 — either with \`{"file":{...}}\` if done within ~25s, or with \`{"taskId":"..."}\` as a handoff for slow models (flux-pro-ultra ~60–180s, veo-3-fal longer). Whenever the output contains a \`taskId\`, keep polling with \`media wait\` until exit 0 (done) or exit 5 (failed). +**Always use the generate→wait loop below.** \`media generate\` always exits 0 — either with \`{"file":{...}}\` if done within ~25s, or with \`{"taskId":"..."}\` as a handoff for slow models. Whenever the output contains a \`taskId\`, keep polling with \`media wait\` until exit 0 (done) or exit 5 (failed). Use **POSIX \`$VAR\` syntax** — do NOT translate to PowerShell (\`$env:VAR\`, \`&\` operator). Uses \`python3\` for JSON parsing (do NOT use \`jq\`): \`\`\`bash # POSIX bash — do NOT convert to PowerShell +IMAGE_MODEL=IMAGE_MODEL_VALUE out=\$("$OD_NODE_BIN" "$OD_BIN" media generate \\ --project "$OD_PROJECT_ID" \\ --surface image \\ - --model flux-pro-ultra \\ + --model "$IMAGE_MODEL" \\ --prompt "..." \\ --aspect 16:9) ec=\$? @@ -320,7 +321,7 @@ printf '%s\\n' "\$last" **Never ask the user for an API key.** The daemon reads provider credentials from its config; keys are never passed through the shell. If the provider returns an auth error, tell the user to open Settings → AI Providers and confirm the key is configured there. -For the best fal image model use \`--model flux-pro-ultra\`. For video use \`--model veo-3-fal\` or \`--model wan-2.1-t2v\`. Always pass \`--surface\` explicitly (\`image\`, \`video\`, or \`audio\`). Any \`fal-ai/*\` path (e.g. \`fal-ai/flux/schnell\`, \`fal-ai/wan-i2v\`) is also a valid \`--model\` value for image/video — pass it through as-is without substitution.`; +MODEL_SELECTION_GUIDANCE`; function renderByokMediaDefaultsHint(defaults?: ByokMediaDefaults): string { const lines: string[] = []; @@ -343,8 +344,28 @@ a different model or voice. ${lines.join('\n')}`; } +function shellDoubleQuote(value: string): string { + return `"${value.replace(/(["\\$`])/g, '\\$1')}"`; +} + +function renderMediaDispatchModelGuidance(defaults?: ByokMediaDefaults): string { + const imageModel = defaults?.imageModel?.trim(); + const videoModel = defaults?.videoModel?.trim(); + const imagePart = imageModel + ? `For image generation prefer your configured model: \`${imageModel}\`.` + : 'For the best fal image model use `--model flux-pro-ultra`.'; + const videoPart = videoModel + ? `For video prefer your configured model: \`${videoModel}\`.` + : 'For video use `--model veo-3-fal` or `--model wan-2.1-t2v`.'; + return `${imagePart} ${videoPart} Always pass \`--surface\` explicitly (\`image\`, \`video\`, or \`audio\`). Any \`fal-ai/*\` path (e.g. \`fal-ai/flux/schnell\`, \`fal-ai/wan-i2v\`) is also a valid \`--model\` value for image/video — pass it through as-is without substitution.`; +} + function renderMediaDispatchHint(defaults?: ByokMediaDefaults): string { - return `${MEDIA_DISPATCH_HINT}${renderByokMediaDefaultsHint(defaults)}`; + const imageModel = defaults?.imageModel?.trim() || 'flux-pro-ultra'; + const hint = MEDIA_DISPATCH_HINT + .replace('IMAGE_MODEL_VALUE', shellDoubleQuote(imageModel)) + .replace('MODEL_SELECTION_GUIDANCE', renderMediaDispatchModelGuidance(defaults)); + return `${hint}${renderByokMediaDefaultsHint(defaults)}`; } const FILESYSTEM_HANDOFF_OVERRIDE = ` diff --git a/apps/daemon/tests/system-prompt-template.test.ts b/apps/daemon/tests/system-prompt-template.test.ts index 0cdf16cdaf..46286e17e2 100644 --- a/apps/daemon/tests/system-prompt-template.test.ts +++ b/apps/daemon/tests/system-prompt-template.test.ts @@ -450,6 +450,11 @@ describe('composeSystemPrompt — metadata.promptTemplate', () => { expect(out).toContain('## Media generation (if asked)'); expect(out).toContain('### Run-scoped BYOK media defaults'); expect(out).toContain('- Image model: `senseaudio-image-1.0-260319`'); + expect(out).toContain('IMAGE_MODEL="senseaudio-image-1.0-260319"'); + expect(out).toContain('--model "$IMAGE_MODEL"'); + expect(out).toContain('For image generation prefer your configured model: `senseaudio-image-1.0-260319`.'); + expect(out).not.toContain('--model flux-pro-ultra'); + expect(out).not.toContain('For the best fal image model use `--model flux-pro-ultra`'); }); it('keeps unrestricted enabled media contract unchanged', () => {