План независимого от каналов привязки сессий
Обзор
В этом документе определена долгосрочная модель привязки сессий, не зависящая от канала, и конкретный объем следующей итерации реализации. Цель:
- сделать маршрутизацию сессий, привязанных к сабагенту, основной возможностью
- оставить специфичное для канала поведение в адаптерах
- избежать регрессий в обычном поведении Discord
Зачем это нужно
Текущее поведение смешивает:
- политику контента завершений
- политику маршрутизации назначения
- специфичные для Discord детали
Это вызывало крайние случаи, такие как:
- дублирование доставки в основной канал и тред при параллельных запусках
- использование устаревших токенов при повторном использовании менеджеров привязки
- отсутствие учета активности для отправок через вебхук
Объем итерации 1
Эта итерация намеренно ограничена.
1. Добавление основных интерфейсов, не зависящих от канала
Добавление основных типов и интерфейсов сервисов для привязок и маршрутизации. Предлагаемые основные типы:
export type BindingTargetKind = "subagent" | "session";
export type BindingStatus = "active" | "ending" | "ended";
export type ConversationRef = {
channel: string;
accountId: string;
conversationId: string;
parentConversationId?: string;
};
export type SessionBindingRecord = {
bindingId: string;
targetSessionKey: string;
targetKind: BindingTargetKind;
conversation: ConversationRef;
status: BindingStatus;
boundAt: number;
expiresAt?: number;
metadata?: Record<string, unknown>;
};
Контракт основного сервиса:
export interface SessionBindingService {
bind(input: {
targetSessionKey: string;
targetKind: BindingTargetKind;
conversation: ConversationRef;
metadata?: Record<string, unknown>;
ttlMs?: number;
}): Promise<SessionBindingRecord>;
listBySession(targetSessionKey: string): SessionBindingRecord[];
resolveByConversation(ref: ConversationRef): SessionBindingRecord | null;
touch(bindingId: string, at?: number): void;
unbind(input: {
bindingId?: string;
targetSessionKey?: string;
reason: string;
}): Promise<SessionBindingRecord[]>;
}
2. Добавление одного основного маршрутизатора доставки для завершений сабагентов
Добавление единого пути разрешения назначения для событий завершения. Контракт маршрутизатора:
export interface BoundDeliveryRouter {
resolveDestination(input: {
eventKind: "task_completion";
targetSessionKey: string;
requester?: ConversationRef;
failClosed: boolean;
}): {
binding: SessionBindingRecord | null;
mode: "bound" | "fallback";
reason: string;
};
}
Для этой итерации:
- только
task_completionмаршрутизируется через этот новый путь - существующие пути для других видов событий остаются без изменений
3. Оставить Discord в качестве адаптера
Discord остается первой реализацией адаптера. Обязанности адаптера:
- создание/повторное использование тредов-бесед
- отправка привязанных сообщений через вебхук или отправку в канал
- проверка состояния треда (архивирован/удален)
- сопоставление метаданных адаптера (идентификатор вебхука, id тредов)
4. Исправление известных на данный момент проблем корректности
Требуется в этой итерации:
- обновление использования токена при повторном использовании существующего менеджера привязки треда
- запись исходящей активности для отправок в Discord через вебхук
- остановка неявного возврата на основной канал, когда для завершения в режиме сессии выбрано назначение в привязанном треде
5. Сохранение текущих настроек безопасности времени выполнения
Без изменения поведения для пользователей с отключенной привязкой порождения к треду. Настройки по умолчанию остаются:
channels.discord.threadBindings.spawnSubagentSessions = false
Результат:
- обычные пользователи Discord остаются на текущем поведении
- новый основной путь затрагивает только маршрутизацию завершений привязанных сессий, где она включена
Не входит в итерацию 1
Явно отложено:
- цели привязки ACP (
targetKind: "acp") - новые адаптеры каналов помимо Discord
- глобальная замена всех путей доставки (
spawn_ack, будущийsubagent_message) - изменения на уровне протокола
- редизайн миграции хранилища/версионирования для всего постоянного хранения привязок
Примечания по ACP:
- дизайн интерфейса оставляет место для ACP
- реализация ACP не начинается в этой итерации
Инварианты маршрутизации
Эти инварианты обязательны для итерации 1.
- выбор назначения и генерация контента являются отдельными шагами
- если завершение в режиме сессии разрешается в активное привязанное назначение, доставка должна быть нацелена на это назначение
- никакой скрытой перемаршрутизации с привязанного назначения на основной канал
- поведение возврата должно быть явным и наблюдаемым
Совместимость и внедрение
Цель совместимости:
- отсутствие регрессии для пользователей с отключенной привязкой порождения к треду
- отсутствие изменений для не-Discord каналов в этой итерации
Внедрение:
- Внедрение интерфейсов и маршрутизатора за текущими флаг-гейтами.
- Маршрутизация привязанных доставок завершений Discord через маршрутизатор.
- Сохранение старого пути для непривязанных потоков.
- Проверка с помощью целевых тестов и логов канареечного запуска.
Требуемые тесты в итерации 1
Требуется покрытие модульными и интеграционными тестами:
- ротация токенов менеджера использует последний токен после повторного использования менеджера
- отправки через вебхук обновляют временные метки активности канала
- две активные привязанные сессии в одном канале инициатора не дублируются в основной канал
- завершение для запуска в режиме привязанной сессии разрешается только в назначение треда
- отключенный флаг порождения оставляет старое поведение неизменным
Предлагаемые файлы реализации
Основное:
src/infra/outbound/session-binding-service.ts(новый)src/infra/outbound/bound-delivery-router.ts(новый)src/agents/subagent-announce.ts(интеграция разрешения назначения завершений)
Адаптер Discord и среда выполнения:
src/discord/monitor/thread-bindings.manager.tssrc/discord/monitor/reply-delivery.tssrc/discord/send.outbound.ts
Тесты:
src/discord/monitor/provider*.test.tssrc/discord/monitor/reply-delivery.test.tssrc/agents/subagent-announce.format.test.ts
Критерии завершения итерации 1
- основные интерфейсы существуют и подключены для маршрутизации завершений
- указанные выше исправления корректности объединены с тестами
- отсутствие дублирования доставки завершений в основной канал и тред для запусков в режиме привязанной сессии
- отсутствие изменения поведения для развертываний с отключенной привязкой порождения
- ACP остается явно отложенным
План PTY и супервизии процессовИсследование памяти рабочего пространства