Repository navigation
Conversation
… EMPTY_COMPLETION When a user sends only file attachments with no text, isEmptyConversation previously returned false (file parts were treated as non-empty). After conversion, the LLM received only a file annotation with no user intent text, which could result in an empty response and trigger EMPTY_COMPLETION. Change the non-text part check from `return false` to `return true` so that a message composed entirely of file parts (with no meaningful text) is treated as an empty conversation. The configured default prompt is used instead, ensuring the LLM always receives actionable text. Mixed messages (text + files) are unaffected because a non-empty text part returns false from parts.every(), keeping the existing conversion path.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8571b12151
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| return !part.text || part.text.trim() === ""; | ||
| } | ||
| return false; | ||
| return true; |
There was a problem hiding this comment.
Limit empty-conversation shortcut to file parts
This change makes isEmptyConversation treat every non-text part as ignorable, not just file parts. In a single user message that contains structured content like data-* or tool-related parts (both valid ChatUiMessagePart variants), parts.every(...) now returns true and the function replaces the message with emptyConversationPrompt, dropping the original payload before prepareProviderModelMessagesFromUiMessages can convert it. That creates a behavioral regression for first-turn structured user inputs; the non-text branch should be narrowed to file-only (or another explicitly allowed subset) instead of all non-text parts.
Useful? React with 👍 / 👎.
|
Closing — this is the wrong fix. The Root cause (deeper investigation)The actual problem is in Correct architectural directionFiles in this system travel out-of-band (uploaded separately, referenced by The right fix is either:
Neither requires changing |
Problem
When a user sends a chat message with only file attachments and no text,
isEmptyConversationreturnedfalsebecause non-text parts short-circuited theevery()check. After conversion viaagent-runtime-message-adapter, the LLM received only a file annotation text with no user intent:With no actionable request, some LLMs return an empty response. This triggers
shouldFailEmptyFinalizedMessagein the agent runtime, producing anEMPTY_COMPLETIONerror — which is the root cause of veryfront/veryfront-studio#3499.Fix
Change the non-text part check in
isEmptyConversationfromreturn falsetoreturn true.A message composed entirely of file parts has no text intent — it should be treated the same as an empty text message. The configured
emptyConversationPrompt(orDEFAULT_EMPTY_CONVERSATION_PROMPT) is used instead, so the LLM always receives actionable text.Mixed messages (text + files) are unaffected: a non-empty text part still returns
falsefromparts.every(), leaving the existing conversion path untouched.Evidence
TDD cycle in
src/agent/runtime-message-preparation.test.ts:return falsecodeRelated