From 2b64fec0e6de457b679188029ac53c0055bc83df Mon Sep 17 00:00:00 2001 From: gavrielc Date: Thu, 9 Apr 2026 11:42:49 +0300 Subject: [PATCH] fix: clean up iMessage adapter type compatibility Replace `as never` cast with proper polyfill for channelIdFromThreadId. Narrow GatewayAdapter cast to only the gateway code path in bridge. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/channels/chat-sdk-bridge.ts | 9 +++++---- src/channels/imessage.ts | 8 ++++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/channels/chat-sdk-bridge.ts b/src/channels/chat-sdk-bridge.ts index 5ab9d88..e87e098 100644 --- a/src/channels/chat-sdk-bridge.ts +++ b/src/channels/chat-sdk-bridge.ts @@ -31,7 +31,7 @@ interface GatewayAdapter extends Adapter { } export interface ChatSdkBridgeConfig { - adapter: GatewayAdapter; + adapter: Adapter; concurrency?: ConcurrencyStrategy; /** Bot token for authenticating forwarded Gateway events (required for interaction handling). */ botToken?: string; @@ -114,17 +114,18 @@ export function createChatSdkBridge(config: ChatSdkBridgeConfig): ChannelAdapter await chat.initialize(); // Start Gateway listener for adapters that support it (e.g., Discord) - if (adapter.startGatewayListener) { + const gatewayAdapter = adapter as GatewayAdapter; + if (gatewayAdapter.startGatewayListener) { gatewayAbort = new AbortController(); // Start local HTTP server to receive forwarded Gateway events (including interactions) - const webhookUrl = await startLocalWebhookServer(adapter, setupConfig, config.botToken); + const webhookUrl = await startLocalWebhookServer(gatewayAdapter, setupConfig, config.botToken); const startGateway = () => { if (gatewayAbort?.signal.aborted) return; // Capture the long-running listener promise via waitUntil let listenerPromise: Promise | undefined; - adapter.startGatewayListener!( + gatewayAdapter.startGatewayListener!( { waitUntil: (p: Promise) => { listenerPromise = p; diff --git a/src/channels/imessage.ts b/src/channels/imessage.ts index 8ab4215..4bda288 100644 --- a/src/channels/imessage.ts +++ b/src/channels/imessage.ts @@ -15,11 +15,15 @@ registerChannelAdapter('imessage', { const isLocal = env.IMESSAGE_LOCAL !== 'false'; if (isLocal && !env.IMESSAGE_ENABLED) return null; if (!isLocal && !env.IMESSAGE_SERVER_URL) return null; - const imessageAdapter = createiMessageAdapter({ + const rawAdapter = createiMessageAdapter({ local: isLocal, serverUrl: env.IMESSAGE_SERVER_URL, apiKey: env.IMESSAGE_API_KEY, }); - return createChatSdkBridge({ adapter: imessageAdapter as never, concurrency: 'concurrent' }); + // Polyfill channelIdFromThreadId (community adapter doesn't implement it) + const imessageAdapter = Object.assign(rawAdapter, { + channelIdFromThreadId: (threadId: string) => threadId, + }); + return createChatSdkBridge({ adapter: imessageAdapter, concurrency: 'concurrent' }); }, });