* 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>
95 lines
2.5 KiB
TypeScript
95 lines
2.5 KiB
TypeScript
/**
|
|
* Step: environment — Detect OS, Node, container runtimes, existing config.
|
|
* Replaces 01-check-environment.sh
|
|
*/
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
import Database from 'better-sqlite3';
|
|
|
|
import { STORE_DIR } from '../src/config.js';
|
|
import { logger } from '../src/logger.js';
|
|
import { commandExists, getPlatform, isHeadless, isWSL } from './platform.js';
|
|
import { emitStatus } from './status.js';
|
|
|
|
export async function run(_args: string[]): Promise<void> {
|
|
const projectRoot = process.cwd();
|
|
|
|
logger.info('Starting environment check');
|
|
|
|
const platform = getPlatform();
|
|
const wsl = isWSL();
|
|
const headless = isHeadless();
|
|
|
|
// Check Apple Container
|
|
let appleContainer: 'installed' | 'not_found' = 'not_found';
|
|
if (commandExists('container')) {
|
|
appleContainer = 'installed';
|
|
}
|
|
|
|
// Check Docker
|
|
let docker: 'running' | 'installed_not_running' | 'not_found' = 'not_found';
|
|
if (commandExists('docker')) {
|
|
try {
|
|
const { execSync } = await import('child_process');
|
|
execSync('docker info', { stdio: 'ignore' });
|
|
docker = 'running';
|
|
} catch {
|
|
docker = 'installed_not_running';
|
|
}
|
|
}
|
|
|
|
// Check existing config
|
|
const hasEnv = fs.existsSync(path.join(projectRoot, '.env'));
|
|
|
|
const authDir = path.join(projectRoot, 'store', 'auth');
|
|
const hasAuth = fs.existsSync(authDir) && fs.readdirSync(authDir).length > 0;
|
|
|
|
let hasRegisteredGroups = false;
|
|
// Check JSON file first (pre-migration)
|
|
if (fs.existsSync(path.join(projectRoot, 'data', 'registered_groups.json'))) {
|
|
hasRegisteredGroups = true;
|
|
} else {
|
|
// Check SQLite directly using better-sqlite3 (no sqlite3 CLI needed)
|
|
const dbPath = path.join(STORE_DIR, 'messages.db');
|
|
if (fs.existsSync(dbPath)) {
|
|
try {
|
|
const db = new Database(dbPath, { readonly: true });
|
|
const row = db
|
|
.prepare('SELECT COUNT(*) as count FROM registered_groups')
|
|
.get() as { count: number };
|
|
if (row.count > 0) hasRegisteredGroups = true;
|
|
db.close();
|
|
} catch {
|
|
// Table might not exist yet
|
|
}
|
|
}
|
|
}
|
|
|
|
logger.info(
|
|
{
|
|
platform,
|
|
wsl,
|
|
appleContainer,
|
|
docker,
|
|
hasEnv,
|
|
hasAuth,
|
|
hasRegisteredGroups,
|
|
},
|
|
'Environment check complete',
|
|
);
|
|
|
|
emitStatus('CHECK_ENVIRONMENT', {
|
|
PLATFORM: platform,
|
|
IS_WSL: wsl,
|
|
IS_HEADLESS: headless,
|
|
APPLE_CONTAINER: appleContainer,
|
|
DOCKER: docker,
|
|
HAS_ENV: hasEnv,
|
|
HAS_AUTH: hasAuth,
|
|
HAS_REGISTERED_GROUPS: hasRegisteredGroups,
|
|
STATUS: 'success',
|
|
LOG: 'logs/setup.log',
|
|
});
|
|
}
|