131 lines
3.9 KiB
TypeScript
131 lines
3.9 KiB
TypeScript
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
import { Database } from 'bun:sqlite';
|
|
|
|
import { STORE_DIR } from '../src/config.js';
|
|
import { listUnexpectedDataStateFiles } from '../src/data-state-files.js';
|
|
import { countPendingLegacyRegisteredGroupRows } from './legacy-room-registrations.js';
|
|
|
|
export interface AssignedRoomsSummary {
|
|
assignedRooms: number;
|
|
roomsByOwnerAgent: Record<string, number>;
|
|
legacyRegisteredGroupRows: number;
|
|
legacyRoomMigrationRequired: boolean;
|
|
unexpectedDataStateFiles: string[];
|
|
unexpectedDataStateDetected: boolean;
|
|
}
|
|
|
|
export interface LegacyMigrationGuidance {
|
|
error: string;
|
|
nextStep: string;
|
|
}
|
|
|
|
function getDataDir(projectRoot: string): string {
|
|
return process.env.EJCLAW_DATA_DIR || path.join(projectRoot, 'data');
|
|
}
|
|
|
|
export function getLegacyMigrationGuidance(
|
|
summary: Pick<
|
|
AssignedRoomsSummary,
|
|
'legacyRoomMigrationRequired' | 'unexpectedDataStateDetected'
|
|
>,
|
|
target: 'setup' | 'verification',
|
|
): LegacyMigrationGuidance | undefined {
|
|
if (
|
|
!summary.legacyRoomMigrationRequired &&
|
|
!summary.unexpectedDataStateDetected
|
|
) {
|
|
return undefined;
|
|
}
|
|
|
|
const error =
|
|
summary.legacyRoomMigrationRequired && summary.unexpectedDataStateDetected
|
|
? 'legacy_migration_and_unexpected_data_state_detected'
|
|
: summary.legacyRoomMigrationRequired
|
|
? 'legacy_room_migration_required'
|
|
: 'unexpected_data_state_files_detected';
|
|
const nextStep =
|
|
summary.legacyRoomMigrationRequired && summary.unexpectedDataStateDetected
|
|
? `Run \`bun setup/index.ts --step migrate-room-registrations\` and remove or archive unexpected data state files before continuing with ${target}`
|
|
: summary.legacyRoomMigrationRequired
|
|
? `Run \`bun setup/index.ts --step migrate-room-registrations\` before continuing with ${target}`
|
|
: `Remove or archive unexpected data state files before continuing with ${target}`;
|
|
|
|
return {
|
|
error,
|
|
nextStep,
|
|
};
|
|
}
|
|
|
|
export function detectRoomRegistrationState(
|
|
options: {
|
|
projectRoot?: string;
|
|
dbPath?: string;
|
|
} = {},
|
|
): AssignedRoomsSummary {
|
|
const projectRoot = options.projectRoot ?? process.cwd();
|
|
const dbPath = options.dbPath ?? path.join(STORE_DIR, 'messages.db');
|
|
let assignedRooms = 0;
|
|
let legacyRegisteredGroupRows = 0;
|
|
const roomsByOwnerAgent: Record<string, number> = {};
|
|
|
|
if (fs.existsSync(dbPath)) {
|
|
try {
|
|
const db = new Database(dbPath, { readonly: true });
|
|
|
|
try {
|
|
const row = db
|
|
.prepare('SELECT COUNT(*) as count FROM room_settings')
|
|
.get() as { count: number };
|
|
assignedRooms = row.count;
|
|
} catch {
|
|
assignedRooms = 0;
|
|
}
|
|
|
|
if (assignedRooms > 0) {
|
|
try {
|
|
const rows = db
|
|
.prepare(
|
|
`SELECT COALESCE(owner_agent_type, 'unknown') AS owner_agent_type,
|
|
COUNT(*) AS count
|
|
FROM room_settings
|
|
GROUP BY COALESCE(owner_agent_type, 'unknown')`,
|
|
)
|
|
.all() as { owner_agent_type: string; count: number }[];
|
|
for (const current of rows) {
|
|
roomsByOwnerAgent[current.owner_agent_type] = current.count;
|
|
}
|
|
} catch {
|
|
// room_settings might not exist in older schema
|
|
}
|
|
}
|
|
|
|
try {
|
|
legacyRegisteredGroupRows = countPendingLegacyRegisteredGroupRows(db);
|
|
} catch {
|
|
legacyRegisteredGroupRows = 0;
|
|
}
|
|
|
|
db.close();
|
|
} catch {
|
|
// Database might not exist yet or schema might be incomplete
|
|
}
|
|
}
|
|
|
|
const unexpectedDataStateFiles = listUnexpectedDataStateFiles(
|
|
getDataDir(projectRoot),
|
|
);
|
|
const legacyRoomMigrationRequired = legacyRegisteredGroupRows > 0;
|
|
const unexpectedDataStateDetected = unexpectedDataStateFiles.length > 0;
|
|
|
|
return {
|
|
assignedRooms,
|
|
roomsByOwnerAgent,
|
|
legacyRegisteredGroupRows,
|
|
legacyRoomMigrationRequired,
|
|
unexpectedDataStateFiles,
|
|
unexpectedDataStateDetected,
|
|
};
|
|
}
|