Skip to content

feat: add configurable typingTtlSeconds to config schema#20622

Closed
chungjchris wants to merge 4 commits into
openclaw:mainfrom
chungjchris:feat/configurable-typing-ttl
Closed

feat: add configurable typingTtlSeconds to config schema#20622
chungjchris wants to merge 4 commits into
openclaw:mainfrom
chungjchris:feat/configurable-typing-ttl

Conversation

@chungjchris

@chungjchris chungjchris commented Feb 19, 2026

Copy link
Copy Markdown

Summary

Adds typingTtlSeconds to both agent-level and session-level config schemas, and passes it through to createTypingController() in get-reply.ts.

Problem

The typing indicator has a hardcoded 2-minute TTL (typingTtlMs = 2 * 60_000). For extended thinking models (e.g. Claude Opus 4.6 with effort:max), tool-heavy workflows, or complex multi-step replies, processing regularly exceeds 2 minutes — causing the typing indicator to disappear while the model is still actively working. This confuses users into thinking the bot has stalled.

typingIntervalSeconds is already configurable in the schema, but there is no config path for the TTL.

Change

5 files, 11 insertions:

File Change
src/config/types.agent-defaults.ts Add typingTtlSeconds?: number
src/config/types.base.ts Add typingTtlSeconds?: number
src/config/zod-schema.agent-defaults.ts Add typingTtlSeconds: z.number().int().nonnegative().optional()
src/config/zod-schema.session.ts Add typingTtlSeconds: z.number().int().nonnegative().optional()
src/auto-reply/reply/get-reply.ts Read from config, pass to createTypingController()

Behavior

typingTtlSeconds Behavior
not set / undefined Default 2-minute TTL (backward compatible)
0 Disabled — typing stays active until run completes
> 0 Custom TTL in seconds

The 0 case works because createTypingController() already has the guard:

if (typingTtlMs <= 0) return; // skip TTL timer entirely

Config Example

# Disable TTL (typing stays active for full processing duration)
agents:
  defaults:
    typingTtlSeconds: 0

# Extend to 5 minutes
agents:
  defaults:
    typingTtlSeconds: 300

Design Decisions

  • .nonnegative() not .positive() — because 0 is a valid value meaning "disabled"
  • Seconds not milliseconds — matches existing typingIntervalSeconds convention
  • Spread with undefined check — only passes typingTtlMs when explicitly configured, preserving the existing default for unset values
  • Agent cascades to sessionagentCfg?.typingTtlSeconds ?? sessionCfg?.typingTtlSeconds follows the same pattern as typingIntervalSeconds

Closes #13673

Greptile Summary

Adds configurable typingTtlSeconds to agent and session config schemas, allowing users to control how long the typing indicator stays active. The implementation follows the existing typingIntervalSeconds pattern and correctly:

  • Adds schema validation with .nonnegative() (allowing 0 to disable TTL)
  • Cascades from agent to session config
  • Converts seconds to milliseconds before passing to createTypingController()
  • Only passes the parameter when explicitly set (preserving the 2-minute default)
  • Supports 0 value to disable TTL entirely (typing stays active until processing completes)

The change solves a real problem for extended thinking models and tool-heavy workflows where processing exceeds the hardcoded 2-minute TTL.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The implementation is straightforward, follows established patterns in the codebase (mirrors typingIntervalSeconds), and makes only additive changes. The type checking, schema validation, and conditional spreading ensure backward compatibility. The existing createTypingController() logic already handles all edge cases including 0 and negative values.
  • No files require special attention

Last reviewed commit: 0514a1b

(5/5) You can turn off certain types of comments like style here!

The typing indicator has a hardcoded 2-minute TTL (typingTtlMs = 2 * 60_000).
For extended thinking models (e.g. Opus 4.6 with effort:max), tool-heavy
workflows, or complex multi-step replies, processing regularly exceeds
2 minutes — causing the typing indicator to disappear while the model
is still working.

The typingTtlMs parameter is already accepted by createTypingController()
with a clean disable guard (if typingTtlMs <= 0, the TTL timer is skipped
entirely). And typingIntervalSeconds is already in the config schema. But
there is no config path for the TTL — it always uses the hardcoded default.

This PR adds typingTtlSeconds to both the agent-level and session-level
config schemas (matching the existing typingIntervalSeconds pattern) and
passes it through to the typing controller in get-reply.ts.

Behavior:
  - Not set (default): 2-minute TTL (backward compatible, no change)
  - 0: TTL disabled — typing stays active until run completes
  - >0: Custom TTL in seconds

Config example:
  agents:
    defaults:
      typingTtlSeconds: 0  # disable TTL

Uses .nonnegative() (not .positive()) in the Zod schema because 0 is a
valid value meaning "disabled".

Closes #13673

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

Copy link
Copy Markdown
Contributor

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: 0514a1bd12

ℹ️ 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 src/auto-reply/reply/get-reply.ts Outdated
const configuredTtlSeconds =
agentCfg?.typingTtlSeconds ?? sessionCfg?.typingTtlSeconds;
const typingTtlMs =
typeof configuredTtlSeconds === "number" ? configuredTtlSeconds * 1000 : undefined;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Badge Clamp configured typing TTL before converting to ms

typingTtlSeconds is currently accepted as any nonnegative integer, then multiplied by 1000 and used for the typing timeout; values above 2_147_483 seconds overflow Node's timer range (2_147_483_647 ms) and get coerced to an almost immediate timeout, so very large TTL configs (often used to approximate “no expiry”) will make typing stop right away instead of lasting longer. Add a max bound or clamp before passing typingTtlMs.

Useful? React with 👍 / 👎.

Values above 2_147_483 seconds would overflow Node.js setTimeout max
(2_147_483_647 ms), causing the timer to fire immediately instead of
after the configured duration.

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

Copy link
Copy Markdown
Contributor

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: 3662d235ea

ℹ️ 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".

agentCfg?.typingIntervalSeconds ?? sessionCfg?.typingIntervalSeconds;
const typingIntervalSeconds =
typeof configuredTypingSeconds === "number" ? configuredTypingSeconds : 6;
const configuredTtlSeconds = agentCfg?.typingTtlSeconds ?? sessionCfg?.typingTtlSeconds;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Badge Let session typing TTL override agent defaults

configuredTtlSeconds currently checks agents.defaults before session, so when both are configured the session value is ignored and cannot override the default TTL for a specific session context. This is inconsistent with the existing typing override behavior (session.typingMode ?? agentCfg?.typingMode in get-reply-run.ts) and with the documented per-session override model, so users setting session.typingTtlSeconds alongside an agent default will see the wrong TTL applied.

Useful? React with 👍 / 👎.

@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Feb 28, 2026
@openclaw-barnacle

Copy link
Copy Markdown

Closing due to inactivity.
If you believe this PR should be revived, post in #pr-thunderdome-dangerzone on Discord to talk to a maintainer.
That channel is the escape hatch for high-quality PRs that get auto-closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size: XS stale Marked as stale due to inactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: 20:58:33 typing TTL reached (2m); stopping typing indicator

1 participant