Skip to content

fix(sessions): expose turn detection and barge-in configuration across SDKs - #1056

Merged
santoshkumarradha merged 2 commits into
Agent-Field:mainfrom
FriendlyPasser:fix/session-turn-detection-663
Sep 15, 2026
Merged

santoshkumarradha merged 2 commits into
Agent-Field:mainfrom
FriendlyPasser:fix/session-turn-detection-663

Conversation

@FriendlyPasser

@FriendlyPasser FriendlyPasser commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Session authors cannot currently configure voice turn detection or interruption, and the stateless WebRTC offer endpoint does not resolve the registered session configuration. This PR adds validated turn_detection options to the Python, TypeScript, and Go SDKs and forwards them to OpenAI under session.audio.input.turn_detection, with interruptible server VAD enabled by default.

  • Support server_vad thresholds/padding/silence duration and semantic_vad eagerness, plus create_response and interrupt_response; preserve explicit false and 0.
  • Reject unsupported provider/transport combinations, incompatible mode-specific fields, unknown fields, and invalid values before contacting the provider.
  • Include the registered target in the returned offer_url, re-read and validate its configuration at offer time, and add CLI session offer --target <node>.<session> support. Legacy direct offers retain default VAD behavior; clients building URLs themselves must include the target to use registered settings.
  • Add cross-SDK usage documentation and regression tests. This does not add a WebSocket connection adapter or change the session database schema.

Type of change

  • Bug fix
  • New feature
  • Breaking change

Test plan

Passed locally:

  • Python: python -m pytest tests/test_agent_session.py tests/test_session_transport.py -o addopts='' -q — 25 tests.
  • TypeScript: npm test -- tests/session_turn_detection.test.ts tests/session_transport.test.ts tests/agent.test.ts — 31 tests.
  • TypeScript: npm run lint and npm run build.
  • Go SDK: go test ./agent -run 'Session|TurnDetection' -count=1 — 9 top-level tests.
  • Control plane: go test ./pkg/types ./internal/handlers ./internal/cli -run 'Session|TurnDetection' -count=1 — 41 top-level tests, including table-driven subtests.
  • git diff --check.

The new control-plane regression tests failed before the handler fix: invalid configurations were accepted and the start response omitted turn detection. They now exercise registration metadata → start → SDP offer → the actual multipart request sent to a mocked OpenAI endpoint, including defaults, explicit false/zero values, semantic VAD, and model/voice resolution.

Not tested: real OpenAI Realtime calls or microphone-based voice conversations. The test environment has no configured OPENAI_API_KEY, so we did not have the credentials needed to perform live voice testing. Actual speech detection, interruption/barge-in behavior, audio quality, and latency remain unverified against the live service. Automated request validation is not a substitute for those checks.

Test coverage

  • I ran tests for the surfaces changed locally.
  • New configuration and forwarding paths have regression tests.
  • The repository-wide coverage and patch-coverage gates are green in CI for 998dba0.

After the initial CI patch-coverage failure (75% for the control plane), commit 998dba0 adds direct parser contract tests and invalid-target handler tests. Using the same gocover-cobertura / diff-cover approach as CI, the local control-plane patch report now covers 156/156 changed lines (100%); the subsequent CI run also passed with 100% control-plane patch coverage.

Coverage baselines have not been changed. The full repository-wide coverage suite was not run locally.

Checklist

  • I have read docs/DEVELOPMENT.md (CONTRIBUTING.md is not present).
  • Commit follows conventional-commits style and includes a sign-off.
  • Commit is cryptographically signed.
  • Related issue is linked below.

Related issues / PRs

Fixes #663

Signed-off-by: WANG Qingmin <75425799+FriendlyPasser@users.noreply.github.com>
@github-actions

github-actions Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Performance

SDK Memory Δ Latency Δ Tests Status
Python 9.0 KB - 0.36 µs +3%
Go 248 B -11% 0.66 µs -34%
TS 506 B +45% 1.48 µs -26%

Regression detected:

  • TypeScript memory: 350 B → 506 B (+45%)

@github-actions

Copy link
Copy Markdown
Contributor

📊 Coverage gate

Thresholds from .coverage-gate.toml: per-surface ≥ 84%, aggregate ≥ 85%, max per-surface regression ≤ 1.0 pp, max aggregate regression ≤ 0.50 pp.

Surface Current Baseline Δ
control-plane 87.80% 87.40% ↑ +0.40 pp 🟡
sdk-go 93.20% 92.00% ↑ +1.20 pp 🟢
sdk-python 94.72% 93.73% ↑ +0.99 pp 🟢
sdk-typescript 91.76% 90.42% ↑ +1.34 pp 🟢
web-ui 84.77% 84.79% ↓ -0.02 pp 🟡
aggregate 85.89% 85.75% ↑ +0.14 pp 🟡

✅ Gate passed

No surface regressed past the allowed threshold and the aggregate stayed above the floor.

@github-actions

github-actions Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

📐 Patch coverage gate

Threshold: 80% on lines this PR touches vs origin/main (from .coverage-gate.toml:thresholds.min_patch).

Surface Touched lines Patch coverage Status
control-plane 156 100.00%
sdk-go 61 100.00%
sdk-python 0 ➖ no changes
sdk-typescript 29 100.00%
web-ui 0 ➖ no changes

✅ Patch gate passed

Every surface whose lines were touched by this PR has patch coverage at or above the threshold.

Signed-off-by: WANG Qingmin <75425799+FriendlyPasser@users.noreply.github.com>
@FriendlyPasser
FriendlyPasser marked this pull request as ready for review September 14, 2026 11:10
@FriendlyPasser
FriendlyPasser requested review from a team and AbirAbbas as code owners September 14, 2026 11:10

@santoshkumarradha santoshkumarradha left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks good. I checked the turn-detection contract across the control plane and all three SDKs, including explicit false and zero values, semantic VAD, target resolution at offer time, and the OpenAI Realtime payload shape. The focused Go, Python, and TypeScript tests pass locally, along with TypeScript lint and build, and the required CI and CLA checks are green.

@santoshkumarradha
santoshkumarradha added this pull request to the merge queue Sep 15, 2026
Merged via the queue into Agent-Field:main with commit 9e69229 Sep 15, 2026
49 checks passed
7vignesh added a commit to 7vignesh/agentfield that referenced this pull request Sep 15, 2026
session_turn_detection.py landed on main (via Agent-Field#1056) after this PR
opened and carries 3 mypy errors (loosely-typed dict value used in
numeric comparisons at line 58). The mypy gate correctly failed on it
because it was not allowlisted - the ratchet working as designed.

Add it to the allowlist to keep this PR a pure CI-wiring change; the
module's type errors can be cleaned in a follow-up (phase 2).
AbirAbbas pushed a commit that referenced this pull request Sep 18, 2026
…971) (#1052)

* ci(python-sdk): enforce mypy with module-by-module allowlist ratchet

Adopts the mypy half of #620 (the ruff half shipped in #812). mypy.ini
existed but nothing ran it. This wires a required mypy step into the
Python SDK CI without changing any behavior.

Phase 1 of #971:
- Pin mypy==1.18.2 in the dev extras (and uv.lock).
- Add a per-module ignore_errors allowlist to mypy.ini for the 34
  modules that currently have type errors, so the gate can be enforced
  now and the allowlist shrunk module by module.
- Add a 'Type check (mypy)' step to .github/workflows/sdk-python.yml
  running 'mypy --config-file mypy.ini agentfield/'.

The gate is green today (Success: no issues found). It fails if a
non-allowlisted module gains a new error, or if a module is removed
from the allowlist while it still has errors. No '# type: ignore'
sprinkles were added.

* ci(python-sdk): pin types-requests so mypy gate is reproducible

Addresses review on #1052. The locked dev environment pins
requests 2.33.1, which ships no type stubs, so 'uv sync --extra dev'
followed by mypy failed with [import-untyped] in multimodal.py and
agent_field_handler.py. CI was green only because 'pip install .[dev]'
resolved a newer requests that bundles stubs, so it wasn't validating
the reproducible environment.

Pin types-requests==2.33.0.20260906 in the dev extras (and uv.lock) so
mypy passes in both the locked (uv sync) and pip-resolved environments.
Verified mypy clean against the locked requests 2.33.1 and a newer
requests; ruff still clean; uv lock --check clean.

* ci(python-sdk): allowlist session_turn_detection for mypy ratchet

session_turn_detection.py landed on main (via #1056) after this PR
opened and carries 3 mypy errors (loosely-typed dict value used in
numeric comparisons at line 58). The mypy gate correctly failed on it
because it was not allowlisted - the ratchet working as designed.

Add it to the allowlist to keep this PR a pure CI-wiring change; the
module's type errors can be cleaned in a follow-up (phase 2).
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.

Sessions: expose turn-detection / server-VAD / barge-in config in @app.session

2 participants