Skip to content

Empty-completion detector does not recognize the Interactions protocol #202

Description

@warelik

The empty-completion detector in sdk/cliproxy/auth/empty_completion.go has no Interactions-protocol branch: no interactionsEventTypes set, no evalInteractions, no interactionsChunk. Every Interactions-protocol stream is therefore classified as unknown data, sawUnknownData flips the accumulator to non-empty, and an empty turn is committed as a valid response — the empty-completion failover never engages for the Interactions protocol.

The repo does ship the Interactions translator (internal/translator/gemini/interactions/), and that translator treats "finish" as a terminal event alongside "interaction.completed" (interactions_gemini_response.go:106), taking usage from metadata.total_usage first (internal/translator/common/interactions_usage.go:5-12). The detector does not know any of these events.

Reproduction

Feed the detector a complete Interactions turn that produced zero output:

payload := []byte("event: interaction.created\ndata: {\"event_type\":\"interaction.created\",\"interaction\":{\"id\":\"int_1\",\"object\":\"interaction\",\"status\":\"in_progress\"}}\n\nevent: step.start\ndata: {\"event_type\":\"step.start\",\"index\":0,\"step\":{\"type\":\"model_output\"}}\n\nevent: finish\ndata: {\"event_type\":\"finish\",\"metadata\":{\"total_usage\":{\"total_output_tokens\":0}}}\n\n")
isEmptyCompletionPayload(payload) // returns false, must be true

With the Interactions branch absent this returns false (unknown data commits the stream). The expected result is true so the conductor can rotate to the next auth instead of handing an empty response to the client.

Context

This gap came to light while addressing the equivalent review on the upstream project: router-for-me/CLIProxyAPI#4881 now recognizes "finish" as a terminal Interactions event reading metadata.total_usage (upstream commit baf43ba5 on fix/empty-completion-retry). The paired failover work here is #195; this detector gap is separate and older — porting the upstream Interactions branch (event set, interactionsChunk, evalInteractions, evalInteractionsUsage, and the finish handling) would close it.

Test expectations

The upstream TestEmptyCompletionPredicate cases that cover this, worth porting together with the branch:

  • interactions sse stream ending in bare finish with zero output is emptytrue
  • interactions sse stream ending in bare finish with output is not emptyfalse

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions