From 650fa4a63187409098dc3bc1f15fa847078ac056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=BE=D1=80=D0=BE=D0=B4=D0=B8=D0=BD=20=D0=A0=D0=BE?= =?UTF-8?q?=D0=BC=D0=B0=D0=BD?= Date: Sat, 26 Sep 2026 10:22:29 +0300 Subject: [PATCH] fix: skip steps after finish:stop, no setTimeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit После finish:stop — все последующие step-события это дубликаты/ перепроекция. Пропускаем их через флаг done. Убран setTimeout cleanup — чистка синхронная. --- index.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/index.ts b/index.ts index 8d5016e..c7c1a2e 100644 --- a/index.ts +++ b/index.ts @@ -126,6 +126,7 @@ async function runPlugin(ctx: any, options: any, dataDir: string) { currentStepID: string | null context: MatrixEventContext finalResponse?: string + done: boolean // true после finish:stop } const sessionsBySessionID = new Map() @@ -253,6 +254,10 @@ async function runPlugin(ctx: any, options: any, dataDir: string) { if (eventType === "session.step.ended" && sessionId && assistantMsgID) { const state = sessionsBySessionID.get(sessionId) + + // Skip steps after final (finish:stop) — they are re-projections/duplicates + if (state?.done) continue + const step = state?.steps.get(assistantMsgID) const finish = eventData?.data?.finish || "" @@ -262,13 +267,15 @@ async function runPlugin(ctx: any, options: any, dataDir: string) { log(`Step ${step.tools.length} tool(s), ${step.text.length} chars text → sent to ${state.context.roomId}`) } - // If this is the final step, resolve the pending promise + // If this is the final step, mark done and resolve the pending promise if (finish === "stop" && state) { + state.done = true const pending = pendingResponses.get(sessionId) if (pending && state.finalResponse) { pendingResponses.delete(sessionId) pending.resolve(state.finalResponse) } + sessionsBySessionID.delete(sessionId) } continue @@ -430,6 +437,7 @@ async function runPlugin(ctx: any, options: any, dataDir: string) { currentStepID: null, context, finalResponse: undefined, + done: false, }) // Wait for response text from event subscription