Persist paired turn output before final delivery
This commit is contained in:
@@ -1318,6 +1318,7 @@ describe('runAgentForGroup room memory', () => {
|
|||||||
it('stores reviewer turn output before transitioning the paired task back to active', async () => {
|
it('stores reviewer turn output before transitioning the paired task back to active', async () => {
|
||||||
const group = { ...makeGroup(), folder: 'test-group' };
|
const group = { ...makeGroup(), folder: 'test-group' };
|
||||||
const deps = makeDeps();
|
const deps = makeDeps();
|
||||||
|
const onOutput = vi.fn(async () => {});
|
||||||
|
|
||||||
vi.mocked(serviceRouting.getEffectiveChannelLease).mockReturnValue({
|
vi.mocked(serviceRouting.getEffectiveChannelLease).mockReturnValue({
|
||||||
chat_jid: 'group@test',
|
chat_jid: 'group@test',
|
||||||
@@ -1397,7 +1398,7 @@ describe('runAgentForGroup room memory', () => {
|
|||||||
chatJid: 'group@test',
|
chatJid: 'group@test',
|
||||||
runId: 'run-reviewer-output-order',
|
runId: 'run-reviewer-output-order',
|
||||||
forcedRole: 'reviewer',
|
forcedRole: 'reviewer',
|
||||||
onOutput: async () => {},
|
onOutput,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result).toBe('success');
|
expect(result).toBe('success');
|
||||||
@@ -1407,6 +1408,11 @@ describe('runAgentForGroup room memory', () => {
|
|||||||
'reviewer',
|
'reviewer',
|
||||||
'DONE_WITH_CONCERNS\nreviewer feedback',
|
'DONE_WITH_CONCERNS\nreviewer feedback',
|
||||||
);
|
);
|
||||||
|
expect(
|
||||||
|
vi.mocked(db.insertPairedTurnOutput).mock.invocationCallOrder[0],
|
||||||
|
).toBeLessThan(
|
||||||
|
onOutput.mock.invocationCallOrder[0],
|
||||||
|
);
|
||||||
expect(
|
expect(
|
||||||
vi.mocked(db.insertPairedTurnOutput).mock.invocationCallOrder[0],
|
vi.mocked(db.insertPairedTurnOutput).mock.invocationCallOrder[0],
|
||||||
).toBeLessThan(
|
).toBeLessThan(
|
||||||
|
|||||||
@@ -315,9 +315,29 @@ export async function runAgentForGroup(
|
|||||||
const effectivePrompt = moaEnrichedPrompt;
|
const effectivePrompt = moaEnrichedPrompt;
|
||||||
let pairedExecutionStatus: 'succeeded' | 'failed' = 'failed';
|
let pairedExecutionStatus: 'succeeded' | 'failed' = 'failed';
|
||||||
let pairedExecutionSummary: string | null = null;
|
let pairedExecutionSummary: string | null = null;
|
||||||
let pairedFullOutput: string | null = null;
|
let pairedFinalOutput: string | null = null;
|
||||||
let pairedExecutionCompleted = false;
|
let pairedExecutionCompleted = false;
|
||||||
let pairedSawOutput = 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 = (
|
const maybeHandoffToCodex = (
|
||||||
reason: AgentTriggerReason,
|
reason: AgentTriggerReason,
|
||||||
@@ -483,7 +503,6 @@ export async function runAgentForGroup(
|
|||||||
|
|
||||||
if (outputText && outputText.length > 0) {
|
if (outputText && outputText.length > 0) {
|
||||||
pairedExecutionSummary = outputText.slice(0, 500);
|
pairedExecutionSummary = outputText.slice(0, 500);
|
||||||
pairedFullOutput = outputText;
|
|
||||||
} else if (
|
} else if (
|
||||||
typeof output.error === 'string' &&
|
typeof output.error === 'string' &&
|
||||||
output.error.length > 0
|
output.error.length > 0
|
||||||
@@ -542,6 +561,22 @@ export async function runAgentForGroup(
|
|||||||
if (outputText && outputText.length > 0) {
|
if (outputText && outputText.length > 0) {
|
||||||
streamedOutputHandler.markVisibleOutput();
|
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) {
|
if (onOutput) {
|
||||||
await onOutput(output);
|
await onOutput(output);
|
||||||
}
|
}
|
||||||
@@ -941,17 +976,9 @@ export async function runAgentForGroup(
|
|||||||
!pairedSawOutput
|
!pairedSawOutput
|
||||||
? 'failed'
|
? 'failed'
|
||||||
: completionStatus;
|
: completionStatus;
|
||||||
// Store full output for direct inter-agent data passing (Discord-independent).
|
if (effectiveStatus === 'succeeded') {
|
||||||
if (pairedFullOutput && effectiveStatus === 'succeeded') {
|
|
||||||
try {
|
try {
|
||||||
const turnNumber =
|
persistPairedTurnOutputIfNeeded(completedRole);
|
||||||
getLatestTurnNumber(pairedExecutionContext.task.id) + 1;
|
|
||||||
insertPairedTurnOutput(
|
|
||||||
pairedExecutionContext.task.id,
|
|
||||||
turnNumber,
|
|
||||||
completedRole,
|
|
||||||
pairedFullOutput,
|
|
||||||
);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log.warn(
|
log.warn(
|
||||||
{ pairedTaskId: pairedExecutionContext.task.id, err },
|
{ pairedTaskId: pairedExecutionContext.task.id, err },
|
||||||
|
|||||||
Reference in New Issue
Block a user