fix: address review feedback on preflight checks

- Consistent error handling: all preflight functions now throw instead
  of mixing process.exit and throw, so callers can catch and clean up
- checkGhAuth distinguishes "not installed" (ENOENT) from "not
  authenticated" by checking gh --version first
- Move checkBuilt() after package.json existence check in start.ts so
  missing web package shows "Run: pnpm install" not "Run: pnpm build"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
suraj-markup 2026-03-02 01:45:39 +05:30
parent 7128a9d469
commit f14465335d
2 changed files with 18 additions and 15 deletions

View File

@ -149,11 +149,11 @@ export function registerStart(program: Command): void {
if (opts?.dashboard !== false) {
// Pre-flight: only check port/build when actually starting the dashboard
await preflight.checkPort(port);
await preflight.checkBuilt();
const webDir = findWebDir();
if (!existsSync(resolve(webDir, "package.json"))) {
throw new Error("Could not find @composio/ao-web package. Run: pnpm install");
}
await preflight.checkBuilt();
if (opts?.rebuild) {
await cleanNextCache(webDir);

View File

@ -3,46 +3,43 @@
*
* Validates runtime prerequisites before entering the main command flow,
* giving clear errors instead of cryptic failures.
*
* All checks throw on failure so callers can catch and handle uniformly.
*/
import { existsSync } from "node:fs";
import { resolve } from "node:path";
import chalk from "chalk";
import { isPortAvailable, findWebDir } from "./web-dir.js";
import { exec } from "./shell.js";
/**
* Check that the dashboard port is free.
* Exits with a clear message if it's already in use.
* Throws if the port is already in use.
*/
async function checkPort(port: number): Promise<void> {
const free = await isPortAvailable(port);
if (!free) {
console.error(
chalk.red(
`Port ${port} is already in use. Free it or change 'port' in agent-orchestrator.yaml.`,
),
throw new Error(
`Port ${port} is already in use. Free it or change 'port' in agent-orchestrator.yaml.`,
);
process.exit(1);
}
}
/**
* Check that packages have been built (the web .next directory exists).
* Exits with a clear message if not.
* Throws if not built.
*/
async function checkBuilt(): Promise<void> {
const webDir = findWebDir();
const buildId = resolve(webDir, ".next", "BUILD_ID");
if (!existsSync(buildId)) {
console.error(chalk.red("Packages not built. Run: pnpm build"));
process.exit(1);
throw new Error("Packages not built. Run: pnpm build");
}
}
/**
* Check that tmux is installed (required for the default runtime).
* Throws with a clear message if not.
* Throws if not installed.
*/
async function checkTmux(): Promise<void> {
try {
@ -53,11 +50,17 @@ async function checkTmux(): Promise<void> {
}
/**
* Check that the GitHub CLI is authenticated.
* Only relevant when the project uses the github tracker plugin.
* Throws with a clear message if not authenticated.
* Check that the GitHub CLI is installed and authenticated.
* Distinguishes between "not installed" and "not authenticated"
* so the user gets the right troubleshooting guidance.
*/
async function checkGhAuth(): Promise<void> {
try {
await exec("gh", ["--version"]);
} catch {
throw new Error("GitHub CLI (gh) is not installed. Install it: https://cli.github.com/");
}
try {
await exec("gh", ["auth", "status"]);
} catch {