11// QA channel protocol helpers validate synthetic channel messages used by QA plugins.
22import { isRecord } from "../../packages/normalization-core/src/record-coerce.js" ;
33
4+ /** Conversation shape supported by the synthetic QA channel bus. */
45export type QaBusConversationKind = "direct" | "channel" | "group" ;
56
7+ /** Addressable conversation used by QA bus messages and thread state. */
68export type QaBusConversation = {
79 id : string ;
810 kind : QaBusConversationKind ;
911 title ?: string ;
1012} ;
1113
14+ /** Media/file attachment fixture accepted by QA bus message APIs. */
1215export type QaBusAttachment = {
1316 id : string ;
1417 kind : "image" | "video" | "audio" | "file" ;
@@ -24,11 +27,13 @@ export type QaBusAttachment = {
2427 transcript ?: string ;
2528} ;
2629
30+ /** Tool-call fixture attached to QA messages for agent-runtime tests. */
2731export type QaBusToolCall = {
2832 name : string ;
2933 arguments ?: Record < string , unknown > ;
3034} ;
3135
36+ /** Stored QA bus message after defaults, reactions, and account ids are normalized. */
3237export type QaBusMessage = {
3338 id : string ;
3439 accountId : string ;
@@ -52,6 +57,7 @@ export type QaBusMessage = {
5257 } > ;
5358} ;
5459
60+ /** Synthetic thread record created inside a QA bus conversation. */
5561export type QaBusThread = {
5662 id : string ;
5763 accountId : string ;
@@ -61,6 +67,7 @@ export type QaBusThread = {
6167 createdBy : string ;
6268} ;
6369
70+ /** Ordered event emitted by QA bus polling and state snapshots. */
6471export type QaBusEvent =
6572 | { cursor : number ; kind : "inbound-message" ; accountId : string ; message : QaBusMessage }
6673 | { cursor : number ; kind : "outbound-message" ; accountId : string ; message : QaBusMessage }
@@ -76,6 +83,7 @@ export type QaBusEvent =
7683 senderId : string ;
7784 } ;
7885
86+ /** Input for injecting an inbound message from a synthetic user/channel. */
7987export type QaBusInboundMessageInput = {
8088 accountId ?: string ;
8189 conversation : QaBusConversation ;
@@ -90,6 +98,7 @@ export type QaBusInboundMessageInput = {
9098 toolCalls ?: QaBusToolCall [ ] ;
9199} ;
92100
101+ /** Input for recording an outbound message sent by an OpenClaw runtime. */
93102export type QaBusOutboundMessageInput = {
94103 accountId ?: string ;
95104 to : string ;
@@ -103,6 +112,7 @@ export type QaBusOutboundMessageInput = {
103112 toolCalls ?: QaBusToolCall [ ] ;
104113} ;
105114
115+ /** Input for creating a synthetic QA bus thread. */
106116export type QaBusCreateThreadInput = {
107117 accountId ?: string ;
108118 conversationId : string ;
@@ -111,6 +121,7 @@ export type QaBusCreateThreadInput = {
111121 timestamp ?: number ;
112122} ;
113123
124+ /** Input for adding a reaction event to an existing QA bus message. */
114125export type QaBusReactToMessageInput = {
115126 accountId ?: string ;
116127 messageId : string ;
@@ -119,19 +130,22 @@ export type QaBusReactToMessageInput = {
119130 timestamp ?: number ;
120131} ;
121132
133+ /** Input for editing an existing QA bus message. */
122134export type QaBusEditMessageInput = {
123135 accountId ?: string ;
124136 messageId : string ;
125137 text : string ;
126138 timestamp ?: number ;
127139} ;
128140
141+ /** Input for marking an existing QA bus message as deleted. */
129142export type QaBusDeleteMessageInput = {
130143 accountId ?: string ;
131144 messageId : string ;
132145 timestamp ?: number ;
133146} ;
134147
148+ /** Search filter accepted by QA bus message lookup helpers. */
135149export type QaBusSearchMessagesInput = {
136150 accountId ?: string ;
137151 query ?: string ;
@@ -140,23 +154,27 @@ export type QaBusSearchMessagesInput = {
140154 limit ?: number ;
141155} ;
142156
157+ /** Lookup key for reading one QA bus message. */
143158export type QaBusReadMessageInput = {
144159 accountId ?: string ;
145160 messageId : string ;
146161} ;
147162
163+ /** Cursor and timeout options used by QA bus polling. */
148164export type QaBusPollInput = {
149165 accountId ?: string ;
150166 cursor ?: number ;
151167 timeoutMs ?: number ;
152168 limit ?: number ;
153169} ;
154170
171+ /** Poll response containing the next cursor and ordered events. */
155172export type QaBusPollResult = {
156173 cursor : number ;
157174 events : QaBusEvent [ ] ;
158175} ;
159176
177+ /** Complete QA bus state snapshot exposed to tests and diagnostics. */
160178export type QaBusStateSnapshot = {
161179 cursor : number ;
162180 conversations : QaBusConversation [ ] ;
@@ -212,6 +230,7 @@ function sanitizeQaBusToolCallValue(value: unknown, depth: number, key?: string)
212230 return undefined ;
213231}
214232
233+ /** Sanitize arbitrary tool-call arguments before storing them in QA bus messages. */
215234export function sanitizeQaBusToolCallArguments (
216235 value : unknown ,
217236) : Record < string , unknown > | undefined {
@@ -222,6 +241,7 @@ export function sanitizeQaBusToolCallArguments(
222241 return isRecord ( sanitized ) ? sanitized : undefined ;
223242}
224243
244+ /** Normalize and redact a bounded list of tool calls from untrusted QA input. */
225245export function sanitizeQaBusToolCalls ( value : unknown ) : QaBusToolCall [ ] | undefined {
226246 if ( ! Array . isArray ( value ) ) {
227247 return undefined ;
@@ -245,6 +265,7 @@ export function sanitizeQaBusToolCalls(value: unknown): QaBusToolCall[] | undefi
245265 return sanitized . length > 0 ? sanitized : undefined ;
246266}
247267
268+ /** Predicate input used by QA helpers that wait for bus events or messages. */
248269export type QaBusWaitForInput =
249270 | {
250271 timeoutMs ?: number ;
0 commit comments