feat(voip): per-agent VoIP config panel + persisted voice (abilityai/trinity-enterprise#28)#1323
Merged
Merged
Conversation
…trinity-enterprise#28)
Add the missing per-agent VoIP config UI (agent Settings/Sharing tab) and a
persisted per-agent Gemini voice. Shipped as plain OSS gated on the existing
voip_available platform flag — NOT entitlement-gated (a UI gate over a
money-spending OSS backend would be cosmetic; deliberate simplification of the
issue's original "entitlement-gated" framing).
Backend:
- agent_ownership.voice_name (default Kore) via dual-track migration
(SQLite db/migrations.py + Alembic 0004 + schema.py/tables.py). db
get/set_voice_name with read-path fallback to Kore for unset/invalid values.
- GET/PUT /api/agents/{name}/voice/name (PUT owner-only, validated against
GEMINI_VOICE_NAMES). _get_voice_name and voip_service now read the persisted
voice instead of the two hardcoded "Kore" sites.
- PUT /api/agents/{name}/voip/enabled toggle (owner-only, 404 when no binding);
create_binding upsert no longer forces enabled=1 so re-saving credentials
preserves a disabled state (call path already refuses disabled bindings).
Frontend:
- VoipChannelPanel.vue (modeled on WhatsAppChannelPanel) mounted in SharingPanel
under voip_available; shared src/constants/voices.js (drift-guarded vs backend);
AgentWorkspace picker defaults to the persisted voice; sessions store surfaces
voip_available.
Tests: tests/unit/test_28_voip_voice_config.py — voice fallback/roundtrip/
invalid->default, enable toggle + re-PUT-preserves-disabled (H3), and the
frontend/backend voice-list drift guard. Schema-parity + voip-db guards green.
Refs abilityai/trinity-enterprise#28
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#28 review I1) Pre-landing /review flagged that the new endpoints were covered only at the DB layer. Add FastAPI TestClient tests (mount real routers, override auth deps, stub db/voip_service) asserting: - PUT /voice/name: owner-gated (403), 400 on unknown voice, empty clears to default, valid voice persists; GET returns voice_name + available_voices. - PUT /voip/enabled: owner-gated (403), 404 when no binding / when voip flag off, 200 reflecting state with no auth_token leaked. Also capture a durable learning (docs/memory/learnings.md): the schema-parity test is blind to db/tables.py drift — a missing Column there passes parity but breaks at runtime; guard it with a db-accessor unit test that executes a live select on the new column. Refs abilityai/trinity-enterprise#28 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Resolve by running |
AndriiPasternak31
approved these changes
Jun 24, 2026
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
GET/PUT/DELETE /api/agents/{name}/voipendpoints — no new binding CRUD.agent_ownership.voice_name, defaultKore), replacing two hardcoded"Kore"sites; applies to the voice overlay/workspace and outbound VoIP calls.voip_availableplatform flag — not entitlement-gated. The issue's original "entitlement-gated" framing was deliberately dropped: a UI gate over a money-spending OSS backend would be cosmetic, and both autoplan reviewers flagged it. (Notrinity-enterprisesubmodule change; one public PR.)Changes
Backend
agent_ownership.voice_name— dual-track migration: SQLitedb/migrations.py+ Alembic0004_agent_ownership_voice_name+db/schema.py/db/tables.py.db.get/set_voice_namewith read-path fallback toKorefor unset/invalid values.GET/PUT /api/agents/{name}/voice/name(PUT owner-only, validated vsGEMINI_VOICE_NAMES).routers/voice.py::_get_voice_name+services/voip_service.pynow read the persisted voice.PUT /api/agents/{name}/voip/enabledtoggle (owner-only, 404 when no binding).create_bindingupsert no longer forcesenabled=1, so re-saving credentials preserves a disabled state (call path already refuses disabled bindings).Frontend
components/VoipChannelPanel.vue(modeled onWhatsAppChannelPanel.vue), mounted inSharingPanel.vueunderv-if="sessionsStore.voipAvailable";stores/sessions.jssurfacesvoip_available.src/constants/voices.js(drift-guarded against the backend list);AgentWorkspace.vuepicker defaults to the persisted voice.Docs/tests:
architecture.md,requirements.md§39.2, feature-flows (voip-telephony.md,voice-chat.md);tests/unit/test_28_voip_voice_config.py.Test Plan
cd tests && python -m pytest unit/test_28_voip_voice_config.py -vtest_schema_parity.py,test_voip_db.py,test_migrations*.py,test_1076_voice_model_config.py,test_1069/1073_voip*(64 tests total)/voice/name,/voip/enabled)Refs abilityai/trinity-enterprise#28
🤖 Generated with Claude Code