Make the network MVP simple to operate: server start refuses a second instance on a port already serving AgentHub (single source of truth, prevents discovery split-brain); commands auto-discover a LAN server when run outside any project so the CLI works from any directory with zero config; walk up to the nearest .agenthub project (cwd-robust) and serve the project root; replace raw stack traces with actionable messages; add tests for findProjectRoot and the single-instance guard. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
45 lines
1.5 KiB
TypeScript
45 lines
1.5 KiB
TypeScript
import Fastify from 'fastify';
|
|
import { registerRoutes } from './routes.js';
|
|
import { resolveAdvertiseUrl, startDiscoveryBroadcaster } from '../discovery.js';
|
|
|
|
export function buildApp(cwd: string) {
|
|
const app = Fastify({ logger: false });
|
|
registerRoutes(app, cwd);
|
|
return app;
|
|
}
|
|
|
|
export async function startServer(cwd: string, options: { port?: number; host?: string } = {}): Promise<{ app: Fastify.FastifyInstance; url: string }> {
|
|
const app = buildApp(cwd);
|
|
const port = options.port ?? 3377;
|
|
const host = options.host ?? '127.0.0.1';
|
|
|
|
let broadcaster: ReturnType<typeof startDiscoveryBroadcaster> | undefined;
|
|
app.addHook('onClose', async () => {
|
|
broadcaster?.stop();
|
|
});
|
|
|
|
try {
|
|
await app.listen({ port, host });
|
|
const address = app.server.address();
|
|
const actualPort = typeof address === 'string' ? port : (address?.port ?? port);
|
|
const url = `http://${host === '0.0.0.0' ? '127.0.0.1' : host}:${actualPort}`;
|
|
console.log(`AgentHub server listening on ${url}`);
|
|
|
|
const advertiseUrl = resolveAdvertiseUrl(host, actualPort);
|
|
broadcaster = startDiscoveryBroadcaster(advertiseUrl);
|
|
|
|
return { app, url };
|
|
} catch (err) {
|
|
const e = err as NodeJS.ErrnoException;
|
|
if (e.code === 'EADDRINUSE') {
|
|
console.error(
|
|
`Port ${port} is already in use by another process that is not AgentHub. ` +
|
|
`Stop it, or start with a different --port.`,
|
|
);
|
|
} else {
|
|
console.error(err);
|
|
}
|
|
process.exit(1);
|
|
}
|
|
}
|