Skip to content

fix(copilot): treat synthetic user messages as agent for x-initiator billing#15821

Closed
Juhwa-Lee1023 wants to merge 1 commit intoanomalyco:devfrom
Juhwa-Lee1023:fix/copilot-x-initiator-synthetic-messages
Closed

fix(copilot): treat synthetic user messages as agent for x-initiator billing#15821
Juhwa-Lee1023 wants to merge 1 commit intoanomalyco:devfrom
Juhwa-Lee1023:fix/copilot-x-initiator-synthetic-messages

Conversation

@Juhwa-Lee1023
Copy link
Copy Markdown

@Juhwa-Lee1023 Juhwa-Lee1023 commented Mar 3, 2026

Issue for this PR

Closes #15824

Originally reported upstream at #8030.

Type of change

  • Bug fix

What does this PR do?

When GitHub Copilot receives a request, it uses the x-initiator header to decide whether to bill the request against the user's premium quota (user) or the agent budget (agent). opencode sets this header based on the role of the last message in the request body.

The problem: tool results, image attachments, and other agent-produced content travel as messages with role: "user" in all three API flavours (Completions, Responses, Anthropic Messages). The Completions and Responses API paths only checked last?.role !== "user", so every agentic turn containing tool results was mis-classified as user-initiated and incorrectly billed against the user's Copilot premium quota.

The Anthropic Messages API path had a partial fix (hasNonToolCalls), but it was inconsistent with the other two paths and only covered tool_result parts.

Fix: introduce a shared isSyntheticUserMessage() helper that returns true when every content part of a role: "user" message is an agent-produced type (tool_result, attachment, input_image, image_url, image). Apply it consistently across all three API paths.

How did you verify your code works?

Added 13 unit tests in packages/opencode/test/provider/copilot/x-initiator.test.ts covering genuine human messages (→ false) and all synthetic agent-produced message shapes (→ true).

bun test test/provider/copilot/
42 pass, 0 fail

Screenshots / recordings

N/A — logic-only change, no UI.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

…billing

Tool results, image attachments, and other agent-produced content arrive as
messages with role 'user'.  Previously only the Anthropic Messages API path
checked for this; the Completions and Responses API paths performed a bare
role check and mis-classified these messages as user-initiated, causing
premium Copilot requests to be billed against the user quota.

Introduce a shared isSyntheticUserMessage() helper that returns true when
every content part of a 'user' message is an agent-produced type
(tool_result, attachment, input_image, image_url, image).  Apply it
consistently across all three API paths.  The Messages API path previously
used a different (inverted) formulation; it is now aligned with the other
two for consistency.

Fixes: anomalyco#8030
@github-actions github-actions bot added the needs:compliance This means the issue will auto-close after 2 hours. label Mar 3, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 3, 2026

The following comment was made by an LLM, it may be inaccurate:

I found a potentially related PR:

Related PR:

This PR (15821) may be a more comprehensive fix or refactor of the issue originally addressed in #8721. You should verify whether #8721 was closed in favor of this new PR or if they address different aspects of the same problem.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 3, 2026

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions github-actions bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Mar 3, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 3, 2026

Thanks for updating your PR! It now meets our contributing guidelines. 👍

@Juhwa-Lee1023
Copy link
Copy Markdown
Author

Closing in favour of #8721 which provides a more complete fix using history-based inference (matching VSCode Copilot's iterationNumber === 0 approach) plus synthetic text pattern detection. Our content-based approach here is a subset of that work. #8721 also tracks the long-term metadata-based solution in #8766.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(copilot): tool results and attachments incorrectly billed as user-initiated (x-initiator header)

1 participant