fix(providers): refuse an empty Responses input before sending instead of retrying a guaranteed 400

Merged
WA
23d ago
+56-1

Summary

  • An Agent block whose system and user messages are absent or resolve to empty (e.g. <start.input> is "") sent the OpenAI Responses API input: [], because empty-content messages are dropped when the input is built. OpenAI rejects that with a 400 on every attempt, yet it surfaced as a plain internal error, logged at ERROR, and burned block retries and model fallbacks
  • executeResponsesProviderRequest now refuses an empty input before any request is sent, throwing EmptyProviderInputError — a UserFailure (classified as the author's to fix) with retryable = false (skips block retries and the fallback chain)
  • The message tells the author the Agent has nothing to send and to add a system/user message or check the referenced value
  • Applies to every Responses caller (OpenAI, Azure OpenAI, Kie); none use previous_response_id, prompt, or conversation, so an empty input could never succeed on any of them
  • Unchanged: system-prompt-only requests, whitespace-only content (only zero-length content is dropped, as before), file-only user messages, tool-loop continuation turns

Type of Change

  • Bug fix

Testing

  • Extended providers/openai/core.response-status.test.ts: empty system prompt + empty messages rejects with the user failure (isNonRetryableExecutionError true, classifyFailure → user) and never calls fetch; a system-prompt-only request still sends [{ role: 'system', … }]
  • Red on the pre-fix code (removing the guard yields ProviderError: OpenAI API error (400)), green with it
  • OpenAI, Azure OpenAI and Kie provider tests pass (154 tests)

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing (new tests pass the test-audit authoring gate)
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)