diff --git a/src/message-agent-executor.test.ts b/src/message-agent-executor.test.ts index 11f30cd..75b2a10 100644 --- a/src/message-agent-executor.test.ts +++ b/src/message-agent-executor.test.ts @@ -1318,6 +1318,7 @@ describe('runAgentForGroup room memory', () => { it('stores reviewer turn output before transitioning the paired task back to active', async () => { const group = { ...makeGroup(), folder: 'test-group' }; const deps = makeDeps(); + const onOutput = vi.fn(async () => {}); vi.mocked(serviceRouting.getEffectiveChannelLease).mockReturnValue({ chat_jid: 'group@test', @@ -1397,7 +1398,7 @@ describe('runAgentForGroup room memory', () => { chatJid: 'group@test', runId: 'run-reviewer-output-order', forcedRole: 'reviewer', - onOutput: async () => {}, + onOutput, }); expect(result).toBe('success'); @@ -1410,9 +1411,13 @@ describe('runAgentForGroup room memory', () => { expect( vi.mocked(db.insertPairedTurnOutput).mock.invocationCallOrder[0], ).toBeLessThan( - vi.mocked( - pairedExecutionContext.completePairedExecutionContext, - ).mock.invocationCallOrder[0], + onOutput.mock.invocationCallOrder[0], + ); + expect( + vi.mocked(db.insertPairedTurnOutput).mock.invocationCallOrder[0], + ).toBeLessThan( + vi.mocked(pairedExecutionContext.completePairedExecutionContext).mock + .invocationCallOrder[0], ); }); diff --git a/src/message-agent-executor.ts b/src/message-agent-executor.ts index 003a9e2..f62a28c 100644 --- a/src/message-agent-executor.ts +++ b/src/message-agent-executor.ts @@ -316,9 +316,29 @@ export async function runAgentForGroup( const effectivePrompt = moaEnrichedPrompt; let pairedExecutionStatus: 'succeeded' | 'failed' = 'failed'; let pairedExecutionSummary: string | null = null; - let pairedFullOutput: string | null = null; + let pairedFinalOutput: string | null = null; let pairedExecutionCompleted = false; let pairedSawOutput = false; + let pairedTurnOutputPersisted = false; + + const persistPairedTurnOutputIfNeeded = (completedRole: PairedRoomRole) => { + if ( + !pairedExecutionContext || + pairedTurnOutputPersisted || + !pairedFinalOutput || + pairedFinalOutput.length === 0 + ) { + return; + } + const turnNumber = getLatestTurnNumber(pairedExecutionContext.task.id) + 1; + insertPairedTurnOutput( + pairedExecutionContext.task.id, + turnNumber, + completedRole, + pairedFinalOutput, + ); + pairedTurnOutputPersisted = true; + }; const maybeHandoffToCodex = ( reason: AgentTriggerReason, @@ -484,7 +504,6 @@ export async function runAgentForGroup( if (outputText && outputText.length > 0) { pairedExecutionSummary = outputText.slice(0, 500); - pairedFullOutput = outputText; } else if ( typeof output.error === 'string' && output.error.length > 0 @@ -543,6 +562,22 @@ export async function runAgentForGroup( if (outputText && outputText.length > 0) { streamedOutputHandler.markVisibleOutput(); } + if ( + outputPhase === 'final' && + output.status === 'success' && + outputText && + outputText.length > 0 + ) { + pairedFinalOutput = outputText; + try { + persistPairedTurnOutputIfNeeded(roomRoleContext?.role ?? 'owner'); + } catch (err) { + log.warn( + { pairedTaskId: pairedExecutionContext?.task.id ?? null, err }, + 'Failed to persist paired turn output before delivery', + ); + } + } if (onOutput) { await onOutput(output); } @@ -939,17 +974,9 @@ export async function runAgentForGroup( !pairedSawOutput ? 'failed' : completionStatus; - // Store full output for direct inter-agent data passing (Discord-independent). - if (pairedFullOutput && effectiveStatus === 'succeeded') { + if (effectiveStatus === 'succeeded') { try { - const turnNumber = - getLatestTurnNumber(pairedExecutionContext.task.id) + 1; - insertPairedTurnOutput( - pairedExecutionContext.task.id, - turnNumber, - completedRole, - pairedFullOutput, - ); + persistPairedTurnOutputIfNeeded(completedRole); } catch (err) { log.warn( { pairedTaskId: pairedExecutionContext.task.id, err },