From 17c57f57f8bad7d9184d5ad7ea040212ca625383 Mon Sep 17 00:00:00 2001 From: Ryder Sun Date: Fri, 16 Oct 2026 16:10:03 +0800 Subject: [PATCH] test: a conversation stuck on an Agent must not stop another from using it End-to-end version of the blocking fix, on the real LocalWorkspace: one direct chat's turn never finishes, and a second direct chat with the same Agent has to answer anyway while the first is still marked running. On the commit before the fix this test times out, which is the symptom that was reported (the second conversation sat on 'waiting for another Agent that is writing in the same folder' until the first finished). --- .../local-workspace-write-scheduling.test.cjs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/desktop/test/workspace/local-workspace-write-scheduling.test.cjs b/desktop/test/workspace/local-workspace-write-scheduling.test.cjs index 6192a4b..05f6e1d 100644 --- a/desktop/test/workspace/local-workspace-write-scheduling.test.cjs +++ b/desktop/test/workspace/local-workspace-write-scheduling.test.cjs @@ -186,6 +186,44 @@ test('the same Agent answers in two conversations at once', { timeout: 10000 }, assert.equal(scheduler.snapshot().active.global, 0) }) +test('a conversation stuck on an Agent does not stop another conversation from using it', { timeout: 10000 }, async (t) => { + const { directory, options } = fixture() + const stuck = deferred() + t.after(() => { + stuck.resolve() + fs.rmSync(directory, { recursive: true, force: true }) + }) + options.runScheduler = new RunScheduler() + options.runAgent = async (agent, prompt) => { + // The first conversation's turn never finishes by itself. + if (prompt.includes('stay busy')) await stuck.promise + return { text: `${agent.kind} answered: ${prompt.includes('quick') ? 'quick' : 'other'}` } + } + const workspace = new LocalWorkspace(options) + await workspace.refreshAgents() + const [busy, free] = [1, 2].map(number => workspace.createGroup({ + name: `Hermes chat ${number}`, agentKinds: ['hermes'], directAgentKind: 'hermes', + conversationType: 'direct', workdir: directory, allowWrite: true, + })) + + const first = workspace.sendMessage({ groupId: busy.id, text: 'stay busy' }) + await new Promise(resolve => setTimeout(resolve, 20)) + assert.equal(workspace.snapshot().runningGroupIds.includes(busy.id), true) + + // The second conversation answers while the first is still running. + await workspace.sendMessage({ groupId: free.id, text: 'a quick question' }) + const answers = workspace.snapshot().messages.filter(message => ( + message.groupId === free.id && message.role === 'agent' + )) + assert.equal(answers.length, 1) + assert.match(answers[0].content, /quick/) + assert.equal(workspace.snapshot().runningGroupIds.includes(busy.id), true, 'the first is still running') + assert.equal(workspace.snapshot().runningGroupIds.includes(free.id), false) + + stuck.resolve() + await first +}) + test('Manual V4 retains parallel readers alongside its single writer and stable message order', { timeout: 10000 }, async (t) => { const { directory, options } = fixture() const release = deferred()