refactor: remove register_group legacy surface

This commit is contained in:
Eyejoker
2026-03-31 21:59:01 +09:00
parent a2d4651a82
commit 2070e0391f
5 changed files with 21 additions and 122 deletions

View File

@@ -495,7 +495,7 @@ server.tool(
'assign_room',
`Assign or update a room using room-level settings. Main group only.
This is the room-level replacement for legacy register_group. If folder is omitted, the host generates one automatically.`,
If folder is omitted, the host generates one automatically.`,
{
jid: z.string().describe('The chat JID (e.g., "120363336345536173@g.us", "tg:-1001234567890", "dc:1234567890123456")'),
name: z.string().describe('Display name for the room'),
@@ -547,42 +547,6 @@ This is the room-level replacement for legacy register_group. If folder is omitt
},
);
server.tool(
'register_group',
`Register a new chat/group so the agent can respond to messages there. Main group only.
Use available_groups.json to find the JID for a group. The folder name must be channel-prefixed: "{channel}_{group-name}" (e.g., "whatsapp_family-chat", "telegram_dev-team", "discord_general"). Use lowercase with hyphens for the group name part.`,
{
jid: z.string().describe('The chat JID (e.g., "120363336345536173@g.us", "tg:-1001234567890", "dc:1234567890123456")'),
name: z.string().describe('Display name for the group'),
folder: z.string().describe('Channel-prefixed folder name (e.g., "whatsapp_family-chat", "telegram_dev-team")'),
trigger: z.string().describe('Trigger word (e.g., "@Andy")'),
},
async (args: { jid: string; name: string; folder: string; trigger: string }) => {
if (!isMain) {
return {
content: [{ type: 'text' as const, text: 'Only the main group can register new groups.' }],
isError: true,
};
}
const data = {
type: 'register_group',
jid: args.jid,
name: args.name,
folder: args.folder,
trigger: args.trigger,
timestamp: new Date().toISOString(),
};
writeIpcFile(TASKS_DIR, data);
return {
content: [{ type: 'text' as const, text: `Group "${args.name}" registration requested.` }],
};
},
);
// Start the stdio transport
const transport = new StdioServerTransport();
await server.connect(transport);

View File

@@ -965,7 +965,7 @@ describe('paired room registration', () => {
});
});
it('keeps room-level metadata synced on legacy register_group writes', () => {
it('keeps room-level metadata synced on setRegisteredGroup helper writes', () => {
setRegisteredGroup('dc:room-settings', {
name: 'Room Settings Test',
folder: 'room-settings-test',

View File

@@ -216,46 +216,6 @@ function clearSession(
}
}
function registerGroup(jid: string, group: RegisteredGroup): void {
const assignedGroup = assignRoom(jid, {
name: group.name,
ownerAgentType: group.agentType,
folder: group.folder,
trigger: group.trigger,
requiresTrigger: group.requiresTrigger,
isMain: group.isMain,
workDir: group.workDir,
addedAt: group.added_at,
ownerAgentConfig: group.agentConfig,
});
if (!assignedGroup) {
logger.warn({ jid }, 'Failed to assign room during legacy registration');
return;
}
let groupDir: string;
try {
groupDir = resolveGroupFolderPath(assignedGroup.folder);
} catch (err) {
logger.warn(
{ jid, folder: assignedGroup.folder, err },
'Rejecting group registration with invalid folder',
);
return;
}
const { jid: _ignoredJid, ...storedGroup } = assignedGroup;
registeredGroups[jid] = storedGroup;
// Create group folder
fs.mkdirSync(path.join(groupDir, 'logs'), { recursive: true });
logger.info(
{ jid, name: assignedGroup.name, folder: assignedGroup.folder },
'Group registered',
);
}
function assignRoomForIpc(jid: string, input: AssignRoomInput): void {
const assignedGroup = assignRoom(jid, input);
if (!assignedGroup) {
@@ -521,7 +481,6 @@ async function main(): Promise<void> {
},
nudgeScheduler: nudgeSchedulerLoop,
registeredGroups: () => registeredGroups,
registerGroup,
assignRoom: assignRoomForIpc,
syncGroups: async (force: boolean) => {
await Promise.all(

View File

@@ -60,11 +60,6 @@ beforeEach(() => {
sendMessage: async () => {},
nudgeScheduler: vi.fn(),
registeredGroups: () => groups,
registerGroup: (jid, group) => {
groups[jid] = group;
setRegisteredGroup(jid, group);
// Mock the fs.mkdirSync that registerGroup does
},
assignRoom: (jid, room) => {
const assigned = assignRoom(jid, room);
if (!assigned) return;
@@ -384,13 +379,13 @@ describe('cancel_task authorization', () => {
});
});
// --- register_group authorization ---
// --- assign_room authorization ---
describe('register_group authorization', () => {
it('non-main group cannot register a group', async () => {
describe('assign_room authorization', () => {
it('non-main group cannot assign a room', async () => {
await processTaskIpc(
{
type: 'register_group',
type: 'assign_room',
jid: 'new@g.us',
name: 'New Group',
folder: 'new-group',
@@ -405,10 +400,10 @@ describe('register_group authorization', () => {
expect(groups['new@g.us']).toBeUndefined();
});
it('main group cannot register with unsafe folder path', async () => {
it('main group cannot assign with unsafe folder path', async () => {
await processTaskIpc(
{
type: 'register_group',
type: 'assign_room',
jid: 'new@g.us',
name: 'New Group',
folder: '../../outside',
@@ -779,13 +774,13 @@ describe('schedule_task context_mode', () => {
});
});
// --- register_group success path ---
// --- assign_room success path ---
describe('register_group success', () => {
it('main group can register a new group', async () => {
describe('assign_room success', () => {
it('main group can assign a new room', async () => {
await processTaskIpc(
{
type: 'register_group',
type: 'assign_room',
jid: 'new@g.us',
name: 'New Group',
folder: 'new-group',
@@ -796,7 +791,6 @@ describe('register_group success', () => {
deps,
);
// Verify group was registered in DB
const group = getRegisteredGroup('new@g.us');
expect(group).toBeDefined();
expect(group!.name).toBe('New Group');
@@ -804,10 +798,10 @@ describe('register_group success', () => {
expect(group!.trigger).toBe('@Andy');
});
it('register_group auto-fills missing folder and trigger for single rooms', async () => {
it('assign_room auto-fills missing folder and trigger for single rooms', async () => {
await processTaskIpc(
{
type: 'register_group',
type: 'assign_room',
jid: 'partial@g.us',
name: 'Partial',
},
@@ -823,7 +817,7 @@ describe('register_group success', () => {
expect(getStoredRoomSettings('partial@g.us')?.roomMode).toBe('single');
});
it('register_group preserves an existing tribunal room mode', async () => {
it('assign_room preserves an existing tribunal room mode when room_mode is omitted', async () => {
assignRoom('legacy-tribunal@g.us', {
name: 'Legacy Tribunal',
roomMode: 'tribunal',
@@ -833,7 +827,7 @@ describe('register_group success', () => {
await processTaskIpc(
{
type: 'register_group',
type: 'assign_room',
jid: 'legacy-tribunal@g.us',
name: 'Legacy Tribunal Renamed',
folder: 'legacy-tribunal',
@@ -854,9 +848,7 @@ describe('register_group success', () => {
'codex',
]);
});
});
describe('assign_room success', () => {
it('main group can assign a tribunal room and materialize capability rows', async () => {
await processTaskIpc(
{

View File

@@ -26,7 +26,6 @@ export interface IpcDeps {
sendMessage: (jid: string, text: string) => Promise<void>;
nudgeScheduler?: () => void;
registeredGroups: () => Record<string, RegisteredGroup>;
registerGroup: (jid: string, group: RegisteredGroup) => void;
assignRoom: (jid: string, room: AssignRoomInput) => void;
syncGroups: (force: boolean) => Promise<void>;
getAvailableGroups: () => AvailableGroup[];
@@ -294,7 +293,7 @@ export async function processTaskIpc(
groupFolder?: string;
chatJid?: string;
targetJid?: string;
// For assign_room / register_group
// For assign_room
jid?: string;
name?: string;
folder?: string;
@@ -304,7 +303,6 @@ export async function processTaskIpc(
owner_agent_type?: AgentType;
isMain?: boolean;
workDir?: string;
agentConfig?: RegisteredGroup['agentConfig'];
},
sourceGroup: string, // Verified identity from IPC directory
isMain: boolean, // Verified from directory path
@@ -602,8 +600,7 @@ export async function processTaskIpc(
break;
case 'assign_room':
case 'register_group':
// Only main group can assign/register rooms
// Only main group can assign rooms
if (!isMain) {
logger.warn(
{ sourceGroup, type: data.type },
@@ -642,28 +639,15 @@ export async function processTaskIpc(
break;
}
if (data.type === 'assign_room') {
deps.assignRoom(data.jid, {
name: data.name,
roomMode: data.room_mode,
ownerAgentType: data.owner_agent_type,
folder: data.folder,
trigger: data.trigger,
requiresTrigger: data.requiresTrigger,
isMain: data.isMain,
workDir: data.workDir,
});
break;
}
deps.assignRoom(data.jid, {
name: data.name,
roomMode: data.room_mode,
ownerAgentType: data.owner_agent_type,
folder: data.folder,
trigger: data.trigger,
requiresTrigger: data.requiresTrigger,
ownerAgentConfig: data.agentConfig,
addedAt: new Date().toISOString(),
isMain: data.isMain,
workDir: data.workDir,
});
} else {
logger.warn(