From e6477363e917155060d81b6fc2a64c07d7ad578f Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 17 Jan 2026 07:58:54 +0000 Subject: [PATCH] refactor: normalize channel capabilities typing --- src/agents/pty-dsr.ts | 4 ++-- src/config/channel-capabilities.test.ts | 14 +++++++------- src/config/channel-capabilities.ts | 21 +++++++++++++-------- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/agents/pty-dsr.ts b/src/agents/pty-dsr.ts index 55040cdb5..5ff88ab1d 100644 --- a/src/agents/pty-dsr.ts +++ b/src/agents/pty-dsr.ts @@ -1,5 +1,5 @@ -// eslint-disable-next-line no-control-regex -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/config/channel-capabilities.test.ts b/src/config/channel-capabilities.test.ts index 9e5dccac7..d70dd8095 100644 --- a/src/config/channel-capabilities.test.ts +++ b/src/config/channel-capabilities.test.ts @@ -16,8 +16,8 @@ describe("resolveChannelCapabilities", () => { it("returns undefined for missing inputs", () => { expect(resolveChannelCapabilities({})).toBeUndefined(); - expect(resolveChannelCapabilities({ cfg: {} as ClawdbotConfig })).toBeUndefined(); - expect(resolveChannelCapabilities({ cfg: {} as ClawdbotConfig, channel: "" })).toBeUndefined(); + expect(resolveChannelCapabilities({ cfg: {} })).toBeUndefined(); + expect(resolveChannelCapabilities({ cfg: {}, channel: "" })).toBeUndefined(); }); it("normalizes and prefers per-account capabilities", () => { @@ -36,7 +36,7 @@ describe("resolveChannelCapabilities", () => { expect( resolveChannelCapabilities({ - cfg: cfg as ClawdbotConfig, + cfg, channel: "telegram", accountId: "default", }), @@ -57,7 +57,7 @@ describe("resolveChannelCapabilities", () => { expect( resolveChannelCapabilities({ - cfg: cfg as ClawdbotConfig, + cfg, channel: "telegram", accountId: "default", }), @@ -77,7 +77,7 @@ describe("resolveChannelCapabilities", () => { expect( resolveChannelCapabilities({ - cfg: cfg as ClawdbotConfig, + cfg, channel: "slack", accountId: "family", }), @@ -100,7 +100,7 @@ describe("resolveChannelCapabilities", () => { expect( resolveChannelCapabilities({ - cfg: cfg as ClawdbotConfig, + cfg, channel: "msteams", }), ).toEqual(["polls"]); @@ -120,7 +120,7 @@ describe("resolveChannelCapabilities", () => { // Should return undefined (not crash), allowing channel-specific handlers to process it. expect( resolveChannelCapabilities({ - cfg: cfg as ClawdbotConfig, + cfg, channel: "telegram", }), ).toBeUndefined(); diff --git a/src/config/channel-capabilities.ts b/src/config/channel-capabilities.ts index 08ffc1b8b..739c65415 100644 --- a/src/config/channel-capabilities.ts +++ b/src/config/channel-capabilities.ts @@ -1,19 +1,24 @@ import { normalizeChannelId } from "../channels/plugins/index.js"; import { normalizeAccountId } from "../routing/session-key.js"; import type { ClawdbotConfig } from "./config.js"; +import type { TelegramCapabilitiesConfig } from "./types.telegram.js"; -function normalizeCapabilities(capabilities: string[] | undefined): string[] | undefined { - if (!capabilities) return undefined; +type CapabilitiesConfig = TelegramCapabilitiesConfig; + +const isStringArray = (value: unknown): value is string[] => + Array.isArray(value) && value.every((entry) => typeof entry === "string"); + +function normalizeCapabilities(capabilities: CapabilitiesConfig | undefined): string[] | undefined { // Handle object-format capabilities (e.g., { inlineButtons: "dm" }) gracefully. // Channel-specific handlers (like resolveTelegramInlineButtonsScope) process these separately. - if (!Array.isArray(capabilities)) return undefined; + if (!isStringArray(capabilities)) return undefined; const normalized = capabilities.map((entry) => entry.trim()).filter(Boolean); return normalized.length > 0 ? normalized : undefined; } function resolveAccountCapabilities(params: { - cfg?: { accounts?: Record } & { - capabilities?: string[]; + cfg?: { accounts?: Record } & { + capabilities?: CapabilitiesConfig; }; accountId?: string | null; }): string[] | undefined { @@ -40,7 +45,7 @@ function resolveAccountCapabilities(params: { } export function resolveChannelCapabilities(params: { - cfg?: ClawdbotConfig; + cfg?: Partial; channel?: string | null; accountId?: string | null; }): string[] | undefined { @@ -51,8 +56,8 @@ export function resolveChannelCapabilities(params: { const channelsConfig = cfg.channels as Record | undefined; const channelConfig = (channelsConfig?.[channel] ?? (cfg as Record)[channel]) as | { - accounts?: Record; - capabilities?: string[]; + accounts?: Record; + capabilities?: CapabilitiesConfig; } | undefined; return resolveAccountCapabilities({