Skip to content

feat(desktop): configurable group chat round cap + model-aware limits + token budget guard - #96842

Closed
beplee wants to merge 2 commits into
NousResearch:mainfrom
beplee:feat/desktop-configurable-round-cap
Closed

feat(desktop): configurable group chat round cap + model-aware limits + token budget guard#96842
beplee wants to merge 2 commits into
NousResearch:mainfrom
beplee:feat/desktop-configurable-round-cap

Conversation

@beplee

@beplee beplee commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replace hardcoded GROUP_CHAT_MAX_ROUNDS constant with config.yaml-driven group_chat.max_rounds (default 3, range 1-20)
  • Add model-aware cap: free models (:free suffix or free_models allowlist) use group_chat.max_rounds_free (null = unlimited, clamped to HARD_CAP=20)
  • Add token-budget guard: cumulative room-log tokens exceeding group_chat.token_budget (default 80k chars) force exitKind='capped' independent of round count — the real safety net for pathological cascades
  • Add getGroupChatConfig(), isFreeModel(), getEffectiveRoundCap(), getCurrentModelName() helpers
  • Add config.yaml schema in cli-config.yaml.example under group_chat:

Why

Hardcoded 3-round cap is too tight for free-model rooms (where API cost is zero) and too loose for paid-model rooms (where each round burns real money). A single config block drives everything automatically.

Config

group_chat:
  max_rounds: 3              # paid models
  max_rounds_free: null      # null = unlimited (HARD_CAP=20 backstop)
  token_budget: 80000        # hard ceiling per drive (chars, ~20k tokens)
  free_models:
    - upstage/solar-pro4
    - meituan/longcat-2.0
    - tencent/hy3
  hard_cap: 20               # absolute ceiling even for free models

Safety

  • Token budget is the real backstop — fires regardless of model type or round count
  • HARD_CAP=20 prevents unbounded free-model cascades (20 rounds × 6 bots = 120 messages max)
  • Paid models always capped at max_rounds (default 3)
  • exitKind='capped' reason logged for every termination path

Test plan

  • Paid model → 3-round cap fires
  • Free model (allowlist) → 20-round cap fires
  • Token budget exhaustion → mid-drive cap fires
  • Model switch mid-drive → cap re-evaluates
  • 6-bot free room → halts cleanly at token budget
  • Empty free_models + :free suffix → allowlist is sole gate (no bypass)

Refs: #96553

beplee added 2 commits August 28, 2026 03:34
…dget guard

- Replace hardcoded GROUP_CHAT_MAX_ROUNDS constant with config.yaml-driven
  group_chat.max_rounds (default 3, range 1-20)
- Add model-aware cap: free models (:free suffix or free_models list) use
  group_chat.max_rounds_free (null = unlimited, clamped to HARD_CAP=20)
- Add token-budget guard: cumulative room-log tokens exceeding
  group_chat.token_budget (default 80k) force exitKind='capped' independent
  of round count — the real safety net for pathological cascades
- Add getGroupChatConfig(), isFreeModel(), getEffectiveRoundCap(),
  getCurrentModelName() helpers
- Add config.yaml schema in cli-config.yaml.example under group_chat:
- Update behavioral model comment to reference effectiveCap

Refs: NousResearch#96553
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/desktop Electron desktop app (apps/desktop/*) area/config Config system, migrations, profiles sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Aug 28, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related to #92213: both extend Desktop Bot Mode limits, but #92213 persists per-room limits while this PR proposes global model-aware configuration and a token budget.

@beplee beplee closed this Aug 28, 2026
OutThisLife added a commit that referenced this pull request Aug 28, 2026
GROUP_CHAT_MAX_ROUNDS and its four siblings carry over at the values
plugin.js shipped, so no rebase inherits a behavior change on top of a
rewrite. Making them configurable is live contributor work — #92213 for
per-room limits, #96842 for config plus a token budget — and both want the
same single seam, so say so where the constants are instead of adding a
config hook this PR has no consumer for.
@beplee

beplee commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Closure rationale

This PR is closed as written because its target file () is deleted by #96726 (OutThisLife, "Rebuild Bot Mode on the app's design system", 230 files, 36k+/32k- diff). #96726 is moving toward merge and the file this PR patches will not exist on after that merge.

The feature itself is still needed. #96726 hardcodes at and the maintainer's comment on #96726 explicitly flags #96842 as the gap-filler:

Real contributor work that does NOT survive and needs re-implementation on the new modules: #96842 (round cap still hardcoded at , no token budget)

Round-cap constant — is newly hardcoded where an open contributor PR (#96842) makes it configurable; a config hook here (or a note ceding that to the follow-up) avoids re-burying the same constant.

What comes next: port the configurable round cap + model-aware limits + token-budget guard to the new module surface (, , ) after #96726 merges. The design work is already done in (branch ). Slot freed — we can open the port PR cleanly when #96726 lands and we have a slot.

andredezzy pushed a commit to andredezzy/hermes-agent that referenced this pull request Aug 29, 2026
A Bot Mode room stops after 3 serial rounds and 10 member messages. That
suits a quick two-bot exchange and cuts short a workflow whose hops are
genuinely serial: a coordinator triaging to a domain expert, to a data
operator, and back needs more passes than three, so the room reports
'turn stopped at the round/message cap' with a bot still holding an
addressed handoff.

Read the ceilings from a group_chat block in config.yaml, falling back to
today's values when it is absent, so the person paying for the model calls
decides what a room may spend.

Config is advisory, never authoritative: each value is clamped to a hard
ceiling (20 rounds / 100 messages / 20 continuations), and anything below 1
or unparseable reads as unset rather than as zero. A typo can neither
silence a room nor uncap it.

The limits resolve once at plugin load and are snapshotted per drive rather
than read inside the round loop, which is hot; a gateway round-trip there
would be a stall the user feels. A config edit reaches a room on its next
send. Reading fails silently to the shipped defaults, because a room that
runs beats a room that refuses to start because config could not be read.

Ports the design from NousResearch#96842 (beplee), which was closed unmerged when
NousResearch#96726 deleted the plugin.js it patched, onto the new modules. Uses the
existing config.get 'full' key rather than adding a gateway method.
Per-room overrides (NousResearch#92213) can layer on the same seam.

Refs NousResearch#98004, NousResearch#96842, NousResearch#89545
melon-xf added a commit to melon-xf/hermes-agent that referenced this pull request Sep 3, 2026
GROUP_CHAT_MAX_ROUNDS and its four siblings carry over at the values
plugin.js shipped, so no rebase inherits a behavior change on top of a
rewrite. Making them configurable is live contributor work — NousResearch#92213 for
per-room limits, NousResearch#96842 for config plus a token budget — and both want the
same single seam, so say so where the constants are instead of adding a
config hook this PR has no consumer for.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/desktop Electron desktop app (apps/desktop/*) P3 Low — cosmetic, nice to have sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants