From da368aa79316ff5aaae2c71301c222a517fe0142 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 2 Mar 2026 02:53:54 +0000 Subject: [PATCH] fix: scope dm topic thread keys by chat id (#31064) (thanks @0xble) --- CHANGELOG.md | 1 + src/agents/tools/nodes-tool.test.ts | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6430f91ea4..f59aa71fc2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -110,6 +110,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Telegram/DM topic session isolation: scope DM topic thread session keys by chat ID (`:`) and parse scoped thread IDs in outbound recovery so parallel DMs cannot collide on shared topic IDs. (#31064) Thanks @0xble. - Docs/Docker images: clarify the official GHCR image source and tag guidance (`main`, `latest`, ``), and document that `OPENCLAW_IMAGE` skips local image builds but still uses the repo-local compose/setup flow. (#27214, #31180) Fixes #15655. Thanks @ipl31. - Agents/Model fallback: classify additional network transport errors (`ECONNREFUSED`, `ENETUNREACH`, `EHOSTUNREACH`, `ENETRESET`, `EAI_AGAIN`) as failover-worthy so fallback chains advance when primary providers are unreachable. Landed from contributor PR #19077 by @ayanesakura. Thanks @ayanesakura. - Agents/Copilot token refresh: refresh GitHub Copilot runtime API tokens after auth-expiry failures and re-run with the renewed token so long-running embedded/subagent turns do not fail on mid-session 401 expiry. Landed from contributor PR #8805 by @Arthur742Ramos. Thanks @Arthur742Ramos. diff --git a/src/agents/tools/nodes-tool.test.ts b/src/agents/tools/nodes-tool.test.ts index 12ac63e4403..b7f787ff0ba 100644 --- a/src/agents/tools/nodes-tool.test.ts +++ b/src/agents/tools/nodes-tool.test.ts @@ -25,20 +25,20 @@ const screenMocks = vi.hoisted(() => ({ })); vi.mock("./gateway.js", () => ({ - callGatewayTool: gatewayMocks.callGatewayTool, - readGatewayCallOptions: gatewayMocks.readGatewayCallOptions, + callGatewayTool: (...args: unknown[]) => gatewayMocks.callGatewayTool(...args), + readGatewayCallOptions: (...args: unknown[]) => gatewayMocks.readGatewayCallOptions(...args), })); vi.mock("./nodes-utils.js", () => ({ - resolveNodeId: nodeUtilsMocks.resolveNodeId, - listNodes: nodeUtilsMocks.listNodes, - resolveNodeIdFromList: nodeUtilsMocks.resolveNodeIdFromList, + resolveNodeId: (...args: unknown[]) => nodeUtilsMocks.resolveNodeId(...args), + listNodes: (...args: unknown[]) => nodeUtilsMocks.listNodes(...args), + resolveNodeIdFromList: (...args: unknown[]) => nodeUtilsMocks.resolveNodeIdFromList(...args), })); vi.mock("../../cli/nodes-screen.js", () => ({ - parseScreenRecordPayload: screenMocks.parseScreenRecordPayload, - screenRecordTempPath: screenMocks.screenRecordTempPath, - writeScreenRecordToFile: screenMocks.writeScreenRecordToFile, + parseScreenRecordPayload: (...args: unknown[]) => screenMocks.parseScreenRecordPayload(...args), + screenRecordTempPath: (...args: unknown[]) => screenMocks.screenRecordTempPath(...args), + writeScreenRecordToFile: (...args: unknown[]) => screenMocks.writeScreenRecordToFile(...args), })); import { createNodesTool } from "./nodes-tool.js";