Skip to content

internal(voice): wire DebugMessage over remote-session wire#1611

Open
toubatbrian wants to merge 7 commits into
mainfrom
brian/bump-protocol-1.46.3
Open

internal(voice): wire DebugMessage over remote-session wire#1611
toubatbrian wants to merge 7 commits into
mainfrom
brian/bump-protocol-1.46.3

Conversation

@toubatbrian
Copy link
Copy Markdown
Contributor

@toubatbrian toubatbrian commented May 26, 2026

Summary

Wires the new AgentSessionEvent.debug_message (livekit/protocol#1593) through SessionHost / RemoteSession, and adds an internal-only AgentSession._emitDebugMessage(payload) helper for the debugger/recorder (e.g. agents-cli).

Not a user-facing API — the leading underscore + /* internal */ JSDoc signal that this is not intended to be called from user code. The event rides the existing AgentSessionEvent wrapper on the wire; nothing else in the session lifecycle changes.

Changes

  • pyproject analog: bumps @livekit/protocol floor ^1.46.3^1.46.4 (picks up DebugMessage, the renamed AgentSessionEvent.debug_message field, FunctionToolsStarted, EotPrediction, SessionRequest.UpdateIO).
  • voice/events.tsAgentSessionEventTypes.CustomEventDebugMessage (topic value 'custom_event''debug_message').
  • voice/agent_session.ts:
    • AgentSessionCallbacks typed as (ev: pb.DebugMessage) => void
    • New internal helper: _emitDebugMessage(payload: Record<string, unknown>): void — wraps Struct.fromJson(payload) into pb.DebugMessage and emits it
  • voice/remote_session.ts:
    • RemoteSessionCallbacks.debug_message typed as pb.DebugMessage
    • SessionHost.onDebugMessage forwards the proto via emitEvent({ case: 'debugMessage', value: event })
    • dispatch re-emits ev.value directly

Usage (internal only)

```ts
// debugger / recorder code only — not for user code
session._emitDebugMessage({ kind: 'anomaly_detected', score: 0.92 });
```

External listeners can subscribe to the event topic (it's discoverable on the EventEmitter), but the canonical emit path is the underscore method. There is no stable public emit API for debug events.

Test plan

  • `pnpm install` — lockfile diff scoped to `@livekit/protocol` resolution only (`1.46.3` → `1.46.4`)
  • `pnpm --filter @livekit/agents exec tsc --noEmit` — clean
  • `pnpm --filter @livekit/agents lint` — no new warnings (127 reported are pre-existing test-file `any` noise)

Notes

Picks up the new agent-session messages required for upcoming work:
CustomEvent, AgentSessionEvent.custom_event (livekit/protocol#1588),
AgentSessionEvent.FunctionToolsStarted, AgentSessionEvent.EotPrediction,
and SessionRequest.UpdateIO.

No runtime change in @livekit/agents itself — this only makes the new
generated types resolvable. Type-check (tsc --noEmit) passes against
the new version.

Co-authored-by: Cursor <cursoragent@cursor.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 26, 2026

🦋 Changeset detected

Latest commit: a710d41

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

toubatbrian and others added 3 commits May 26, 2026 15:05
`Struct.fromJson` expects `JsonValue`, but the helper accepts
`Record<string, unknown>` which is structurally wider (unknown is
broader than JsonValue). Cast at the trust boundary — the caller is
contractually responsible for JSON-serializable values, and
`Struct.fromJson` validates at runtime anyway.

Fixes the `build:types` failure:

  src/voice/remote_session.ts:85:26 - error TS2345: Argument of type
  'Record<string, unknown>' is not assignable to parameter of type
  'JsonValue'.

Co-authored-by: Cursor <cursoragent@cursor.com>
Mirrors the Python-side decision (livekit/agents#5855): with
CustomEvent already defined in livekit/protocol, the parallel TS
wrapper + dict<->Struct conversion was pure ceremony with no semantic
gain. Drop the wrapper and forward the proto unchanged.

- events.ts: remove `CustomEvent` type + `createCustomEvent` helper +
  membership in the `AgentEvent` union. Keep the
  `AgentSessionEventTypes.CustomEvent` enum entry so the listener
  topic name stays stable.
- agent_session.ts: callback signature is now
  `(ev: pb.CustomEvent) => void` (import-as-type).
- remote_session.ts:
  - drop `dictToStruct` / `structToDict` and the `JsonValue` import
  - `RemoteSessionCallbacks.custom_event` typed as `pb.CustomEvent`
  - `onCustomEvent` forwards the proto as-is via
    `emitEvent({ case: 'customEvent', value: event })`
  - dispatch side re-emits `ev.value` directly (no Struct->dict round-trip)

User-facing emit:

    session.emit(
      'custom_event',
      new pb.CustomEvent({
        type: 'anomaly_detected',
        payload: Struct.fromJson({ score: 0.92 }),
      }),
    );

`tsc --noEmit` and lint clean (no new warnings beyond the pre-existing
test-file `any` noise).

Co-authored-by: Cursor <cursoragent@cursor.com>
@toubatbrian toubatbrian changed the title chore(deps): bump @livekit/protocol to ^1.46.3 feat(voice): add CustomEvent (proto-native, no wrapper) May 26, 2026
devin-ai-integration[bot]

This comment was marked as resolved.

Sugar for the common case: build pb.CustomEvent from a JSON-like
payload and emit it, so callers don't have to import Struct +
construct the proto at the call site.

    session.emitCustomEvent('anomaly_detected', { score: 0.92 });

is equivalent to:

    import { Struct } from '@bufbuild/protobuf';
    import { AgentSession as pb } from '@livekit/protocol';

    session.emit(
      AgentSessionEventTypes.CustomEvent,
      new pb.CustomEvent({
        type: 'anomaly_detected',
        payload: Struct.fromJson({ score: 0.92 }),
      }),
    );

The framework layer stays proto-native (SessionHost / RemoteSession
forward pb.CustomEvent as-is); this is purely a call-site
convenience. Mirrors the python `AgentSession.emit_custom_event`
helper.

`tsc --noEmit` clean; lint clean (one pre-existing `any` warning
elsewhere in the file is unchanged).

Co-authored-by: Cursor <cursoragent@cursor.com>
toubatbrian added a commit to livekit/protocol that referenced this pull request May 27, 2026
…1593)

* agent_session: rename CustomEvent -> DebugMessage; drop type field

Renames the agent-session event added in #1588 before any consumer
ships it. Repositioned as an internal debug/trace channel surfaced
only to the debugger/recorder, not to user code -- the `type`
discriminator was unnecessary since callers just emit a free-form JSON
payload.

Wire: AgentSessionEvent.custom_event (field 21) ->
AgentSessionEvent.debug_message (same field number, same type slot).
No schema-compat concerns -- nothing has been built downstream against
this yet (livekit/agents#5855 and livekit/agents-js#1611 are both
still open).

Regenerated Go (.pb.go) with protoc 25.1; JS (@livekit/protocol)
regenerated via `pnpm --filter @livekit/protocol generate:proto`.

Co-authored-by: Cursor <cursoragent@cursor.com>

* generated protobuf

* changeset: patch bump, not minor

Co-authored-by: Cursor <cursoragent@cursor.com>

* drop 'free-form' from DebugMessage docs

Co-authored-by: Cursor <cursoragent@cursor.com>

* generated protobuf

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
…otocol 1.46.4

Picks up livekit/protocol#1593 which renamed the agent-session event
before any consumer shipped it. The message is repositioned as an
internal debug/trace channel surfaced only to the debugger/recorder
(e.g. agents-cli), not to user code.

Proto change (mechanical rename):
- AgentSessionEvent.custom_event -> AgentSessionEvent.debug_message (field 21)
- pb.CustomEvent (string type, Struct payload) -> pb.DebugMessage (Struct payload)

Surface change:
- AgentSession.emitCustomEvent(type, payload) -> AgentSession._emitDebugMessage(payload)
  - underscore prefix + `/* internal */` JSDoc signal: not for user code
  - type discriminator dropped; callers just emit a JSON payload
- AgentSessionEventTypes.CustomEvent -> AgentSessionEventTypes.DebugMessage
- RemoteSessionCallbacks.custom_event -> debug_message
- SessionHost.onCustomEvent -> onDebugMessage
- Dispatch oneof case 'customEvent' -> 'debugMessage'

Bumps `@livekit/protocol` floor `^1.46.3` -> `^1.46.4`.

tsc --noEmit clean; lint clean (only pre-existing test-file `any` warnings).

Co-authored-by: Cursor <cursoragent@cursor.com>
@toubatbrian toubatbrian changed the title feat(voice): add CustomEvent (proto-native, no wrapper) internal(voice): wire DebugMessage over remote-session wire May 27, 2026
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