refactor: CI optimization, logging improvements, and codebase formatting (#456)
* fix(db): remove unique constraint on folder to support multi-channel agents * ci: implement automated skill drift detection and self-healing PRs * fix: align registration logic with Gavriel's feedback and fix build/test issues from Daniel Mi * style: conform to prettier standards for CI validation * test: fix branch naming inconsistency in CI (master vs main) * fix(ci): robust module resolution by removing file extensions in scripts * refactor(ci): simplify skill validation by removing redundant combination tests * style: conform skills-engine to prettier, unify logging in index.ts and cleanup unused imports * refactor: extract multi-channel DB changes to separate branch Move channel column, folder suffix logic, and related migrations to feat/multi-channel-db-v2 for independent review. This PR now contains only CI/CD optimizations, Prettier formatting, and logging improvements. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -66,8 +66,14 @@ function parseArgs(args: string[]): { method: string; phone: string } {
|
||||
let method = '';
|
||||
let phone = '';
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i] === '--method' && args[i + 1]) { method = args[i + 1]; i++; }
|
||||
if (args[i] === '--phone' && args[i + 1]) { phone = args[i + 1]; i++; }
|
||||
if (args[i] === '--method' && args[i + 1]) {
|
||||
method = args[i + 1];
|
||||
i++;
|
||||
}
|
||||
if (args[i] === '--phone' && args[i + 1]) {
|
||||
phone = args[i + 1];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return { method, phone };
|
||||
}
|
||||
@@ -87,7 +93,10 @@ function readFileSafe(filePath: string): string {
|
||||
function getPhoneNumber(projectRoot: string): string {
|
||||
try {
|
||||
const creds = JSON.parse(
|
||||
fs.readFileSync(path.join(projectRoot, 'store', 'auth', 'creds.json'), 'utf-8'),
|
||||
fs.readFileSync(
|
||||
path.join(projectRoot, 'store', 'auth', 'creds.json'),
|
||||
'utf-8',
|
||||
),
|
||||
);
|
||||
if (creds.me?.id) {
|
||||
return creds.me.id.split(':')[0].split('@')[0];
|
||||
@@ -121,18 +130,24 @@ export async function run(args: string[]): Promise<void> {
|
||||
const qrFile = path.join(projectRoot, 'store', 'qr-data.txt');
|
||||
|
||||
if (!method) {
|
||||
emitAuthStatus('unknown', 'failed', 'failed', { ERROR: 'missing_method_flag' });
|
||||
emitAuthStatus('unknown', 'failed', 'failed', {
|
||||
ERROR: 'missing_method_flag',
|
||||
});
|
||||
process.exit(4);
|
||||
}
|
||||
|
||||
// qr-terminal is a manual flow
|
||||
if (method === 'qr-terminal') {
|
||||
emitAuthStatus('qr-terminal', 'manual', 'manual', { PROJECT_PATH: projectRoot });
|
||||
emitAuthStatus('qr-terminal', 'manual', 'manual', {
|
||||
PROJECT_PATH: projectRoot,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (method === 'pairing-code' && !phone) {
|
||||
emitAuthStatus('pairing-code', 'failed', 'failed', { ERROR: 'missing_phone_number' });
|
||||
emitAuthStatus('pairing-code', 'failed', 'failed', {
|
||||
ERROR: 'missing_phone_number',
|
||||
});
|
||||
process.exit(4);
|
||||
}
|
||||
|
||||
@@ -143,14 +158,30 @@ export async function run(args: string[]): Promise<void> {
|
||||
|
||||
// Clean stale state
|
||||
logger.info({ method }, 'Starting WhatsApp auth');
|
||||
try { fs.rmSync(path.join(projectRoot, 'store', 'auth'), { recursive: true, force: true }); } catch { /* ok */ }
|
||||
try { fs.unlinkSync(qrFile); } catch { /* ok */ }
|
||||
try { fs.unlinkSync(statusFile); } catch { /* ok */ }
|
||||
try {
|
||||
fs.rmSync(path.join(projectRoot, 'store', 'auth'), {
|
||||
recursive: true,
|
||||
force: true,
|
||||
});
|
||||
} catch {
|
||||
/* ok */
|
||||
}
|
||||
try {
|
||||
fs.unlinkSync(qrFile);
|
||||
} catch {
|
||||
/* ok */
|
||||
}
|
||||
try {
|
||||
fs.unlinkSync(statusFile);
|
||||
} catch {
|
||||
/* ok */
|
||||
}
|
||||
|
||||
// Start auth process in background
|
||||
const authArgs = method === 'pairing-code'
|
||||
? ['src/whatsapp-auth.ts', '--pairing-code', '--phone', phone]
|
||||
: ['src/whatsapp-auth.ts'];
|
||||
const authArgs =
|
||||
method === 'pairing-code'
|
||||
? ['src/whatsapp-auth.ts', '--pairing-code', '--phone', phone]
|
||||
: ['src/whatsapp-auth.ts'];
|
||||
|
||||
const authProc = spawn('npx', ['tsx', ...authArgs], {
|
||||
cwd: projectRoot,
|
||||
@@ -165,7 +196,11 @@ export async function run(args: string[]): Promise<void> {
|
||||
|
||||
// Cleanup on exit
|
||||
const cleanup = () => {
|
||||
try { authProc.kill(); } catch { /* ok */ }
|
||||
try {
|
||||
authProc.kill();
|
||||
} catch {
|
||||
/* ok */
|
||||
}
|
||||
};
|
||||
process.on('exit', cleanup);
|
||||
|
||||
@@ -221,10 +256,14 @@ async function handleQrBrowser(
|
||||
if (!isHeadless()) {
|
||||
const opened = openBrowser(htmlPath);
|
||||
if (!opened) {
|
||||
logger.warn('Could not open browser — display QR in terminal as fallback');
|
||||
logger.warn(
|
||||
'Could not open browser — display QR in terminal as fallback',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
logger.info('Headless environment — QR HTML saved but browser not opened');
|
||||
logger.info(
|
||||
'Headless environment — QR HTML saved but browser not opened',
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error({ err }, 'Failed to generate QR HTML');
|
||||
@@ -261,15 +300,24 @@ async function handlePairingCode(
|
||||
}
|
||||
|
||||
if (!pairingCode) {
|
||||
emitAuthStatus('pairing-code', 'failed', 'failed', { ERROR: 'pairing_code_timeout' });
|
||||
emitAuthStatus('pairing-code', 'failed', 'failed', {
|
||||
ERROR: 'pairing_code_timeout',
|
||||
});
|
||||
process.exit(3);
|
||||
}
|
||||
|
||||
// Emit pairing code immediately so the caller can display it to the user
|
||||
emitAuthStatus('pairing-code', 'pairing_code_ready', 'waiting', { PAIRING_CODE: pairingCode });
|
||||
emitAuthStatus('pairing-code', 'pairing_code_ready', 'waiting', {
|
||||
PAIRING_CODE: pairingCode,
|
||||
});
|
||||
|
||||
// Poll for completion (120s)
|
||||
await pollAuthCompletion('pairing-code', statusFile, projectRoot, pairingCode);
|
||||
await pollAuthCompletion(
|
||||
'pairing-code',
|
||||
statusFile,
|
||||
projectRoot,
|
||||
pairingCode,
|
||||
);
|
||||
}
|
||||
|
||||
async function pollAuthCompletion(
|
||||
|
||||
Reference in New Issue
Block a user