refactor: drop legacy room chatType

This commit is contained in:
Peter Steinberger
2026-01-17 05:40:28 +00:00
parent 07a3db153d
commit 8b42902cee
18 changed files with 19 additions and 42 deletions

View File

@@ -12,6 +12,7 @@
### Breaking
- **BREAKING:** Channel auth now prefers config over env for Discord/Telegram/Matrix (env is fallback only). (#1040) — thanks @thewilloftheshadow.
- **BREAKING:** `clawdbot message` and message tool now require `target` (dropping `to`/`channelId` for destinations). (#1034) — thanks @tobalsan.
- **BREAKING:** Drop legacy `chatType: "room"` support; use `chatType: "channel"`.
### Changes
- Tools: improve `web_fetch` extraction using Readability (with fallback).

View File

@@ -309,7 +309,6 @@ export function createSessionStatusTool(opts?: {
const isGroup =
resolved.entry.chatType === "group" ||
resolved.entry.chatType === "channel" ||
resolved.entry.chatType === "room" ||
resolved.key.startsWith("group:") ||
resolved.key.includes(":group:") ||
resolved.key.includes(":channel:");

View File

@@ -299,8 +299,7 @@ export async function runPreparedReply(
});
const isGroupSession =
sessionEntry?.chatType === "group" ||
sessionEntry?.chatType === "channel" ||
sessionEntry?.chatType === "room";
sessionEntry?.chatType === "channel";
const isMainSession = !isGroupSession && sessionKey === normalizeMainKey(sessionCfg?.mainKey);
prefixedBodyBase = await prependSystemEvents({
cfg,

View File

@@ -8,7 +8,7 @@ describe("finalizeInboundContext", () => {
const ctx: MsgContext = {
Body: "a\\nb\r\nc",
RawBody: "raw\\nline",
ChatType: "room",
ChatType: "channel",
From: "group:123@g.us",
GroupSubject: "Test",
};
@@ -35,4 +35,3 @@ describe("finalizeInboundContext", () => {
expect(ctx.BodyForCommands).toBe("say hi");
});
});

View File

@@ -254,7 +254,6 @@ export function buildStatusMessage(args: StatusArgs): string {
const isGroupSession =
entry?.chatType === "group" ||
entry?.chatType === "channel" ||
entry?.chatType === "room" ||
Boolean(args.sessionKey?.includes(":group:")) ||
Boolean(args.sessionKey?.includes(":channel:")) ||
Boolean(args.sessionKey?.startsWith("group:"));

View File

@@ -8,13 +8,12 @@ describe("normalizeChatType", () => {
expect(normalizeChatType("dm")).toBe("direct");
expect(normalizeChatType("group")).toBe("group");
expect(normalizeChatType("channel")).toBe("channel");
expect(normalizeChatType("room")).toBe("channel");
});
it("returns undefined for empty/unknown values", () => {
expect(normalizeChatType(undefined)).toBeUndefined();
expect(normalizeChatType("")).toBeUndefined();
expect(normalizeChatType("nope")).toBeUndefined();
expect(normalizeChatType("room")).toBeUndefined();
});
});

View File

@@ -5,7 +5,6 @@ export function normalizeChatType(raw?: string): NormalizedChatType | undefined
if (!value) return undefined;
if (value === "direct" || value === "dm") return "direct";
if (value === "group") return "group";
if (value === "channel" || value === "room") return "channel";
if (value === "channel") return "channel";
return undefined;
}

View File

@@ -110,7 +110,7 @@ const formatAge = (ms: number | null | undefined) => {
function classifyKey(key: string, entry?: SessionEntry): SessionRow["kind"] {
if (key === "global") return "global";
if (key === "unknown") return "unknown";
if (entry?.chatType === "group" || entry?.chatType === "channel" || entry?.chatType === "room") {
if (entry?.chatType === "group" || entry?.chatType === "channel") {
return "group";
}
if (key.startsWith("group:") || key.includes(":group:") || key.includes(":channel:")) {

View File

@@ -19,7 +19,7 @@ import type { HeartbeatStatus, SessionStatus, StatusSummary } from "./status.typ
const classifyKey = (key: string, entry?: SessionEntry): SessionStatus["kind"] => {
if (key === "global") return "global";
if (key === "unknown") return "unknown";
if (entry?.chatType === "group" || entry?.chatType === "channel" || entry?.chatType === "room") {
if (entry?.chatType === "group" || entry?.chatType === "channel") {
return "group";
}
if (key.startsWith("group:") || key.includes(":group:") || key.includes(":channel:")) {

View File

@@ -10,9 +10,7 @@ export type SessionChannelId = ChannelId | "webchat";
export type SessionChatType =
| "direct"
| "group"
| "channel"
// Legacy alias for "channel".
| "room";
| "channel";
export type SessionEntry = {
/**

View File

@@ -41,7 +41,7 @@ export type HumanDelayConfig = {
export type SessionSendPolicyAction = "allow" | "deny";
export type SessionSendPolicyMatch = {
channel?: string;
chatType?: "direct" | "group" | "channel" | "room";
chatType?: "direct" | "group" | "channel";
keyPrefix?: string;
};
export type SessionSendPolicyRule = {

View File

@@ -2,7 +2,7 @@ import type { AgentElevatedAllowFromConfig, SessionSendPolicyAction } from "./ty
export type MediaUnderstandingScopeMatch = {
channel?: string;
chatType?: "direct" | "group" | "channel" | "room";
chatType?: "direct" | "group" | "channel";
keyPrefix?: string;
};

View File

@@ -255,7 +255,6 @@ export const MediaUnderstandingScopeSchema = z
z.literal("direct"),
z.literal("group"),
z.literal("channel"),
z.literal("room"),
])
.optional(),
keyPrefix: z.string().optional(),

View File

@@ -43,8 +43,6 @@ export const SessionSchema = z
z.literal("direct"),
z.literal("group"),
z.literal("channel"),
// Legacy alias for "channel".
z.literal("room"),
])
.optional(),
keyPrefix: z.string().optional(),

View File

@@ -59,7 +59,7 @@ export function loadSessionEntry(sessionKey: string) {
export function classifySessionKey(key: string, entry?: SessionEntry): GatewaySessionRow["kind"] {
if (key === "global") return "global";
if (key === "unknown") return "unknown";
if (entry?.chatType === "group" || entry?.chatType === "channel" || entry?.chatType === "room") {
if (entry?.chatType === "group" || entry?.chatType === "channel") {
return "group";
}
if (key.startsWith("group:") || key.includes(":group:") || key.includes(":channel:")) {

View File

@@ -15,7 +15,7 @@ export type GatewaySessionRow = {
subject?: string;
room?: string;
space?: string;
chatType?: "direct" | "group" | "channel" | "room";
chatType?: "direct" | "group" | "channel";
updatedAt: number | null;
sessionId?: string;
systemSent?: boolean;

View File

@@ -3,17 +3,10 @@ import { describe, expect, it } from "vitest";
import { normalizeMediaUnderstandingChatType, resolveMediaUnderstandingScope } from "./scope.js";
describe("media understanding scope", () => {
it("normalizes channel/room", () => {
it("normalizes chatType", () => {
expect(normalizeMediaUnderstandingChatType("channel")).toBe("channel");
expect(normalizeMediaUnderstandingChatType("room")).toBe("channel");
});
it("treats room match as channel", () => {
const scope = {
rules: [{ action: "deny", match: { chatType: "room" } }],
} as const;
expect(resolveMediaUnderstandingScope({ scope, chatType: "channel" })).toBe("deny");
expect(normalizeMediaUnderstandingChatType("dm")).toBe("direct");
expect(normalizeMediaUnderstandingChatType("room")).toBeUndefined();
});
it("matches channel chatType explicitly", () => {
@@ -24,4 +17,3 @@ describe("media understanding scope", () => {
expect(resolveMediaUnderstandingScope({ scope, chatType: "channel" })).toBe("deny");
});
});

View File

@@ -1,4 +1,5 @@
import type { MediaUnderstandingScopeConfig } from "../config/types.tools.js";
import { normalizeChatType } from "../channels/chat-type.js";
export type MediaUnderstandingScopeDecision = "allow" | "deny";
@@ -15,12 +16,7 @@ function normalizeMatch(value?: string | null): string | undefined {
}
export function normalizeMediaUnderstandingChatType(raw?: string | null): string | undefined {
const value = raw?.trim().toLowerCase();
if (!value) return undefined;
if (value === "dm" || value === "direct_message" || value === "private") return "direct";
if (value === "groups") return "group";
if (value === "room") return "channel";
return value;
return normalizeChatType(raw ?? undefined);
}
export function resolveMediaUnderstandingScope(params: {
@@ -33,7 +29,7 @@ export function resolveMediaUnderstandingScope(params: {
if (!scope) return "allow";
const channel = normalizeMatch(params.channel);
const chatType = normalizeMediaUnderstandingChatType(params.chatType) ?? normalizeMatch(params.chatType);
const chatType = normalizeMediaUnderstandingChatType(params.chatType);
const sessionKey = normalizeMatch(params.sessionKey) ?? "";
for (const rule of scope.rules ?? []) {
@@ -41,8 +37,7 @@ export function resolveMediaUnderstandingScope(params: {
const action = normalizeDecision(rule.action) ?? "allow";
const match = rule.match ?? {};
const matchChannel = normalizeMatch(match.channel);
const matchChatType =
normalizeMediaUnderstandingChatType(match.chatType) ?? normalizeMatch(match.chatType);
const matchChatType = normalizeMediaUnderstandingChatType(match.chatType);
const matchPrefix = normalizeMatch(match.keyPrefix);
if (matchChannel && matchChannel !== channel) continue;