Skip to content

feat(voice): configurable ElevenLabs max conversation duration - #230

Closed
heavygee wants to merge 5 commits into
mainfrom
feat/elevenlabs-max-duration
Closed

heavygee wants to merge 5 commits into
mainfrom
feat/elevenlabs-max-duration

Conversation

@heavygee

@heavygee heavygee commented Oct 8, 2026

Copy link
Copy Markdown
Owner

Fixes #229.

Auto-created ConvAI agents never set conversation.max_duration_seconds, so ElevenLabs applied its 600s default and cut conversations off.

  • New ELEVENLABS_MAX_DURATION_SECONDS, default 1800 (bounds the cost of a dead-open conversation; not the 7200 ceiling). Validated 60-7200; invalid values fail the token request with a clear message.
  • Applied at agent creation; reconciled onto existing hub-managed agents (found by name) once per process. Operator-supplied agents keep their own cap.
  • Tests assert the create payload carries the default and the configured value, plus PATCH reconciliation and rejection.
  • Verified live: created a temp agent via the payload (1800), drifted to 600, reconciled via the hub's PATCH body (1800, prompt/voice preserved), deleted it. API itself returns 400 on 7201.
  • Not done: friendlier agent names (needs a voice-name lookup).

🤖 Generated with Claude Code

Auto-created ConvAI agents never set conversation.max_duration_seconds, so
ElevenLabs applied its 600s default and cut voice conversations off.

Add ELEVENLABS_MAX_DURATION_SECONDS (default 1800, validated 60-7200). The cap
is applied when the hub creates an agent and reconciled onto existing
hub-managed agents (found by name) once per process. Operator-supplied agents
(ELEVENLABS_AGENT_ID / voice map / customAgentId) keep their own cap. Invalid
values fail the token request with a clear message instead of an API 422.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-12T17:58:33.171019Z 89e3b5c New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Extend the hub-owner credentials panel (Settings -> Voice -> manage
providers) with a numeric field for ELEVENLABS_MAX_DURATION_SECONDS,
reusing the same env-wins-over-Settings overlay that already backs the
ElevenLabs API key field. A Settings save takes effect on the very next
token request in the same process; the env var still requires a restart.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@heavygee

Copy link
Copy Markdown
Owner Author

Added the Settings UI on top of the env var, per operator request: Settings → Voice → manage providers (hub owner only) now has a "max conversation length" field under the ElevenLabs entry.

  • Backed by the same providerCredentials.ts overlay that already serves the ElevenLabs API key field: env wins and locks the field; otherwise a plain (unmasked — not a secret) value persisted to settings.json, held in the in-memory overlay, so a Settings save takes effect on the very next token request with no hub restart.
  • Client- and server-side range validation (60-7200), 400 on invalid, 409 if env-locked.
  • New hub tests cover default status, persist, reset-to-default, range rejection, env-lock conflict, and an end-to-end test proving a Settings PUT changes the very next token request's agent-creation payload in the same process.
  • Translated into en/zh-CN/ru.
  • Full suite: hub 1386 pass / 2 pre-existing unrelated failures (ambient FCM_SERVICE_ACCOUNT_PATH/Overseer env vars on this box affecting serverSettings.test.ts and titleSuggestion.test.ts, neither file touched by this change), shared 327 pass, web 3340 pass.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d23172d07c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hub/src/web/routes/voice.ts
…r process

Codex review on #230 caught this: getOrCreateAgentIdForVoice's
agentIdCache short-circuited before ever reaching ensureAgentOverrides, and
ensureAgentOverrides's overridesEnsuredAgents gate was a one-time-forever
marker that didn't account for the configured duration changing after the
first reconciliation. Together, any voice already used once in the hub
process would keep its old cap until a restart, contradicting the Settings
UI's 'takes effect immediately' claim.

Track the last-applied max duration per agent and compare it against the
live setting on every call, including agentIdCache hits, so a Settings
change reaches an already-cached agent on its very next token request.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@heavygee

Copy link
Copy Markdown
Owner Author

Good catch from the Codex review — fixed in 89e3b5c.

getOrCreateAgentIdForVoice's agentIdCache returned a cached agent ID before ever reaching ensureAgentOverrides, and overridesEnsuredAgents was a one-time-forever marker that didn't account for the duration setting changing after the first reconciliation. Net effect: a voice already used once in the hub process would keep its old cap until a restart, which directly contradicted this PR's "takes effect on the next token request" claim.

Fix: track the last-applied max duration per agent (reconciledMaxDurationByAgent) and compare it against the live setting on every call, including cache hits. New regression test exercises the exact scenario: request a token for a voice, change the duration, request again for the same (now-cached) voice, and assert a PATCH with the new value fires without a re-create — then a third request confirms no further PATCH once it's current.

heavygee added a commit that referenced this pull request Oct 12, 2026
Dogfood the ElevenLabs max-duration fix + Settings UI before it merges.
Thin soup tip resolves two trivial union conflicts against other layers in
hub/src/config/settings.ts and hub/src/web/routes/voice.test.ts; no semantic
changes vs the upstream-aimed feat/elevenlabs-max-duration tip.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Fix TS2769 typecheck failure: test assertions casting the credentials
  response narrowed the type to omit 'editable', which upstream CI's
  bun typecheck catches and this fork's (currently broken) CI did not.
- An invalid ELEVENLABS_MAX_DURATION_SECONDS env value threw out of
  buildMaxDurationStatus(), which is shared by every provider's
  GET/PUT credentials status — breaking visibility into OpenAI/Deepgram/
  Groq settings too, not just ElevenLabs. The token-issuance hot path
  (getConfiguredElevenLabsMaxDurationSeconds) still throws there by
  design; only the status/update endpoints now degrade gracefully.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

Nit from tiann#2017 follow-up review: the hint under the max-duration
field rendered the literal '{min}-{max}' placeholders instead of '60-7200'.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

heavygee added a commit to tiann/hapi that referenced this pull request Oct 15, 2026
* feat(voice): configurable ElevenLabs max conversation duration

Auto-created ConvAI agents never set conversation.max_duration_seconds, so
ElevenLabs applied its 600s default and cut voice conversations off.

Add ELEVENLABS_MAX_DURATION_SECONDS (default 1800, validated 60-7200). The cap
is applied when the hub creates an agent and reconciled onto existing
hub-managed agents (found by name) once per process. Operator-supplied agents
(ELEVENLABS_AGENT_ID / voice map / customAgentId) keep their own cap. Invalid
values fail the token request with a clear message instead of an API 422.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* feat(voice): Settings UI for ElevenLabs max conversation duration

Extend the hub-owner credentials panel (Settings -> Voice -> manage
providers) with a numeric field for ELEVENLABS_MAX_DURATION_SECONDS,
reusing the same env-wins-over-Settings overlay that already backs the
ElevenLabs API key field. A Settings save takes effect on the very next
token request in the same process; the env var still requires a restart.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(voice): reconcile max duration on cached agents, not just once per process

Codex review on heavygee#230 caught this: getOrCreateAgentIdForVoice's
agentIdCache short-circuited before ever reaching ensureAgentOverrides, and
ensureAgentOverrides's overridesEnsuredAgents gate was a one-time-forever
marker that didn't account for the configured duration changing after the
first reconciliation. Together, any voice already used once in the hub
process would keep its old cap until a restart, contradicting the Settings
UI's 'takes effect immediately' claim.

Track the last-applied max duration per agent and compare it against the
live setting on every call, including agentIdCache hits, so a Settings
change reaches an already-cached agent on its very next token request.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(voice): address #2017 review findings

- Fix TS2769 typecheck failure: test assertions casting the credentials
  response narrowed the type to omit 'editable', which upstream CI's
  bun typecheck catches and this fork's (currently broken) CI did not.
- An invalid ELEVENLABS_MAX_DURATION_SECONDS env value threw out of
  buildMaxDurationStatus(), which is shared by every provider's
  GET/PUT credentials status — breaking visibility into OpenAI/Deepgram/
  Groq settings too, not just ElevenLabs. The token-issuance hot path
  (getConfiguredElevenLabsMaxDurationSeconds) still throws there by
  design; only the status/update endpoints now degrade gracefully.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(voice): interpolate duration range in the Settings hint

Nit from #2017 follow-up review: the hint under the max-duration
field rendered the literal '{min}-{max}' placeholders instead of '60-7200'.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
@heavygee

Copy link
Copy Markdown
Owner Author

Merged upstream as tiann#2017 (squash 7b00df4). Closing the fork-stage copy; branch stays until Gate A cleanup deletes it.

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.

bug(voice): auto-created ElevenLabs agents get the 10-minute default; the fix is manual and silently reverts

1 participant