Bỏ qua để đến nội dung

Sự kiện miền

DomainEventBus là một bus publish/subscribe quảng bá trong cùng tiến trình. Bên phát gọi publish(event); bên đăng ký tiêu thụ một luồng on<T>() có kiểu. Mọi sự kiện đều triển khai DomainEvent và mang theo occurredAt.

Bus chạy bên trong cc_server. Mọi bên phát và mọi bên đăng ký đang hoạt động đều nằm ở đó. Không máy khách nào nhìn thấy bus này — máy chủ chuyển tiếp một tập con được tuyển chọn dưới dạng các khung JSON-RPC notifications/*, lọc theo từng bên đăng ký dựa trên tư cách thành viên không gian làm việc.

Chỉ số Số lượng
Các lớp sự kiện cụ thể 54
Các tệp nguồn (packages/cc_domain/lib/core/domain/events/) 14 (cộng domain_event_bus.dart)
Các lớp cơ sở trừu tượng không bao giờ được phát trực tiếp 1 (TaskLifecycleEvent, một hệ thống phân cấp sealed)

Mọi sự kiện trong danh mục dưới đây đều nằm trong một thư mục đó; không có sự kiện miền nào được khai báo ở nơi khác.

Sự kiện không gian làm việc, agent và kho mã

Phần tiêu đề “Sự kiện không gian làm việc, agent và kho mã”
Sự kiện Dữ liệu tải Kích hoạt khi
WorkspaceCreated workspaceId Không gian làm việc được tạo
AgentRunCompleted agentId, runId?, workspaceId?, conversationId? Agent kết thúc một lượt chạy (thành công hay thất bại)
AgentAwaitingInput workspaceId, kind, summary, spaceId?, conversationId?, agentId?, agentName? Một agent bắt đầu chờ con người: một yêu cầu phê duyệt, một câu hỏi ask_user hoặc một lượt chạy bị giữ lại vì thông tin xác thực (kind là approval, question hoặc credential)
RepoAdded repoId, path, workspaceId Một kho mã được đăng ký; kích hoạt việc lập chỉ mục mã chạy nền
SkillUpdated workspaceId, slug, origin, computedHash, scanVerdict? Một skill được cài đặt hoặc cập nhật, kèm theo kết luận quét chuỗi cung ứng của nó

Khối đầu tiên là vòng đời của chính PR. Khối thứ hai là phần theo dõi PR do mình tạo: các tín hiệu về một PR bạn đã mở, mỗi tín hiệu đều mang forUserId để lượt thăm dò có thể định tuyến chúng tới đúng người mà chúng liên quan thay vì quảng bá.

Sự kiện Dữ liệu tải Kích hoạt khi
PullRequestPublished prId, workspaceId, repoOwner, repoName Agent mở một PR
PullRequestStatusChanged status, workspaceId, prId?, repoFullName?, prNumber? PR được merge/đóng/mở/mở lại/phê duyệt
PrMerged prId, workspaceId, agentId PR được merge — một tín hiệu hẹp chỉ dành cho merge, được giữ lại cho phân tích/thông báo
PrReviewRequested workspaceId, repoOwner, repoName, prNumber, prTitle GitHub yêu cầu người dùng máy chủ đánh giá (lượt thăm dò thông báo, review_requested)
PrMentioned workspaceId, repoOwner, repoName, prNumber, prTitle Người dùng máy chủ được nhắc tên trong một PR (lượt thăm dò thông báo, mention)
ExternalPrMerged workspaceId, repoOwner, repoName, prNumber, prTitle, mergedByLogin? Một PR được theo dõi từ bên ngoài (không phải của agent) đã được merge, phát hiện bởi lượt thăm dò thông báo GitHub; ánh xạ tới danh mục thông báo prMerged
ExternalPrDetected repoOwner, repoName, prNumber, prTitle, author, workspaceId? PR không phải của agent được tìm thấy qua thăm dò — chỉ dùng cho quy trình (điều khiển external_pr_welcome), không tạo thông báo nào
PrHeadChanged repoOwner, repoName, prNumber, prTitle, previousHeadSha, headSha, workspaceId SHA head của PR đã dịch chuyển — tác giả đã push
ReviewBecameStale workspaceId, spaceId, repoOwner, repoName, prNumber, prTitle, reviewedHeadSha, headSha Một đánh giá AI đã hoàn tất không còn mô tả đúng PR mà nó đã đánh giá. Chỉ kích hoạt khi đã có một đánh giá cho commit bị thay thế, nên nó vẫn là một tín hiệu thay vì ping theo từng lần push

Cả sáu sự kiện đều mang workspaceId, repoOwner, repoName, prNumber, prTitle và forUserId tùy chọn.

Sự kiện Dữ liệu tải bổ sung Kích hoạt khi
PrMergeReadinessChanged ready, reason Một PR bạn là tác giả trở nên merge được, hoặc không còn merge được nữa
PrReviewDecisionChanged decision, reviewersRemaining, approverLogin? Một người đánh giá đã phê duyệt, yêu cầu thay đổi, hoặc bị hủy phê duyệt
PrChecksStatusChanged failing, failingCheckName?, failingCheckUrl? CI chuyển sang đỏ, hoặc đã phục hồi
PrCommentMentioned commentId, authorLogin, bodyPreview, isReviewComment, threadId?, path?, line? Ai đó nhắc tên bạn trong một bình luận PR hoặc bình luận đánh giá
PrThreadReplied commentId, authorLogin, bodyPreview, threadId?, path?, line? Ai đó trả lời trong một luồng đánh giá mà bạn tham gia
PrThreadResolved threadId, commentId?, path?, line? Ai đó giải quyết một luồng đánh giá mà bạn tham gia
Sự kiện Dữ liệu tải Kích hoạt khi
MessageReceived spaceId, messageId, senderName, contentPreview, isAgentMessage, workspaceId?, mentions, requestedByUserId?, senderUserId? Tin nhắn mới đến
SpaceCreated spaceId, workspaceId Space được tạo
SpaceDeleted spaceId, workspaceId Space bị xóa
SpaceProvisioningChanged workspaceId, spaceId, status, step? Không gian làm việc của space bước vào quá trình cấp phát, chạm tới một bước (clone một kho mã, checkout một PR, thiết lập một agent), hoặc chuyển sang trạng thái sẵn sàng/thất bại — cầu chat tường thuật lại điều đó trên thẻ tác vụ của nó
Sự kiện Dữ liệu tải Kích hoạt khi
TicketCreated ticketId, workspaceId Phiếu được tạo
TicketAssigned ticketId, ticketTitle, ticketBody?, ticketUrl?, assignedAgentId?, assigneeType, assignedTeamId?, workspaceId Phiếu được gán cho một principal hoặc một nhóm
TicketCompleted ticketId Công việc kết thúc (kết cục cuối)
TicketFailed ticketId, errorMessage Agent thất bại (kết cục cuối)
TicketCancelled ticketId Phiếu bị hủy (kết cục cuối)
TicketStatusChanged ticketId, workspaceId, from, to Mọi thay đổi trạng thái
TicketReassigned ticketId, workspaceId, fromAgentId?, toAgentId? Phiếu được gán lại
TicketDetailsUpdated ticketId, workspaceId Tiêu đề, mô tả hoặc mức ưu tiên thay đổi

Luồng vòng đời tác vụ hợp nhất — một lượt chạy agent đã được điều phối, được khóa theo id nhật ký lượt chạy của nó. Mọi sự kiện đều mang taskId, một seq đơn điệu tăng theo từng tác vụ, workspaceId?, agentId? và một phase; các hàng dưới đây chỉ liệt kê những trường bổ sung.

Sự kiện Dữ liệu tải Kích hoạt khi
TaskDispatched — Tác vụ được giao cho một backend để thực thi
TaskRunning — Tác vụ bắt đầu tạo ra kết quả
TaskWaitingLocalDirectory lockedPath, holderTaskId? Tác vụ bị tạm dừng — một tác vụ khác đang giữ khóa đường dẫn trên đĩa mà nó cần
TaskProgress note? Điểm kiểm tra tiến độ giữa lượt chạy
TaskMessage messageType, content Tin nhắn được truyền theo luồng (text/thinking/tool_use/tool_result/error); được báo cáo trong phase progress
TaskCompleted summary? Tác vụ kết thúc thành công
TaskFailed errorMessage Tác vụ kết thúc với lỗi
TaskCancelled — Tác vụ bị hủy trước khi hoàn tất

Enum TaskPhase cũng có một thành viên queued, nhưng không có gì phát ra sự kiện queued — không tồn tại lớp TaskQueued. Khung quan sát được đầu tiên của một tác vụ là TaskDispatched.

Sự kiện Dữ liệu tải Kích hoạt khi
PipelineRunCompleted workspaceId, pipelineRunId, templateId Lượt chạy kết thúc
PipelineRunCancelled workspaceId, pipelineRunId, templateId Lượt chạy bị hủy (bởi người dùng hoặc hệ thống) — một điểm dừng có chủ đích, không phải lỗi
PipelineRunFailed workspaceId, pipelineRunId, templateId, errorMessage Lượt chạy thất bại

Chỉ những chuyển đổi kết cục cuối mới được phát. Không có PipelineRunStarted và cũng không có sự kiện theo từng bước: tiến độ của một bước đến với máy khách qua chính các hàng của lượt chạy và luồng vòng đời tác vụ của agent mà nó đã điều phối, chứ không qua bus.

Sự kiện Dữ liệu tải Kích hoạt khi
ActivityLogged id, actorType, actorId?, action, entityType, entityId?, details?, workspaceId?, runId? Mục nhật ký kiểm toán được tạo
BudgetThresholdCrossed scopeType, scopeId, spentCents, budgetCents, isHardStop Chi tiêu vượt ngưỡng
Sự kiện Dữ liệu tải Kích hoạt khi
WorkspaceMemberAdded workspaceId, userId, role Một người dùng tham gia không gian làm việc (đổi lời mời hoặc được quản trị viên thêm vào)
WorkspaceMemberRemoved workspaceId, userId Một thành viên bị xóa — các phiên đang hoạt động của người dùng đó trong phạm vi không gian làm việc phải kiểm tra lại quyền truy cập ngay lập tức
WorkspaceMemberRoleChanged workspaceId, userId, role Vai trò của một thành viên thay đổi

Tư cách thành viên là toàn bộ bề mặt danh tính trên bus. Việc tạo người dùng và thu hồi thiết bị vẫn diễn ra, nhưng chúng không được phát dưới dạng sự kiện miền — việc thu hồi được thực thi trực tiếp trên các phiên đang hoạt động thay vì đi qua bus.

Sự kiện Dữ liệu tải Kích hoạt khi
CalendarAuthExpired workspaceId, accountEmail Token làm mới OAuth của một tài khoản đã kết nối không còn hợp lệ vĩnh viễn (phát một lần cho mỗi đợt mất kết nối)
MeetingStartingSoon workspaceId, eventId, title, startTime, meetingUrl? Một sự kiện trên lịch sắp bắt đầu trong cửa sổ báo trước đã cấu hình
MeetingRecordingStopped workspaceId, meetingId, title, userNotes, transcript, summaryInstructions? Một bản ghi cuộc họp kết thúc và kích hoạt quy trình meeting_summary tích hợp sẵn
Sự kiện Dữ liệu tải Kích hoạt khi
RigClosedEvent workspaceId, rigId, reason Một rig biến mất, kèm lý do đóng của nó; các bên tiêu thụ chỉ hành động với backendFailure — mọi lý do khác đều do được yêu cầu hoặc đi kèm một RigReaped
RigControlChanged workspaceId, rigId, controller? Một con người nắm quyền điều khiển độc quyền một rig hoặc trả lại quyền đó (controller là null khi nhả — sự kiện không ghi lại ai đã nhả)
RigReaped workspaceId, rigId, reason, agentId? Hệ thống thu hồi một máy: do nhàn rỗi, hết TTL, hoặc bị loại bỏ vì áp lực bộ nhớ (được báo cáo là idleTimeout), kèm theo agent đang điều khiển

Việc một rig mở không phải là một sự kiện. Quá trình khởi động hoàn tất và hàng dữ liệu của rig chuyển sang trạng thái sẵn sàng; không có gì được phát, nên không tồn tại RigOpened để đăng ký.

Những miền con hoàn toàn không có sự kiện

Phần tiêu đề “Những miền con hoàn toàn không có sự kiện”

Một số hệ thống con trông có vẻ hướng sự kiện khi nhìn từ bên ngoài nhưng thực tế không phải vậy. Chúng được liệt kê ở đây vì sự vắng mặt của chúng là một quyết định thiết kế đáng biết trước khi bạn đi tìm một điểm móc nối:

Miền con Trạng thái vận động bằng cách nào thay vào đó
Bộ nhớ record_memory_fact và những công cụ cùng nhóm ghi rồi trả về; việc truy hồi thì đọc. Không có gì được phát khi có một dữ kiện hay xung đột
Điều phối Đề xuất, việc phê duyệt đề xuất và lượt chạy quy trình được tạo ra đều là các hàng dữ liệu và lời gọi RPC
Tài liệu kế hoạch submit_plan ghi một bản sửa đổi; việc phê duyệt hiện thực hóa một điều phối. Cả hai đều không được thông báo
Artifact publish_artifact / revise_artifact ghi bản sửa đổi trực tiếp
Phê duyệt Việc leo thang được xử lý bên trong dịch vụ quy trình phê duyệt
Đồng bộ phiếu Bộ điều phối nhà cung cấp đăng ký các sự kiện phiếu ở trên; các webhook đến được áp dụng trực tiếp
Làm mới lịch Một lần đồng bộ upsert các sự kiện và máy khách đọc lại; không có quảng bá làm mới nào
Merge worktree Được ghi vào worktree_merge_log và đọc từ đó

Mọi bên đăng ký dưới đây đều được khởi tạo bên trong runCcServer (hoặc một dịch vụ do nó dựng nên). Không có bên đăng ký nào phía máy khách.

Bên đăng ký Những sự kiện nó tiêu thụ
WorkspaceSeeder WorkspaceCreated
Gieo mầm bộ đánh giá khởi đầu (nội tuyến) WorkspaceCreated
Cấp phát space chat (nội tuyến) SpaceCreated
PipelineTriggerDispatcher Mọi DomainEvent; mỗi trình kích hoạt đang bật tự lọc theo loại của nó
SubPipelineResumeListener PipelineRunCompleted, PipelineRunFailed
PipelineCostRollupListener AgentRunCompleted
BudgetEvaluationListener AgentRunCompleted
MeetingSummaryReconciler PipelineRunCompleted, PipelineRunFailed, PipelineRunCancelled (chỉ các lượt chạy meeting_summary)
PipelineStepResumeListener AgentRunCompleted
AgentRunTaskCompleter AgentRunCompleted
GoalSupervisor AgentRunCompleted
CheckerDispatchListener AgentRunCompleted
TeamRoutingService AgentRunCompleted, TicketAssigned
OrchestrationRunListener PipelineRunCancelled, PipelineRunFailed
MultiVendorTicketSyncCoordinator TicketCreated, TicketAssigned, TicketReassigned, TicketStatusChanged, TicketDetailsUpdated
WorktreeGcListener TicketCompleted, TicketCancelled, SpaceDeleted, PrMerged, PullRequestStatusChanged
ChatBridgeService MessageReceived, SpaceProvisioningChanged
ActivityLogPersister ActivityLogged
RigEventListener RigControlChanged, RigReaped, RigClosedEvent — đưa một thông báo bằng ngôn ngữ đời thường vào làn điều hướng của agent đang điều khiển
StaleReviewWatcher PrHeadChanged — chỉ phát ReviewBecameStale khi đã có một đánh giá hoàn tất cho commit bị thay thế
GitHubPrConversationBridge AgentRunCompleted — các câu trả lời hội thoại PR gửi ra ngoài
NotificationFeedRecorder Hai mươi hai sự kiện thuộc lớp thông báo ở dưới
RemoteEventForwarder Hai mươi hai sự kiện đó cùng TicketReassigned và mọi TaskLifecycleEvent. Ba sự kiện tư cách thành viên chỉ vô hiệu hóa bộ nhớ đệm tư cách thành viên theo từng không gian làm việc của nó; chúng không được chuyển tiếp dưới dạng khung
LocalRpcServer / RemoteRelayHost WorkspaceMemberRemoved — loại bỏ các đăng ký không gian làm việc mà người dùng đó đã gắn vào; socket vẫn mở

TicketAssigned là một tín hiệu kiểm toán và thông báo, đồng thời là một trình kích hoạt quy trình. Việc gán cho một agent ghi lại quyền sở hữu và không khởi chạy lượt chạy nào — không có bộ điều phối phiếu. Việc gán cho một nhóm (khi assignedTeamId được đặt) là ngoại lệ: TeamRoutingService điều phối trưởng nhóm.

TicketRemoteSyncHandler được khai báo nhưng không bao giờ được khởi tạo trong mã chạy thật, nên hiện nay nó không đăng ký gì cả. NotificationEventMapper phía máy khách chỉ được khởi tạo trong chính bài kiểm thử của nó — đó là tàn dư của đường đi trong cùng tiến trình từ trước khi tách máy khách/máy chủ. Toast trực tiếp đến từ các khung truyền ở dưới.

Trên máy chủ, NotificationFeedRecorder và RemoteEventForwarder biến những sự kiện này thành các khung truyền notifications/* (notification_wire.dart). Trên máy khách, RpcNotificationMapper → mapNotificationFrame biến một khung thành một AppNotification.

Có đúng mười bảy danh mục thông báo. Một số sự kiện ánh xạ tới nhiều hơn một phương thức truyền, vì khung mang theo diễn biến (thất bại so với phục hồi) còn danh mục mang theo câu hỏi (“CI đang làm gì?”).

Danh mục Sự kiện nguồn Phương thức truyền
newMessage MessageReceived notifications/message_received (nhắc đến bạn)
agentRunCompleted MessageReceived notifications/message_received (is_agent_message, không nhắc đến bạn)
agentAwaitingInput AgentAwaitingInput notifications/agent_awaiting_input
ticketAssigned TicketAssigned notifications/ticket_assigned
ticketStatusChanged TicketStatusChanged notifications/ticket_status_changed
pullRequestPublished PullRequestPublished notifications/pr_published
prMerged PrMerged notifications/pr_merged
prMerged ExternalPrMerged notifications/external_pr_merged
prMentioned PrMentioned notifications/pr_mentioned
prMentioned PrCommentMentioned notifications/pr_comment_mentioned
reviewRequested PrReviewRequested notifications/pr_review_requested
reviewStale ReviewBecameStale notifications/review_stale
prMergeReadiness PrMergeReadinessChanged notifications/pr_ready_to_merge / pr_merge_blocked
prReviewDecision PrReviewDecisionChanged notifications/pr_approved / pr_changes_requested / pr_review_dismissed
prChecksStatus PrChecksStatusChanged notifications/pr_checks_failed / pr_checks_recovered
prThreadActivity PrThreadReplied notifications/pr_thread_replied
prThreadActivity PrThreadResolved notifications/pr_thread_resolved
meetingStartsSoon MeetingStartingSoon notifications/meeting_starting_soon
calendarAuthExpired CalendarAuthExpired notifications/calendar_auth_expired
rigStatusChanged RigControlChanged notifications/rig_control_changed
rigStatusChanged RigReaped notifications/rig_reaped
rigStatusChanged RigClosedEvent notifications/rig_closed

Khung tiếp quản rig không được gửi trả lại cho người đã nắm quyền lái, một lần nhả thì không được lọc (sự kiện không ghi lại ai đã nhả), và chỉ một lần đóng với backendFailure mới tạo ra khung rig_closed — những lý do khác hoặc là do được yêu cầu, hoặc đã được khung thu hồi bao phủ.

AgentAwaitingInput do AgentAwaitingInputPublisher phát ra. Thành phần này theo dõi các mục mới trong sổ đăng ký phê duyệt và sổ đăng ký chặn do thông tin xác thực, đồng thời được AgentQuestionService báo về từng câu hỏi ask_user. Mỗi lần chờ là một sự kiện; không có gì được phát khi việc chờ kết thúc.

Năm danh mục dành cho PR do mình tạo đều mang forUserId, nên chúng đến với tác giả thay vì mọi người trong không gian làm việc.

RemoteEventForwarder còn chuyển tiếp TicketReassigned dưới dạng notifications/ticket_reassigned và mọi TaskLifecycleEvent dưới dạng notifications/task_<phase>. Cả hai đều không ánh xạ tới một danh mục thông báo nào — chúng điều khiển giao diện trực tiếp, không phải trung tâm thông báo. Các sự kiện tư cách thành viên không được chuyển tiếp dưới dạng khung: chúng vô hiệu hóa bộ nhớ đệm của bộ chuyển tiếp, và các máy chủ phiên loại bỏ những đăng ký không gian làm việc của thành viên đã bị xóa.