Skip to content

feat(protoface): add avatar plugin#1876

Open
rosetta-livekit-bot[bot] wants to merge 1 commit into
mainfrom
shame-knack-disjoint
Open

feat(protoface): add avatar plugin#1876
rosetta-livekit-bot[bot] wants to merge 1 commit into
mainfrom
shame-knack-disjoint

Conversation

@rosetta-livekit-bot

@rosetta-livekit-bot rosetta-livekit-bot Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add a new @livekit/agents-plugin-protoface avatar plugin ported from feat: add Protoface avatar plugin agents#6164
  • support Protoface session start/end APIs, LiveKit worker token minting, and DataStream audio output
  • add a Protoface avatar example and changeset

Testing

  • pnpm --filter @livekit/agents build
  • pnpm --filter @livekit/agents-plugin-protoface lint
  • pnpm --filter @livekit/agents-plugin-protoface build
  • pnpm --filter @livekit/agents-plugin-protoface api:update
  • pnpm --filter @livekit/agents-plugin-protoface api:check

Note: pnpm --filter livekit-agents-examples build is currently blocked by pre-existing unbuilt workspace plugin declaration outputs; it also caught and I fixed the new Protoface example option name.


Ported from livekit/agents#6164

Original PR description

Docs
Public demo

@changeset-bot

changeset-bot Bot commented Jun 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e6d4664

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

This PR includes changesets to release 36 packages
Name Type
@livekit/agents-plugin-protoface Patch
@livekit/agents Patch
@livekit/agents-plugin-anam Patch
@livekit/agents-plugin-assemblyai Patch
@livekit/agents-plugin-baseten Patch
@livekit/agents-plugin-bey Patch
@livekit/agents-plugin-cartesia Patch
@livekit/agents-plugin-cerebras Patch
@livekit/agents-plugin-deepgram Patch
@livekit/agents-plugin-did Patch
@livekit/agents-plugin-elevenlabs Patch
@livekit/agents-plugin-fishaudio Patch
@livekit/agents-plugin-google Patch
@livekit/agents-plugin-hedra Patch
@livekit/agents-plugin-hume Patch
@livekit/agents-plugin-inworld Patch
@livekit/agents-plugin-lemonslice Patch
@livekit/agents-plugin-liveavatar Patch
@livekit/agents-plugin-livekit Patch
@livekit/agents-plugin-minimax Patch
@livekit/agents-plugin-mistral Patch
@livekit/agents-plugin-mistralai Patch
@livekit/agents-plugin-neuphonic Patch
@livekit/agents-plugin-openai Patch
@livekit/agents-plugin-perplexity Patch
@livekit/agents-plugin-phonic Patch
@livekit/agents-plugin-resemble Patch
@livekit/agents-plugin-rime Patch
@livekit/agents-plugin-runway Patch
@livekit/agents-plugin-sarvam Patch
@livekit/agents-plugin-silero Patch
@livekit/agents-plugin-soniox Patch
@livekit/agents-plugin-tavus Patch
@livekit/agents-plugin-trugen Patch
@livekit/agents-plugin-xai Patch
@livekit/agents-plugins-test Patch

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

Comment on lines +68 to +71
this.apiUrl = (options.apiUrl ?? process.env.PROTOFACE_API_URL ?? DEFAULT_API_URL).replace(
/\/+$/,
'',
);

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Devin Review found 2 potential issues.

View 1 additional finding in Devin Review.

Open in Devin Review

/** Protoface API key. Falls back to the `PROTOFACE_API_KEY` env var. */
apiKey?: string | null;
/** Optional maximum session duration. Protoface applies the lower of this and the plan limit. */
maxDurationSeconds?: number | null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Time-based parameter maxDurationSeconds violates CLAUDE.md naming convention

The CLAUDE.md convention explicitly states: "Use milliseconds for all time-based values by default. Only use seconds when the name explicitly ends with InS." The maxDurationSeconds field name uses seconds but ends with Seconds instead of InS. This appears in both plugins/protoface/src/avatar.ts:34 (the AvatarSessionOptions interface) and plugins/protoface/src/api.ts:41 (the StartSessionOptions interface), as well as the class field at plugins/protoface/src/avatar.ts:61. Per the convention, this should either be stored as milliseconds (e.g., maxDurationMs) with conversion at the API boundary, or named with the InS suffix (e.g., maxDurationInS).

Prompt for agents
The CLAUDE.md convention requires all time-based values to use milliseconds by default, with the InS suffix being the only exception for seconds. The maxDurationSeconds field appears in AvatarSessionOptions (avatar.ts:34), the AvatarSession class field (avatar.ts:61), StartSessionOptions (api.ts:41), and usages in avatar.ts:72,126 and api.ts:80-81. Either rename to maxDurationInS across both files (keeping seconds, matching the InS convention), or rename to maxDurationMs (using milliseconds) and convert to seconds at the API call site in api.ts startSession() where it sets body.max_duration_seconds.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +173 to +178
try {
const jobCtx = getJobContext();
localParticipantIdentity = jobCtx.agent?.identity || '';
} catch {
// Fall back to the connected room below when no job context is available.
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚩 Protoface uses jobCtx.agent?.identity while Bey/Trugen use jobCtx.job.participant?.identity for publish-on-behalf

In mintWorkerToken, the Protoface plugin resolves the local participant identity via jobCtx.agent?.identity (plugins/protoface/src/avatar.ts:175), which is room.localParticipant — the agent's own identity. In contrast, Bey (plugins/bey/src/avatar.ts:175) and Trugen (plugins/trugen/src/avatar.ts:140) use jobCtx.job.participant?.identity, which is the remote human participant who triggered the job. For the lk.publish_on_behalf attribute, the avatar should publish on behalf of the local agent, so the Protoface approach appears semantically more correct. However, this inconsistency between plugins is worth noting — the older plugins may have a latent bug.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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