mirror of
https://github.com/cline/cline.git
synced 2026-10-24 02:02:27 +08:00
fix(webview): keep Thinking hidden during cloud provisioning before the send is acknowledged
The optimistic forceShow path bypassed the provisioning check inside computeIsWaitingForResponse, so Thinking could render next to the progress card until the backend's state post arrived. Gate the combined loader condition on the provisioning tail instead, and cover it with a full-hook test.
This commit is contained in:
+10
-9
@@ -53,15 +53,6 @@ describe("computeIsWaitingForResponse (turnState path)", () => {
|
||||
// phase to "completed"; the loader must not flash during that gap.
|
||||
expect(computeIsWaitingForResponse(inputsFor([say(1, "completion_result", false)], streaming()))).toBe(false)
|
||||
})
|
||||
|
||||
it("does not wait while a cloud sandbox is provisioning, which shows its own progress", () => {
|
||||
expect(computeIsWaitingForResponse(inputsFor([say(1, "cloud_provisioning", false)], streaming()))).toBe(false)
|
||||
expect(
|
||||
computeIsWaitingForResponse(
|
||||
inputsFor([say(1, "cloud_provisioning", false), say(2, "api_req_started", false)], streaming()),
|
||||
),
|
||||
).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("computeIsWaitingForResponse (legacy path)", () => {
|
||||
@@ -187,6 +178,16 @@ describe("useThinkingLoaderRow anti-flash debounce", () => {
|
||||
expect(result.current).toBe(true)
|
||||
})
|
||||
|
||||
it("stays hidden while a cloud sandbox provisions, even before the optimistic send is acknowledged", () => {
|
||||
const provisioning = say(1, "cloud_provisioning", false, JSON.stringify({ phase: "starting" }))
|
||||
const idle: TurnState = { phase: "idle", seq: 1 }
|
||||
const { result, rerender } = renderLoader({ ...inputsFor([provisioning], idle), forceShow: true })
|
||||
expect(result.current).toBe(false)
|
||||
|
||||
rerender({ ...inputsFor([provisioning, say(2, "api_req_started", false)], idle), forceShow: true })
|
||||
expect(result.current).toBe(true)
|
||||
})
|
||||
|
||||
it("does not flash on attempt_completion turns even without the debounce timing", () => {
|
||||
const { result, rerender } = renderLoader(inputsFor([say(1, "completion_result", true)], streaming()))
|
||||
expect(result.current).toBe(false)
|
||||
|
||||
@@ -52,11 +52,6 @@ export function computeIsWaitingForResponse({
|
||||
}: ThinkingLoaderInputs): boolean {
|
||||
const lastMsg = modifiedMessages[modifiedMessages.length - 1]
|
||||
|
||||
// A provisioning cloud sandbox shows its own progress card.
|
||||
if (lastRawMessage?.type === "say" && lastRawMessage.say === "cloud_provisioning") {
|
||||
return false
|
||||
}
|
||||
|
||||
// AUTHORITATIVE PATH: when the backend provides a TurnState, the agent is only "thinking"
|
||||
// while phase === "streaming". Any other phase (awaiting_approval/followup, completed,
|
||||
// error, resumable, idle) is never a thinking state — this is what makes the footer
|
||||
@@ -252,8 +247,11 @@ export function useThinkingLoaderRow(inputs: ThinkingLoaderInputs): boolean {
|
||||
// started, unless a visible content row is already streaming.
|
||||
const optimisticShow = forceShow === true && lastVisibleMessage?.partial !== true
|
||||
|
||||
// A provisioning cloud sandbox shows its own progress card.
|
||||
const cloudProvisioning = lastRawMessage?.type === "say" && lastRawMessage.say === "cloud_provisioning"
|
||||
|
||||
return useDebouncedLoaderVisibility(
|
||||
optimisticShow || isWaitingForResponse || handoffToReasoningPending,
|
||||
!cloudProvisioning && (optimisticShow || isWaitingForResponse || handoffToReasoningPending),
|
||||
lastVisibleMessage?.ts,
|
||||
lastVisibleMessage?.partial === true,
|
||||
// A reasoning tail finishing never ends the turn (the model always emits content after
|
||||
|
||||
Reference in New Issue
Block a user