116 lines
3.1 KiB
TypeScript
116 lines
3.1 KiB
TypeScript
import { getDaemonPid, readMeta, LOG_FILE, GATEWAY_HOME } from './daemon.js';
|
|
|
|
interface GatewayOpts {
|
|
host: string;
|
|
port: number;
|
|
token?: string;
|
|
}
|
|
|
|
interface ServiceStatus {
|
|
name: string;
|
|
status: string;
|
|
latency?: string;
|
|
}
|
|
|
|
interface AdminHealth {
|
|
status: string;
|
|
services: {
|
|
database: { status: string; latencyMs: number };
|
|
cache: { status: string; latencyMs: number };
|
|
};
|
|
agentPool?: { active: number };
|
|
providers?: Array<{ name: string; available: boolean; models: number }>;
|
|
}
|
|
|
|
export async function runStatus(opts: GatewayOpts): Promise<void> {
|
|
const meta = readMeta();
|
|
const pid = getDaemonPid();
|
|
|
|
console.log('Mosaic Gateway Status');
|
|
console.log('─────────────────────');
|
|
|
|
// Daemon status
|
|
if (pid !== null) {
|
|
console.log(` Status: running (PID ${pid.toString()})`);
|
|
} else {
|
|
console.log(' Status: stopped');
|
|
}
|
|
|
|
// Version
|
|
console.log(` Version: ${meta?.version ?? 'unknown'}`);
|
|
|
|
// Endpoint
|
|
const host = opts.host;
|
|
const port = opts.port;
|
|
console.log(` Endpoint: http://${host}:${port.toString()}`);
|
|
console.log(` Config: ${GATEWAY_HOME}`);
|
|
console.log(` Logs: ${LOG_FILE}`);
|
|
|
|
if (pid === null) return;
|
|
|
|
// Health check
|
|
try {
|
|
const healthRes = await fetch(`http://${host}:${port.toString()}/health`);
|
|
if (!healthRes.ok) {
|
|
console.log('\n Health: unreachable');
|
|
return;
|
|
}
|
|
} catch {
|
|
console.log('\n Health: unreachable');
|
|
return;
|
|
}
|
|
|
|
// Admin health (requires token)
|
|
const token = opts.token ?? meta?.adminToken;
|
|
if (!token) {
|
|
console.log(
|
|
'\n (No admin token — run `mosaic gateway config` to set one for detailed status)',
|
|
);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const res = await fetch(`http://${host}:${port.toString()}/api/admin/health`, {
|
|
headers: { Authorization: `Bearer ${token}` },
|
|
});
|
|
|
|
if (!res.ok) {
|
|
console.log('\n Admin health: unauthorized or unavailable');
|
|
return;
|
|
}
|
|
|
|
const health = (await res.json()) as AdminHealth;
|
|
|
|
console.log('\n Services:');
|
|
const services: ServiceStatus[] = [
|
|
{
|
|
name: 'Database',
|
|
status: health.services.database.status,
|
|
latency: `${health.services.database.latencyMs.toString()}ms`,
|
|
},
|
|
{
|
|
name: 'Cache',
|
|
status: health.services.cache.status,
|
|
latency: `${health.services.cache.latencyMs.toString()}ms`,
|
|
},
|
|
];
|
|
|
|
for (const svc of services) {
|
|
const latStr = svc.latency ? ` (${svc.latency})` : '';
|
|
console.log(` ${svc.name}:${' '.repeat(10 - svc.name.length)}${svc.status}${latStr}`);
|
|
}
|
|
|
|
if (health.providers && health.providers.length > 0) {
|
|
const available = health.providers.filter((p) => p.available);
|
|
const names = available.map((p) => p.name).join(', ');
|
|
console.log(`\n Providers: ${available.length.toString()} active (${names})`);
|
|
}
|
|
|
|
if (health.agentPool) {
|
|
console.log(` Sessions: ${health.agentPool.active.toString()} active`);
|
|
}
|
|
} catch {
|
|
console.log('\n Admin health: connection error');
|
|
}
|
|
}
|