From 3ab4c3a3c447925faa5e0f11ca24f3e809b283bd Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 17 Jan 2026 07:31:19 +0000 Subject: [PATCH] fix: add object capabilities coverage (#1071) (thanks @danielz1z) --- CHANGELOG.md | 1 + src/agents/pty-dsr.ts | 3 ++- src/cli/hooks-cli.ts | 6 +++--- src/config/channel-capabilities.test.ts | 23 +++++++++++++++++++++++ 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81f26700340..dad7659e799 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ ### Fixes - Sub-agents: normalize announce delivery origin + queue bucketing by accountId to keep multi-account routing stable. (#1061, #1058) — thanks @adam91holt. +- Config: handle object-format Telegram capabilities in channel capability resolution. (#1071) — thanks @danielz1z. - Sessions: include deliveryContext in sessions.list and reuse normalized delivery routing for announce/restart fallbacks. (#1058) - Sessions: propagate deliveryContext into last-route updates to keep account/channel routing stable. (#1058) - Gateway: honor explicit delivery targets without implicit accountId fallback; preserve lastAccountId for implicit routing. diff --git a/src/agents/pty-dsr.ts b/src/agents/pty-dsr.ts index 0a3533ec600..5ff88ab1de1 100644 --- a/src/agents/pty-dsr.ts +++ b/src/agents/pty-dsr.ts @@ -1,4 +1,5 @@ -const DSR_PATTERN = /\x1b\[\??6n/g; +const ESC = String.fromCharCode(0x1b); +const DSR_PATTERN = new RegExp(`${ESC}\\[\\??6n`, "g"); export function stripDsrRequests(input: string): { cleaned: string; requests: number } { let requests = 0; diff --git a/src/cli/hooks-cli.ts b/src/cli/hooks-cli.ts index 8c31eaa492c..3a85af0d6c3 100644 --- a/src/cli/hooks-cli.ts +++ b/src/cli/hooks-cli.ts @@ -679,15 +679,15 @@ export function registerHooksCli(program: Command): void { for (const hookId of targets) { const record = installs[hookId]; if (!record) { - defaultRuntime.log(chalk.yellow(`No install record for \"${hookId}\".`)); + defaultRuntime.log(chalk.yellow(`No install record for "${hookId}".`)); continue; } if (record.source !== "npm") { - defaultRuntime.log(chalk.yellow(`Skipping \"${hookId}\" (source: ${record.source}).`)); + defaultRuntime.log(chalk.yellow(`Skipping "${hookId}" (source: ${record.source}).`)); continue; } if (!record.spec) { - defaultRuntime.log(chalk.yellow(`Skipping \"${hookId}\" (missing npm spec).`)); + defaultRuntime.log(chalk.yellow(`Skipping "${hookId}" (missing npm spec).`)); continue; } diff --git a/src/config/channel-capabilities.test.ts b/src/config/channel-capabilities.test.ts index 9e5dccac7bd..46767a9b1fa 100644 --- a/src/config/channel-capabilities.test.ts +++ b/src/config/channel-capabilities.test.ts @@ -125,6 +125,29 @@ describe("resolveChannelCapabilities", () => { }), ).toBeUndefined(); }); + + it("falls back to channel capabilities when account capabilities use object format", () => { + const cfg = { + channels: { + telegram: { + capabilities: ["inlineButtons"], + accounts: { + default: { + capabilities: { inlineButtons: "dm" }, + }, + }, + }, + }, + } satisfies Partial; + + expect( + resolveChannelCapabilities({ + cfg: cfg as ClawdbotConfig, + channel: "telegram", + accountId: "default", + }), + ).toEqual(["inlineButtons"]); + }); }); const createRegistry = (channels: PluginRegistry["channels"]): PluginRegistry => ({