Kế hoạch binding phiên độc lập kênh
Tổng quan
Tài liệu này định nghĩa mô hình binding phiên độc lập kênh dài hạn và phạm vi cụ thể cho iteration triển khai tiếp theo.
Mục tiêu:
- làm cho định tuyến phiên bound subagent trở thành khả năng cốt lõi
- giữ hành vi riêng kênh trong adapter
- tránh regression trong hành vi Discord bình thường
Tại sao điều này tồn tại
Hành vi hiện tại trộn lẫn:
- chính sách nội dung hoàn thành
- chính sách định tuyến đích
- chi tiết riêng Discord
Điều này gây ra trường hợp biên như:
- phân phối main và thread trùng lặp dưới run đồng thời
- sử dụng token cũ trên manager binding được tái sử dụng
- kế toán hoạt động thiếu cho webhook send
Phạm vi iteration 1
Iteration này bị giới hạn cố ý.
1. Thêm giao diện cốt lõi độc lập kênh
Thêm kiểu cốt lõi và giao diện dịch vụ cho binding và routing.
Kiểu cốt lõi đề xuất:
tsexport 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>; };
Hợp đồng dịch vụ cốt lõi:
tsexport 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. Thêm một router phân phối cốt lõi cho hoàn thành subagent
Thêm một đường dẫn giải quyết đích duy nhất cho sự kiện hoàn thành.
Hợp đồng router:
tsexport interface BoundDeliveryRouter { resolveDestination(input: { eventKind: "task_completion"; targetSessionKey: string; requester?: ConversationRef; failClosed: boolean; }): { binding: SessionBindingRecord | null; mode: "bound" | "fallback"; reason: string; }; }
Cho iteration này:
- chỉ
task_completionđược định tuyến qua đường dẫn mới này - đường dẫn hiện có cho loại sự kiện khác vẫn như cũ
3. Giữ Discord như adapter
Discord vẫn là triển khai adapter đầu tiên.
Trách nhiệm adapter:
- tạo/tái sử dụng cuộc trò chuyện thread
- gửi message bound qua webhook hoặc channel send
- xác thực trạng thái thread (archived/deleted)
- ánh xạ metadata adapter (định danh webhook, id thread)
4. Sửa các vấn đề đúng đắn hiện biết
Bắt buộc trong iteration này:
- làm mới sử dụng token khi tái sử dụng manager binding thread hiện có
- ghi lại hoạt động đi cho Discord send dựa trên webhook
- dừng dự phòng main channel ngầm khi đích thread bound được chọn cho hoàn thành chế độ phiên
5. Bảo toàn mặc định an toàn runtime hiện tại
Không có thay đổi hành vi cho người dùng với spawn bound thread bị tắt.
Mặc định vẫn:
channels.discord.threadBindings.spawnSubagentSessions = false
Kết quả:
- người dùng Discord bình thường vẫn trên hành vi hiện tại
- đường dẫn cốt lõi mới chỉ ảnh hưởng định tuyến hoàn thành phiên bound nơi được bật
Không có trong iteration 1
Rõ ràng bị hoãn:
- Mục tiêu binding ACP (
targetKind: "acp") - Adapter kênh mới ngoài Discord
- Thay thế toàn cầu của tất cả đường dẫn phân phối (
spawn_ack,subagent_messagetương lai) - Thay đổi cấp giao thức
- Migration/versioning lưu trữ thiết kế lại cho tất cả lưu trữ binding
Lưu ý về ACP:
- thiết kế giao diện giữ chỗ cho ACP
- triển khai ACP không được bắt đầu trong iteration này
Bất biến routing
Các bất biến này là bắt buộc cho iteration 1.
- lựa chọn đích và tạo nội dung là các bước riêng biệt
- nếu hoàn thành chế độ phiên giải quyết thành đích bound đang hoạt động, phân phối phải nhắm mục tiêu đích đó
- không có định tuyến lại ẩn từ đích bound sang main channel
- hành vi dự phòng phải rõ ràng và có thể quan sát
Tương thích và triển khai
Mục tiêu tương thích:
- không có regression cho người dùng với spawn bound thread tắt
- không có thay đổi cho kênh không phải Discord trong iteration này
Triển khai:
- Đưa giao diện và router ra sau cổng tính năng hiện tại.
- Định tuyến phân phối bound chế độ hoàn thành Discord qua router.
- Giữ đường dẫn cũ cho luồng không bound.
- Xác minh với test được nhắm mục tiêu và log runtime canary.
Test bắt buộc trong iteration 1
Bao phủ đơn vị và tích hợp bắt buộc:
- xoay token manager sử dụng token mới nhất sau khi tái sử dụng manager
- webhook send cập nhật timestamp hoạt động kênh
- hai phiên bound đang hoạt động trong cùng kênh requester không trùng lặp sang main channel
- hoàn thành cho run chế độ phiên bound giải quyết chỉ đích thread
- flag spawn bị tắt giữ hành vi cũ không thay đổi
File triển khai đề xuất
Cốt lõi:
src/infra/outbound/session-binding-service.ts(mới)src/infra/outbound/bound-delivery-router.ts(mới)src/agents/subagent-announce.ts(tích hợp giải quyết đích hoàn thành)
Adapter Discord và runtime:
src/discord/monitor/thread-bindings.manager.tssrc/discord/monitor/reply-delivery.tssrc/discord/send.outbound.ts
Test:
src/discord/monitor/provider*.test.tssrc/discord/monitor/reply-delivery.test.tssrc/agents/subagent-announce.format.e2e.test.ts
Tiêu chí hoàn thành cho iteration 1
- giao diện cốt lõi tồn tại và được kết nối cho routing hoàn thành
- sửa đúng đắn ở trên được hợp nhất với test
- không có phân phối hoàn thành trùng lặp main và thread trong run bound chế độ phiên
- không có thay đổi hành vi cho triển khai spawn bound bị tắt
- ACP vẫn bị hoãn rõ ràng