Skip to content

fix: refresh /tools availability when the session model changes#54184

Merged
Takhoffman merged 1 commit into
mainfrom
codex/tools-effective-model-refresh
Mar 25, 2026
Merged

fix: refresh /tools availability when the session model changes#54184
Takhoffman merged 1 commit into
mainfrom
codex/tools-effective-model-refresh

Conversation

@Takhoffman

Copy link
Copy Markdown
Contributor

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: the Control UI cached tools.effective results by agentId + sessionKey, so a model change in the same session could reuse stale runtime tool availability.
  • Why it matters: effective tool exposure is model-sensitive, so /tools and the "Available Right Now" panel could show the wrong inventory after switching models.
  • What changed: the UI now keys effective-tool results by agentId + sessionKey + effective model, and the runtime model-switch paths reuse a shared refresh helper for the visible Tools panel.
  • What did NOT change (scope boundary): gateway/runtime tool resolution logic and model compatibility rules stayed the same; this PR only fixes UI cache invalidation and refresh behavior.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #
  • Related #
  • This PR fixes a bug or regression

Root Cause / Regression History (if applicable)

For bug fixes or regressions, explain why this happened, not just what changed. Otherwise write N/A. If the cause is unclear, write Unknown.

  • Root cause: the effective-tools refresh guard only compared agentId + sessionKey, but tools.effective is also a function of the session's effective model.
  • Missing detection / guardrail: there was no test covering a model switch in the same session while reusing the same Tools panel/session key.
  • Prior context (git blame, prior PR, issue, or refactor if known): this follows the runtime-effective /tools work that moved the UI off catalog guesses and onto tools.effective.
  • Why this regressed now: once the UI started trusting the runtime-effective result, the old coarse cache key became incorrect for model-sensitive tool exposure.
  • If unknown, what was ruled out: ruled out gateway/runtime resolver bugs; the stale behavior came from client-side request-key reuse.

Regression Test Plan (if applicable)

For bug fixes or regressions, name the smallest reliable test coverage that should have caught this. Otherwise write N/A.

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: ui/src/ui/views/chat.test.ts, ui/src/ui/app-chat.test.ts, ui/src/ui/controllers/agents.test.ts
  • Scenario the test should lock in: switching the session model should force a fresh tools.effective request and produce a model-aware cache key for the same agentId + sessionKey.
  • Why this is the smallest reliable guardrail: the bug lives in UI state/cache handling, and these focused tests exercise the exact model-switch entry points without needing a full browser/channel environment.
  • Existing test that already covers this (if any): none covered model changes against the effective-tools cache key before this PR.
  • If no new test is added, why not:

User-visible / Behavior Changes

List user-visible changes (including defaults/config).
If none, write None.

  • After changing the current session model, the Control UI Tools panel refreshes "Available Right Now" instead of reusing stale availability for the prior model.
  • Reopening the Tools panel after a same-session model switch no longer reuses the old effective-tools result.

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local pnpm/vitest
  • Model/provider: example session switch from openai/gpt-5 to openai/gpt-5-mini
  • Integration/channel (if any): Control UI / web chat header + /model
  • Relevant config (redacted): active session owned by the selected agent, Tools panel open or reopened after model switch

Steps

  1. Open the Control UI Tools panel for the current session's agent.
  2. Change the session model via the chat header picker or /model.
  3. Observe whether the Tools panel reuses the previous tools.effective result or reloads.

Expected

  • The effective-tools request key changes with the session model, and the Tools panel reloads the runtime inventory.

Actual

  • Before this fix, the guard reused the stale agentId + sessionKey result and could skip reloading after a model switch.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: ran the focused UI/controller tests that cover the chat header model picker, /model, and effective-tools request-key behavior.
  • Edge cases checked: same session key with a different model; cached override vs. server/default model fallback in the request key.
  • What you did not verify: manual browser/channel interaction outside the focused local test suite.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: revert this commit to restore the previous session-key-only refresh behavior.
  • Files/config to restore: ui/src/ui/controllers/agents.ts, ui/src/ui/app-render.ts, ui/src/ui/app-render.helpers.ts, ui/src/ui/app-chat.ts, ui/src/ui/app.ts
  • Known bad symptoms reviewers should watch for: stale or wrong "Available Right Now" inventory after changing models in the same session.

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk: the UI-side effective-model key could diverge from the server's final resolved model in an edge case.
    • Mitigation: the key prefers in-flight overrides, then session row data, then defaults, matching the UI's own model-selection resolution path and covered by focused tests.

@aisle-research-bot

aisle-research-bot Bot commented Mar 25, 2026

Copy link
Copy Markdown

🔒 Aisle Security Analysis

We found 1 potential security issue(s) in this PR:

# Severity Title
1 🔵 Low Client-triggerable request amplification: tools.effective fetch not debounced/cancelled across changing request keys
Vulnerabilities

1. 🔵 Client-triggerable request amplification: tools.effective fetch not debounced/cancelled across changing request keys

Property Value
Severity Low
CWE CWE-400
Location ui/src/ui/controllers/agents.ts:134-146

Description

The UI can repeatedly trigger tools.effective network requests without any debouncing/throttling, and the in-flight suppression only applies to the same requestKey.

Key points:

  • Multiple new pathways call refreshVisibleToolsEffectiveForCurrentSession() on model/config changes (e.g., model switch, agents config edit, /model override).
  • loadToolsEffective() only avoids duplicate concurrent requests when toolsEffectiveLoadingKey === requestKey.
  • The requestKey now includes modelKey (buildToolsEffectiveRequestKey()), so rapid model/override changes produce different keys; each call will start a new request even if another is already in flight.
  • Old responses are ignored client-side when keys mismatch, but the server still processes every request, allowing client-side request amplification and potential DoS against the backend endpoint tools.effective.

Vulnerable logic:

if (state.toolsEffectiveLoading && state.toolsEffectiveLoadingKey === requestKey) {
  return;
}
state.toolsEffectiveLoading = true;
state.toolsEffectiveLoadingKey = requestKey;
...
await state.client.request("tools.effective", { agentId, sessionKey });

Recommendation

Add client-side request coalescing and/or debouncing for tools.effective refreshes, and cancel in-flight requests when a new refresh supersedes them.

Example approach (debounce + abort):

let toolsEffectiveAbort: AbortController | null = null;
let toolsEffectiveTimer: number | null = null;

export function scheduleToolsEffectiveRefresh(state: AgentsState, params: {agentId: string; sessionKey: string}) {
  if (toolsEffectiveTimer) window.clearTimeout(toolsEffectiveTimer);
  toolsEffectiveTimer = window.setTimeout(() => {
    toolsEffectiveAbort?.abort();
    toolsEffectiveAbort = new AbortController();
    void loadToolsEffective(state, params, { signal: toolsEffectiveAbort.signal });
  }, 250);
}

Additionally:

  • Suppress new requests while any toolsEffectiveLoading is true (not only matching keys), or coalesce to the latest requested key.
  • Ensure server-side rate limiting on tools.effective to prevent abuse from automated clients.

Analyzed PR: #54184 at commit 65f07ce

Last updated on: 2026-03-25T02:57:08Z

@openclaw-barnacle openclaw-barnacle Bot added app: web-ui App: web-ui size: M maintainer Maintainer-authored PR labels Mar 25, 2026
@greptile-apps

greptile-apps Bot commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a UI-side cache invalidation bug where the Tools panel's "Available Right Now" inventory could go stale after switching the session model, because the effective-tools request key only incorporated agentId + sessionKey but not the session's effective model.

Key changes:

  • buildToolsEffectiveRequestKey now appends the effective model (resolving override → session row → default, matching the UI's own picker resolution order) to produce a model-aware cache key.
  • A shared refreshVisibleToolsEffectiveForCurrentSession helper is called from all model-switch entry points: the chat-header picker (switchChatModel), the /model slash command (via onSlashAction), and the agent-config model picker in renderApp.
  • New regression tests lock in the key format change and the reload behavior for each switch path.
  • AgentsState gains optional fields (sessionKey, sessionsResult, chatModelOverrides, chatModelCatalog, agentsPanel) so controllers that only use a subset of app state remain type-safe.
  • No gateway/runtime logic was changed; this is a pure UI cache-invalidation fix.

Confidence Score: 5/5

  • Safe to merge — the fix is UI-only, backward compatible, and all three model-switch paths are covered by new focused tests.
  • The bug is clearly isolated to client-side cache-key construction. The fix correctly mirrors the UI's existing model-resolution priority order (chatModelOverrides → session row → defaults). The deduplication guards in loadToolsEffective prevent redundant concurrent fetches, and new tests cover the chat-header picker, /model slash command, and the agent-config form paths. No gateway, auth, or data-access surface is touched.
  • No files require special attention.

Reviews (1): Last reviewed commit: "fix: refresh available tools when the se..." | Re-trigger Greptile

@Takhoffman
Takhoffman merged commit f3eb620 into main Mar 25, 2026
72 of 75 checks passed
@Takhoffman
Takhoffman deleted the codex/tools-effective-model-refresh branch March 25, 2026 03:07
kvokka added a commit to kvokka/openclaw that referenced this pull request Mar 25, 2026
…nto add-json-schema-to-cli

* 'add-json-schema-to-cli' of github.com:kvokka/openclaw: (58 commits)
  test: make vitest config tests platform-aware
  fix: refresh available tools when the session model changes (openclaw#54184)
  fix: prefer freshest transcript session owners
  test: disable Vitest fs cache on Windows
  fix: prefer deterministic transcript session keys
  fix: prefer deterministic session usage targets
  fix: prefer deterministic session id resume targets
  feat: add /tools runtime availability view (openclaw#54088)
  fix: enforce sandbox visibility for session_status ids
  fix: drop spawned visibility list caps
  fix: verify exact spawned session visibility
  fix: enforce spawned session visibility in key resolve
  fix: resolve exact session ids without fuzzy limits
  Discord: resolve /think autocomplete from session model (openclaw#49176)
  chore(agents): normalize pi embedded runner imports
  feat(gateway): make openai compatibility agent-first
  test(parallel): force unit-fast batch planning
  test(browser): stabilize default browser detection mocks
  fix: prefer current parents in session rows
  fix: prefer current subagent owners in session rows
  ...
netandreus pushed a commit to netandreus/openclaw that referenced this pull request Mar 25, 2026
npmisantosh pushed a commit to npmisantosh/openclaw that referenced this pull request Mar 25, 2026
fuller-stack-dev pushed a commit to fuller-stack-dev/openclaw that referenced this pull request Mar 25, 2026
jacobtomlinson pushed a commit to jacobtomlinson/openclaw that referenced this pull request Mar 25, 2026
godlin-gh pushed a commit to YouMindInc/openclaw that referenced this pull request Mar 27, 2026
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
goweii pushed a commit to goweii/openclaw that referenced this pull request May 24, 2026
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
Nachx639 pushed a commit to Nachx639/clawdbot that referenced this pull request Jun 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui maintainer Maintainer-authored PR size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant