refactor: read default room owner from room settings
This commit is contained in:
16
src/db.ts
16
src/db.ts
@@ -913,6 +913,22 @@ export function _initTestDatabaseFromFile(dbPath: string): void {
|
||||
createSchema(db);
|
||||
}
|
||||
|
||||
/** @internal - for tests only. */
|
||||
export function _setStoredRoomOwnerAgentTypeForTests(
|
||||
chatJid: string,
|
||||
ownerAgentType: AgentType | null,
|
||||
): void {
|
||||
if (!db) {
|
||||
throw new Error('Database not initialized');
|
||||
}
|
||||
db.prepare(
|
||||
`UPDATE room_settings
|
||||
SET owner_agent_type = ?,
|
||||
updated_at = ?
|
||||
WHERE chat_jid = ?`,
|
||||
).run(ownerAgentType, new Date().toISOString(), chatJid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store chat metadata only (no message content).
|
||||
* Used for all chats to enable group discovery without storing sensitive content.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { beforeEach, describe, expect, it } from 'vitest';
|
||||
|
||||
import {
|
||||
_setStoredRoomOwnerAgentTypeForTests,
|
||||
_initTestDatabase,
|
||||
setExplicitRoomMode,
|
||||
setRegisteredGroup,
|
||||
@@ -108,6 +109,53 @@ describe('service-routing global failover', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('uses stored owner agent type when room_settings selects a different owner', () => {
|
||||
setRegisteredGroup('dc:stored-owner-claude', {
|
||||
name: 'Stored Owner Claude',
|
||||
folder: 'stored-owner-claude',
|
||||
trigger: '@Andy',
|
||||
added_at: '2024-01-01T00:00:00.000Z',
|
||||
agentType: 'claude-code',
|
||||
});
|
||||
setRegisteredGroup('dc:stored-owner-claude', {
|
||||
name: 'Stored Owner Claude',
|
||||
folder: 'stored-owner-claude',
|
||||
trigger: '@Codex',
|
||||
added_at: '2024-01-01T00:00:00.000Z',
|
||||
agentType: 'codex',
|
||||
});
|
||||
setExplicitRoomMode('dc:stored-owner-claude', 'single');
|
||||
_setStoredRoomOwnerAgentTypeForTests(
|
||||
'dc:stored-owner-claude',
|
||||
'claude-code',
|
||||
);
|
||||
|
||||
expect(getEffectiveChannelLease('dc:stored-owner-claude')).toMatchObject({
|
||||
chat_jid: 'dc:stored-owner-claude',
|
||||
owner_service_id: 'claude',
|
||||
reviewer_service_id: null,
|
||||
explicit: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('falls back to the available service when stored owner agent type is unavailable', () => {
|
||||
setRegisteredGroup('dc:stored-owner-fallback', {
|
||||
name: 'Stored Owner Fallback',
|
||||
folder: 'stored-owner-fallback',
|
||||
trigger: '@Andy',
|
||||
added_at: '2024-01-01T00:00:00.000Z',
|
||||
agentType: 'claude-code',
|
||||
});
|
||||
_setStoredRoomOwnerAgentTypeForTests('dc:stored-owner-fallback', 'codex');
|
||||
|
||||
expect(getEffectiveChannelLease('dc:stored-owner-fallback')).toMatchObject({
|
||||
chat_jid: 'dc:stored-owner-fallback',
|
||||
owner_service_id: 'claude',
|
||||
reviewer_service_id: null,
|
||||
explicit: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('creates a same-service reviewer lease when explicit tribunal is runnable on a solo registration', () => {
|
||||
setRegisteredGroup('dc:explicit-tribunal', {
|
||||
name: 'Explicit Tribunal Claude',
|
||||
@@ -145,4 +193,13 @@ describe('service-routing global failover', () => {
|
||||
explicit: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps the legacy claude fallback for chats without room settings', () => {
|
||||
expect(getEffectiveChannelLease('dc:unregistered')).toMatchObject({
|
||||
chat_jid: 'dc:unregistered',
|
||||
owner_service_id: 'claude',
|
||||
reviewer_service_id: null,
|
||||
explicit: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,10 +14,12 @@ import {
|
||||
getAllChannelOwnerLeases,
|
||||
getEffectiveRuntimeRoomMode,
|
||||
getRegisteredAgentTypesForJid,
|
||||
getStoredRoomSettings,
|
||||
setChannelOwnerLease,
|
||||
type ChannelOwnerLeaseRow,
|
||||
} from './db.js';
|
||||
import { logger } from './logger.js';
|
||||
import type { AgentType } from './types.js';
|
||||
|
||||
export interface EffectiveChannelLease {
|
||||
chat_jid: string;
|
||||
@@ -55,21 +57,44 @@ function normalizeLeaseRow(
|
||||
};
|
||||
}
|
||||
|
||||
function getDefaultLease(chatJid: string): EffectiveChannelLease {
|
||||
function getServiceIdForAgentType(agentType: AgentType): string {
|
||||
return agentType === 'codex' ? CODEX_MAIN_SERVICE_ID : CLAUDE_SERVICE_ID;
|
||||
}
|
||||
|
||||
function inferFallbackOwnerAgentType(
|
||||
hasClaude: boolean,
|
||||
hasCodex: boolean,
|
||||
): AgentType | undefined {
|
||||
if (hasClaude && hasCodex) return OWNER_AGENT_TYPE;
|
||||
if (hasCodex) return 'codex';
|
||||
if (hasClaude) return 'claude-code';
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function resolveDefaultOwnerAgentType(chatJid: string): AgentType | undefined {
|
||||
const types = getRegisteredAgentTypesForJid(chatJid);
|
||||
const hasClaude = types.includes('claude-code');
|
||||
const hasCodex = types.includes('codex');
|
||||
const storedOwnerAgentType = getStoredRoomSettings(chatJid)?.ownerAgentType;
|
||||
|
||||
if (storedOwnerAgentType === 'claude-code' && hasClaude) {
|
||||
return 'claude-code';
|
||||
}
|
||||
if (storedOwnerAgentType === 'codex' && hasCodex) {
|
||||
return 'codex';
|
||||
}
|
||||
|
||||
return inferFallbackOwnerAgentType(hasClaude, hasCodex);
|
||||
}
|
||||
|
||||
function getDefaultLease(chatJid: string): EffectiveChannelLease {
|
||||
const roomMode = getEffectiveRuntimeRoomMode(chatJid);
|
||||
const ownerAgentType = resolveDefaultOwnerAgentType(chatJid);
|
||||
const ownerServiceId = ownerAgentType
|
||||
? getServiceIdForAgentType(ownerAgentType)
|
||||
: CLAUDE_SERVICE_ID;
|
||||
|
||||
if (roomMode === 'tribunal') {
|
||||
const ownerServiceId =
|
||||
hasClaude && hasCodex
|
||||
? OWNER_AGENT_TYPE === 'codex'
|
||||
? CODEX_MAIN_SERVICE_ID
|
||||
: CLAUDE_SERVICE_ID
|
||||
: hasCodex
|
||||
? CODEX_MAIN_SERVICE_ID
|
||||
: CLAUDE_SERVICE_ID;
|
||||
return {
|
||||
chat_jid: chatJid,
|
||||
owner_service_id: ownerServiceId,
|
||||
@@ -81,33 +106,9 @@ function getDefaultLease(chatJid: string): EffectiveChannelLease {
|
||||
};
|
||||
}
|
||||
|
||||
if (hasCodex) {
|
||||
return {
|
||||
chat_jid: chatJid,
|
||||
owner_service_id: CODEX_MAIN_SERVICE_ID,
|
||||
reviewer_service_id: null,
|
||||
arbiter_service_id: null,
|
||||
activated_at: null,
|
||||
reason: null,
|
||||
explicit: false,
|
||||
};
|
||||
}
|
||||
|
||||
if (hasClaude) {
|
||||
return {
|
||||
chat_jid: chatJid,
|
||||
owner_service_id: CLAUDE_SERVICE_ID,
|
||||
reviewer_service_id: null,
|
||||
arbiter_service_id: null,
|
||||
activated_at: null,
|
||||
reason: null,
|
||||
explicit: false,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
chat_jid: chatJid,
|
||||
owner_service_id: CLAUDE_SERVICE_ID,
|
||||
owner_service_id: ownerServiceId,
|
||||
reviewer_service_id: null,
|
||||
arbiter_service_id: null,
|
||||
activated_at: null,
|
||||
|
||||
Reference in New Issue
Block a user