Skip to content

feat: add per-turn automatic translation delivery - #182

Open
Gwen317 wants to merge 1 commit into
1024XEngineer:devfrom
Gwen317:codex/issue-176-auto-delivery
Open

feat: add per-turn automatic translation delivery#182
Gwen317 wants to merge 1 commit into
1024XEngineer:devfrom
Gwen317:codex/issue-176-auto-delivery

Conversation

@Gwen317

@Gwen317 Gwen317 commented Aug 3, 2026

Copy link
Copy Markdown

Summary

Implements the confirmed design for Issue #176:

  • Capture tts_enabled and delivery_enabled independently for each target language at Turn start.
  • Persist each Final Turn before scheduling delivery; one enabled channel creates one asynchronous message.
  • Pin one verified destination_ref per channel and use auto:final_turn:{turn_id}:{channel}:{destination_ref} for idempotency.
  • Keep message snapshots immutable and include both source text and translated text.
  • Allow both email and WeCom through the existing outbox, queue, worker, retry, and provider path.
  • Add migration, contracts, focused tests, and the short design proposal.

Verification

  • go test -count=1 -race ./... in packages/contracts
  • go test -count=1 -race ./... in services/api
  • go test -count=1 -race ./... in services/realtime-audio

Refs #176

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review summary:

Found one hard persistence bug and one wiring gap in the new automatic-delivery path.

var stored Preference
err := r.pool.QueryRow(ctx, `
INSERT INTO message_preferences (account_id,channel,enabled,verified,updated_at)
INSERT INTO message_preferences (account_id,channel,destination_ref,enabled,verified,updated_at)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter order here is wrong: $3 is bound from preference.Enabled, but the third column is destination_ref. This will try to store a bool into the destination-ref column and swap the enabled/destination values for every preference write.


// NewRealtimeAudioLanguageConfigReader preserves the full output route in the
// turn-start snapshot consumed by the media-plane pipeline.
func NewRealtimeAudioLanguageConfigReader(reader languages.LanguageConfigReader) (realtimeaudio.LanguageConfigReader, error) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adapter is only useful if the realtime runtime actually uses it. In this repo the manager still consumes session.LanguageConfigReader, and there is no call site for NewRealtimeAudioLanguageConfigReader, so OutputRoutes never reach the turn opener in production.

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.

1 participant