diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts index ebb362f7eb..99a7f38324 100644 --- a/src/core/task/Task.ts +++ b/src/core/task/Task.ts @@ -1380,22 +1380,15 @@ export class Task extends EventEmitter implements TaskLike { this.blanketDeniedCommandThisTurn = true } + /** When provided, historyItem overrides task and images in the startup metadata. */ static create(options: TaskOptions): [Task, Promise] { - const instance = new Task({ ...options, startTask: false }) - const { images, task, historyItem } = options - let promise - - instance.startIdleTelemetryCheck() - - if (images || task) { - promise = instance.startTask(task, images) - } else if (historyItem) { - promise = instance.resumeTaskFromHistory() - } else { + if (!options.task && !options.images && !options.historyItem) { throw new Error("Either historyItem or task/images must be provided") } - return [instance, promise] + const instance = new Task({ ...options, startTask: false }) + + return [instance, instance.run()] } // API Messages diff --git a/src/core/task/__tests__/Task.spec.ts b/src/core/task/__tests__/Task.spec.ts index 3066613263..ad07230204 100644 --- a/src/core/task/__tests__/Task.spec.ts +++ b/src/core/task/__tests__/Task.spec.ts @@ -1440,6 +1440,35 @@ describe("Cline", () => { }) }) + describe("create", () => { + it("rejects missing task inputs before constructing the task", () => { + const onCreated = vi.fn() + + expect(() => Task.create({ provider: mockProvider, apiConfiguration: mockApiConfig, onCreated })).toThrow( + "Either historyItem or task/images must be provided", + ) + expect(onCreated).not.toHaveBeenCalled() + }) + + it("returns the cached run promise", async () => { + const startTaskSpy = vi.spyOn(getTaskTestAccess(Task.prototype), "startTask").mockResolvedValue(undefined) + + try { + const [task, promise] = Task.create({ + provider: mockProvider, + apiConfiguration: mockApiConfig, + task: "x", + }) + + expect(task.run()).toBe(promise) + expect(startTaskSpy).toHaveBeenCalledExactlyOnceWith("x", undefined) + await promise + } finally { + startTaskSpy.mockRestore() + } + }) + }) + describe("constructor", () => { it.each([{ apiConfigName: "parent-local-profile" }, { apiConfigName: undefined }])( "uses an explicit delegated-child context without shared state or startup persistence",