From c8e58583c0b1dfa233ec41897b7b9ab2f99c89d0 Mon Sep 17 00:00:00 2001 From: HCL Date: Tue, 5 May 2026 00:13:20 +0800 Subject: [PATCH] fix(active-memory): skip colon-containing channels from session store (#77396) QQ c2c agent IDs such as `c2c:10D4F7C2...` were stored as the session channel. When the recall subagent resolved this as a runnable channel the colon reached `normalizeBundledPluginDirName` which rejects names containing `:`, crashing the recall run. Apply the same guard already used for explicit `channelId` params (#76704) to store-derived channels. --- CHANGELOG.md | 1 + extensions/active-memory/index.ts | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a149cb9fb5..0d6ff1d07ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Docs: https://docs.openclaw.ai ### Changes +- Plugins/active-memory: skip session-store channel entries that contain `:` when resolving the recall subagent's channel, so QQ c2c agent IDs (e.g. `c2c:10D4F7C2…`) and other scoped conversation IDs do not reach bundled-plugin `dirName` validation and crash the recall run. The same guard already applied to explicit `channelId` params (#76704); this extends it to store-derived channels. (#77396) - Models/auth: add `openclaw models auth list [--provider ] [--json]` so users can inspect saved per-agent auth profiles without dumping secrets or hitting the old “too many arguments” path. Thanks @vincentkoc. - Control UI/header: show the active agent name in dashboard breadcrumbs without adding the current session key, keeping non-chat views oriented without crowding the topbar. - Control UI/cron: make the New Job sidebar collapsible so the jobs list can reclaim space while keeping the form one click away. Thanks @BunsDev. diff --git a/extensions/active-memory/index.ts b/extensions/active-memory/index.ts index a7d4e195953..314c3df6490 100644 --- a/extensions/active-memory/index.ts +++ b/extensions/active-memory/index.ts @@ -560,9 +560,17 @@ function resolveRecallRunChannelContext(params: { store, sessionKey: resolvedSessionKey, }).existing; - const strongEntryChannel = + const rawStrongEntryChannel = normalizeOptionalString(sessionEntry?.lastChannel) ?? normalizeOptionalString(sessionEntry?.channel); + // Channel IDs containing ":" are scoped conversation IDs (e.g. QQ c2c + // "c2c:10D4F7C2..."), not runnable channel names. The same guard that + // applies to explicit channelId (#76704) must also apply to channels + // read from the session store (#77396). + const strongEntryChannel = + rawStrongEntryChannel && !rawStrongEntryChannel.includes(":") + ? rawStrongEntryChannel + : undefined; const weakEntryChannel = normalizeOptionalString(sessionEntry?.origin?.provider); return resolveReturnValue({ resolvedChannel: strongEntryChannel ?? weakEntryChannel,