Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
cf5abe6
fix(task): stage-independent saveClineMessages + finalize open partia…
easonLiangWorldedtech Oct 5, 2026
d172c95
feat(write-to-file): per-task partial stream state + cleanup primitives
easonLiangWorldedtech Oct 5, 2026
52699c6
test(write-to-file): cover partial-state cleanup primitives directly
easonLiangWorldedtech Oct 5, 2026
4b23b6a
fix(write-to-file): capture streaming failure once, report it once
easonLiangWorldedtech Oct 5, 2026
950bf6a
chore(ci): re-trigger the unit suite after a flaky writeToFileTool pa…
Oct 6, 2026
6906c02
test(write-to-file): align the partial-path case with handlePartial's…
Oct 6, 2026
e0b0e0e
fix(tools): release the failed task's stream state without clobbering…
Oct 6, 2026
7752664
fix(diff-view): roll back the created file and dirs when open() fails…
Oct 8, 2026
753c22f
fix(tools): report the captured stream failure on the parse-failure path
Oct 8, 2026
875110d
test(tools): move the cleanup tests under a describe that matches them
Oct 8, 2026
bc9a156
fix(write-to-file): release the partial stream state when the preview…
Oct 9, 2026
0bb8efa
Merge org main (036245c5e, U1 #1927) into p1066/u5-task-partial-ask-f…
Oct 9, 2026
7b78345
fix(write-to-file): report rollback failure, discard unapproved buffe…
easonLiangWorldedtech Oct 9, 2026
6cae369
fix(diff-view): treat a refused discard as a rollback failure
easonLiangWorldedtech Oct 9, 2026
eb24549
fix(editor): gate rollback on an in-progress edit and restore buffers…
easonLiangWorldedtech Oct 9, 2026
215e32d
chore(lint): prune the stale no-explicit-any suppression in DiffViewP…
easonLiangWorldedtech Oct 9, 2026
e1c304f
fix(tools): report the real failure and never leak the stream state
Oct 10, 2026
53ed5b3
fix(editor): treat a refused buffer restore as a rollback failure
Oct 10, 2026
30023a9
Merge org main 09e7326cf into p1066/u5-streaming-failure-capture
Oct 10, 2026
e41ebe0
style: apply prettier to the files this PR touches
Oct 10, 2026
9c54765
fix(editor): fail closed when a rollback restore or save is refused
Oct 10, 2026
2f15ff7
fix(write-to-file): fail closed after refused streaming rollback; cov…
Oct 10, 2026
605756a
fix(write-to-file): release the abandoned stream from the malformed-c…
Oct 11, 2026
9bdc349
fix(write-to-file): keep the malformed-call report reachable when the…
Oct 11, 2026
3e8c7b6
fix(write-to-file): keep a lost chat row from changing the reported f…
Oct 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/__tests__/removeClineFromStack-delegation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ClineProvider } from "../core/webview/ClineProvider"
import { TaskRegistry } from "../core/task/TaskRegistry"
import { PendingActionSettlementError, type Task } from "../core/task/Task"
import { makeProviderStub } from "./helpers/provider-stub"
import { writeToFileTool } from "../core/tools/WriteToFileTool"

type MockTask = Pick<Task, "taskId" | "instanceId"> &
Partial<Pick<Task, "parentTaskId" | "abort" | "abandoned">> & {
Expand Down Expand Up @@ -208,6 +209,47 @@ describe("ClineProvider failed history restoration cleanup", () => {
expect(task.dispose).toHaveBeenCalledOnce()
})

it("releases the tool's per-task state before a directly disposed task loses its listeners", async () => {
const key = "failed-history-task.inst-1"
const order: string[] = []
const task = {
taskId: "failed-history-task",
instanceId: "inst-1",
emit: vi.fn(),
once: vi.fn(),
off: vi.fn(),
dispose: vi.fn().mockImplementation(() => {
// Dispose removes every listener, so this is the last moment the abort
// cleanup could still have run; the entry must already be gone here.
order.push(writeToFileTool["taskPartialStreamState"].has(key) ? "state-retained" : "state-cleared")
order.push("dispose")
return Promise.resolve()
}),
} as unknown as Task
// Fixture: the state entry the tool would have created during a partial stream.
writeToFileTool["taskPartialStreamState"].set(key, {
lastSeenPartialPath: undefined,
streamFailed: false,
streamError: undefined,
rollbackFailure: undefined,
task,
abortCleanup: () => {},
})
const taskEventListeners = new Map([[task, [vi.fn()]]])
const taskRegistry = new TaskRegistry()
taskRegistry.push(task)
const provider = { taskRegistry, taskEventListeners, log: vi.fn() } as unknown as ClineProvider

await privateClineProvider.cleanupFailedHistoryTask.call(
provider,
task,
new PendingActionSettlementError("settlement failed"),
)

expect(order).toEqual(["state-cleared", "dispose"])
expect(writeToFileTool["taskPartialStreamState"].size).toBe(0)
})

it("keeps the task active after an unrelated history resume failure", async () => {
const cleanupListener = vi.fn()
const task = {
Expand Down
Loading
Loading