diff --git a/resources/js/components/posts/ai/AiGenerateDialog.vue b/resources/js/components/posts/ai/AiGenerateDialog.vue index 788190c1..bd3a1f6a 100644 --- a/resources/js/components/posts/ai/AiGenerateDialog.vue +++ b/resources/js/components/posts/ai/AiGenerateDialog.vue @@ -45,8 +45,24 @@ const startGeneration = async () => { } }; +// The streamer agent shares the structured-output prompt template with +// PostContentGenerator, so what comes through the stream is a JSON object +// like {"content": "...", "image_title": "...", ...}. We only want the +// content field — and only once the JSON is complete (mid-stream the parse +// fails and we show nothing, avoiding the typewriter-of-JSON effect). +const previewText = computed(() => { + if (! text.value) return ''; + try { + const parsed = JSON.parse(text.value); + if (parsed && typeof parsed.content === 'string') return parsed.content; + } catch { + // Mid-stream the JSON is incomplete — leave preview empty. + } + return ''; +}); + const apply = () => { - emit('apply', text.value); + emit('apply', previewText.value); open.value = false; }; @@ -56,7 +72,7 @@ const retry = () => { startGeneration(); }; -const canApply = computed(() => status.value === 'completed' && text.value.trim().length > 0); +const canApply = computed(() => status.value === 'completed' && previewText.value.trim().length > 0); const canRetry = computed(() => status.value === 'completed' || status.value === 'failed'); watch(open, () => { @@ -88,15 +104,16 @@ watch(open, () => {
{{ errorMessage }}