Problem
When codewhale asks the user a question (await_user_input) or waits for an approval decision, it waits a fixed 300 seconds and then cancels with a timeout:
// crates/tui/src/core/engine/approval.rs:15
const USER_INPUT_TIMEOUT: Duration = Duration::from_secs(300);
// crates/tui/src/runtime_threads.rs:547
const APPROVAL_DECISION_TIMEOUT: Duration = Duration::from_secs(300);
This is hard-coded — there is no config key and no env var in the engine to change it (only [tools] user_input_max_questions / user_input_max_options, which cap the count of questions, not the wait). The wait is also not documented in docs/CONFIGURATION.md.
The fixed 5-minute window is wrong for two groups:
- Users who need longer: they step away or read carefully, come back after 5 minutes, and the question/approval has already timed out (
ToolError::Timeout { seconds: 300 }).
- Users who want no timeout at all (e.g. overnight automation, long human review), which is currently impossible.
A timeout that silently cancels a question the user was about to answer is a real workflow breaker — related closed bug: #3821 (approval dialog timeout left the agent unable to respond).
Proposed solution
Make the wait timeout configurable and disableable, mirroring how other limits are already exposed:
- Add a config key such as:
[tools]
# seconds to wait for a user answer / approval decision
# user_input_timeout_secs = 300 # default; 0 = wait indefinitely
- Or an env var, e.g.
CODEWHALE_USER_INPUT_TIMEOUT_SECS, applied at engine start.
0 (or none) should mean wait indefinitely (no timeout), for users who explicitly opt out.
- Unify/alias both constants (
USER_INPUT_TIMEOUT in approval.rs, APPROVAL_DECISION_TIMEOUT in runtime_threads.rs) so the knob controls both paths consistently.
Use case
I routinely have several questions/approvals pending while I context-switch. After ~5 minutes codewhale cancels them even though I am about to answer. I want to raise the window — or disable it entirely for unattended stretches — instead of losing the turn.
Alternatives considered
- Re-asking the question after a timeout (today it is just cancelled; the agent may or may not re-ask).
- Per-invocation timeout in the question payload (the
user_input tool already carries other fields; a timeout_secs there would allow "answer this within N" without a global knob).
- A notification/beeper when a question is about to expire (does not fix the fixed-window problem).
My preferred option: global config key with 0 = unlimited, plus optionally per-invocation override later.
Impact
Anyone who does not answer within 5 minutes loses the question/approval. Configurability removes a silent failure mode and matches the pattern already used for user_input_max_questions / user_input_max_options (PR #5963).
Additional context
Problem
When codewhale asks the user a question (
await_user_input) or waits for an approval decision, it waits a fixed 300 seconds and then cancels with a timeout:This is hard-coded — there is no config key and no env var in the engine to change it (only
[tools] user_input_max_questions/user_input_max_options, which cap the count of questions, not the wait). The wait is also not documented indocs/CONFIGURATION.md.The fixed 5-minute window is wrong for two groups:
ToolError::Timeout { seconds: 300 }).A timeout that silently cancels a question the user was about to answer is a real workflow breaker — related closed bug: #3821 (approval dialog timeout left the agent unable to respond).
Proposed solution
Make the wait timeout configurable and disableable, mirroring how other limits are already exposed:
CODEWHALE_USER_INPUT_TIMEOUT_SECS, applied at engine start.0(ornone) should mean wait indefinitely (no timeout), for users who explicitly opt out.USER_INPUT_TIMEOUTinapproval.rs,APPROVAL_DECISION_TIMEOUTinruntime_threads.rs) so the knob controls both paths consistently.Use case
I routinely have several questions/approvals pending while I context-switch. After ~5 minutes codewhale cancels them even though I am about to answer. I want to raise the window — or disable it entirely for unattended stretches — instead of losing the turn.
Alternatives considered
user_inputtool already carries other fields; atimeout_secsthere would allow "answer this within N" without a global knob).My preferred option: global config key with
0 = unlimited, plus optionally per-invocation override later.Impact
Anyone who does not answer within 5 minutes loses the question/approval. Configurability removes a silent failure mode and matches the pattern already used for
user_input_max_questions/user_input_max_options(PR #5963).Additional context
crates/tui/src/core/engine/approval.rs:15(USER_INPUT_TIMEOUT) andcrates/tui/src/runtime_threads.rs:547(APPROVAL_DECISION_TIMEOUT); bothDuration::from_secs(300).*APPROVAL_TIMEOUT*in the tree isCODEWHALE_APPROVAL_TIMEOUT_MS, which is wecom-bridge only (integrations/wecom-bridge/src/index.mjs:52) and does not affect the engine — useful as a naming precedent.