-
Notifications
You must be signed in to change notification settings - Fork 2.9k
fix(channels): deliver background agent replies #7336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -314,15 +314,23 @@ export class AcpBridge extends EventEmitter implements ChannelAgentBridge { | |
| switch (type) { | ||
| case 'agent_message_chunk': { | ||
| const meta = update['_meta'] as Record<string, unknown> | undefined; | ||
| if ( | ||
| typeof meta?.['parentToolCallId'] === 'string' || | ||
| meta?.['qwenDiscreteMessage'] === true | ||
| ) { | ||
| if (typeof meta?.['parentToolCallId'] === 'string') { | ||
| break; | ||
| } | ||
| const content = update['content'] as | ||
| | { type?: string; text?: string } | ||
| | undefined; | ||
| if (meta?.['qwenDiscreteMessage'] === true) { | ||
| if ( | ||
| meta['source'] === 'background_notification_response' && | ||
| meta['rewritten'] !== true && | ||
| content?.type === 'text' && | ||
| content.text | ||
| ) { | ||
| this.emit('backgroundResponse', sessionId, content.text); | ||
| } | ||
|
Comment on lines
+323
to
+331
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] When — qwen3.7-max via Qwen Code /review |
||
| break; | ||
| } | ||
|
Comment on lines
+323
to
+333
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] The 4-condition background response detection predicate ( Consider extracting the meta-conditions into a shared predicate (e.g., — qwen3.7-max via Qwen Code /review |
||
| if (content?.type === 'text' && content.text) { | ||
| this.emit( | ||
| meta?.['source'] === 'slash_command' | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -346,6 +346,18 @@ export abstract class ChannelBase { | |
| private readonly bridgeToolCallListener = (event: ToolCallEvent): void => { | ||
| this.dispatchToolCall(event); | ||
| }; | ||
| private readonly bridgeBackgroundResponseListener = ( | ||
| sessionId: string, | ||
| text: string, | ||
| ): void => { | ||
| void this.dispatchBackgroundResponse(sessionId, text).catch( | ||
| (err: unknown) => { | ||
| process.stderr.write( | ||
| `[${this.name}] background response delivery failed for session ${sanitizeLogText(sessionId, 128)}: ${this.lifecycleError(err)}\n`, | ||
| ); | ||
| }, | ||
| ); | ||
| }; | ||
| private readonly bridgeSessionDiedListener = ( | ||
| event: SessionDiedEvent, | ||
| ): void => { | ||
|
|
@@ -403,6 +415,25 @@ export abstract class ChannelBase { | |
| this.onToolCall(chatId, event); | ||
| } | ||
|
|
||
| async dispatchBackgroundResponse( | ||
| sessionId: string, | ||
| text: string, | ||
| ): Promise<void> { | ||
| const target = this.router.getTarget(sessionId); | ||
| if ( | ||
| !target || | ||
| target.channelName !== this.name || | ||
| text.trim().length === 0 | ||
| ) { | ||
| return; | ||
| } | ||
|
Comment on lines
+422
to
+429
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] Consider adding tests for each guard branch: (1) session with a different — qwen3.7-max via Qwen Code /review |
||
| if (this.supportsProactiveSend() && this.supportsProactiveTarget(target)) { | ||
| await this.pushProactive(target, text); | ||
| return; | ||
| } | ||
| await this.sendResponseMessage(target.chatId, text, sessionId); | ||
|
Comment on lines
+430
to
+434
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Suggestion] The Add a test with — qwen3.7-max via Qwen Code /review |
||
| } | ||
|
|
||
| async dispatchPermissionRequest( | ||
| event: PermissionRequestEvent, | ||
| ): Promise<void> { | ||
|
|
@@ -1704,13 +1735,15 @@ export abstract class ChannelBase { | |
|
|
||
| private attachBridgeEvents(bridge: ChannelAgentBridge): void { | ||
| bridge.on('toolCall', this.bridgeToolCallListener); | ||
| bridge.on('backgroundResponse', this.bridgeBackgroundResponseListener); | ||
| bridge.on('sessionDied', this.bridgeSessionDiedListener); | ||
| bridge.on('permissionRequest', this.bridgePermissionRequestListener); | ||
| bridge.on('permissionResolved', this.bridgePermissionResolvedListener); | ||
| } | ||
|
|
||
| private detachBridgeEvents(bridge: ChannelAgentBridge): void { | ||
| bridge.off('toolCall', this.bridgeToolCallListener); | ||
| bridge.off('backgroundResponse', this.bridgeBackgroundResponseListener); | ||
| bridge.off('sessionDied', this.bridgeSessionDiedListener); | ||
| bridge.off('permissionRequest', this.bridgePermissionRequestListener); | ||
| bridge.off('permissionResolved', this.bridgePermissionResolvedListener); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Suggestion] The test asserts
backgroundResponseis emitted but does not assert thattextChunkis NOT emitted for the same message. — Failure scenario: if thebreakat line 331 ofAcpBridge.tswere removed, the background response text would be emitted as bothbackgroundResponse(delivered via Channel proactive send) andtextChunk(accumulated into the active turn), causing duplicate message delivery. This test would still pass because it only checks the positive assertion.— qwen3.7-max via Qwen Code /review