feat(coding-agent): allow message_end replacements

closes #3982
This commit is contained in:
Mario Zechner
2026-04-30 21:19:09 +02:00
parent 24dec9fcd5
commit 40c6eabb8f
7 changed files with 188 additions and 4 deletions

View File

@@ -610,6 +610,22 @@ export class AgentSession {
return undefined;
}
private _replaceMessageInPlace(target: AgentMessage, replacement: AgentMessage): void {
// Agent-core stores the finalized message object in its state before emitting message_end.
// SessionManager persistence happens later in _processAgentEvent() with event.message.
// Mutating this object in place keeps agent state, later turn/agent events, listeners,
// and the eventual SessionManager.appendMessage(event.message) persistence in sync.
if (target === replacement) {
return;
}
const targetRecord = target as unknown as Record<string, unknown>;
for (const key of Object.keys(targetRecord)) {
delete targetRecord[key];
}
Object.assign(targetRecord, replacement);
}
/** Emit extension events based on agent events */
private async _emitExtensionEvent(event: AgentEvent): Promise<void> {
if (event.type === "agent_start") {
@@ -651,7 +667,10 @@ export class AgentSession {
type: "message_end",
message: event.message,
};
await this._extensionRunner.emit(extensionEvent);
const replacement = await this._extensionRunner.emitMessageEnd(extensionEvent);
if (replacement) {
this._replaceMessageInPlace(event.message, replacement);
}
} else if (event.type === "tool_execution_start") {
const extensionEvent: ToolExecutionStartEvent = {
type: "tool_execution_start",