// Package chat — мультиканальное общение с пользователем. // // Единый Router поверх любых Channel (Telegram / TUI / GUI...). Сессии // ключуются по UserID («кто»), доставка — по Address («где»), а pull/push // разница (polling/scan/подписка) скрыта внутри каждого Channel. // // Примитивы обмена: Send (уведомить), Ask (спросить, асинхронно), // + входящие события через OnMessage. Ask привязан к адресу вопроса. package chat import "context" // Address — «где» пользователь: конкретный канал+адрес (tg://123, tui://local). type Address string // UserID — «кто» владелец сессии (один на человека, канал неважен). type UserID string // Option — выбор (кнопка в TG, пронумерованный пункт в TUI). type Option struct { ID string Label string } // Message — один исходящий/входящий контент. type Message struct { Text string Options []Option // Confirm = Ask с да/нет; выбор = список QuestionID string // блок 4: идентификатор вопроса в каждом Message } // Incoming — входящее событие, канал сам заполняет UserID/Address. type Incoming struct { UserID UserID Address Address Msg Message Channel Channel } // Handler — единый вход всех каналов в Router. type Handler func(Incoming) // Channel — любой канал связи. pull/push разница скрыта внутри Run. type Channel interface { // Run запускает цикл канала (polling/scan/подписка). Может вернуть // M5 ChannelFatal — тогда Router перезапустит канал. Run(ctx context.Context) error // OnMessage регистрирует единый обработчик входящих (Router). OnMessage(h Handler) // Send — fire-and-forget уведомление. M1 если нет адреса, M2 если не доставлено. Send(ctx context.Context, to Address, m Message) error // Ask — неблокирующий вопрос: регистрирует pending и возвращается сразу. // M3 если pending уже открыт. Ответ придёт через OnMessage с тем же QuestionID. Ask(ctx context.Context, to Address, prompt Message) error // Close закрывает канал. Close() error } // PendingQ — незакрытый вопрос (блок 4: один на сессию). type PendingQ struct { UserID UserID AnswerAddr Address Msg Message } // Route — куда доставить следующий ответ пользователю. type Route struct { Address Address Channel Channel }