refactor: centralize cursor key resolution with resolveCursorKey()

Replace all manual cursor key construction (hardcoded chatJid:reviewer,
chatJid:arbiter, pairedCursorKey, 3-way ternary) with a single
resolveCursorKey(chatJid, taskStatus) function.

- Removed pairedCursorKey import (no longer needed)
- Removed loopIsReviewerTurn, loopIsArbiterTurn intermediate variables
- All cursor key logic now flows through one function that maps
  task status to the correct role-specific key
This commit is contained in:
Eyejoker
2026-03-30 22:54:35 +09:00
parent 46926f32f3
commit 7ad40276d9
2 changed files with 29 additions and 17 deletions

View File

@@ -39,6 +39,30 @@ export function pairedCursorKey(
return isReviewerTurn ? `${chatJid}:reviewer` : chatJid; return isReviewerTurn ? `${chatJid}:reviewer` : chatJid;
} }
/**
* Auto-resolve the cursor key based on current paired task status.
* Non-paired rooms always return chatJid.
* Paired rooms return role-specific keys so owner/reviewer/arbiter
* cursors are independent.
*/
export function resolveCursorKey(
chatJid: string,
taskStatus?: string | null,
): string {
if (!isPairedRoomJid(chatJid)) return chatJid;
if (!taskStatus) return chatJid;
switch (taskStatus) {
case 'review_ready':
case 'in_review':
return `${chatJid}:reviewer`;
case 'arbiter_requested':
case 'in_arbitration':
return `${chatJid}:arbiter`;
default:
return chatJid;
}
}
export function createImplicitContinuationTracker(idleTimeout: number) { export function createImplicitContinuationTracker(idleTimeout: number) {
const implicitContinuationUntil = new Map<string, number>(); const implicitContinuationUntil = new Map<string, number>();

View File

@@ -41,7 +41,7 @@ import { isTriggerAllowed, loadSenderAllowlist } from './sender-allowlist.js';
import { import {
advanceLastAgentCursor, advanceLastAgentCursor,
createImplicitContinuationTracker, createImplicitContinuationTracker,
pairedCursorKey, resolveCursorKey,
filterLoopingPairedBotMessages, filterLoopingPairedBotMessages,
getProcessableMessages, getProcessableMessages,
hasAllowedTrigger, hasAllowedTrigger,
@@ -634,7 +634,7 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): {
deps.saveState, deps.saveState,
chatJid, chatJid,
cursor, cursor,
`${chatJid}:reviewer`, resolveCursorKey(chatJid, pendingReviewTask?.status),
); );
} }
@@ -665,7 +665,7 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): {
deps.saveState, deps.saveState,
chatJid, chatJid,
cursor, cursor,
`${chatJid}:arbiter`, resolveCursorKey(chatJid, pendingReviewTask?.status),
); );
} }
@@ -839,9 +839,7 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): {
: useReviewerChannel : useReviewerChannel
? reviewerChannel ? reviewerChannel
: channel; : channel;
const cursorKey = useArbiterChannel const cursorKey = resolveCursorKey(chatJid, pendingTaskForChannel?.status);
? `${chatJid}:arbiter`
: pairedCursorKey(chatJid, !!useReviewerChannel);
// Arbiter turns use a dedicated context prompt; regular turns use formatted messages. // Arbiter turns use a dedicated context prompt; regular turns use formatted messages.
let prompt: string; let prompt: string;
@@ -1049,17 +1047,7 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): {
const loopPendingTask = isPairedRoomJid(chatJid) const loopPendingTask = isPairedRoomJid(chatJid)
? getLatestOpenPairedTaskForChat(chatJid) ? getLatestOpenPairedTaskForChat(chatJid)
: null; : null;
const loopIsReviewerTurn = const loopCursorKey = resolveCursorKey(chatJid, loopPendingTask?.status);
!!loopPendingTask &&
(loopPendingTask.status === 'review_ready' ||
loopPendingTask.status === 'in_review');
const loopIsArbiterTurn =
!!loopPendingTask &&
(loopPendingTask.status === 'arbiter_requested' ||
loopPendingTask.status === 'in_arbitration');
const loopCursorKey = loopIsArbiterTurn
? `${chatJid}:arbiter`
: pairedCursorKey(chatJid, loopIsReviewerTurn);
const rawPendingMessages = getMessagesSinceSeq( const rawPendingMessages = getMessagesSinceSeq(
chatJid, chatJid,