Skip to content

feat(voice): preserve context across sequential turns - #9412

Open
sandl99 wants to merge 3 commits into
mainfrom
feat/9411-voice-conversation-context
Open

feat(voice): preserve context across sequential turns#9412
sandl99 wants to merge 3 commits into
mainfrom
feat/9411-voice-conversation-context

Conversation

@sandl99

@sandl99 sandl99 commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

Voice Gateway admissions now derive an internal OpenClaw session key from the configured agent, runtime profile, runtime identity, and validated runtimeConversationId. Sequential one-turn admissions for one voice call reuse OpenClaw context, while a new conversation or configured binding receives a separate context.

Related Issue

Fixes #9411

Changes

  • Replace the random per-admission OpenClaw session key with a SHA-256 digest of the validated runtime binding inside the nemoclaw-voice namespace.
  • Add source tests for deterministic reuse, binding isolation, and omission of the raw conversation ID from the derived key.
  • Add HTTP integration tests that reject malformed, oversized, and runtime-supplied session-key input before OpenClaw client creation.
  • Extend the pinned OpenClaw fixture to prove context reuse across two separate admissions and context isolation for a new voice call.
  • Keep the existing one-turn admission, timeout, duplicate-turn, active-turn, and redaction behavior. Session close or expiry still removes the grant and closes the client.
  • Keep the gateway experimental. A real VoiceClaw/WebRTC two-question run and new-call isolation check remain external evidence before this draft can become approval-ready.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging)
  • Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: Pending independent review; this PR is a draft.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

DGX Station Hardware Evidence

  • Tested on DGX Station
  • Tested commit:
  • Station profile/scenario:
  • Result:
  • Supporting evidence:

Verification

  • PR description includes a Signed-off-by: line and every commit appears as Verified in GitHub
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run validate:pr passed after refreshing origin/main when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — npx vitest run --project cli --project integration src/lib/voice-gateway/session-service.test.ts test/voice-gateway-integration.test.ts passed 2 files and 17 tests.
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — Not run; the change is limited to one service and its focused integration fixture.
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: San Dang sdang@nvidia.com

Summary by CodeRabbit

  • New Features

    • Voice sessions now consistently retain agent context across admissions within the same runtime conversation.
    • Context remains isolated when conversations, identities, profiles, or agents differ.
  • Bug Fixes

    • Improved session continuity by using stable session keys instead of newly generated identifiers.
    • Strengthened admission validation to reject invalid conversation IDs, namespace escapes, unauthorized session-key selection, and runtime authority overrides.
    • Prevented duplicate commits and repeated final responses during voice interactions.

@sandl99 sandl99 self-assigned this Aug 18, 2026
@copy-pr-bot

copy-pr-bot Bot commented Aug 18, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 88fd01ed-27da-4b7a-ae8a-c2a3e969ab0b

📥 Commits

Reviewing files that changed from the base of the PR and between 7d516f2 and 2ebe3c8.

📒 Files selected for processing (4)
  • src/lib/voice-gateway/session-service.test.ts
  • src/lib/voice-gateway/session-service.ts
  • test/fixtures/voice-gateway/pinned-openclaw-gateway.ts
  • test/voice-gateway-integration.test.ts

Included review availability: Your plan includes up to 12 reviews per rolling hour; 11 remain after this review.


📝 Walkthrough

Walkthrough

Voice Gateway session keys are now deterministically derived from trusted runtime bindings. Tests verify key reuse, isolation, context continuity across admissions, internal key hiding, and rejection of invalid caller-controlled values.

Changes

Voice session context

Layer / File(s) Summary
Deterministic session-key derivation
src/lib/voice-gateway/session-service.ts, src/lib/voice-gateway/session-service.test.ts
VoiceSessionService derives agent session keys with SHA-256 from the agent, runtime profile, runtime identity, and runtime conversation ID. Unit tests verify reuse and isolation.
Context-aware gateway fixture
test/fixtures/voice-gateway/pinned-openclaw-gateway.ts
PinnedOpenClawGateway accepts conversation context and emits a context-aware final turn when context is configured.
Integration validation
test/voice-gateway-integration.test.ts
Integration tests verify context continuity, isolated conversations, hidden internal keys, updated ID sequences, and rejection of invalid or runtime-selected values.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: ⚪ Minimal · up to 2ebe3

The change preserves voice-call context across sequential turns while isolating new conversations; no actionable merge-blocking risk remains beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant VoiceRuntime
  participant VoiceSessionService
  participant PinnedOpenClawGateway
  participant OpenClaw
  VoiceRuntime->>VoiceSessionService: Submit runtime conversation and trusted binding
  VoiceSessionService->>VoiceSessionService: Derive internal session key
  VoiceSessionService->>PinnedOpenClawGateway: Admit turn with derived key
  PinnedOpenClawGateway->>OpenClaw: Send turn with session key
  OpenClaw-->>PinnedOpenClawGateway: Return contextual response
  PinnedOpenClawGateway-->>VoiceRuntime: Return assistant response
Loading

Suggested reviewers: brandonpelfrey

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The implementation meets the coding objectives, but the required composed two-question VoiceClaw test remains outstanding. Add and pass the composed VoiceClaw/WebRTC test that proves two sequential questions share context and a new call receives isolated context.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: preserving context across sequential voice turns.
Out of Scope Changes check ✅ Passed The changes support deterministic session keys, admission validation, and context-preservation tests without adding unrelated functionality.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/9411-voice-conversation-context

Comment @coderabbitai help to get the list of available commands.

@github-code-quality

github-code-quality Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit 2ebe3c8 in the feat/9411-voice-conv... branch remains at 96%, unchanged from commit 7d516f2 in the main branch.


Updated August 18, 2026 06:27 UTC

@jyaunches jyaunches 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.

LOC Reduction / Codebase Simplicity Review

Why this blocks

test/voice-gateway-integration.test.ts:362-433 adds two standalone admission-rejection tests. Each recreates the same VoiceSessionService, clientsCreated counter, HTTP server, and listener setup at lines 364-379 and 403-418. The existing authority-boundary test immediately below already owns that setup at lines 435-454 and already proves that caller-selected admission fields are rejected before createClient.

The two new tests total 71 lines even though their distinct behavior is only three request bodies and their expected invalid_request responses.

Refactor direction

Fold the malformed conversation ID, oversized conversation ID, and caller-supplied sessionKey bodies into the existing admission-authority test, preferably as one small table. Reuse its single service and server, assert each exact 400 response, then keep one clientsCreated === 0 assertion before the existing valid admission.

Keep the composed context-reuse test and pinned OpenClaw context fixture; they cover distinct #9411 behavior and do not need another abstraction.

Expected result

All three rejection cases still prove fail-before-client behavior, while the duplicated setup disappears. This should remove roughly 40 lines from the +155/-3 integration-test change and leave one test owner for the HTTP admission authority boundary.

@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Blocking findings reported

Advisor assessment: Blockers require maintainer review
Next action: Review the blockers below.
Findings: 1 blocker · 0 warnings · 0 suggestions

Model lanes

  • GPT-5.6 Terra (primary): Completed · medium confidence · 1 blocker · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Model comparison: normalized findings differ; normalized terminology decisions differ; normalized E2E selections match; Nemotron reported 1 fewer blocker, the same number of warnings, the same number of suggestions.
5 terminology differences from the second opinion

Advisory only. These are normalized differences from the primary terminology receipt.

  • agent session key at src/lib/voice-gateway/session-service.test.ts:77: primary classified it as justified; the second opinion classified it as define.
  • runtime binding at src/lib/voice-gateway/session-service.test.ts:77: primary classified it as define; the second opinion classified it as conflict.
  • runtime conversation at src/lib/voice-gateway/session-service.test.ts:100: selected only by the second-opinion lane as established.
  • runtimeConversationId at src/lib/voice-gateway/session-service.ts:71: selected only by the second-opinion lane as established.
  • voice call at test/voice-gateway-integration.test.ts:342: selected only by the second-opinion lane as conflict.

Second-opinion terminology and E2E selections are advisory. Live E2E does not run automatically for pull requests.

2 semantic terminology decisions

Terminology decisions are advisory. They affect the assessment only when a separate finding identifies concrete semantic impact.

  • define — runtime binding at src/lib/voice-gateway/session-service.test.ts:77: Define the tuple fields in the test title or use "agent session-key binding" consistently.
  • justified — agent session key at src/lib/voice-gateway/session-service.test.ts:77: Keep "agent session key" for this internal OpenClaw context identifier.

E2E guidance

Advisory only. A maintainer can dispatch the default E2E suite for the commit under review.

Recommended E2E: None

Blockers

PRA-1 Blocker — Bind the sandbox to the persistent agent session key

  • Location: src/lib/voice-gateway/session-service.ts:69
  • Category: scope
  • Problem: The derived OpenClaw session key omits the trusted sandbox binding.
  • Impact: Two gateway launches with equal agent, runtime profile, runtime identity, and conversation ID but different sandboxes can share OpenClaw conversation context.
  • Fix: Include options.sandbox in the serialized binding that deriveAgentSessionKey hashes.
  • Verification: Compare derived keys from two VoiceSessionService instances that differ only in sandbox.
  • Test coverage: Create sessions with bindings that differ only in sandbox and assert that the OpenClaw session keys differ.
  • Simplification (shrink): Remove The incomplete binding tuple.; use Hash one tuple that includes sandbox with the existing trusted binding fields.. Net: 1 lines.
  • Keep: Keep all trusted runtime fields that partition OpenClaw context in the tuple.
  • Evidence: src/lib/voice-gateway/session-service.ts:69-80 derives the key without options.sandbox. src/lib/voice-gateway/launcher.ts:14-22 and 58-65 define sandbox as a fixed trusted launch field. src/lib/voice-gateway/session-service.test.ts:160-199 verifies isolation for agent, runtime profile, runtime identity, and conversation, but not sandbox.

Workflow run details

This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge.

@sandl99

sandl99 commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed in 525218e.

  • Consolidated the malformed ID, oversized ID, caller-supplied sessionKey, and runtime authority override cases into the existing admission-authority test.
  • Reused one service, server, and client counter. A named helper sends the request table outside the test callback to comply with the repository growth guardrail.
  • Kept one clientsCreated === 0 assertion before the valid admission.
  • Reduced the review-response commit to 26 additions and 82 deletions.

Validation:

  • npx vitest run --project cli --project integration src/lib/voice-gateway/session-service.test.ts test/voice-gateway-integration.test.ts — 2 files and 17 tests passed.
  • npx vitest run --project integration test/growth-guardrails.test.ts — 25 tests passed.
  • Normal pre-commit, commit-msg, and pre-push hooks passed.

@sandl99
sandl99 marked this pull request as ready for review August 18, 2026 06:26
@sandl99 sandl99 added v0.0.111 Release target voiceclaw labels Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v0.0.111 Release target voiceclaw

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Voice Gateway: preserve OpenClaw context across sequential turns

2 participants