feat(x): configurable model-call limits by workflow (#768)

Replace the hardcoded 20-call turn budget with user settings: a global
model-call limit that every turn inherits (headless/knowledge work,
scheduled agents, sub-agents) plus an optional chat-only override for
interactive turns. Settings live in config/turn_limits.json (1-100,
default 20) and are edited from a new Advanced tab in Settings.

The limit is resolved at turn creation via an ITurnLimitsResolver
injected into TurnRuntime, keyed on humanAvailable; explicit per-call
overrides still win, and the resolved value is persisted in
turn_created.config.maxModelCalls as before, so historical and
in-flight turns are unaffected by settings changes. Sub-agents now
default to and are capped by the global limit instead of the constant.
This commit is contained in:
Gagan 2026-07-21 15:25:21 +05:30
parent 63a99e5fe4
commit eece1af90e
16 changed files with 518 additions and 16 deletions

View file

@ -512,7 +512,13 @@ Rules:
- `input` is the user message that defines this turn boundary.
- `autoPermission` defaults to `false` before persistence.
- `humanAvailable` is required explicitly.
- `maxModelCalls` defaults to `20` before persistence.
- `maxModelCalls`, when omitted, is resolved at creation from the user's
turn-limit settings (`config/turn_limits.json`) via the injected
`ITurnLimitsResolver`: turns with `humanAvailable: true` use the chat
override when set, otherwise the global limit; headless turns always use
the global limit. Without a resolver (tests) it defaults to `20`. Spawned
sub-agents default to the global limit, which also caps the budget a
parent may grant them. Settings changes affect only newly created turns.
- Persisted values are fully resolved and immutable.
The capability is named `humanAvailable`, not `headless`. `headless` describes