Switch to double quotes and reformat codebase with Biome
This commit is contained in:
@@ -1,260 +1,260 @@
|
||||
import type { Command } from 'commander'
|
||||
import { execFileSync } from 'node:child_process'
|
||||
import { createRequire } from 'node:module'
|
||||
import { getOrCreateServerId, findExecutable, applyProviderEnv } from '@getpaseo/server'
|
||||
import { tryConnectToDaemon } from '../../utils/client.js'
|
||||
import type { CommandOptions, ListResult, OutputSchema } from '../../output/index.js'
|
||||
import { resolveLocalDaemonState, resolveTcpHostFromListen } from './local-daemon.js'
|
||||
import { resolveNodePathFromPid } from './runtime-toolchain.js'
|
||||
import type { Command } from "commander";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { createRequire } from "node:module";
|
||||
import { getOrCreateServerId, findExecutable, applyProviderEnv } from "@getpaseo/server";
|
||||
import { tryConnectToDaemon } from "../../utils/client.js";
|
||||
import type { CommandOptions, ListResult, OutputSchema } from "../../output/index.js";
|
||||
import { resolveLocalDaemonState, resolveTcpHostFromListen } from "./local-daemon.js";
|
||||
import { resolveNodePathFromPid } from "./runtime-toolchain.js";
|
||||
|
||||
interface ProviderBinaryStatus {
|
||||
label: string
|
||||
path: string | null
|
||||
version: string | null
|
||||
label: string;
|
||||
path: string | null;
|
||||
version: string | null;
|
||||
}
|
||||
|
||||
interface DaemonStatus {
|
||||
serverId: string | null
|
||||
status: 'running' | 'stopped' | 'unresponsive'
|
||||
home: string
|
||||
listen: string
|
||||
hostname: string | null
|
||||
pid: number | null
|
||||
startedAt: string | null
|
||||
owner: string | null
|
||||
logPath: string
|
||||
runningAgents: number | null
|
||||
idleAgents: number | null
|
||||
daemonNode: string
|
||||
cliNode: string
|
||||
cliVersion: string
|
||||
providers: ProviderBinaryStatus[]
|
||||
note?: string
|
||||
serverId: string | null;
|
||||
status: "running" | "stopped" | "unresponsive";
|
||||
home: string;
|
||||
listen: string;
|
||||
hostname: string | null;
|
||||
pid: number | null;
|
||||
startedAt: string | null;
|
||||
owner: string | null;
|
||||
logPath: string;
|
||||
runningAgents: number | null;
|
||||
idleAgents: number | null;
|
||||
daemonNode: string;
|
||||
cliNode: string;
|
||||
cliVersion: string;
|
||||
providers: ProviderBinaryStatus[];
|
||||
note?: string;
|
||||
}
|
||||
|
||||
interface StatusRow {
|
||||
key: string
|
||||
value: string
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
type CliPackageJson = {
|
||||
version?: unknown
|
||||
}
|
||||
version?: unknown;
|
||||
};
|
||||
|
||||
const require = createRequire(import.meta.url)
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
function normalizeError(error: unknown): string {
|
||||
if (error instanceof Error) {
|
||||
return error.message
|
||||
return error.message;
|
||||
}
|
||||
return String(error)
|
||||
return String(error);
|
||||
}
|
||||
|
||||
function shortenMessage(message: string, max = 120): string {
|
||||
const normalized = message.replace(/\s+/g, ' ').trim()
|
||||
const normalized = message.replace(/\s+/g, " ").trim();
|
||||
if (normalized.length <= max) {
|
||||
return normalized
|
||||
return normalized;
|
||||
}
|
||||
return `${normalized.slice(0, max - 3)}...`
|
||||
return `${normalized.slice(0, max - 3)}...`;
|
||||
}
|
||||
|
||||
function appendNote(current: string | undefined, next: string | undefined): string | undefined {
|
||||
if (!next) return current
|
||||
if (!current) return next
|
||||
return `${current}; ${next}`
|
||||
if (!next) return current;
|
||||
if (!current) return next;
|
||||
return `${current}; ${next}`;
|
||||
}
|
||||
|
||||
function resolveCliVersion(): string {
|
||||
try {
|
||||
const packageJson = require('../../../package.json') as CliPackageJson
|
||||
if (typeof packageJson.version === 'string' && packageJson.version.trim().length > 0) {
|
||||
return packageJson.version.trim()
|
||||
const packageJson = require("../../../package.json") as CliPackageJson;
|
||||
if (typeof packageJson.version === "string" && packageJson.version.trim().length > 0) {
|
||||
return packageJson.version.trim();
|
||||
}
|
||||
} catch {
|
||||
// Fall through.
|
||||
}
|
||||
return 'unknown'
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
function createStatusSchema(status: DaemonStatus): OutputSchema<StatusRow> {
|
||||
return {
|
||||
idField: 'key',
|
||||
idField: "key",
|
||||
columns: [
|
||||
{ header: 'KEY', field: 'key' },
|
||||
{ header: "KEY", field: "key" },
|
||||
{
|
||||
header: 'VALUE',
|
||||
field: 'value',
|
||||
header: "VALUE",
|
||||
field: "value",
|
||||
color: (_, item) => {
|
||||
if (item.key === 'Status') {
|
||||
if (item.value === 'running') return 'green'
|
||||
if (item.value === 'unresponsive') return 'yellow'
|
||||
return 'red'
|
||||
if (item.key === "Status") {
|
||||
if (item.value === "running") return "green";
|
||||
if (item.value === "unresponsive") return "yellow";
|
||||
return "red";
|
||||
}
|
||||
if (item.key.startsWith(' ')) {
|
||||
if (item.value === 'not found') return 'red'
|
||||
if (item.value.endsWith('(--version failed)')) return 'yellow'
|
||||
return 'green'
|
||||
if (item.key.startsWith(" ")) {
|
||||
if (item.value === "not found") return "red";
|
||||
if (item.value.endsWith("(--version failed)")) return "yellow";
|
||||
return "green";
|
||||
}
|
||||
return undefined
|
||||
return undefined;
|
||||
},
|
||||
},
|
||||
],
|
||||
serialize: () => status,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function toStatusRows(status: DaemonStatus): StatusRow[] {
|
||||
const rows: StatusRow[] = [
|
||||
{ key: 'Server ID', value: status.serverId ?? '-' },
|
||||
{ key: 'Status', value: status.status },
|
||||
{ key: 'Home', value: status.home },
|
||||
{ key: 'Listen', value: status.listen },
|
||||
{ key: 'Hostname', value: status.hostname ?? '-' },
|
||||
{ key: 'PID', value: status.pid === null ? '-' : String(status.pid) },
|
||||
{ key: 'Started', value: status.startedAt ?? '-' },
|
||||
{ key: 'Owner', value: status.owner ?? '-' },
|
||||
{ key: 'Logs', value: status.logPath },
|
||||
{ key: 'Daemon Node', value: status.daemonNode },
|
||||
{ key: 'CLI Node', value: status.cliNode },
|
||||
{ key: 'CLI', value: status.cliVersion },
|
||||
]
|
||||
{ key: "Server ID", value: status.serverId ?? "-" },
|
||||
{ key: "Status", value: status.status },
|
||||
{ key: "Home", value: status.home },
|
||||
{ key: "Listen", value: status.listen },
|
||||
{ key: "Hostname", value: status.hostname ?? "-" },
|
||||
{ key: "PID", value: status.pid === null ? "-" : String(status.pid) },
|
||||
{ key: "Started", value: status.startedAt ?? "-" },
|
||||
{ key: "Owner", value: status.owner ?? "-" },
|
||||
{ key: "Logs", value: status.logPath },
|
||||
{ key: "Daemon Node", value: status.daemonNode },
|
||||
{ key: "CLI Node", value: status.cliNode },
|
||||
{ key: "CLI", value: status.cliVersion },
|
||||
];
|
||||
|
||||
if (status.runningAgents !== null && status.idleAgents !== null) {
|
||||
rows.push({
|
||||
key: 'Agents',
|
||||
key: "Agents",
|
||||
value: `${status.runningAgents} running, ${status.idleAgents} idle`,
|
||||
})
|
||||
});
|
||||
} else {
|
||||
rows.push({
|
||||
key: 'Agents',
|
||||
value: 'Unavailable (daemon API not reachable)',
|
||||
})
|
||||
key: "Agents",
|
||||
value: "Unavailable (daemon API not reachable)",
|
||||
});
|
||||
}
|
||||
|
||||
if (status.note) {
|
||||
rows.push({ key: 'Note', value: status.note })
|
||||
rows.push({ key: "Note", value: status.note });
|
||||
}
|
||||
|
||||
rows.push({ key: '', value: '' })
|
||||
rows.push({ key: 'Providers', value: '' })
|
||||
rows.push({ key: "", value: "" });
|
||||
rows.push({ key: "Providers", value: "" });
|
||||
for (const provider of status.providers) {
|
||||
if (!provider.path) {
|
||||
rows.push({ key: ` ${provider.label}`, value: 'not found' })
|
||||
rows.push({ key: ` ${provider.label}`, value: "not found" });
|
||||
} else if (!provider.version) {
|
||||
rows.push({ key: ` ${provider.label}`, value: `${provider.path} (--version failed)` })
|
||||
rows.push({ key: ` ${provider.label}`, value: `${provider.path} (--version failed)` });
|
||||
} else {
|
||||
rows.push({ key: ` ${provider.label}`, value: `${provider.path} (${provider.version})` })
|
||||
rows.push({ key: ` ${provider.label}`, value: `${provider.path} (${provider.version})` });
|
||||
}
|
||||
}
|
||||
|
||||
return rows
|
||||
return rows;
|
||||
}
|
||||
|
||||
const PROVIDER_BINARIES: { label: string; binary: string }[] = [
|
||||
{ label: 'Claude', binary: 'claude' },
|
||||
{ label: 'Codex', binary: 'codex' },
|
||||
{ label: 'OpenCode', binary: 'opencode' },
|
||||
]
|
||||
{ label: "Claude", binary: "claude" },
|
||||
{ label: "Codex", binary: "codex" },
|
||||
{ label: "OpenCode", binary: "opencode" },
|
||||
];
|
||||
|
||||
function checkProviderBinary(binary: string): { path: string | null; version: string | null } {
|
||||
const binaryPath = findExecutable(binary)
|
||||
const binaryPath = findExecutable(binary);
|
||||
if (!binaryPath) {
|
||||
return { path: null, version: null }
|
||||
return { path: null, version: null };
|
||||
}
|
||||
const env = applyProviderEnv(process.env)
|
||||
const env = applyProviderEnv(process.env);
|
||||
try {
|
||||
const output = execFileSync(binaryPath, ['--version'], {
|
||||
encoding: 'utf8',
|
||||
const output = execFileSync(binaryPath, ["--version"], {
|
||||
encoding: "utf8",
|
||||
timeout: 5000,
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
env,
|
||||
}).trim()
|
||||
return { path: binaryPath, version: output || null }
|
||||
}).trim();
|
||||
return { path: binaryPath, version: output || null };
|
||||
} catch {
|
||||
return { path: binaryPath, version: null }
|
||||
return { path: binaryPath, version: null };
|
||||
}
|
||||
}
|
||||
|
||||
function checkProviderBinaries(): ProviderBinaryStatus[] {
|
||||
return PROVIDER_BINARIES.map(({ label, binary }) => {
|
||||
const result = checkProviderBinary(binary)
|
||||
return { label, ...result }
|
||||
})
|
||||
const result = checkProviderBinary(binary);
|
||||
return { label, ...result };
|
||||
});
|
||||
}
|
||||
|
||||
function resolveOwnerLabel(uid: number | undefined, hostname: string | undefined): string | null {
|
||||
if (uid === undefined && !hostname) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
const uidPart = uid === undefined ? '?' : String(uid)
|
||||
const hostPart = hostname ?? 'unknown-host'
|
||||
return `${uidPart}@${hostPart}`
|
||||
const uidPart = uid === undefined ? "?" : String(uid);
|
||||
const hostPart = hostname ?? "unknown-host";
|
||||
return `${uidPart}@${hostPart}`;
|
||||
}
|
||||
|
||||
export type StatusResult = ListResult<StatusRow>
|
||||
export type StatusResult = ListResult<StatusRow>;
|
||||
|
||||
export async function runStatusCommand(
|
||||
options: CommandOptions,
|
||||
_command: Command
|
||||
_command: Command,
|
||||
): Promise<StatusResult> {
|
||||
const home = typeof options.home === 'string' ? options.home : undefined
|
||||
const state = resolveLocalDaemonState({ home })
|
||||
const home = typeof options.home === "string" ? options.home : undefined;
|
||||
const state = resolveLocalDaemonState({ home });
|
||||
|
||||
const owner = resolveOwnerLabel(state.pidInfo?.uid, state.pidInfo?.hostname)
|
||||
let daemonNode: string
|
||||
const owner = resolveOwnerLabel(state.pidInfo?.uid, state.pidInfo?.hostname);
|
||||
let daemonNode: string;
|
||||
if (!state.running) {
|
||||
daemonNode = '-'
|
||||
daemonNode = "-";
|
||||
} else if (state.pidInfo?.pid) {
|
||||
const fromPid = resolveNodePathFromPid(state.pidInfo.pid)
|
||||
daemonNode = fromPid.nodePath ?? `unknown (${fromPid.error ?? 'could not resolve from PID'})`
|
||||
const fromPid = resolveNodePathFromPid(state.pidInfo.pid);
|
||||
daemonNode = fromPid.nodePath ?? `unknown (${fromPid.error ?? "could not resolve from PID"})`;
|
||||
} else {
|
||||
daemonNode = 'unknown (no PID available)'
|
||||
daemonNode = "unknown (no PID available)";
|
||||
}
|
||||
const cliNode = process.execPath
|
||||
let status: DaemonStatus['status'] = state.running ? 'running' : 'stopped'
|
||||
let runningAgents: number | null = null
|
||||
let idleAgents: number | null = null
|
||||
let note: string | undefined
|
||||
const cliNode = process.execPath;
|
||||
let status: DaemonStatus["status"] = state.running ? "running" : "stopped";
|
||||
let runningAgents: number | null = null;
|
||||
let idleAgents: number | null = null;
|
||||
let note: string | undefined;
|
||||
|
||||
if (!state.running && state.stalePidFile && state.pidInfo) {
|
||||
note = `Stale PID file found for PID ${state.pidInfo.pid}`
|
||||
note = `Stale PID file found for PID ${state.pidInfo.pid}`;
|
||||
}
|
||||
|
||||
if (state.running) {
|
||||
const host = resolveTcpHostFromListen(state.listen)
|
||||
const host = resolveTcpHostFromListen(state.listen);
|
||||
if (host) {
|
||||
const client = await tryConnectToDaemon({ host, timeout: 1500 })
|
||||
const client = await tryConnectToDaemon({ host, timeout: 1500 });
|
||||
if (client) {
|
||||
try {
|
||||
const agentsPayload = await client.fetchAgents({ filter: { includeArchived: true } })
|
||||
const agents = agentsPayload.entries.map((entry) => entry.agent)
|
||||
runningAgents = agents.filter(a => a.status === 'running').length
|
||||
idleAgents = agents.filter(a => a.status === 'idle').length
|
||||
const agentsPayload = await client.fetchAgents({ filter: { includeArchived: true } });
|
||||
const agents = agentsPayload.entries.map((entry) => entry.agent);
|
||||
runningAgents = agents.filter((a) => a.status === "running").length;
|
||||
idleAgents = agents.filter((a) => a.status === "idle").length;
|
||||
} catch {
|
||||
status = 'unresponsive'
|
||||
note = appendNote(note, `Daemon PID is running but API requests to ${host} failed`)
|
||||
status = "unresponsive";
|
||||
note = appendNote(note, `Daemon PID is running but API requests to ${host} failed`);
|
||||
} finally {
|
||||
await client.close().catch(() => {})
|
||||
await client.close().catch(() => {});
|
||||
}
|
||||
} else {
|
||||
status = 'unresponsive'
|
||||
note = appendNote(note, `Daemon PID is running but websocket at ${host} is not reachable`)
|
||||
status = "unresponsive";
|
||||
note = appendNote(note, `Daemon PID is running but websocket at ${host} is not reachable`);
|
||||
}
|
||||
} else {
|
||||
note = appendNote(note, 'Daemon is configured for unix socket listen; API probe skipped')
|
||||
note = appendNote(note, "Daemon is configured for unix socket listen; API probe skipped");
|
||||
}
|
||||
}
|
||||
|
||||
const cliVersion = resolveCliVersion()
|
||||
const cliVersion = resolveCliVersion();
|
||||
|
||||
let serverId: string | null = null
|
||||
let serverId: string | null = null;
|
||||
try {
|
||||
serverId = getOrCreateServerId(state.home)
|
||||
serverId = getOrCreateServerId(state.home);
|
||||
} catch (error) {
|
||||
note = appendNote(note, `serverId unavailable: ${shortenMessage(normalizeError(error))}`)
|
||||
note = appendNote(note, `serverId unavailable: ${shortenMessage(normalizeError(error))}`);
|
||||
}
|
||||
|
||||
const providers = checkProviderBinaries()
|
||||
const providers = checkProviderBinaries();
|
||||
|
||||
const daemonStatus: DaemonStatus = {
|
||||
serverId,
|
||||
@@ -273,11 +273,11 @@ export async function runStatusCommand(
|
||||
cliVersion,
|
||||
providers,
|
||||
note,
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
type: 'list',
|
||||
type: "list",
|
||||
data: toStatusRows(daemonStatus),
|
||||
schema: createStatusSchema(daemonStatus),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user