feat: add channel adapter abstraction with Telegram and WebChat adapters

Implement Phase 3 channel adapters that decouple message sources from
the agent via a uniform ChannelAdapter interface and ChannelRegistry.

- Add ChannelAdapter/InboundMessage/OutboundMessage types
- Add ChannelRegistry for adapter lifecycle and message routing
- Add TelegramAdapter (grammy bot, auth middleware, confirmations, chunking)
- Add WebChatAdapter (thin shim over GatewayServer)
- Refactor daemon to use ChannelRegistry with per-channel-per-user agents
- Add config.get/config.patch gateway handlers (Phase 2 loose end)
- Add system.restart gateway handler (Phase 2 loose end)
- Add implementation plans and design docs

Tests: 225 passing (33 new channel adapter + gateway handler tests)
This commit is contained in:
William Valentin
2026-02-05 20:00:36 -08:00
parent 282a15d2b9
commit aa95f2132c
19 changed files with 4123 additions and 37 deletions
+14
View File
@@ -18,8 +18,10 @@ import {
createSessionHandlers,
createToolHandlers,
createAgentHandlers,
createConfigHandlers,
} from './handlers/index.js';
import type { SessionManager } from '../session/manager.js';
import type { Config } from '../config/index.js';
import type { ToolRegistry } from '../tools/registry.js';
import type { ToolExecutor } from '../tools/executor.js';
@@ -34,6 +36,9 @@ export interface GatewayServerConfig {
version?: string;
auth?: AuthConfig;
uiDir?: string;
config?: Config;
/** Optional callback for system.restart. Should trigger graceful shutdown + process restart. */
restart?: () => Promise<void>;
}
export class GatewayServer {
@@ -67,6 +72,7 @@ export class GatewayServer {
getSessionCount: () => this.sessionBridge.listSessions().length,
getToolCount: () => this.config.toolRegistry.list().length,
getConnectionCount: () => this.sessionBridge.connectionCount,
restart: this.config.restart,
});
const sessionHandlers = createSessionHandlers({
@@ -82,6 +88,14 @@ export class GatewayServer {
sessionBridge: this.sessionBridge,
});
// Config handlers (only if config object is provided)
if (this.config.config) {
const configHandlers = createConfigHandlers({ config: this.config.config });
for (const [method, handler] of Object.entries(configHandlers)) {
this.router.register(method, handler);
}
}
// Register all methods
for (const [method, handler] of Object.entries(systemHandlers)) {
this.router.register(method, handler);