v2 phase 4: channel adapter interface, registry, and host wiring
ChannelAdapter interface with setup/deliver/teardown/setTyping lifecycle. Self-registration pattern via channel-registry. Host wiring in index-v2 bridges inbound messages to routeInbound and outbound delivery to adapters. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
72
src/channels/channel-registry.ts
Normal file
72
src/channels/channel-registry.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* v2 Channel adapter registry.
|
||||
*
|
||||
* Channels self-register on import. The host calls initChannelAdapters() at startup
|
||||
* to instantiate and set up all registered adapters.
|
||||
*/
|
||||
import type { ChannelAdapter, ChannelRegistration, ChannelSetup } from './adapter.js';
|
||||
import { log } from '../log.js';
|
||||
|
||||
const registry = new Map<string, ChannelRegistration>();
|
||||
const activeAdapters = new Map<string, ChannelAdapter>();
|
||||
|
||||
/** Register a channel adapter factory. Called by channel modules on import. */
|
||||
export function registerChannelAdapter(name: string, registration: ChannelRegistration): void {
|
||||
registry.set(name, registration);
|
||||
}
|
||||
|
||||
/** Get a live adapter by channel type. */
|
||||
export function getChannelAdapter(channelType: string): ChannelAdapter | undefined {
|
||||
return activeAdapters.get(channelType);
|
||||
}
|
||||
|
||||
/** Get all active adapters. */
|
||||
export function getActiveAdapters(): ChannelAdapter[] {
|
||||
return [...activeAdapters.values()];
|
||||
}
|
||||
|
||||
/** Get all registered channel names. */
|
||||
export function getRegisteredChannelNames(): string[] {
|
||||
return [...registry.keys()];
|
||||
}
|
||||
|
||||
/** Get container config for a channel (used by container-runner for additional mounts/env). */
|
||||
export function getChannelContainerConfig(name: string): ChannelRegistration['containerConfig'] {
|
||||
return registry.get(name)?.containerConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate and set up all registered channel adapters.
|
||||
* Skips adapters that return null (missing credentials).
|
||||
*/
|
||||
export async function initChannelAdapters(setupFn: (adapter: ChannelAdapter) => ChannelSetup): Promise<void> {
|
||||
for (const [name, registration] of registry) {
|
||||
try {
|
||||
const adapter = registration.factory();
|
||||
if (!adapter) {
|
||||
log.warn('Channel credentials missing, skipping', { channel: name });
|
||||
continue;
|
||||
}
|
||||
|
||||
const setup = setupFn(adapter);
|
||||
await adapter.setup(setup);
|
||||
activeAdapters.set(adapter.channelType, adapter);
|
||||
log.info('Channel adapter started', { channel: name, type: adapter.channelType });
|
||||
} catch (err) {
|
||||
log.error('Failed to start channel adapter', { channel: name, err });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Tear down all active adapters. */
|
||||
export async function teardownChannelAdapters(): Promise<void> {
|
||||
for (const [name, adapter] of activeAdapters) {
|
||||
try {
|
||||
await adapter.teardown();
|
||||
log.info('Channel adapter stopped', { channel: name });
|
||||
} catch (err) {
|
||||
log.error('Failed to stop channel adapter', { channel: name, err });
|
||||
}
|
||||
}
|
||||
activeAdapters.clear();
|
||||
}
|
||||
Reference in New Issue
Block a user