feat: Migrate synthetic message detection to metadata-based approach #6364

Open
opened 2026-02-16 18:03:36 -05:00 by yindo · 0 comments
Owner

Originally created by @ananas-viber on GitHub (Jan 15, 2026).

Originally assigned to: @thdxr on GitHub.

Summary

Currently, copilot.ts detects synthetic user messages (compaction, tool attachments, subtasks) via regex pattern matching on message text. This works but has maintenance coupling.

Current State

  • synthetic: boolean already exists on TextPart (message-v2.ts:64)
  • It's already being set in various places (prompt.ts:1374, etc.)
  • BUT toModelMessage() does not propagate this flag to the final UIMessage

Proposed Change

  1. In message-v2.ts toModelMessage():

    • Pass providerMetadata: { synthetic: true } for user text parts when part.synthetic === true
    • Add same metadata for compaction/subtask generated messages
  2. In copilot.ts:

    • Check part.providerMetadata?.synthetic === true instead of pattern matching
    • Remove SYNTHETIC_PATTERNS array

Benefits

  • Type-safe detection (no string coupling)
  • Compile-time enforcement if field is renamed
  • Cleaner architecture
  • Eliminates theoretical "hackability" of pattern matching

Context

This is a follow-up to #8721 which implements the pattern-matching approach as a minimal fix.

Related issues:

  • #8030 - Original report of excessive premium request consumption
  • #8700 - Describes synthetic user messages burning premium requests (same root cause)
  • #8721 - Pattern-matching fix (immediate solution)
Originally created by @ananas-viber on GitHub (Jan 15, 2026). Originally assigned to: @thdxr on GitHub. ## Summary Currently, `copilot.ts` detects synthetic user messages (compaction, tool attachments, subtasks) via regex pattern matching on message text. This works but has maintenance coupling. ## Current State - `synthetic: boolean` already exists on `TextPart` (message-v2.ts:64) - It's already being set in various places (prompt.ts:1374, etc.) - BUT `toModelMessage()` does not propagate this flag to the final `UIMessage` ## Proposed Change 1. In `message-v2.ts` `toModelMessage()`: - Pass `providerMetadata: { synthetic: true }` for user text parts when `part.synthetic === true` - Add same metadata for compaction/subtask generated messages 2. In `copilot.ts`: - Check `part.providerMetadata?.synthetic === true` instead of pattern matching - Remove `SYNTHETIC_PATTERNS` array ## Benefits - Type-safe detection (no string coupling) - Compile-time enforcement if field is renamed - Cleaner architecture - Eliminates theoretical "hackability" of pattern matching ## Context This is a follow-up to #8721 which implements the pattern-matching approach as a minimal fix. Related issues: - #8030 - Original report of excessive premium request consumption - #8700 - Describes synthetic user messages burning premium requests (same root cause) - #8721 - Pattern-matching fix (immediate solution)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#6364