Unify paired status transitions and retry handling

This commit is contained in:
ejclaw
2026-04-07 02:49:02 +09:00
parent 4511ca5692
commit b8e8c9dabf
13 changed files with 574 additions and 280 deletions

View File

@@ -8,6 +8,7 @@ import {
buildArbiterPromptForTask,
buildFinalizePendingPrompt,
buildOwnerPendingPrompt,
buildPairedTurnPrompt,
buildReviewerPendingPrompt,
} from './message-runtime-prompts.js';
import {
@@ -47,6 +48,26 @@ export type BotOnlyPairedFollowUpAction =
nextRole: 'owner' | 'reviewer' | 'arbiter';
};
export type QueuedTurnDispatch = {
formatted: string;
botOnlyFollowUpAction: BotOnlyPairedFollowUpAction;
isBotOnlyPairedFollowUp: boolean;
loopCursorKey: string;
endSeq: number | null;
};
export function isBotOnlyPairedRoomTurn(
chatJid: string,
messages: NewMessage[],
): boolean {
return (
hasReviewerLease(chatJid) &&
messages.every(
(message) => message.is_from_me === true || !!message.is_bot_message,
)
);
}
export function resolveLastDeliveredBotRole(
messages: NewMessage[],
): PairedRoomRole | null {
@@ -384,6 +405,54 @@ export async function executeBotOnlyPairedFollowUpAction(args: {
return true;
}
export function buildQueuedTurnDispatch(args: {
chatJid: string;
timezone: string;
loopPendingTask: PairedTask | null | undefined;
rawPendingMessages: NewMessage[];
messagesToSend: NewMessage[];
labeledMessagesToSend: NewMessage[];
formatMessages: (messages: NewMessage[], timezone: string) => string;
}): QueuedTurnDispatch {
const loopCursorKey = resolveCursorKey(
args.chatJid,
args.loopPendingTask?.status,
);
const formatted = args.loopPendingTask
? buildPairedTurnPrompt({
taskId: args.loopPendingTask.id,
chatJid: args.chatJid,
timezone: args.timezone,
missedMessages: args.messagesToSend,
labeledFallbackMessages: args.labeledMessagesToSend,
turnOutputs: getPairedTurnOutputs(args.loopPendingTask.id),
})
: args.formatMessages(args.labeledMessagesToSend, args.timezone);
const isBotOnlyPairedFollowUp = isBotOnlyPairedRoomTurn(
args.chatJid,
args.messagesToSend,
);
const pendingCursorSource =
args.rawPendingMessages.length > 0
? args.rawPendingMessages[args.rawPendingMessages.length - 1]
: args.messagesToSend[args.messagesToSend.length - 1];
const botOnlyFollowUpAction = resolveBotOnlyPairedFollowUpAction({
chatJid: args.chatJid,
task: args.loopPendingTask,
isBotOnlyPairedFollowUp,
lastDeliveredMessages: args.labeledMessagesToSend,
pendingCursorSource,
});
return {
formatted,
botOnlyFollowUpAction,
isBotOnlyPairedFollowUp,
loopCursorKey,
endSeq: args.messagesToSend[args.messagesToSend.length - 1]?.seq ?? null,
};
}
export function shouldSkipGenericFollowUpAfterDeliveryRetry(args: {
chatJid: string;
deliveryRole: PairedRoomRole;