refactor: extract resolveEffectiveAgentType/resolveSessionFolder as SSOT, deduplicate CONTAINER_IMAGE
This commit is contained in:
@@ -40,8 +40,7 @@ import type { RegisteredGroup } from './types.js';
|
||||
|
||||
// ── Config ────────────────────────────────────────────────────────
|
||||
|
||||
const CONTAINER_IMAGE =
|
||||
process.env.REVIEWER_CONTAINER_IMAGE || 'ejclaw-reviewer:latest';
|
||||
import { REVIEWER_CONTAINER_IMAGE as CONTAINER_IMAGE } from './config.js';
|
||||
|
||||
// ── Types ─────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -23,7 +23,11 @@ import {
|
||||
completePairedExecutionContext,
|
||||
preparePairedExecutionContext,
|
||||
} from './paired-execution-context.js';
|
||||
import { resolveActiveRole } from './message-runtime-rules.js';
|
||||
import {
|
||||
resolveActiveRole,
|
||||
resolveEffectiveAgentType,
|
||||
resolveSessionFolder,
|
||||
} from './message-runtime-rules.js';
|
||||
import { buildRoomRoleContext } from './room-role-context.js';
|
||||
import {
|
||||
classifyRotationTrigger,
|
||||
@@ -35,11 +39,8 @@ import {
|
||||
shouldRetryFreshSessionOnAgentFailure,
|
||||
} from './session-recovery.js';
|
||||
import {
|
||||
ARBITER_AGENT_TYPE,
|
||||
CODEX_MAIN_SERVICE_ID,
|
||||
CODEX_REVIEW_SERVICE_ID,
|
||||
SERVICE_SESSION_SCOPE,
|
||||
REVIEWER_AGENT_TYPE,
|
||||
isClaudeService,
|
||||
getRoleModelConfig,
|
||||
} from './config.js';
|
||||
@@ -107,34 +108,20 @@ export async function runAgentForGroup(
|
||||
const reviewerMode = activeRole === 'reviewer';
|
||||
const arbiterMode = activeRole === 'arbiter';
|
||||
|
||||
// Override agent type based on role config (OWNER_AGENT_TYPE / REVIEWER_AGENT_TYPE).
|
||||
// When the reviewer uses a different agent type than the group default,
|
||||
// swap in the configured type for the duration of this execution.
|
||||
const reviewerAgentTypeOverride =
|
||||
reviewerMode && REVIEWER_AGENT_TYPE !== (group.agentType || 'claude-code');
|
||||
const arbiterAgentTypeOverride =
|
||||
arbiterMode &&
|
||||
ARBITER_AGENT_TYPE != null &&
|
||||
ARBITER_AGENT_TYPE !== (group.agentType || 'claude-code');
|
||||
const effectiveAgentType = arbiterAgentTypeOverride
|
||||
? ARBITER_AGENT_TYPE!
|
||||
: reviewerAgentTypeOverride
|
||||
? REVIEWER_AGENT_TYPE
|
||||
: group.agentType || 'claude-code';
|
||||
const effectiveGroup = arbiterAgentTypeOverride
|
||||
? { ...group, agentType: ARBITER_AGENT_TYPE! }
|
||||
: reviewerAgentTypeOverride
|
||||
? { ...group, agentType: REVIEWER_AGENT_TYPE }
|
||||
const effectiveAgentType = resolveEffectiveAgentType(
|
||||
activeRole,
|
||||
group.agentType,
|
||||
);
|
||||
const effectiveGroup =
|
||||
effectiveAgentType !== (group.agentType || 'claude-code')
|
||||
? { ...group, agentType: effectiveAgentType }
|
||||
: group;
|
||||
const isClaudeCodeAgent = effectiveAgentType === 'claude-code';
|
||||
|
||||
// When the reviewer/arbiter uses a different agent type than the group default,
|
||||
// use a separate session key so owner, reviewer, and arbiter sessions don't collide.
|
||||
const sessionFolder = arbiterAgentTypeOverride
|
||||
? `${group.folder}:arbiter`
|
||||
: reviewerAgentTypeOverride
|
||||
? `${group.folder}:reviewer`
|
||||
: group.folder;
|
||||
const sessionFolder = resolveSessionFolder(
|
||||
group.folder,
|
||||
activeRole,
|
||||
group.agentType,
|
||||
);
|
||||
const sessionId = sessions[sessionFolder];
|
||||
const memoryBriefing = sessionId
|
||||
? undefined
|
||||
@@ -478,10 +465,7 @@ export async function runAgentForGroup(
|
||||
groupFolder: group.folder,
|
||||
runId,
|
||||
provider: effectiveAgentType,
|
||||
reviewerMode,
|
||||
arbiterMode,
|
||||
reviewerAgentTypeOverride,
|
||||
arbiterAgentTypeOverride,
|
||||
role: activeRole,
|
||||
},
|
||||
`Using provider: ${effectiveAgentType}`,
|
||||
);
|
||||
|
||||
@@ -4,6 +4,12 @@ import { normalizeStoredSeqCursor } from './message-cursor.js';
|
||||
import { isTriggerAllowed, loadSenderAllowlist } from './sender-allowlist.js';
|
||||
import { isTaskStatusControlMessage } from './task-watch-status.js';
|
||||
import {
|
||||
ARBITER_AGENT_TYPE,
|
||||
OWNER_AGENT_TYPE,
|
||||
REVIEWER_AGENT_TYPE,
|
||||
} from './config.js';
|
||||
import {
|
||||
type AgentType,
|
||||
type Channel,
|
||||
type NewMessage,
|
||||
type RegisteredGroup,
|
||||
@@ -57,6 +63,38 @@ export function resolveCursorKey(
|
||||
return role === 'owner' ? chatJid : `${chatJid}:${role}`;
|
||||
}
|
||||
|
||||
/** Resolve the effective agent type for a role, considering per-role overrides. */
|
||||
export function resolveEffectiveAgentType(
|
||||
role: 'owner' | 'reviewer' | 'arbiter',
|
||||
groupAgentType: AgentType | undefined,
|
||||
): AgentType {
|
||||
const groupDefault: AgentType = groupAgentType || 'claude-code';
|
||||
switch (role) {
|
||||
case 'reviewer':
|
||||
return REVIEWER_AGENT_TYPE !== groupDefault
|
||||
? REVIEWER_AGENT_TYPE
|
||||
: groupDefault;
|
||||
case 'arbiter':
|
||||
return ARBITER_AGENT_TYPE != null && ARBITER_AGENT_TYPE !== groupDefault
|
||||
? ARBITER_AGENT_TYPE
|
||||
: groupDefault;
|
||||
default:
|
||||
return groupDefault;
|
||||
}
|
||||
}
|
||||
|
||||
/** Session folder key for a role. Owner uses groupFolder, others use groupFolder:role. */
|
||||
export function resolveSessionFolder(
|
||||
groupFolder: string,
|
||||
role: 'owner' | 'reviewer' | 'arbiter',
|
||||
groupAgentType: AgentType | undefined,
|
||||
): string {
|
||||
const effectiveType = resolveEffectiveAgentType(role, groupAgentType);
|
||||
const groupDefault: AgentType = groupAgentType || 'claude-code';
|
||||
if (effectiveType === groupDefault) return groupFolder;
|
||||
return `${groupFolder}:${role}`;
|
||||
}
|
||||
|
||||
export function createImplicitContinuationTracker(idleTimeout: number) {
|
||||
const implicitContinuationUntil = new Map<string, number>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user