Skip to content

[BUG] Runtime tool validation re-reads live settings mid-request, so a mid-request disabledTools change can contradict the prompt #1642

Description

@DaubnerF

Problem

The system prompt for a request is generated once, from the settings at that moment, when the request is built (getSystemPrompt is awaited once in src/core/task/Task.ts). Tool-call validation during the streaming response does not reuse that moment: for every tool call it re-reads current settings. In src/core/assistant-message/presentAssistantMessage.ts, each tool call fetches fresh state inside the tool_use case of presentAssistantMessage (const state = await cline.providerRef.deref()?.getState() at presentAssistantMessage.ts:347), destructures disabledTools from it (presentAssistantMessage.ts:348), and converts it into the validation requirements passed to validateToolUse.

Observed in version v3.82.1

Consequence

Generating once and validating live makes the two moments diverge whenever settings change mid-request. If disabledTools gains an entry after the prompt was built, validation rejects a tool the prompt advertised, and the model gets a rejection for following its instructions. If an entry is removed mid-request, validation accepts a tool the prompt never advertised. Either way the effective tool policy differs between the prompt and the validator within a single request.

Desired behavior

Runtime validation during an in-flight request should consume the same policy snapshot the prompt for that request was generated from. This is a new property: on version v3.82.1 both layers read live state, and no request-scoped snapshot exists to share.

For this issue, the request's policy snapshot is exactly the set of inputs the request's tool validation consumes: disabledTools, experiments, customModes, and the request's modelInfo (the source of the model's excluded and included tools). Validation must consume that snapshot rather than re-read live settings.

Acceptance criteria

  • The request's policy snapshot is threaded through the streaming presentation chain as a required parameter, with no fallback re-read of live settings (terminal contract: callers that do not supply it fail fast rather than silently reverting to live reads).
  • A disabledTools change landing mid-request cannot change validation behavior for the in-flight request; it takes effect for the next request. Each API-request attempt captures its own snapshot of the configuration-derived inputs disabledTools, experiments, and customModes, retries included, so a settings change landing mid-request can affect a later retry attempt, but never the one in flight. The request's modelInfo is the deliberate exception: it is resolved once per request, and each attempt of that request publishes a snapshot carrying that same resolution and builds its prompt from it, so validation and prompt can never contradict each other about the model, and re-resolving the model mid-request is out of scope for this issue.
  • Tests cover both directions with a mid-stream settings mutation: rejecting a tool the prompt advertised, and accepting a tool the prompt omitted. These tests belong at the src unit/integration layer (the presentation-chain tests under src/core/assistant-message); no VS Code extension-host end-to-end test is required.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions