Backfill paired agent metadata for raw service ids

This commit is contained in:
ejclaw
2026-04-10 16:20:23 +09:00
parent 2e62e125ae
commit ce3854745d
4 changed files with 48 additions and 3 deletions

View File

@@ -22,6 +22,8 @@ export function normalizeServiceId(serviceId: string): string {
} }
export const SERVICE_SESSION_SCOPE = normalizeServiceId(SERVICE_ID); export const SERVICE_SESSION_SCOPE = normalizeServiceId(SERVICE_ID);
export const CURRENT_RUNTIME_AGENT_TYPE =
SERVICE_SESSION_SCOPE === CLAUDE_SERVICE_ID ? 'claude-code' : 'codex';
export function isClaudeService(serviceId: string = SERVICE_ID): boolean { export function isClaudeService(serviceId: string = SERVICE_ID): boolean {
return normalizeServiceId(serviceId) === CLAUDE_SERVICE_ID; return normalizeServiceId(serviceId) === CLAUDE_SERVICE_ID;

View File

@@ -92,6 +92,7 @@ import {
CLAUDE_SERVICE_ID, CLAUDE_SERVICE_ID,
CODEX_MAIN_SERVICE_ID, CODEX_MAIN_SERVICE_ID,
CODEX_REVIEW_SERVICE_ID, CODEX_REVIEW_SERVICE_ID,
OWNER_AGENT_TYPE,
SERVICE_ID, SERVICE_ID,
SERVICE_SESSION_SCOPE, SERVICE_SESSION_SCOPE,
normalizeServiceId, normalizeServiceId,
@@ -1091,6 +1092,34 @@ describe('paired task state', () => {
}); });
}); });
it('backfills configured owner agent type when creating a paired task with a raw non-shadow owner service id', () => {
createPairedTask({
id: 'paired-task-raw-owner-service',
chat_jid: 'dc:paired-raw-owner-service',
group_folder: 'paired-raw-owner-service',
owner_service_id: 'andy',
reviewer_service_id: CLAUDE_SERVICE_ID,
title: null,
source_ref: 'HEAD',
plan_notes: null,
review_requested_at: null,
round_trip_count: 0,
status: 'active',
arbiter_verdict: null,
arbiter_requested_at: null,
completion_reason: null,
created_at: '2026-03-28T00:00:00.000Z',
updated_at: '2026-03-28T00:00:00.000Z',
});
expect(getPairedTaskById('paired-task-raw-owner-service')).toMatchObject({
owner_service_id: 'andy',
reviewer_service_id: CLAUDE_SERVICE_ID,
owner_agent_type: OWNER_AGENT_TYPE,
reviewer_agent_type: 'claude-code',
});
});
it('preserves raw legacy paired task service ids during init when registered group metadata is present', () => { it('preserves raw legacy paired task service ids during init when registered group metadata is present', () => {
const tempDir = fs.mkdtempSync('/tmp/ejclaw-paired-task-legacy-groups-'); const tempDir = fs.mkdtempSync('/tmp/ejclaw-paired-task-legacy-groups-');
const dbPath = path.join(tempDir, 'messages.db'); const dbPath = path.join(tempDir, 'messages.db');

View File

@@ -1,4 +1,9 @@
import { ARBITER_AGENT_TYPE, SERVICE_SESSION_SCOPE } from '../config.js'; import {
ARBITER_AGENT_TYPE,
OWNER_AGENT_TYPE,
REVIEWER_AGENT_TYPE,
SERVICE_SESSION_SCOPE,
} from '../config.js';
import { import {
inferAgentTypeFromServiceShadow, inferAgentTypeFromServiceShadow,
inferRoleFromServiceShadow, inferRoleFromServiceShadow,
@@ -12,6 +17,7 @@ interface RequiredRoleMetadataInput {
role: PairedRoomRole; role: PairedRoomRole;
storedAgentType?: string | null; storedAgentType?: string | null;
storedServiceId?: string | null; storedServiceId?: string | null;
fallbackAgentType?: AgentType | null;
} }
interface OptionalRoleMetadataInput extends RequiredRoleMetadataInput {} interface OptionalRoleMetadataInput extends RequiredRoleMetadataInput {}
@@ -31,7 +37,8 @@ function resolveRequiredAgentType(input: RequiredRoleMetadataInput): AgentType {
); );
} }
const agentType = persistedAgentType ?? inferredAgentType; const agentType =
persistedAgentType ?? inferredAgentType ?? input.fallbackAgentType ?? null;
if (agentType) { if (agentType) {
return agentType; return agentType;
} }
@@ -100,12 +107,14 @@ export function canonicalizePairedTaskMetadata(input: {
role: 'owner', role: 'owner',
storedAgentType: input.owner_agent_type, storedAgentType: input.owner_agent_type,
storedServiceId: input.owner_service_id, storedServiceId: input.owner_service_id,
fallbackAgentType: OWNER_AGENT_TYPE,
}); });
const reviewerAgentType = resolveRequiredAgentType({ const reviewerAgentType = resolveRequiredAgentType({
context, context,
role: 'reviewer', role: 'reviewer',
storedAgentType: input.reviewer_agent_type, storedAgentType: input.reviewer_agent_type,
storedServiceId: input.reviewer_service_id, storedServiceId: input.reviewer_service_id,
fallbackAgentType: REVIEWER_AGENT_TYPE,
}); });
return { return {

View File

@@ -1,6 +1,10 @@
import { Database } from 'bun:sqlite'; import { Database } from 'bun:sqlite';
import { SERVICE_ID, normalizeServiceId } from '../config.js'; import {
CURRENT_RUNTIME_AGENT_TYPE,
SERVICE_ID,
normalizeServiceId,
} from '../config.js';
import { import {
buildPairedTurnIdentity, buildPairedTurnIdentity,
resolvePairedTurnRole, resolvePairedTurnRole,
@@ -602,6 +606,7 @@ export function claimPairedTurnReservationInDatabase(
const currentAttempt = markPairedTurnRunningInDatabase(database, { const currentAttempt = markPairedTurnRunningInDatabase(database, {
turnIdentity, turnIdentity,
executorServiceId: CURRENT_SERVICE_ID, executorServiceId: CURRENT_SERVICE_ID,
executorAgentType: CURRENT_RUNTIME_AGENT_TYPE,
runId: args.runId, runId: args.runId,
}); });
if (!currentAttempt) { if (!currentAttempt) {