fix(core): flip text content fields#2013
Open
rosetta-livekit-bot[bot] wants to merge 3 commits into
Open
Conversation
🦋 Changeset detectedLatest commit: 87819ed The changes in this PR will be included in the next version bump. This PR includes changesets to release 36 packages
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 |
Remove unmatched expressive delimiters so malformed model output cannot leak into user-facing text, and lock in raw-content diff behavior. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ports livekit/agents#6353 to agents-js: assistant
textContentstrips only LiveKit<expr/>markup, while provider/runtime paths userawTextContentso model-facing expressive markup is preserved. The follow-up repair also strips unmatched opening and closing<expr>delimiters independently, matching Python's current_split_exprbehavior for malformed model output.Source diff coverage
Coverage classification
livekit-agents/livekit/agents/llm/_provider_format/anthropic.py- ported toplugins/anthropic/src/llm.ts; Anthropic context building usesrawTextContent.livekit-agents/livekit/agents/llm/_provider_format/aws.py- not applicable; agents-js has no AWS provider-format counterpart.livekit-agents/livekit/agents/llm/_provider_format/google.py- ported toagents/src/llm/provider_format/google.ts; system messages userawTextContent.livekit-agents/livekit/agents/llm/_provider_format/utils.py- ported toagents/src/llm/provider_format/utils.ts; mid-conversation instructions preserve raw instruction text.livekit-agents/livekit/agents/llm/chat_context.py- adapted toagents/src/llm/chat_context.tsandagents/src/tts/provider_format.ts; addedrawTextContent, made assistanttextContentstrip only<expr/>, addedstripMarkupJSON handling, and ported expr-only stripping without pulling in Python's full provider-format parser.livekit-agents/livekit/agents/llm/utils.py- adapted toagents/src/llm/utils.ts; changed same-ID raw message text is represented as remove/create because agents-js has no Python-styleto_updateoperation.livekit-agents/livekit/agents/telemetry/traces.py- adapted/no code change; agents-js telemetry already iterates raw message content.livekit-agents/livekit/agents/tts/_provider_format.py- adapted toagents/src/tts/provider_format.ts; paired, self-closing, and independent unmatched expr delimiters are removed while provider-native markup remains untouched.livekit-agents/livekit/agents/voice/agent_activity.py- ported toagents/src/voice/agent_activity.ts; realtime reply input, preemptive transcript comparison, and user-input tracing userawTextContent.livekit-agents/livekit/agents/voice/agent_session.py- not applicable; the exact Python debug logging path does not exist in agents-js.livekit-agents/livekit/agents/voice/remote_session.py- adapted/no code change; agents-js remote session serialization already transports raw message content.textContent, matching Python's new behavior.tests/test_expr_markup.py- ported toagents/src/llm/chat_context.test.ts; tests cover expr-only stripping, assistant/non-assistant accessors, undefined text, JSON stripping, malformed delimiters, and stream-assembled markers.agents/src/llm/utils.test.tscovers same-IDrawTextContentchanges.Release decision
Keep the existing core
minorchangeset: this intentionally changes the documented public meaning ofChatMessage.textContentand addsrawTextContent. Anthropic and Phonic only adapt internal provider call sites, so their entries remainpatch.Verification
Exact head:
87819ed41c1842adcd70b4d615c36a948b58c2e9.pnpm test agents/src/llm/chat_context.test.ts agents/src/llm/utils.test.ts- passed: 2 files, 122 tests.pnpm build:agents- passed.pnpm build- passed.pnpm typecheck- passed.pnpm lint- passed.pnpm format:check- passed.git diff --check- passed.Known unrelated local blockers:
pnpm api:checkreaches unrelatedplugins/liveavatar, whose package definesapi:checkwithout anapi-extractor.json. Scoped core extraction is separately blocked by API Extractor 7.43.7 rejecting generated TypeScript 5.9export * asdeclarations.pnpm testruns credentialed provider suites in this environment: 1627 tests passed, while external/provider cases failed (including Baseten model 404 responses and unsupported Baseten STTrecognize). The focused core suites above pass.Cue voice E2E
sid_9e17ea494cd9.87819ed41c1842adcd70b4d615c36a948b58c2e9.Alpha <expr type="break" label="1s"/> bravo.debug_message(.payload.kind="expr_text_clean",.payload.text="Alpha bravo").waitForPlayout()), exit code 0. Persisted events contained no literal<expr>markup.c99f191e569f8be77534970dd741eb77764139c0ea6e801db0b790c3fb8f89a4.82d5bf3e6ccfb39b9824428fe61147fa89377c0d1c466f567085d1352c4de4bb.Alpha Bravo.No markup was spoken.cartesia/sonic-3TTS; Whisper was used only to inspect the persisted WAVs.conversation_item_addedintentionally carries raw content in both Python and JS, so the clean-text assertion used a path-specific debug event derived fromChatMessage.textContent; chat insertion was disabled to avoid conflating raw transport with user-facing cleaned text. Artifacts are persisted locally under~/.cue-cli/sessions/sid_9e17ea494cd9/and are identified above by cryptographic hash.Ported from livekit/agents#6353
Original PR description
Before:
text_contentraw content, with expressive tags and bracket tags;plain_text_contentclean content, without any tags;Now:
text_contentclean content, without any expressive-only tagsexprraw_text_contentraw content withexprtags