From 2a915e8af09adef67092b6f6c54b402b7054f74f Mon Sep 17 00:00:00 2001 From: Gavriel Cohen Date: Sat, 2 May 2026 15:24:57 +0300 Subject: [PATCH] fix(migrate-v2): infer is_group from JID format v1 didn't track is_group separately; db.ts hardcoded `is_group: 1` for every messaging_group. v2 uses is_group=0 to collapse DM sub-thread sessions and to drive routing decisions, so getting it wrong is latent risk on otherwise-working installs. New helper inferIsGroup(channelType, platformId) lives in shared.ts so tasks.ts and any future migration step can reuse it. Inferred per channel: - whatsapp: `@g.us` is a group, anything else is a DM - telegram: negative chat IDs are groups, positive are DMs - everything else: default to 1 (least surprising for chats v1 chose to register, where DM auto-create paths weren't used) Co-Authored-By: Claude Opus 4.7 (1M context) --- setup/migrate-v2/db.ts | 3 ++- setup/migrate-v2/shared.ts | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/setup/migrate-v2/db.ts b/setup/migrate-v2/db.ts index fb15ab0..da2bab7 100644 --- a/setup/migrate-v2/db.ts +++ b/setup/migrate-v2/db.ts @@ -29,6 +29,7 @@ import { readEnvFile } from '../../src/env.js'; import { buildDiscordResolver, type DiscordResolver } from './discord-resolver.js'; import { generateId, + inferIsGroup, parseJid, triggerToEngage, v2PlatformId, @@ -148,7 +149,7 @@ async function main(): Promise { channel_type: channelType, platform_id: platformId, name: g.name || null, - is_group: 1, + is_group: inferIsGroup(channelType, platformId), unknown_sender_policy: 'public', created_at: createdAt, }); diff --git a/setup/migrate-v2/shared.ts b/setup/migrate-v2/shared.ts index ff219df..58c0b16 100644 --- a/setup/migrate-v2/shared.ts +++ b/setup/migrate-v2/shared.ts @@ -74,6 +74,27 @@ export function v2PlatformId(channelType: string, jid: string): string { return id.startsWith(`${channelType}:`) ? id : `${channelType}:${id}`; } +/** + * Infer messaging_groups.is_group from a v2 platform_id, given a channel type. + * + * v1 didn't track is_group, but most channels encode it in the JID/id format: + * - whatsapp: `@g.us` is a group, `@s.whatsapp.net` / `@lid` is a DM + * - telegram: negative chat IDs are groups, positive are DMs + * - everything else: default to 1 (group/channel) — least-surprising guess + * for chats v1 chose to register, where DM auto-create paths weren't used + */ +export function inferIsGroup(channelType: string, platformId: string): number { + if (channelType === 'whatsapp') { + return platformId.endsWith('@g.us') ? 1 : 0; + } + if (channelType === 'telegram') { + // platform_id is `telegram:` — negative chatId means group/channel. + const chatId = platformId.replace(/^telegram:/, ''); + return chatId.startsWith('-') ? 1 : 0; + } + return 1; +} + // ── Trigger mapping ───────────────────────────────────────────────────── /**