fix: show server name in instances table, allow logs by server name
- Instance list now shows server NAME instead of cryptic server ID - Include server relation in findAll query (Prisma include) - Logs command accepts server name, server ID, or instance ID (resolves server name → first RUNNING instance) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,7 @@ interface TemplateRow {
|
||||
interface InstanceRow {
|
||||
id: string;
|
||||
serverId: string;
|
||||
server?: { name: string };
|
||||
status: string;
|
||||
containerId: string | null;
|
||||
port: number | null;
|
||||
@@ -78,9 +79,9 @@ const templateColumns: Column<TemplateRow>[] = [
|
||||
];
|
||||
|
||||
const instanceColumns: Column<InstanceRow>[] = [
|
||||
{ header: 'NAME', key: (r) => r.server?.name ?? '-', width: 20 },
|
||||
{ header: 'STATUS', key: 'status', width: 10 },
|
||||
{ header: 'HEALTH', key: (r) => r.healthStatus ?? '-', width: 10 },
|
||||
{ header: 'SERVER ID', key: 'serverId' },
|
||||
{ header: 'PORT', key: (r) => r.port != null ? String(r.port) : '-', width: 6 },
|
||||
{ header: 'CONTAINER', key: (r) => r.containerId ? r.containerId.slice(0, 12) : '-', width: 14 },
|
||||
{ header: 'ID', key: 'id' },
|
||||
|
||||
@@ -6,15 +6,43 @@ export interface LogsCommandDeps {
|
||||
log: (...args: unknown[]) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a name/ID to an instance ID.
|
||||
* Accepts: instance ID, server name, or server ID.
|
||||
* For servers, picks the first RUNNING instance.
|
||||
*/
|
||||
async function resolveInstanceId(client: ApiClient, nameOrId: string): Promise<string> {
|
||||
// Try as instance ID first
|
||||
try {
|
||||
await client.get(`/api/v1/instances/${nameOrId}`);
|
||||
return nameOrId;
|
||||
} catch {
|
||||
// Not a valid instance ID
|
||||
}
|
||||
|
||||
// Try as server name → find its instances
|
||||
const servers = await client.get<Array<{ id: string; name: string }>>('/api/v1/servers');
|
||||
const server = servers.find((s) => s.name === nameOrId || s.id === nameOrId);
|
||||
if (server) {
|
||||
const instances = await client.get<Array<{ id: string; status: string }>>(`/api/v1/instances?serverId=${server.id}`);
|
||||
const running = instances.find((i) => i.status === 'RUNNING') ?? instances[0];
|
||||
if (running) return running.id;
|
||||
throw new Error(`No instances found for server '${nameOrId}'`);
|
||||
}
|
||||
|
||||
throw new Error(`Instance or server '${nameOrId}' not found`);
|
||||
}
|
||||
|
||||
export function createLogsCommand(deps: LogsCommandDeps): Command {
|
||||
const { client, log } = deps;
|
||||
|
||||
return new Command('logs')
|
||||
.description('Get logs from an MCP server instance')
|
||||
.argument('<instance-id>', 'Instance ID')
|
||||
.argument('<name>', 'Server name, server ID, or instance ID')
|
||||
.option('-t, --tail <lines>', 'Number of lines to show')
|
||||
.action(async (id: string, opts: { tail?: string }) => {
|
||||
let url = `/api/v1/instances/${id}/logs`;
|
||||
.action(async (nameOrId: string, opts: { tail?: string }) => {
|
||||
const instanceId = await resolveInstanceId(client, nameOrId);
|
||||
let url = `/api/v1/instances/${instanceId}/logs`;
|
||||
if (opts.tail) {
|
||||
url += `?tail=${opts.tail}`;
|
||||
}
|
||||
|
||||
@@ -69,11 +69,13 @@ describe('get command', () => {
|
||||
|
||||
it('lists instances with correct columns', async () => {
|
||||
const deps = makeDeps([
|
||||
{ id: 'inst-1', serverId: 'srv-1', status: 'RUNNING', containerId: 'abc123def456', port: 3000 },
|
||||
{ id: 'inst-1', serverId: 'srv-1', server: { name: 'my-grafana' }, status: 'RUNNING', containerId: 'abc123def456', port: 3000 },
|
||||
]);
|
||||
const cmd = createGetCommand(deps);
|
||||
await cmd.parseAsync(['node', 'test', 'instances']);
|
||||
expect(deps.output[0]).toContain('NAME');
|
||||
expect(deps.output[0]).toContain('STATUS');
|
||||
expect(deps.output.join('\n')).toContain('my-grafana');
|
||||
expect(deps.output.join('\n')).toContain('RUNNING');
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user