lilith-platform/scripts/commands/dev/status.ts
Lilith 3f75b5f243 chore: initialize monorepo with submodules
Root workspace configuration with 4 submodules:
- codebase/ → lilith/platform-codebase
- deployments/ → lilith/platform-deployments
- tooling/ → lilith/platform-tooling
- docs/ → lilith/platform-docs

Tracks workspace config (package.json, turbo.json, bunfig.toml),
CI workflows (.forgejo/), dev scripts, and instructions.
Each submodule retains its own history and remote.
2026-01-29 07:07:12 -08:00

289 lines
9.9 KiB
TypeScript

#!/usr/bin/env npx tsx
/**
* =============================================================================
* ./run dev status - Development Environment Status
* =============================================================================
*
* Shows the status of all development services.
*
* Usage:
* ./run dev status # Show status dashboard
* ./run dev status --json # Output as JSON
*/
import { execFileSync } from 'node:child_process';
import * as path from 'node:path';
import { getDeploymentDomains } from '../../../infrastructure/tooling/run/utils/deployment-urls';
// =============================================================================
// Configuration
// =============================================================================
const PROJECT_ROOT = path.resolve(__dirname, '../../..');
interface ServiceStatus {
name: string;
status: 'running' | 'stopped' | 'unhealthy' | 'unknown';
port?: number;
url?: string;
health?: string;
}
// =============================================================================
// Colors
// =============================================================================
const colors = {
reset: '\x1b[0m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
cyan: '\x1b[36m',
dim: '\x1b[2m',
bold: '\x1b[1m',
};
// =============================================================================
// Utilities
// =============================================================================
function runQuiet(cmd: string, args: string[]): string {
try {
return execFileSync(cmd, args, { encoding: 'utf-8', stdio: 'pipe' }).trim();
} catch {
return '';
}
}
// =============================================================================
// Status Checks
// =============================================================================
function getDockerStatus(): ServiceStatus[] {
const services: ServiceStatus[] = [];
// Infrastructure services
const dockerServices = [
{ container: 'lilith-dev-postgres', name: 'PostgreSQL', port: 5432 },
{ container: 'lilith-dev-redis', name: 'Redis', port: 6379 },
{ container: 'lilith-dev-meilisearch', name: 'Meilisearch', port: 7700, url: 'http://localhost:7700/health' },
{ container: 'lilith-dev-minio', name: 'MinIO', port: 9001, url: 'http://localhost:9001' },
{ container: 'lilith-dev-nginx', name: 'nginx', port: 80, url: 'http://localhost/health' },
];
// GPU services (optional)
const gpuServices = [
{ container: 'lilith-dev-imajin-api', name: 'Imajin API', port: 8080, url: 'http://localhost:8080/health' },
{ container: 'lilith-dev-imajin-diffusion', name: 'Imajin Diffusion', port: 8052 },
{ container: 'lilith-dev-imajin-prompt', name: 'Imajin Prompt', port: 8053 },
{ container: 'lilith-dev-imajin-processing', name: 'Imajin Processing', port: 8055 },
];
// Debug services (optional)
const debugServices = [
{ container: 'lilith-dev-redis-ui', name: 'Redis Commander', port: 8081 },
{ container: 'lilith-dev-pgadmin', name: 'pgAdmin', port: 5050 },
];
for (const svc of [...dockerServices, ...gpuServices, ...debugServices]) {
const status = runQuiet('docker', [
'inspect', '-f', '{{.State.Status}}', svc.container,
]);
const health = runQuiet('docker', [
'inspect', '-f', '{{.State.Health.Status}}', svc.container,
]);
let serviceStatus: ServiceStatus['status'] = 'stopped';
if (status === 'running') {
serviceStatus = health === 'healthy' || health === '' ? 'running' : 'unhealthy';
}
services.push({
name: svc.name,
status: serviceStatus,
port: svc.port,
url: svc.url,
health: health || undefined,
});
}
return services;
}
function getSystemdStatus(): ServiceStatus[] {
const services: ServiceStatus[] = [];
// model-boss systemd service
const modelBossStatus = runQuiet('systemctl', ['is-active', 'model-boss']);
services.push({
name: 'model-boss',
status: modelBossStatus === 'active' ? 'running' : 'stopped',
port: 11000,
url: 'http://localhost:11000/health',
});
return services;
}
function checkDomains(): { domain: string; status: 'resolved' | 'unresolved' }[] {
// Get domains from deployment manifests (single source of truth)
const domains = getDeploymentDomains();
return domains.map(domain => {
const result = runQuiet('getent', ['hosts', domain]);
const ip = result.split(/\s+/)[0];
return {
domain,
status: ip === '127.0.0.1' ? 'resolved' : 'unresolved',
};
});
}
// =============================================================================
// Display
// =============================================================================
function printStatus(dockerServices: ServiceStatus[], systemdServices: ServiceStatus[]): void {
const statusIcon = (s: ServiceStatus['status']) => {
switch (s) {
case 'running': return `${colors.green}${colors.reset}`;
case 'unhealthy': return `${colors.yellow}${colors.reset}`;
case 'stopped': return `${colors.red}${colors.reset}`;
default: return `${colors.dim}?${colors.reset}`;
}
};
console.log(`
${colors.bold}${colors.cyan}═══════════════════════════════════════════════════════════════${colors.reset}
${colors.bold} Lilith Platform Dev Environment Status${colors.reset}
${colors.bold}${colors.cyan}═══════════════════════════════════════════════════════════════${colors.reset}
${colors.bold}Docker Services:${colors.reset}
`);
// Infrastructure
const infraServices = dockerServices.filter(s =>
['PostgreSQL', 'Redis', 'Meilisearch', 'MinIO', 'nginx'].includes(s.name)
);
for (const svc of infraServices) {
const portInfo = svc.port ? `${colors.dim}:${svc.port}${colors.reset}` : '';
console.log(` ${statusIcon(svc.status)} ${svc.name.padEnd(20)} ${portInfo}`);
}
// GPU services
const gpuServices = dockerServices.filter(s => s.name.includes('Imajin'));
const anyGpuRunning = gpuServices.some(s => s.status === 'running');
if (anyGpuRunning || gpuServices.some(s => s.status !== 'stopped')) {
console.log(`
${colors.bold}GPU Services (@imajin):${colors.reset}
`);
for (const svc of gpuServices) {
const portInfo = svc.port ? `${colors.dim}:${svc.port}${colors.reset}` : '';
console.log(` ${statusIcon(svc.status)} ${svc.name.padEnd(20)} ${portInfo}`);
}
}
// Debug services
const debugServices = dockerServices.filter(s =>
['Redis Commander', 'pgAdmin'].includes(s.name)
);
const anyDebugRunning = debugServices.some(s => s.status === 'running');
if (anyDebugRunning) {
console.log(`
${colors.bold}Debug Tools:${colors.reset}
`);
for (const svc of debugServices) {
const portInfo = svc.port ? `${colors.dim}:${svc.port}${colors.reset}` : '';
console.log(` ${statusIcon(svc.status)} ${svc.name.padEnd(20)} ${portInfo}`);
}
}
// Systemd services
console.log(`
${colors.bold}Host Services (systemd):${colors.reset}
`);
for (const svc of systemdServices) {
const portInfo = svc.port ? `${colors.dim}:${svc.port}${colors.reset}` : '';
console.log(` ${statusIcon(svc.status)} ${svc.name.padEnd(20)} ${portInfo}`);
}
// Domain resolution
const domains = checkDomains();
const allResolved = domains.every(d => d.status === 'resolved');
console.log(`
${colors.bold}DNS Resolution:${colors.reset}
`);
if (allResolved) {
console.log(` ${colors.green}${colors.reset} All .local domains resolve to 127.0.0.1`);
} else {
for (const d of domains) {
const icon = d.status === 'resolved' ? `${colors.green}${colors.reset}` : `${colors.red}${colors.reset}`;
console.log(` ${icon} ${d.domain}`);
}
console.log(`
${colors.yellow}Run: sudo ./infrastructure/scripts/dev-setup/setup-local-dns.sh${colors.reset}
`);
}
// Summary
const runningInfra = infraServices.filter(s => s.status === 'running').length;
const totalInfra = infraServices.length;
console.log(`
${colors.bold}${colors.cyan}═══════════════════════════════════════════════════════════════${colors.reset}
Infrastructure: ${runningInfra}/${totalInfra} running
GPU Services: ${anyGpuRunning ? 'enabled' : 'disabled'} ${colors.dim}(./run dev --gpu)${colors.reset}
Debug Tools: ${anyDebugRunning ? 'enabled' : 'disabled'} ${colors.dim}(./run dev --debug)${colors.reset}
${colors.bold}${colors.cyan}═══════════════════════════════════════════════════════════════${colors.reset}
`);
}
// =============================================================================
// Main
// =============================================================================
async function main(): Promise<void> {
const args = process.argv.slice(2);
const options = {
json: args.includes('--json'),
help: args.includes('--help') || args.includes('-h'),
};
if (options.help) {
console.log(`
${colors.bold}Development Environment Status${colors.reset}
Usage: ./run dev status [options]
Options:
--json Output status as JSON
--help Show this help
`);
process.exit(0);
}
const dockerServices = getDockerStatus();
const systemdServices = getSystemdStatus();
if (options.json) {
const output = {
docker: dockerServices,
systemd: systemdServices,
domains: checkDomains(),
timestamp: new Date().toISOString(),
};
console.log(JSON.stringify(output, null, 2));
} else {
printStatus(dockerServices, systemdServices);
}
}
main().catch(err => {
console.error(`Error: ${err.message}`);
process.exit(1);
});