feat(voice): v0.0.13 — ChatGPT Voice catalog discovery (list_voices) - #31
feat(voice): v0.0.13 — ChatGPT Voice catalog discovery (list_voices)#31robotlearning123 wants to merge 12 commits into
Conversation
Reject a voices list above _MAX_VOICES (128) as contract drift instead of normalizing an unbounded private response, and add tests at and above the bound. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VAbFRELj9M3MYQt7SkUaLG
Document list_voices as the 26th tool across README, docs, skill, and reference; state that catalog discovery is supported while GPT-Live realtime audio, transport, synthesis, and transcript guarantees are not. Add docs/roadmap.md (version lanes, GPT-Live boundary, language policy, release gates) and an install regression asserting the bundled skill allowlists all 26 tools. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VAbFRELj9M3MYQt7SkUaLG
Bump pyproject, package, plugin, and server metadata to 0.0.13 and add the dated CHANGELOG section for the read-only Voice catalog. Release is held (no tag or publish) until 0.0.12 lands on its own lane. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VAbFRELj9M3MYQt7SkUaLG
Forward an optional voice_mode query param (standard/advanced/live/wingman and future modes) to /backend-api/settings/voices; charset-validate it and reject malformed values before any request. Cover mode passthrough, default omission, and rejection offline, and parametrize the opt-in live contract test over the real modes. list_voices(voice_mode="live") targets the GPT-Live catalog. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VAbFRELj9M3MYQt7SkUaLG
📝 WalkthroughWalkthroughAdds a read-only ChangesVoice catalog release
Estimated code review effort: 3 (Moderate) | ~30 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
gpt2agent/tools/voice.py (1)
29-31: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider typing
_fail_contractasNoReturn.The function always raises but is annotated
-> None. UsingNoReturnwould let type checkers narrow types correctly in_bounded_textand_normalize_catalog(e.g., confirmingvalueisstrafter the guard).♻️ Optional refactor
-from typing import Any +from typing import Any, NoReturn -def _fail_contract() -> None: +def _fail_contract() -> NoReturn: """Raise a payload-free error for a private response-shape change.""" raise RuntimeError(_CONTRACT_ERROR)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@gpt2agent/tools/voice.py` around lines 29 - 31, Update the return annotation of _fail_contract from None to NoReturn and ensure NoReturn is imported from the typing module as needed. Leave its existing RuntimeError behavior unchanged so type checkers can narrow guarded values in _bounded_text and _normalize_catalog.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/roadmap.md`:
- Line 22: In the roadmap wording near the Voice product note, replace the
phrase “post-merge main checks” with “post-merge checks on `main`,” preserving
the surrounding text.
In `@docs/superpowers/plans/2026-07-10-v0.0.13-voice-release.md`:
- Around line 65-75: Update the voice-listing contract and implementation around
_normalize_catalog and list_voices to accept an optional voice_mode parameter,
omit it when unset, and URL-encode it in the request query when provided.
Validate supported lowercase mode values and explicitly reject live; add
coverage for omitted mode, supported modes, query encoding, invalid values, and
live.
In `@docs/superpowers/specs/2026-07-10-account-native-feature-coverage-design.md`:
- Around line 258-263: Update the Voice API records to document the implemented
voice_mode contract: identify the accepted modes and explicitly state that live
is rejected. Apply this clarification in the list_voices() section of
docs/superpowers/specs/2026-07-10-account-native-feature-coverage-design.md
(lines 258-263) and the corresponding review conclusions in
docs/superpowers/reviews/2026-07-10-account-native-feature-coverage-cross-model-review.md
(lines 67-76), keeping both descriptions aligned.
---
Nitpick comments:
In `@gpt2agent/tools/voice.py`:
- Around line 29-31: Update the return annotation of _fail_contract from None to
NoReturn and ensure NoReturn is imported from the typing module as needed. Leave
its existing RuntimeError behavior unchanged so type checkers can narrow guarded
values in _bounded_text and _normalize_catalog.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6a900e60-bcd0-4dce-ab4e-9de6416bbc72
📒 Files selected for processing (26)
.claude-plugin/marketplace.json.claude-plugin/plugin.jsonCHANGELOG.mdCLAUDE.mdCONTRIBUTING.mdREADME.mddocs/README.mddocs/faq.mddocs/how-it-works.mddocs/roadmap.mddocs/superpowers/plans/2026-07-10-v0.0.13-voice-release.mddocs/superpowers/reviews/2026-07-10-account-native-feature-coverage-cross-model-review.mddocs/superpowers/specs/2026-07-10-account-native-feature-coverage-design.mdgpt2agent/__init__.pygpt2agent/install.pygpt2agent/skills/gpt2agent/SKILL.mdgpt2agent/skills/gpt2agent/tools-reference.mdgpt2agent/tools/__init__.pygpt2agent/tools/voice.pypyproject.tomlserver.jsontests/test_audit_2026_07_09_tools.pytests/test_backend_tools.pytests/test_install.pytests/test_none_guards.pytests/test_tools.py
|
|
||
| ## The GPT-Live boundary | ||
|
|
||
| Voice is an official ChatGPT product, but the routes this project touches are |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Clarify the main branch gate wording.
Replace “post-merge main checks” with “post-merge checks on main” to avoid ambiguity.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/roadmap.md` at line 22, In the roadmap wording near the Voice product
note, replace the phrase “post-merge main checks” with “post-merge checks on
`main`,” preserving the surrounding text.
Source: Linters/SAST tools
| - [ ] Implement a pure `_normalize_catalog(data)` helper with these rules: | ||
| - require a dict envelope and list-valued `voices`; | ||
| - accept an empty list as an honest empty catalog; | ||
| - require every item to be a dict with printable, non-empty string `voice`, `name`, and `description` fields, bounded to 128, 256, and 2,000 characters respectively; | ||
| - require `preview_url`, when present, to be a string or null; | ||
| - redact display text before returning it; | ||
| - represent missing, mistyped, or catalog-unknown selection as `selected: None`; only a selected ID present in the normalized catalog produces per-item `true/false` values; | ||
| - return only `id`, `name`, `description`, `selected`, and `has_preview`; | ||
| - raise one safe, response-free `RuntimeError` on contract drift. | ||
| - [ ] Implement async `list_voices()` using `async_get(client, "/backend-api/settings/voices", target_path="/backend-api/settings/voices")`. | ||
| - [ ] Decorate it with official MCP annotations: read-only, non-destructive, idempotent, and open-world. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Add voice_mode and explicit live rejection to the implementation contract.
The plan omits the optional voice_mode parameter, its query encoding, and validation tests. The supplied gpt2agent/tools/voice.py implementation accepts generic lowercase tokens, so live must be explicitly rejected to match the PR objective. Add tests for omitted mode, supported modes, URL encoding, invalid values, and live.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/superpowers/plans/2026-07-10-v0.0.13-voice-release.md` around lines 65 -
75, Update the voice-listing contract and implementation around
_normalize_catalog and list_voices to accept an optional voice_mode parameter,
omit it when unset, and URL-encode it in the request query when provided.
Validate supported lowercase mode values and explicitly reject live; add
coverage for omitted mode, supported modes, query encoding, invalid values, and
live.
| #### `list_voices()` | ||
|
|
||
| - Route: `GET /backend-api/settings/voices` | ||
| - Return live voice IDs and display metadata supplied by the account response. | ||
| - Do not hard-code documentation names because voice catalogs can be rollout-specific. | ||
| - This is catalog access only; it does not claim audio streaming or speech synthesis. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Keep the design and review records aligned with the shipped Voice API.
Both records describe catalog-only Voice support but omit the implemented voice_mode input contract.
docs/superpowers/specs/2026-07-10-account-native-feature-coverage-design.md#L258-L263: document accepted modes andliverejection.docs/superpowers/reviews/2026-07-10-account-native-feature-coverage-cross-model-review.md#L67-L76: record the same validation boundary in the review conclusions.
📍 Affects 2 files
docs/superpowers/specs/2026-07-10-account-native-feature-coverage-design.md#L258-L263(this comment)docs/superpowers/reviews/2026-07-10-account-native-feature-coverage-cross-model-review.md#L67-L76
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/superpowers/specs/2026-07-10-account-native-feature-coverage-design.md`
around lines 258 - 263, Update the Voice API records to document the implemented
voice_mode contract: identify the accepted modes and explicitly state that live
is rejected. Apply this clarification in the list_voices() section of
docs/superpowers/specs/2026-07-10-account-native-feature-coverage-design.md
(lines 258-263) and the corresponding review conclusions in
docs/superpowers/reviews/2026-07-10-account-native-feature-coverage-cross-model-review.md
(lines 67-76), keeping both descriptions aligned.
v0.0.13 — ChatGPT Voice catalog discovery
Adds
list_voices, a read-only MCP tool exposing the signed-in account's Voice catalog from the privateGET /backend-api/settings/voicesroute. Brings the server to 26 MCP tools.What's in it
list_voices— bounded, stable per-voice shape (id,name,description,selected,has_preview); backend voice IDs preserved verbatim, display text redacted.list_voices(voice_mode=...)— optional mode-specific catalog (standard/advanced/wingmanaccepted by the live contract on 2026-07-11); charset-validated before any request.voice_mode=liveis rejected by the catalog route (HTTP 422) — GPT-Live is a separate session contract, out of scope here.docs/roadmap.md— version lanes, GPT-Live boundary, language policy (Python core + optional TS sidecar), release gates.Scope guard
Catalog discovery only. Does not start a Voice session, fetch preview media, capture a microphone, synthesize speech, stream GPT-Live audio, or extract transcripts. Malformed responses fail closed (
voice catalog contract changed) rather than pretending the catalog is empty.Verification
pytest: 360 passed, 15 skipped (skips areSKIP_LIVE-gated live/network tests; no credentials configured).ruff check gpt2agent tests scripts: clean (mirrors CI).scripts/verify_release.py:release metadata verified: 0.0.13.Merge ordering
Per the roadmap, this release is held until v0.0.12 (#30) lands. This branch is based on current
mainand is independent of #30's 47 commits — after #30 merges,mainshould be merged in before release so 0.0.12's changes are carried forward.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Chores